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

Re: [PATCH 4/4] submodule: port submodule subcommand 'foreach' from shell to C

From
Junio C Hamano <gitster@pobox.com>
Date
May 10, 2018, 06:37 UTC
Message-ID
<xmqqo9hoj9s7.fsf@gitster-ct.c.googlers.com>
In-Reply-To
<20180509002952.172347-5-sbeller@google.com>
Stefan Beller <sbeller@google.com> writes:
Show 29 quoted lines
> +static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
> +				       void *cb_data)
> +{
> +	struct cb_foreach *info = cb_data;
> +	const char *path = list_item->name;
> +	const struct object_id *ce_oid = &list_item->oid;
> +
> +	const struct submodule *sub;
> +	struct child_process cp = CHILD_PROCESS_INIT;
> +	char *displaypath;
> +
> +	displaypath = get_submodule_displaypath(path, info->prefix);
> +
> +	sub = submodule_from_path(the_repository, &null_oid, path);
> +
> +	if (!sub)
> +		die(_("No url found for submodule path '%s' in .gitmodules"),
> +			displaypath);
> +
> +	if (!is_submodule_populated_gently(path, NULL))
> +		goto cleanup;
> +
> +	prepare_submodule_repo_env(&cp.env_array);
> +
> +	/*
> +	* For the purpose of executing <command> in the submodule,
> +	* separate shell is used for the purpose of running the
> +	* child process.
> +	*/
Micronit: this multi-line comment is indented in a funny way.
Show 9 quoted lines
> +	cp.use_shell = 1;
> +	cp.dir = path;
> +
> +	/*
> +	* NEEDSWORK: the command currently has access to the variables $name,
> +	* $sm_path, $displaypath, $sha1 and $toplevel only when the command
> +	* contains a single argument. This is done for maintaining a faithful
> +	* translation from shell script.
> +	*/
Same micronit.
The scripted version does 'eval "$1"', so $1 could be something like 
	for-each 'echo "$name:$sm_path:$displaypath:$sha1:$toplevel"'

and it can see any variable, not just these 5 (i.e. we could have fed e.g. $wt_prefix and $mode to the above 'echo' and with the scripted version the script would have learned their values; with this version it no longer does, but only these 5 are part of the documented API, so we choose not to consider it a regression).

Show 23 quoted lines
> +	if (info->argc == 1) {
> +		char *toplevel = xgetcwd();
> +		struct strbuf sb = STRBUF_INIT;
> +
> +		argv_array_pushf(&cp.env_array, "name=%s", sub->name);
> +		argv_array_pushf(&cp.env_array, "sm_path=%s", path);
> +		argv_array_pushf(&cp.env_array, "displaypath=%s", displaypath);
> +		argv_array_pushf(&cp.env_array, "sha1=%s",
> +				oid_to_hex(ce_oid));
> +		argv_array_pushf(&cp.env_array, "toplevel=%s", toplevel);
> +
> +		/*
> +		* Since the path variable was accessible from the script
> +		* before porting, it is also made available after porting.
> +		* The environment variable "PATH" has a very special purpose
> +		* on windows. And since environment variables are
> +		* case-insensitive in windows, it interferes with the
> +		* existing PATH variable. Hence, to avoid that, we expose
> +		* path via the args argv_array and not via env_array.
> +		*/
> +		sq_quote_buf(&sb, path);
> +		argv_array_pushf(&cp.args, "path=%s; %s",
> +				 sb.buf, info->argv[0]);
OK, so we do the equivalent of
	name=... sm_path=... displaypath=... sha1=... toplevel=... \
	sh -c 'path=...; echo "$name:$sm_path:..."'
when doing
	for-each 'echo "$name:$sm_path:..."'

with parts denoted with ... correctly quoted as necessary. I guess it would be the best we could do.

I myself do not know if it is true that bash ported to Windows won't get confused with the above "we use path (all lowercase) only as a pure shell variable without exporting it ourselves"; I'd trust those who are more familiar with the platform to raise objections and suggest a better alternative if it is not the case.

Thanks for the (malformatted;-) leading comment to highlight why the 'path' variable alone is treated differently from the others.

Show 39 quoted lines
> +		strbuf_release(&sb);
> +		free(toplevel);
> +	} else {
> +		argv_array_pushv(&cp.args, info->argv);
> +	}
> +
> +	if (!info->quiet)
> +		printf(_("Entering '%s'\n"), displaypath);
> +
> +	if (info->argv[0] && run_command(&cp))
> +		die(_("run_command returned non-zero status for %s\n."),
> +			displaypath);
> +
> +	if (info->recursive) {
> +		struct child_process cpr = CHILD_PROCESS_INIT;
> +
> +		cpr.git_cmd = 1;
> +		cpr.dir = path;
> +		prepare_submodule_repo_env(&cpr.env_array);
> +
> +		argv_array_pushl(&cpr.args, "--super-prefix", NULL);
> +		argv_array_pushf(&cpr.args, "%s/", displaypath);
> +		argv_array_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
> +				NULL);
> +
> +		if (info->quiet)
> +			argv_array_push(&cpr.args, "--quiet");
> +
> +		argv_array_pushv(&cpr.args, info->argv);
> +
> +		if (run_command(&cpr))
> +			die(_("run_command returned non-zero status while"
> +				"recursing in the nested submodules of %s\n."),
> +				displaypath);
> +	}
> +
> +cleanup:
> +	free(displaypath);
> +}
Previous: Stefan BellerNext: Stefan Beller
Message 20 of 22 in “Rebooting pc/submodule-helper-foreach”
  1. 0/5 Rebooting pc/submodule-helper-foreachStefan Beller, May 3, 2018
  2. 1/5 submodule foreach: correct '$path' in nested submodules from a subdirectoryStefan Beller, May 3, 2018
  3. Ramsay JonesMay 3, 2018
  4. Jonathan TanMay 3, 2018
  5. Stefan BellerMay 3, 2018
  6. Jonathan TanMay 4, 2018
  7. 3/5 submodule foreach: clarify the '$toplevel' variable documentationStefan Beller, May 3, 2018
  8. Jonathan TanMay 3, 2018
  9. 2/5 submodule foreach: document '$sm_path' instead of '$path'Stefan Beller, May 3, 2018
  10. Jonathan TanMay 3, 2018
  11. 4/5 submodule foreach: document variable '$displaypath'Stefan Beller, May 3, 2018
  12. 5/5 submodule: port submodule subcommand 'foreach' from shell to CStefan Beller, May 3, 2018
  13. Stefan BellerMay 3, 2018
  14. Jonathan TanMay 3, 2018
  15. 0/4 Rebooting pc/submodule-helper-foreachStefan Beller, May 9, 2018
  16. 1/4 submodule foreach: correct '$path' in nested submodules from a subdirectoryStefan Beller, May 9, 2018
  17. 2/4 submodule foreach: document '$sm_path' instead of '$path'Stefan Beller, May 9, 2018
  18. 3/4 submodule foreach: document variable '$displaypath'Stefan Beller, May 9, 2018
  19. 4/4 submodule: port submodule subcommand 'foreach' from shell to CStefan Beller, May 9, 2018
  20. Junio C HamanoMay 10, 2018
  21. submodule: port submodule subcommand 'foreach' from shell to CStefan Beller, May 10, 2018
  22. Jonathan TanMay 9, 2018

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.