Browse Source

Use simpler relative_path when set_git_dir

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
as remove_leading_path, and call it in setup.c.

Suggested-by: Karsten Blees <karsten.blees@gmail.com>
Signed-off-by: Jiang Xin <worldhello.net@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
maint
Jiang Xin 11 years ago committed by Jonathan Nieder
parent
commit
41894ae3a3
  1. 1
      cache.h
  2. 45
      path.c
  3. 5
      setup.c

1
cache.h

@ -737,6 +737,7 @@ int is_directory(const char *); @@ -737,6 +737,7 @@ int is_directory(const char *);
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 *remove_leading_path(const char *in, const char *prefix);
const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
int normalize_path_copy(char *dst, const char *src);
int longest_ancestor_length(const char *path, struct string_list *prefixes);

45
path.c

@ -557,6 +557,51 @@ const char *relative_path(const char *in, const char *prefix, @@ -557,6 +557,51 @@ const char *relative_path(const char *in, const char *prefix,
return sb->buf;
}

/*
* A simpler implementation of relative_path
*
* 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 *remove_leading_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;
}

/*
* It is okay if dst == src, but they should not overlap otherwise.
*

5
setup.c

@ -360,7 +360,6 @@ int is_inside_work_tree(void) @@ -360,7 +360,6 @@ int is_inside_work_tree(void)

void setup_work_tree(void)
{
struct strbuf sb = STRBUF_INIT;
const char *work_tree, *git_dir;
static int initialized = 0;

@ -380,10 +379,8 @@ void setup_work_tree(void) @@ -380,10 +379,8 @@ void setup_work_tree(void)
if (getenv(GIT_WORK_TREE_ENVIRONMENT))
setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);

set_git_dir(relative_path(git_dir, work_tree, &sb));
set_git_dir(remove_leading_path(git_dir, work_tree));
initialized = 1;

strbuf_release(&sb);
}

static int check_repository_format_gently(const char *gitdir, int *nongit_ok)

Loading…
Cancel
Save