Skip to content

Commit 41894ae

Browse files
jiangxinjrn
authored andcommitted
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 <[email protected]> Signed-off-by: Jiang Xin <[email protected]> Signed-off-by: Jonathan Nieder <[email protected]>
1 parent 7fbd422 commit 41894ae

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ int is_directory(const char *);
737737
const char *real_path(const char *path);
738738
const char *real_path_if_valid(const char *path);
739739
const char *absolute_path(const char *path);
740+
const char *remove_leading_path(const char *in, const char *prefix);
740741
const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
741742
int normalize_path_copy(char *dst, const char *src);
742743
int longest_ancestor_length(const char *path, struct string_list *prefixes);

path.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,51 @@ const char *relative_path(const char *in, const char *prefix,
557557
return sb->buf;
558558
}
559559

560+
/*
561+
* A simpler implementation of relative_path
562+
*
563+
* Get relative path by removing "prefix" from "in". This function
564+
* first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
565+
* to increase performance when traversing the path to work_tree.
566+
*/
567+
const char *remove_leading_path(const char *in, const char *prefix)
568+
{
569+
static char buf[PATH_MAX + 1];
570+
int i = 0, j = 0;
571+
572+
if (!prefix || !prefix[0])
573+
return in;
574+
while (prefix[i]) {
575+
if (is_dir_sep(prefix[i])) {
576+
if (!is_dir_sep(in[j]))
577+
return in;
578+
while (is_dir_sep(prefix[i]))
579+
i++;
580+
while (is_dir_sep(in[j]))
581+
j++;
582+
continue;
583+
} else if (in[j] != prefix[i]) {
584+
return in;
585+
}
586+
i++;
587+
j++;
588+
}
589+
if (
590+
/* "/foo" is a prefix of "/foo" */
591+
in[j] &&
592+
/* "/foo" is not a prefix of "/foobar" */
593+
!is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
594+
)
595+
return in;
596+
while (is_dir_sep(in[j]))
597+
j++;
598+
if (!in[j])
599+
strcpy(buf, ".");
600+
else
601+
strcpy(buf, in + j);
602+
return buf;
603+
}
604+
560605
/*
561606
* It is okay if dst == src, but they should not overlap otherwise.
562607
*

setup.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,6 @@ int is_inside_work_tree(void)
360360

361361
void setup_work_tree(void)
362362
{
363-
struct strbuf sb = STRBUF_INIT;
364363
const char *work_tree, *git_dir;
365364
static int initialized = 0;
366365

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

383-
set_git_dir(relative_path(git_dir, work_tree, &sb));
382+
set_git_dir(remove_leading_path(git_dir, work_tree));
384383
initialized = 1;
385-
386-
strbuf_release(&sb);
387384
}
388385

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

0 commit comments

Comments
 (0)