зеркало из https://github.com/microsoft/git.git
Merge branch 'mw/symlinks' into maint
* mw/symlinks: setup: fix windows path buffer over-stepping setup: don't dereference in-tree symlinks for absolute paths setup: add abspath_part_inside_repo() function t0060: add tests for prefix_path when path begins with work tree t0060: add test for prefix_path when path == work tree t0060: add test for prefix_path on symlinks via absolute paths t3004: add test for ls-files on symlinks via absolute paths
This commit is contained in:
Коммит
64d8c31ebe
94
setup.c
94
setup.c
|
@ -5,6 +5,70 @@
|
||||||
static int inside_git_dir = -1;
|
static int inside_git_dir = -1;
|
||||||
static int inside_work_tree = -1;
|
static int inside_work_tree = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The input parameter must contain an absolute path, and it must already be
|
||||||
|
* normalized.
|
||||||
|
*
|
||||||
|
* Find the part of an absolute path that lies inside the work tree by
|
||||||
|
* dereferencing symlinks outside the work tree, for example:
|
||||||
|
* /dir1/repo/dir2/file (work tree is /dir1/repo) -> dir2/file
|
||||||
|
* /dir/file (work tree is /) -> dir/file
|
||||||
|
* /dir/symlink1/symlink2 (symlink1 points to work tree) -> symlink2
|
||||||
|
* /dir/repolink/file (repolink points to /dir/repo) -> file
|
||||||
|
* /dir/repo (exactly equal to work tree) -> (empty string)
|
||||||
|
*/
|
||||||
|
static int abspath_part_inside_repo(char *path)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
size_t wtlen;
|
||||||
|
char *path0;
|
||||||
|
int off;
|
||||||
|
const char *work_tree = get_git_work_tree();
|
||||||
|
|
||||||
|
if (!work_tree)
|
||||||
|
return -1;
|
||||||
|
wtlen = strlen(work_tree);
|
||||||
|
len = strlen(path);
|
||||||
|
off = offset_1st_component(path);
|
||||||
|
|
||||||
|
/* check if work tree is already the prefix */
|
||||||
|
if (wtlen <= len && !strncmp(path, work_tree, wtlen)) {
|
||||||
|
if (path[wtlen] == '/') {
|
||||||
|
memmove(path, path + wtlen + 1, len - wtlen);
|
||||||
|
return 0;
|
||||||
|
} else if (path[wtlen - 1] == '/' || path[wtlen] == '\0') {
|
||||||
|
/* work tree is the root, or the whole path */
|
||||||
|
memmove(path, path + wtlen, len - wtlen + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* work tree might match beginning of a symlink to work tree */
|
||||||
|
off = wtlen;
|
||||||
|
}
|
||||||
|
path0 = path;
|
||||||
|
path += off;
|
||||||
|
|
||||||
|
/* check each '/'-terminated level */
|
||||||
|
while (*path) {
|
||||||
|
path++;
|
||||||
|
if (*path == '/') {
|
||||||
|
*path = '\0';
|
||||||
|
if (strcmp(real_path(path0), work_tree) == 0) {
|
||||||
|
memmove(path0, path + 1, len - (path - path0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*path = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check whole path */
|
||||||
|
if (strcmp(real_path(path0), work_tree) == 0) {
|
||||||
|
*path0 = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Normalize "path", prepending the "prefix" for relative paths. If
|
* Normalize "path", prepending the "prefix" for relative paths. If
|
||||||
* remaining_prefix is not NULL, return the actual prefix still
|
* remaining_prefix is not NULL, return the actual prefix still
|
||||||
|
@ -22,11 +86,17 @@ char *prefix_path_gently(const char *prefix, int len,
|
||||||
const char *orig = path;
|
const char *orig = path;
|
||||||
char *sanitized;
|
char *sanitized;
|
||||||
if (is_absolute_path(orig)) {
|
if (is_absolute_path(orig)) {
|
||||||
const char *temp = real_path(path);
|
sanitized = xmalloc(strlen(path) + 1);
|
||||||
sanitized = xmalloc(len + strlen(temp) + 1);
|
|
||||||
strcpy(sanitized, temp);
|
|
||||||
if (remaining_prefix)
|
if (remaining_prefix)
|
||||||
*remaining_prefix = 0;
|
*remaining_prefix = 0;
|
||||||
|
if (normalize_path_copy_len(sanitized, path, remaining_prefix)) {
|
||||||
|
free(sanitized);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (abspath_part_inside_repo(sanitized)) {
|
||||||
|
free(sanitized);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sanitized = xmalloc(len + strlen(path) + 1);
|
sanitized = xmalloc(len + strlen(path) + 1);
|
||||||
if (len)
|
if (len)
|
||||||
|
@ -34,26 +104,10 @@ char *prefix_path_gently(const char *prefix, int len,
|
||||||
strcpy(sanitized + len, path);
|
strcpy(sanitized + len, path);
|
||||||
if (remaining_prefix)
|
if (remaining_prefix)
|
||||||
*remaining_prefix = len;
|
*remaining_prefix = len;
|
||||||
}
|
if (normalize_path_copy_len(sanitized, sanitized, remaining_prefix)) {
|
||||||
if (normalize_path_copy_len(sanitized, sanitized, remaining_prefix))
|
|
||||||
goto error_out;
|
|
||||||
if (is_absolute_path(orig)) {
|
|
||||||
size_t root_len, len, total;
|
|
||||||
const char *work_tree = get_git_work_tree();
|
|
||||||
if (!work_tree)
|
|
||||||
goto error_out;
|
|
||||||
len = strlen(work_tree);
|
|
||||||
root_len = offset_1st_component(work_tree);
|
|
||||||
total = strlen(sanitized) + 1;
|
|
||||||
if (strncmp(sanitized, work_tree, len) ||
|
|
||||||
(len > root_len && sanitized[len] != '\0' && sanitized[len] != '/')) {
|
|
||||||
error_out:
|
|
||||||
free(sanitized);
|
free(sanitized);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (sanitized[len] == '/')
|
|
||||||
len++;
|
|
||||||
memmove(sanitized, sanitized + len, total - len);
|
|
||||||
}
|
}
|
||||||
return sanitized;
|
return sanitized;
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,27 @@ 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")"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success SYMLINKS 'prefix_path works with absolute paths to work tree symlinks' '
|
||||||
|
ln -s target symlink &&
|
||||||
|
test "$(test-path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'prefix_path works with only absolute path to work tree' '
|
||||||
|
echo "" >expected &&
|
||||||
|
test-path-utils prefix_path prefix "$(pwd)" >actual &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'prefix_path rejects absolute path to dir with same beginning as work tree' '
|
||||||
|
test_must_fail test-path-utils prefix_path prefix "$(pwd)a"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success SYMLINKS 'prefix_path works with absolute path to a symlink to work tree having same beginning as work tree' '
|
||||||
|
git init repo &&
|
||||||
|
ln -s repo repolink &&
|
||||||
|
test "a" = "$(cd repo && test-path-utils prefix_path prefix "$(pwd)/../repolink/a")"
|
||||||
|
'
|
||||||
|
|
||||||
relative_path /foo/a/b/c/ /foo/a/b/ c/
|
relative_path /foo/a/b/c/ /foo/a/b/ c/
|
||||||
relative_path /foo/a/b/c/ /foo/a/b c/
|
relative_path /foo/a/b/c/ /foo/a/b c/
|
||||||
relative_path /foo/a//b//c/ ///foo/a/b// c/ POSIX
|
relative_path /foo/a//b//c/ ///foo/a/b// c/ POSIX
|
||||||
|
|
|
@ -36,4 +36,21 @@ test_expect_success 'ls-files -h in corrupt repository' '
|
||||||
test_i18ngrep "[Uu]sage: git ls-files " broken/usage
|
test_i18ngrep "[Uu]sage: git ls-files " broken/usage
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' '
|
||||||
|
mkdir subs &&
|
||||||
|
ln -s nosuch link &&
|
||||||
|
ln -s ../nosuch subs/link &&
|
||||||
|
git add link subs/link &&
|
||||||
|
git ls-files -s link subs/link >expect &&
|
||||||
|
git ls-files -s "$(pwd)/link" "$(pwd)/subs/link" >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
|
||||||
|
(
|
||||||
|
cd subs &&
|
||||||
|
git ls-files -s link >../expect &&
|
||||||
|
git ls-files -s "$(pwd)/link" >../actual
|
||||||
|
) &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
Загрузка…
Ссылка в новой задаче