Skip to content

Commit 21d4572

Browse files
committed
Merge remote-tracking branch 'junio/jx/relative-path-regression-fix'
2 parents 31376f5 + 41894ae commit 21d4572

File tree

5 files changed

+101
-34
lines changed

5 files changed

+101
-34
lines changed

Documentation/config.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,8 +794,8 @@ browser.<tool>.path::
794794
working repository in gitweb (see linkgit:git-instaweb[1]).
795795

796796
clean.requireForce::
797-
A boolean to make git-clean do nothing unless given -f
798-
or -n. Defaults to true.
797+
A boolean to make git-clean do nothing unless given -f,
798+
-i or -n. Defaults to true.
799799

800800
color.branch::
801801
A boolean to enable/disable color in the output of

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,7 @@ int is_directory(const char *);
768768
const char *real_path(const char *path);
769769
const char *real_path_if_valid(const char *path);
770770
const char *absolute_path(const char *path);
771+
const char *remove_leading_path(const char *in, const char *prefix);
771772
const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
772773
int normalize_path_copy(char *dst, const char *src);
773774
int longest_ancestor_length(const char *path, struct string_list *prefixes);

path.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,16 @@ int adjust_shared_perm(const char *path)
434434
return 0;
435435
}
436436

437+
static int have_same_root(const char *path1, const char *path2)
438+
{
439+
int is_abs1, is_abs2;
440+
441+
is_abs1 = is_absolute_path(path1);
442+
is_abs2 = is_absolute_path(path2);
443+
return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
444+
(!is_abs1 && !is_abs2);
445+
}
446+
437447
/*
438448
* Give path as relative to prefix.
439449
*
@@ -454,6 +464,16 @@ const char *relative_path(const char *in, const char *prefix,
454464
else if (!prefix_len)
455465
return in;
456466

467+
if (have_same_root(in, prefix)) {
468+
/* bypass dos_drive, for "c:" is identical to "C:" */
469+
if (has_dos_drive_prefix(in)) {
470+
i = 2;
471+
j = 2;
472+
}
473+
} else {
474+
return in;
475+
}
476+
457477
while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
458478
if (is_dir_sep(prefix[i])) {
459479
while (is_dir_sep(prefix[i]))
@@ -530,6 +550,51 @@ const char *relative_path(const char *in, const char *prefix,
530550
return sb->buf;
531551
}
532552

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

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)

t/t0060-path-utils.sh

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -190,33 +190,37 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
190190
test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
191191
'
192192

193-
relative_path /a/b/c/ /a/b/ c/
194-
relative_path /a/b/c/ /a/b c/
195-
relative_path /a//b//c/ //a/b// c/ POSIX
196-
relative_path /a/b /a/b ./
197-
relative_path /a/b/ /a/b ./
198-
relative_path /a /a/b ../
199-
relative_path / /a/b/ ../../
200-
relative_path /a/c /a/b/ ../c
201-
relative_path /a/c /a/b ../c
202-
relative_path /x/y /a/b/ ../../x/y
203-
relative_path /a/b "<empty>" /a/b
204-
relative_path /a/b "<null>" /a/b
205-
relative_path a/b/c/ a/b/ c/
206-
relative_path a/b/c/ a/b c/
207-
relative_path a/b//c a//b c
208-
relative_path a/b/ a/b/ ./
209-
relative_path a/b/ a/b ./
210-
relative_path a a/b ../
211-
relative_path x/y a/b ../../x/y
212-
relative_path a/c a/b ../c
213-
relative_path a/b "<empty>" a/b
214-
relative_path a/b "<null>" a/b
215-
relative_path "<empty>" /a/b ./
216-
relative_path "<empty>" "<empty>" ./
217-
relative_path "<empty>" "<null>" ./
218-
relative_path "<null>" "<empty>" ./
219-
relative_path "<null>" "<null>" ./
220-
relative_path "<null>" /a/b ./
193+
relative_path /foo/a/b/c/ /foo/a/b/ c/
194+
relative_path /foo/a/b/c/ /foo/a/b c/
195+
relative_path /foo/a//b//c/ ///foo/a/b// c/ POSIX
196+
relative_path /foo/a/b /foo/a/b ./
197+
relative_path /foo/a/b/ /foo/a/b ./
198+
relative_path /foo/a /foo/a/b ../
199+
relative_path / /foo/a/b/ ../../../
200+
relative_path /foo/a/c /foo/a/b/ ../c
201+
relative_path /foo/a/c /foo/a/b ../c
202+
relative_path /foo/x/y /foo/a/b/ ../../x/y
203+
relative_path /foo/a/b "<empty>" /foo/a/b
204+
relative_path /foo/a/b "<null>" /foo/a/b
205+
relative_path foo/a/b/c/ foo/a/b/ c/
206+
relative_path foo/a/b/c/ foo/a/b c/
207+
relative_path foo/a/b//c foo/a//b c
208+
relative_path foo/a/b/ foo/a/b/ ./
209+
relative_path foo/a/b/ foo/a/b ./
210+
relative_path foo/a foo/a/b ../
211+
relative_path foo/x/y foo/a/b ../../x/y
212+
relative_path foo/a/c foo/a/b ../c
213+
relative_path foo/a/b /foo/x/y foo/a/b
214+
relative_path /foo/a/b foo/x/y /foo/a/b
215+
relative_path d:/a/b D:/a/c ../b MINGW
216+
relative_path C:/a/b D:/a/c C:/a/b MINGW
217+
relative_path foo/a/b "<empty>" foo/a/b
218+
relative_path foo/a/b "<null>" foo/a/b
219+
relative_path "<empty>" /foo/a/b ./
220+
relative_path "<empty>" "<empty>" ./
221+
relative_path "<empty>" "<null>" ./
222+
relative_path "<null>" "<empty>" ./
223+
relative_path "<null>" "<null>" ./
224+
relative_path "<null>" /foo/a/b ./
221225

222226
test_done

0 commit comments

Comments
 (0)