Subject: Re: [PATCH v2 2/9] setup: introduce startup_info->original_cwd

From: Junio C Hamano <[email-masked]>
Date: Thu, 25 Nov 2021 22:52:18 -0800

"Elijah Newren via GitGitGadget" <[email-masked]> writes:

> diff --git a/git.c b/git.c
> index 5ff21be21f3..2c98ab48936 100644
> --- a/git.c
> +++ b/git.c
> @@ -866,6 +866,8 @@ int cmd_main(int argc, const char **argv)
>  
>  	trace_command_performance(argv);
>  
> +	startup_info->original_cwd = xgetcwd();

We assume that, unless we are an auxiliary tool like git-remote-http,
we should always have cwd?

> diff --git a/setup.c b/setup.c
> index 347d7181ae9..f30657723ea 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -432,6 +432,54 @@ void setup_work_tree(void)
>  	initialized = 1;
>  }
>  
> +static void setup_original_cwd(void)
> +{
> +	struct strbuf tmp = STRBUF_INIT;
> +	const char *worktree = NULL;
> +	int offset = -1;
> +
> +	/*
> +	 * startup_info->original_cwd wass set early on in cmd_main(), unless

s/wass/was/;

> +	 * we're an auxiliary tool like git-remote-http or test-tool.
> +	 */
> +	if (!startup_info->original_cwd)
> +		return;
> +
> +	/*
> +	 * startup_info->original_cwd points to the current working
> +	 * directory we inherited from our parent process, which is a
> +	 * directory we want to avoid incidentally removing.
> +	 *
> +	 * For convience, we would like to have the path relative to the
> +	 * worktree instead of an absolute path.
> +	 *
> +	 * Yes, startup_info->original_cwd is usually the same as 'prefix',
> +	 * but differs in two ways:
> +	 *   - prefix has a trailing '/'
> +	 *   - if the user passes '-C' to git, that modifies the prefix but
> +	 *     not startup_info->original_cwd.
> +	 */
> +
> +	/* Normalize the directory */
> +	strbuf_realpath(&tmp, startup_info->original_cwd, 1);
> +	free((char*)startup_info->original_cwd);
> +	startup_info->original_cwd = strbuf_detach(&tmp, NULL);
> +
> +	/* Find out if this is in the worktree */
> +	worktree = get_git_work_tree();
> +	if (worktree)
> +		offset = dir_inside_of(startup_info->original_cwd, worktree);
> +	if (offset >= 0) {
> +		/*
> +		 * original_cwd was inside worktree; precompose it just as
> +		 * we do prefix so that built up paths will match
> +		 */
> +		startup_info->original_cwd = \
> +			precompose_string_if_needed(startup_info->original_cwd
> +						    + offset);
> +	}

I wonder if we want to clear the .original_cwd member, so that the
"cwd protection" do not have to worry about anything at all when we
are in a bare repository.

> +}
> +
>  static int read_worktree_config(const char *var, const char *value, void *vdata)
>  {
>  	struct repository_format *data = vdata;
> @@ -1330,6 +1378,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
>  		setenv(GIT_PREFIX_ENVIRONMENT, "", 1);
>  	}
>  
> +	setup_original_cwd();
>  
>  	strbuf_release(&dir);
>  	strbuf_release(&gitdir);