git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 4/8] use child_process member "args" instead of string array variable

From
René Scharfe <l.s.r@web.de>
Date
Oct 28, 2022, 14:23 UTC
Message-ID
<6c30a1f6-8d89-31b9-faf8-c695c46173cd@web.de>
In-Reply-To
<221027.86zgdh9cqg.gmgdl@evledraar.gmail.com>
Am 27.10.22 um 23:09 schrieb Ævar Arnfjörð Bjarmason:
Show 39 quoted lines
>
> On Thu, Oct 27 2022, René Scharfe wrote:
>
>> @@ -729,20 +727,22 @@ static int is_expected_rev(const struct object_id *oid)
>>  enum bisect_error bisect_checkout(const struct object_id *bisect_rev,
>>  				  int no_checkout)
>>  {
>> -	char bisect_rev_hex[GIT_MAX_HEXSZ + 1];
>>  	struct commit *commit;
>>  	struct pretty_print_context pp = {0};
>>  	struct strbuf commit_msg = STRBUF_INIT;
>>
>> -	oid_to_hex_r(bisect_rev_hex, bisect_rev);
>>  	update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
>>
>> -	argv_checkout[2] = bisect_rev_hex;
>>  	if (no_checkout) {
>>  		update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0,
>>  			   UPDATE_REFS_DIE_ON_ERR);
>>  	} else {
>> -		if (run_command_v_opt(argv_checkout, RUN_GIT_CMD))
>> +		struct child_process cmd = CHILD_PROCESS_INIT;
>> +
>> +		cmd.git_cmd = 1;
>> +		strvec_pushl(&cmd.args, "checkout", "-q",
>> +			     oid_to_hex(bisect_rev), "--", NULL);
>> +		if (run_command(&cmd))
>>  			/*
>>  			 * Errors in `run_command()` itself, signaled by res < 0,
>>  			 * and errors in the child process, signaled by res > 0
>
> Perhaps I went overboard with it in my version, but it's probably worth
> mentioning when converting some of these that the reason for the
> pre-image of some is really not like the others.
>
> Now that we're on C99 it perhaps make s no difference, but the pre-image
> here is explicitly trying to avoid dynamic initializer elements, per
> 442c27dde78 (CodingGuidelines: mention dynamic C99 initializer elements,
> 2022-10-10).

True, some cases could be converted to string array initializations, which also would get rid of magic numbers. This would make the final patch to convert them to run_command() longer.

Show 31 quoted lines
> Well, partially, some of it appears to just be based on a
> misunderstanding of how our own APIs work, i.e. the use of
> oid_to_hex_r() over oid_to_hex().
>
>> diff --git a/builtin/am.c b/builtin/am.c
>> index 39fea24833..20aea0d248 100644
>> --- a/builtin/am.c
>> +++ b/builtin/am.c
>> @@ -2187,14 +2187,12 @@ static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
>>  	int len;
>>
>>  	if (!is_null_oid(&state->orig_commit)) {
>> -		const char *av[4] = { "show", NULL, "--", NULL };
>> -		char *new_oid_str;
>> -		int ret;
>> +		struct child_process cmd = CHILD_PROCESS_INIT;
>>
>> -		av[1] = new_oid_str = xstrdup(oid_to_hex(&state->orig_commit));
>> -		ret = run_command_v_opt(av, RUN_GIT_CMD);
>> -		free(new_oid_str);
>> -		return ret;
>> +		strvec_pushl(&cmd.args, "show", oid_to_hex(&state->orig_commit),
>> +			     "--", NULL);
>> +		cmd.git_cmd = 1;
>> +		return run_command(&cmd);
>>  	}
>
> The same goes for this, FWIW I split this one out into its own commit (I
> left the earlier one alone):
> https://lore.kernel.org/git/patch-v2-04.10-5cfd6a94ce3-20221017T170316Z-avarab@gmail.com/;
> It uses the same pattern

OK, I just chalked that up as "slightly odd" and bulldozed over them without a second thought. Hmm.

Show 50 quoted lines
>
>> diff --git a/builtin/difftool.c b/builtin/difftool.c
>> index 4b10ad1a36..22bcc3444b 100644
>> --- a/builtin/difftool.c
>> +++ b/builtin/difftool.c
>> @@ -360,8 +360,8 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
>>  	struct pair_entry *entry;
>>  	struct index_state wtindex;
>>  	struct checkout lstate, rstate;
>> -	int flags = RUN_GIT_CMD, err = 0;
>> -	const char *helper_argv[] = { "difftool--helper", NULL, NULL, NULL };
>> +	int err = 0;
>> +	struct child_process cmd = CHILD_PROCESS_INIT;
>
> In general, I like the disection of this series, but with this...
>
>>  	struct hashmap wt_modified, tmp_modified;
>>  	int indices_loaded = 0;
>>
>> @@ -563,16 +563,17 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
>>  	}
>>
>>  	strbuf_setlen(&ldir, ldir_len);
>> -	helper_argv[1] = ldir.buf;
>>  	strbuf_setlen(&rdir, rdir_len);
>> -	helper_argv[2] = rdir.buf;
>>
>>  	if (extcmd) {
>> -		helper_argv[0] = extcmd;
>> -		flags = 0;
>> -	} else
>> +		strvec_push(&cmd.args, extcmd);
>> +	} else {
>> +		strvec_push(&cmd.args, "difftool--helper");
>> +		cmd.git_cmd = 1;
>
> ...and the frequent occurance of just e.g. "cmd.git_cmd = 1" and nothing
> else I'm wondering if we're not throwing the baby out with the bath
> water in having no convenience wrappers or macros at all.
>
> A lot of your 3-lines would be 1 lines if we just had e.g. (untested,
> and could be a function not a macro, but you get the idea):
>
> 	#define run_command_git_simple(__VA_ARGS__) \
> 		struct child_process cmd = CHILD_PROCESS_INIT; \
> 		cmd.git_cmd = 1; \
> 		strvec_pushl(&cmd.args, __VA_ARGS__); \
> 		run_command(&cmd);
>
> But maybe nobody except me thinks that's worthwhile...

I have similar temptations; you could see that in my scratch patch https://lore.kernel.org/git/9d924a5d-5c72-fbe6-270c-a8f6c5fc5850@web.de/ which added run_git_or_die() in builtin/gc.c. Why, oh why? Perhaps because taking a blank form (CHILD_PROCESS_INIT), ticking boxes (.git_cmd = 1), filling out text fields (strvec_push(...)) and submitting it (run_command()) feels tedious and bureaucratic, Java-esque even. And some patterns appear again and again.

How bad is that? Is it bad at all? I think overall we should try to reduce the number of external calls and make those we have to do self-documenting and leak-free. A bit of tedium is OK; this API should be used rarely and sparingly. Still I get the urge to search for patterns and define shortcuts when I see all those similar calls..

run_command_git_simple as defined above wouldn't compile, but I get it. Reducing the number of lines feels good, but it also makes the code less flexible -- adding a conditional parameter requires converting back to run_command().

Show 50 quoted lines
>
>>  static void read_empty(const struct object_id *oid)
>>  {
>> -	int i = 0;
>> -	const char *args[7];
>> -
>> -	args[i++] = "read-tree";
>> -	args[i++] = "-m";
>> -	args[i++] = "-u";
>> -	args[i++] = empty_tree_oid_hex();
>> -	args[i++] = oid_to_hex(oid);
>> -	args[i] = NULL;
>> +	struct child_process cmd = CHILD_PROCESS_INIT;
>> +
>> +	strvec_pushl(&cmd.args, "read-tree", "-m", "-u", empty_tree_oid_hex(),
>> +		     oid_to_hex(oid), NULL);
>> +	cmd.git_cmd = 1;
>>
>> -	if (run_command_v_opt(args, RUN_GIT_CMD))
>> +	if (run_command(&cmd))
>>  		die(_("read-tree failed"));
>>  }
>>
>>  static void reset_hard(const struct object_id *oid)
>>  {
>> -	int i = 0;
>> -	const char *args[6];
>> -
>> -	args[i++] = "read-tree";
>> -	args[i++] = "-v";
>> -	args[i++] = "--reset";
>> -	args[i++] = "-u";
>> -	args[i++] = oid_to_hex(oid);
>> -	args[i] = NULL;
>> +	struct child_process cmd = CHILD_PROCESS_INIT;
>> +
>> +	strvec_pushl(&cmd.args, "read-tree", "-v", "--reset", "-u",
>> +		     oid_to_hex(oid), NULL);
>> +	cmd.git_cmd = 1;
>>
>> -	if (run_command_v_opt(args, RUN_GIT_CMD))
>> +	if (run_command(&cmd))
>>  		die(_("read-tree failed"));
>>  }
>
> Two perfect examples, e.g. the former would just be:
>
> 	if (run_command_git_simple("read-tree", "-m", "-u", empty_tree_oid_hex(),
> 				   oid_to_hex(oid), NULL))
> 		die(...);
Previous: Ævar Arnfjörð BjarmasonNext: Taylor Blau
Message 12 of 49 in “run-command: remove run_command_v_*()”
  1. 0/8 run-command: remove run_command_v_*()René Scharfe, Oct 27, 2022
  2. 1/8 merge: remove always-the-same "verbose" argumentsRené Scharfe, Oct 27, 2022
  3. Taylor BlauOct 29, 2022
  4. 2/8 bisect--helper: factor out do_bisect_run()René Scharfe, Oct 27, 2022
  5. Ævar Arnfjörð BjarmasonOct 27, 2022
  6. Taylor BlauOct 29, 2022
  7. 3/8 use child_process members "args" and "env" directlyRené Scharfe, Oct 27, 2022
  8. Junio C HamanoOct 27, 2022
  9. Ævar Arnfjörð BjarmasonOct 27, 2022
  10. 4/8 use child_process member "args" instead of string array variableRené Scharfe, Oct 27, 2022
  11. Ævar Arnfjörð BjarmasonOct 27, 2022
  12. René ScharfeOct 28, 2022
  13. Taylor BlauOct 29, 2022
  14. Taylor BlauOct 29, 2022
  15. 5/8 replace and remove run_command_v_opt_cd_env()René Scharfe, Oct 27, 2022
  16. Ævar Arnfjörð BjarmasonOct 27, 2022
  17. Taylor BlauOct 29, 2022
  18. 6/8 replace and remove run_command_v_opt_tr2()René Scharfe, Oct 27, 2022
  19. 7/8 replace and remove run_command_v_opt_cd_env_tr2()René Scharfe, Oct 27, 2022
  20. Ævar Arnfjörð BjarmasonOct 27, 2022
  21. René ScharfeOct 28, 2022
  22. 8/8 replace and remove run_command_v_opt()René Scharfe, Oct 27, 2022
  23. Ævar Arnfjörð BjarmasonOct 27, 2022
  24. René ScharfeOct 28, 2022
  25. Jeff KingOct 27, 2022
  26. René ScharfeOct 28, 2022
  27. Ævar Arnfjörð BjarmasonOct 27, 2022
  28. René ScharfeOct 28, 2022
  29. Ævar Arnfjörð BjarmasonOct 28, 2022
  30. René ScharfeOct 28, 2022
  31. Ævar Arnfjörð BjarmasonOct 29, 2022
  32. René ScharfeOct 29, 2022
  33. Taylor BlauOct 29, 2022
  34. 0/12 run-command: remove run_command_v_*()René Scharfe, Oct 30, 2022
  35. 01/12 merge: remove always-the-same "verbose" argumentsRené Scharfe, Oct 30, 2022
  36. 02/12 run-command: fix return value commentRené Scharfe, Oct 30, 2022
  37. 03/12 am: simplify building "show" argument listRené Scharfe, Oct 30, 2022
  38. 04/12 bisect: simplify building "checkout" argument listRené Scharfe, Oct 30, 2022
  39. 05/12 bisect--helper: factor out do_bisect_run()René Scharfe, Oct 30, 2022
  40. 06/12 sequencer: simplify building argument list in do_exec()René Scharfe, Oct 30, 2022
  41. 07/12 use child_process member "args" instead of string array variableRené Scharfe, Oct 30, 2022
  42. 08/12 use child_process members "args" and "env" directlyRené Scharfe, Oct 30, 2022
  43. 09/12 replace and remove run_command_v_opt_cd_env()René Scharfe, Oct 30, 2022
  44. 10/12 replace and remove run_command_v_opt_tr2()René Scharfe, Oct 30, 2022
  45. 11/12 replace and remove run_command_v_opt_cd_env_tr2()René Scharfe, Oct 30, 2022
  46. 12/12 replace and remove run_command_v_opt()René Scharfe, Oct 30, 2022
  47. René ScharfeOct 30, 2022
  48. Taylor BlauOct 30, 2022
  49. Ævar Arnfjörð BjarmasonOct 31, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.