Subject: Re: [PATCH 2/2] Use simpler relative_path when set_git_dir

From: Johannes Sixt <[email-masked]>
Date: Thu, 12 Sep 2013 19:36:02 +0200

Am 12.09.2013 11:12, schrieb Jiang Xin:
> Using a relative_path as git_dir first appears in v1.5.6-1-g044bbbc.
> It will make git_dir shorter only if git_dir is inside work_tree,
> and this will increase performance. But my last refactor effort on
> relative_path function (commit v1.8.3-rc2-12-ge02ca72) changed that.
> Always use relative_path as git_dir may bring troubles like
> $gmane/234434.
> 
> Because new relative_path is a combination of original relative_path
> from path.c and original path_relative from quote.c, so in order to
> restore the origin implementation, save the original relative_path
> to simple_relative_path, and call it in setup.c.
> 
> Suggested-by: Karsten Blees <[email-masked]>
> Signed-off-by: Jiang Xin <[email-masked]>
> ---
>  cache.h |  1 +
>  path.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
>  setup.c |  5 +----
>  3 files changed, 47 insertions(+), 4 deletions(-)
> 
> diff --git a/cache.h b/cache.h
> index 8e42256..ab17f1d 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -738,6 +738,7 @@ const char *real_path(const char *path);
>  const char *real_path_if_valid(const char *path);
>  const char *absolute_path(const char *path);
>  const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
> +const char *simple_relative_path(const char *in, const char *prefix);
>  int normalize_path_copy(char *dst, const char *src);
>  int longest_ancestor_length(const char *path, struct string_list *prefixes);
>  char *strip_path_suffix(const char *path, const char *suffix);
> diff --git a/path.c b/path.c
> index ffcdea1..0f0c92f 100644
> --- a/path.c
> +++ b/path.c
> @@ -558,6 +558,51 @@ const char *relative_path(const char *in, const char *prefix,
>  }
>  
>  /*
> + * A simpler implementation of relative_path

So we have a heavy-duty function relative_path(), but it is not capable
of doing the "simple" operations that this function does?

There must be something wrong.

This function were easier to sell if it were named
remove_optional_prefix() or something.

> + *
> + * Get relative path by removing "prefix" from "in". This function
> + * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
> + * to increase performance when traversing the path to work_tree.
> + */
> +const char *simple_relative_path(const char *in, const char *prefix)
> +{
> +	static char buf[PATH_MAX + 1];
> +	int i = 0, j = 0;
> +
> +	if (!prefix || !prefix[0])
> +		return in;
> +	while (prefix[i]) {
> +		if (is_dir_sep(prefix[i])) {
> +			if (!is_dir_sep(in[j]))
> +				return in;
> +			while (is_dir_sep(prefix[i]))
> +				i++;
> +			while (is_dir_sep(in[j]))
> +				j++;
> +			continue;
> +		} else if (in[j] != prefix[i]) {
> +			return in;
> +		}
> +		i++;
> +		j++;
> +	}
> +	if (
> +	    /* "/foo" is a prefix of "/foo" */
> +	    in[j] &&
> +	    /* "/foo" is not a prefix of "/foobar" */
> +	    !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
> +	   )
> +		return in;
> +	while (is_dir_sep(in[j]))
> +		j++;
> +	if (!in[j])
> +		strcpy(buf, ".");
> +	else
> +		strcpy(buf, in + j);
> +	return buf;
> +}
> ...