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:
commit
e22c1c7f19
1
cache.h
1
cache.h
@ -751,6 +751,7 @@ int is_directory(const char *);
|
|||||||
const char *real_path(const char *path);
|
const char *real_path(const char *path);
|
||||||
const char *real_path_if_valid(const char *path);
|
const char *real_path_if_valid(const char *path);
|
||||||
const char *absolute_path(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);
|
const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
|
||||||
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
|
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
|
||||||
int normalize_path_copy(char *dst, const char *src);
|
int normalize_path_copy(char *dst, const char *src);
|
||||||
|
65
path.c
65
path.c
@ -434,6 +434,16 @@ int adjust_shared_perm(const char *path)
|
|||||||
return 0;
|
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.
|
* Give path as relative to prefix.
|
||||||
*
|
*
|
||||||
@ -454,6 +464,16 @@ const char *relative_path(const char *in, const char *prefix,
|
|||||||
else if (!prefix_len)
|
else if (!prefix_len)
|
||||||
return in;
|
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]) {
|
while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
|
||||||
if (is_dir_sep(prefix[i])) {
|
if (is_dir_sep(prefix[i])) {
|
||||||
while (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;
|
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.
|
* It is okay if dst == src, but they should not overlap otherwise.
|
||||||
*
|
*
|
||||||
|
5
setup.c
5
setup.c
@ -227,7 +227,6 @@ int is_inside_work_tree(void)
|
|||||||
|
|
||||||
void setup_work_tree(void)
|
void setup_work_tree(void)
|
||||||
{
|
{
|
||||||
struct strbuf sb = STRBUF_INIT;
|
|
||||||
const char *work_tree, *git_dir;
|
const char *work_tree, *git_dir;
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
|
||||||
@ -247,10 +246,8 @@ void setup_work_tree(void)
|
|||||||
if (getenv(GIT_WORK_TREE_ENVIRONMENT))
|
if (getenv(GIT_WORK_TREE_ENVIRONMENT))
|
||||||
setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
|
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;
|
initialized = 1;
|
||||||
|
|
||||||
strbuf_release(&sb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
|
static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
|
||||||
|
@ -190,33 +190,37 @@ test_expect_success SYMLINKS 'real path works on symlinks' '
|
|||||||
test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
|
test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
|
||||||
'
|
'
|
||||||
|
|
||||||
relative_path /a/b/c/ /a/b/ c/
|
relative_path /foo/a/b/c/ /foo/a/b/ c/
|
||||||
relative_path /a/b/c/ /a/b c/
|
relative_path /foo/a/b/c/ /foo/a/b c/
|
||||||
relative_path /a//b//c/ //a/b// c/ POSIX
|
relative_path /foo/a//b//c/ ///foo/a/b// c/ POSIX
|
||||||
relative_path /a/b /a/b ./
|
relative_path /foo/a/b /foo/a/b ./
|
||||||
relative_path /a/b/ /a/b ./
|
relative_path /foo/a/b/ /foo/a/b ./
|
||||||
relative_path /a /a/b ../
|
relative_path /foo/a /foo/a/b ../
|
||||||
relative_path / /a/b/ ../../
|
relative_path / /foo/a/b/ ../../../
|
||||||
relative_path /a/c /a/b/ ../c
|
relative_path /foo/a/c /foo/a/b/ ../c
|
||||||
relative_path /a/c /a/b ../c
|
relative_path /foo/a/c /foo/a/b ../c
|
||||||
relative_path /x/y /a/b/ ../../x/y
|
relative_path /foo/x/y /foo/a/b/ ../../x/y
|
||||||
relative_path /a/b "<empty>" /a/b
|
relative_path /foo/a/b "<empty>" /foo/a/b
|
||||||
relative_path /a/b "<null>" /a/b
|
relative_path /foo/a/b "<null>" /foo/a/b
|
||||||
relative_path a/b/c/ a/b/ c/
|
relative_path foo/a/b/c/ foo/a/b/ c/
|
||||||
relative_path a/b/c/ a/b c/
|
relative_path foo/a/b/c/ foo/a/b c/
|
||||||
relative_path a/b//c a//b c
|
relative_path foo/a/b//c foo/a//b c
|
||||||
relative_path a/b/ a/b/ ./
|
relative_path foo/a/b/ foo/a/b/ ./
|
||||||
relative_path a/b/ a/b ./
|
relative_path foo/a/b/ foo/a/b ./
|
||||||
relative_path a a/b ../
|
relative_path foo/a foo/a/b ../
|
||||||
relative_path x/y a/b ../../x/y
|
relative_path foo/x/y foo/a/b ../../x/y
|
||||||
relative_path a/c a/b ../c
|
relative_path foo/a/c foo/a/b ../c
|
||||||
relative_path a/b "<empty>" a/b
|
relative_path foo/a/b /foo/x/y foo/a/b
|
||||||
relative_path a/b "<null>" a/b
|
relative_path /foo/a/b foo/x/y /foo/a/b
|
||||||
relative_path "<empty>" /a/b ./
|
relative_path d:/a/b D:/a/c ../b MINGW
|
||||||
relative_path "<empty>" "<empty>" ./
|
relative_path C:/a/b D:/a/c C:/a/b MINGW
|
||||||
relative_path "<empty>" "<null>" ./
|
relative_path foo/a/b "<empty>" foo/a/b
|
||||||
relative_path "<null>" "<empty>" ./
|
relative_path foo/a/b "<null>" foo/a/b
|
||||||
relative_path "<null>" "<null>" ./
|
relative_path "<empty>" /foo/a/b ./
|
||||||
relative_path "<null>" /a/b ./
|
relative_path "<empty>" "<empty>" ./
|
||||||
|
relative_path "<empty>" "<null>" ./
|
||||||
|
relative_path "<null>" "<empty>" ./
|
||||||
|
relative_path "<null>" "<null>" ./
|
||||||
|
relative_path "<null>" /foo/a/b ./
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
x
Reference in New Issue
Block a user