Merge branch 'jx/relative-path-regression-fix'
* jx/relative-path-regression-fix: Use simpler relative_path when set_git_dir relative_path should honor dos-drive-prefix test: use unambigous leading path (/foo) for MSYS
This commit is contained in:
65
path.c
65
path.c
@ -434,6 +434,16 @@ int adjust_shared_perm(const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int have_same_root(const char *path1, const char *path2)
|
||||
{
|
||||
int is_abs1, is_abs2;
|
||||
|
||||
is_abs1 = is_absolute_path(path1);
|
||||
is_abs2 = is_absolute_path(path2);
|
||||
return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
|
||||
(!is_abs1 && !is_abs2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Give path as relative to prefix.
|
||||
*
|
||||
@ -454,6 +464,16 @@ const char *relative_path(const char *in, const char *prefix,
|
||||
else if (!prefix_len)
|
||||
return in;
|
||||
|
||||
if (have_same_root(in, prefix)) {
|
||||
/* bypass dos_drive, for "c:" is identical to "C:" */
|
||||
if (has_dos_drive_prefix(in)) {
|
||||
i = 2;
|
||||
j = 2;
|
||||
}
|
||||
} else {
|
||||
return in;
|
||||
}
|
||||
|
||||
while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
|
||||
if (is_dir_sep(prefix[i])) {
|
||||
while (is_dir_sep(prefix[i]))
|
||||
@ -530,6 +550,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.
|
||||
*
|
||||
|
Reference in New Issue
Block a user