mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-05 17:12:51 +00:00
Merge pull request #1825 from nvloff/resolve_relative
path: properly resolve relative paths
This commit is contained in:
commit
37fc44ddff
31
src/path.c
31
src/path.c
@ -646,12 +646,33 @@ int git_path_resolve_relative(git_buf *path, size_t ceiling)
|
||||
/* do nothing with singleton dot */;
|
||||
|
||||
else if (len == 2 && from[0] == '.' && from[1] == '.') {
|
||||
while (to > base && to[-1] == '/') to--;
|
||||
while (to > base && to[-1] != '/') to--;
|
||||
}
|
||||
/* error out if trying to up one from a hard base */
|
||||
if (to == base && ceiling != 0) {
|
||||
giterr_set(GITERR_INVALID,
|
||||
"Cannot strip root component off url");
|
||||
return -1;
|
||||
}
|
||||
|
||||
else {
|
||||
if (*next == '/')
|
||||
/* no more path segments to strip,
|
||||
* use '../' as a new base path */
|
||||
if (to == base) {
|
||||
if (*next == '/')
|
||||
len++;
|
||||
|
||||
if (to != from)
|
||||
memmove(to, from, len);
|
||||
|
||||
to += len;
|
||||
/* this is now the base, can't back up from a
|
||||
* relative prefix */
|
||||
base = to;
|
||||
} else {
|
||||
/* back up a path segment */
|
||||
while (to > base && to[-1] == '/') to--;
|
||||
while (to > base && to[-1] != '/') to--;
|
||||
}
|
||||
} else {
|
||||
if (*next == '/' && *from != '/')
|
||||
len++;
|
||||
|
||||
if (to != from)
|
||||
|
@ -446,16 +446,15 @@ void test_core_path__14_apply_relative(void)
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../../.."));
|
||||
cl_assert_equal_s("/this/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../../"));
|
||||
cl_git_pass(git_path_apply_relative(&p, "../"));
|
||||
cl_assert_equal_s("/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../.."));
|
||||
cl_assert_equal_s("/", p.ptr);
|
||||
cl_git_fail(git_path_apply_relative(&p, "../../.."));
|
||||
|
||||
|
||||
cl_git_pass(git_buf_sets(&p, "d:/another/test"));
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../.."));
|
||||
cl_git_pass(git_path_apply_relative(&p, "../.."));
|
||||
cl_assert_equal_s("d:/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "from/here/to/../and/./back/."));
|
||||
@ -473,8 +472,97 @@ void test_core_path__14_apply_relative(void)
|
||||
cl_git_pass(git_path_apply_relative(&p, ".."));
|
||||
cl_assert_equal_s("https://my.url.com/full/path/", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../../"));
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../"));
|
||||
cl_assert_equal_s("https://", p.ptr);
|
||||
|
||||
|
||||
cl_git_pass(git_buf_sets(&p, "../../this/is/relative"));
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../preserves/the/prefix"));
|
||||
cl_assert_equal_s("../../this/preserves/the/prefix", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../../../../that"));
|
||||
cl_assert_equal_s("../../that", p.ptr);
|
||||
|
||||
cl_git_pass(git_path_apply_relative(&p, "../there"));
|
||||
cl_assert_equal_s("../../there", p.ptr);
|
||||
git_buf_free(&p);
|
||||
}
|
||||
|
||||
static inline void assert_resolve_relative(git_buf *buf, const char *expected, const char *path)
|
||||
{
|
||||
cl_git_pass(git_buf_sets(buf, path));
|
||||
cl_git_pass(git_path_resolve_relative(buf, 0));
|
||||
cl_assert_equal_s(expected, buf->ptr);
|
||||
}
|
||||
|
||||
void test_core_path__15_resolve_relative(void)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
assert_resolve_relative(&buf, "", "");
|
||||
assert_resolve_relative(&buf, "", ".");
|
||||
assert_resolve_relative(&buf, "", "./");
|
||||
assert_resolve_relative(&buf, "..", "..");
|
||||
assert_resolve_relative(&buf, "../", "../");
|
||||
assert_resolve_relative(&buf, "..", "./..");
|
||||
assert_resolve_relative(&buf, "../", "./../");
|
||||
assert_resolve_relative(&buf, "../", "../.");
|
||||
assert_resolve_relative(&buf, "../", ".././");
|
||||
assert_resolve_relative(&buf, "../..", "../..");
|
||||
assert_resolve_relative(&buf, "../../", "../../");
|
||||
|
||||
assert_resolve_relative(&buf, "/", "/");
|
||||
assert_resolve_relative(&buf, "/", "/.");
|
||||
|
||||
assert_resolve_relative(&buf, "", "a/..");
|
||||
assert_resolve_relative(&buf, "", "a/../");
|
||||
assert_resolve_relative(&buf, "", "a/../.");
|
||||
|
||||
assert_resolve_relative(&buf, "/a", "/a");
|
||||
assert_resolve_relative(&buf, "/a/", "/a/.");
|
||||
assert_resolve_relative(&buf, "/", "/a/../");
|
||||
assert_resolve_relative(&buf, "/", "/a/../.");
|
||||
assert_resolve_relative(&buf, "/", "/a/.././");
|
||||
|
||||
assert_resolve_relative(&buf, "a", "a");
|
||||
assert_resolve_relative(&buf, "a/", "a/");
|
||||
assert_resolve_relative(&buf, "a/", "a/.");
|
||||
assert_resolve_relative(&buf, "a/", "a/./");
|
||||
|
||||
assert_resolve_relative(&buf, "a/b", "a//b");
|
||||
assert_resolve_relative(&buf, "a/b/c", "a/b/c");
|
||||
assert_resolve_relative(&buf, "b/c", "./b/c");
|
||||
assert_resolve_relative(&buf, "a/c", "a/./c");
|
||||
assert_resolve_relative(&buf, "a/b/", "a/b/.");
|
||||
|
||||
assert_resolve_relative(&buf, "/a/b/c", "///a/b/c");
|
||||
assert_resolve_relative(&buf, "/a/b/c", "//a/b/c");
|
||||
assert_resolve_relative(&buf, "/", "////");
|
||||
assert_resolve_relative(&buf, "/a", "///a");
|
||||
assert_resolve_relative(&buf, "/", "///.");
|
||||
assert_resolve_relative(&buf, "/", "///a/..");
|
||||
|
||||
assert_resolve_relative(&buf, "../../path", "../../test//../././path");
|
||||
assert_resolve_relative(&buf, "../d", "a/b/../../../c/../d");
|
||||
|
||||
cl_git_pass(git_buf_sets(&buf, "/.."));
|
||||
cl_git_fail(git_path_resolve_relative(&buf, 0));
|
||||
|
||||
cl_git_pass(git_buf_sets(&buf, "/./.."));
|
||||
cl_git_fail(git_path_resolve_relative(&buf, 0));
|
||||
|
||||
cl_git_pass(git_buf_sets(&buf, "/.//.."));
|
||||
cl_git_fail(git_path_resolve_relative(&buf, 0));
|
||||
|
||||
cl_git_pass(git_buf_sets(&buf, "/../."));
|
||||
cl_git_fail(git_path_resolve_relative(&buf, 0));
|
||||
|
||||
cl_git_pass(git_buf_sets(&buf, "/../.././../a"));
|
||||
cl_git_fail(git_path_resolve_relative(&buf, 0));
|
||||
|
||||
cl_git_pass(git_buf_sets(&buf, "////.."));
|
||||
cl_git_fail(git_path_resolve_relative(&buf, 0));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user