From 31171d9e454d71144685866cfd6476b8ac69d314 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Sun, 28 Oct 2012 17:16:24 +0100 Subject: longest_ancestor_length(): take a string_list argument for prefixes Change longest_ancestor_length() to take the prefixes argument as a string_list rather than as a colon-separated string. This will make it easier for the caller to alter the entries before calling longest_ancestor_length(). Signed-off-by: Michael Haggerty Signed-off-by: Jeff King --- test-path-utils.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'test-path-utils.c') diff --git a/test-path-utils.c b/test-path-utils.c index 3bc20e91da..acb05600df 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "string-list.h" int main(int argc, char **argv) { @@ -30,7 +31,12 @@ int main(int argc, char **argv) } if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) { - int len = longest_ancestor_length(argv[2], argv[3]); + int len; + struct string_list ceiling_dirs = STRING_LIST_INIT_DUP; + + string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1); + len = longest_ancestor_length(argv[2], &ceiling_dirs); + string_list_clear(&ceiling_dirs, 0); printf("%d\n", len); return 0; } -- cgit v1.2.1 From 9e2326c7e1efb1ae42b17e3fa38c16711a8d0bd8 Mon Sep 17 00:00:00 2001 From: Michael Haggerty Date: Sun, 28 Oct 2012 17:16:25 +0100 Subject: longest_ancestor_length(): require prefix list entries to be normalized Move the responsibility for normalizing prefixes from longest_ancestor_length() to its callers. Use slightly different normalizations at the two callers: In setup_git_directory_gently_1(), use the old normalization, which ignores paths that are not usable. In the next commit we will change this caller to also resolve symlinks in the paths from GIT_CEILING_DIRECTORIES as part of the normalization. In "test-path-utils longest_ancestor_length", use the old normalization, but die() if any paths are unusable. Also change t0060 to only pass normalized paths to the test program (no empty entries or non-absolute paths, strip trailing slashes from the paths, and remove tests that thereby become redundant). The point of this change is to reduce the scope of the ancestor_length tests in t0060 from testing normalization+longest_prefix to testing only mostly longest_prefix. This is necessary because when setup_git_directory_gently_1() starts resolving symlinks as part of its normalization, it will not be reasonable to do the same in the test suite, because that would make the test results depend on the contents of the root directory of the filesystem on which the test is run. HOWEVER: under Windows, bash mangles arguments that look like absolute POSIX paths into DOS paths. So we have to retain the level of normalization done by normalize_path_copy() to convert the bash-mangled DOS paths (which contain backslashes) into paths that use forward slashes. Signed-off-by: Michael Haggerty Signed-off-by: Jeff King --- test-path-utils.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'test-path-utils.c') diff --git a/test-path-utils.c b/test-path-utils.c index acb05600df..0092cbf354 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -1,6 +1,33 @@ #include "cache.h" #include "string-list.h" +/* + * A "string_list_each_func_t" function that normalizes an entry from + * GIT_CEILING_DIRECTORIES. If the path is unusable for some reason, + * die with an explanation. + */ +static int normalize_ceiling_entry(struct string_list_item *item, void *unused) +{ + const char *ceil = item->string; + int len = strlen(ceil); + char buf[PATH_MAX+1]; + + if (len == 0) + die("Empty path is not supported"); + if (len > PATH_MAX) + die("Path \"%s\" is too long", ceil); + if (!is_absolute_path(ceil)) + die("Path \"%s\" is not absolute", ceil); + if (normalize_path_copy(buf, ceil) < 0) + die("Path \"%s\" could not be normalized", ceil); + len = strlen(buf); + if (len > 1 && buf[len-1] == '/') + die("Normalized path \"%s\" ended with slash", buf); + free(item->string); + item->string = xstrdup(buf); + return 1; +} + int main(int argc, char **argv) { if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) { @@ -33,10 +60,26 @@ int main(int argc, char **argv) if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) { int len; struct string_list ceiling_dirs = STRING_LIST_INIT_DUP; + char *path = xstrdup(argv[2]); + /* + * We have to normalize the arguments because under + * Windows, bash mangles arguments that look like + * absolute POSIX paths or colon-separate lists of + * absolute POSIX paths into DOS paths (e.g., + * "/foo:/foo/bar" might be converted to + * "D:\Src\msysgit\foo;D:\Src\msysgit\foo\bar"), + * whereas longest_ancestor_length() requires paths + * that use forward slashes. + */ + if (normalize_path_copy(path, path)) + die("Path \"%s\" could not be normalized", argv[2]); string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1); - len = longest_ancestor_length(argv[2], &ceiling_dirs); + filter_string_list(&ceiling_dirs, 0, + normalize_ceiling_entry, NULL); + len = longest_ancestor_length(path, &ceiling_dirs); string_list_clear(&ceiling_dirs, 0); + free(path); printf("%d\n", len); return 0; } -- cgit v1.2.1 From 203439b2840c4c384060df2fa192994e4b6740ed Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Tue, 25 Jun 2013 23:53:42 +0800 Subject: test: add test cases for relative_path Add subcommand "relative_path" in test-path-utils, and add test cases in t0060. Johannes tested an earlier version of this patch on Windows, and found that some relative_path tests should be skipped on Windows. This is because the bash on Windows rewrites arguments of regular Windows programs, such as git and the test helpers, if the arguments look like absolute POSIX paths. As a consequence, the actual tests performed are not what the tests scripts expect. The tests that need *not* be skipped are those where the two paths passed to 'test-path-utils relative_path' have the same prefix and the result is expected to be a relative path. This is because the rewriting changes "/a/b" to "D:/Src/MSysGit/a/b", and when both inputs are extended the same way, this just cancels out in the relative path computation. Signed-off-by: Jiang Xin Helped-by: Johannes Sixt Signed-off-by: Junio C Hamano --- test-path-utils.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'test-path-utils.c') diff --git a/test-path-utils.c b/test-path-utils.c index 0092cbf354..8a6d22404e 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -28,6 +28,19 @@ static int normalize_ceiling_entry(struct string_list_item *item, void *unused) return 1; } +static void normalize_argv_string(const char **var, const char *input) +{ + if (!strcmp(input, "")) + *var = NULL; + else if (!strcmp(input, "")) + *var = ""; + else + *var = input; + + if (*var && (**var == '<' || **var == '(')) + die("Bad value: %s\n", input); +} + int main(int argc, char **argv) { if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) { @@ -103,6 +116,18 @@ int main(int argc, char **argv) return 0; } + if (argc == 4 && !strcmp(argv[1], "relative_path")) { + const char *in, *prefix, *rel; + normalize_argv_string(&in, argv[2]); + normalize_argv_string(&prefix, argv[3]); + rel = relative_path(in, prefix); + if (!rel) + puts("(null)"); + else + puts(strlen(rel) > 0 ? rel : "(empty)"); + return 0; + } + fprintf(stderr, "%s: unknown function name: %s\n", argv[0], argv[1] ? argv[1] : "(there was none)"); return 1; -- cgit v1.2.1 From e02ca72f70ed8f0268a81f72cb3230c72e538e77 Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Tue, 25 Jun 2013 23:53:43 +0800 Subject: path.c: refactor relative_path(), not only strip prefix Original design of relative_path() is simple, just strip the prefix (*base) from the absolute path (*abs). In most cases, we need a real relative path, such as: ../foo, ../../bar. That's why there is another reimplementation (path_relative()) in quote.c. Borrow some codes from path_relative() in quote.c to refactor relative_path() in path.c, so that it could return real relative path, and user can reuse this function without reimplementing his/her own. The function path_relative() in quote.c will be substituted, and I would use the new relative_path() function when implementing the interactive git-clean later. Different results for relative_path() before and after this refactor: abs path base path relative (original) relative (refactor) ======== ========= =================== =================== /a/b /a/b . ./ /a/b/ /a/b . ./ /a /a/b/ /a ../ / /a/b/ / ../../ /a/c /a/b/ /a/c ../c /x/y /a/b/ /x/y ../../x/y a/b/ a/b/ . ./ a/b/ a/b . ./ a a/b a ../ x/y a/b/ x/y ../../x/y a/c a/b a/c ../c (empty) (null) (empty) ./ (empty) (empty) (empty) ./ (empty) /a/b (empty) ./ (null) (null) (null) ./ (null) (empty) (null) ./ (null) /a/b (segfault) ./ You may notice that return value "." has been changed to "./". It is because: * Function quote_path_relative() in quote.c will show the relative path as "./" if abs(in) and base(prefix) are the same. * Function relative_path() is called only once (in setup.c), and it will be OK for the return value as "./" instead of ".". Signed-off-by: Jiang Xin Signed-off-by: Junio C Hamano --- test-path-utils.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'test-path-utils.c') diff --git a/test-path-utils.c b/test-path-utils.c index 8a6d22404e..1bf4730619 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -117,14 +117,16 @@ int main(int argc, char **argv) } if (argc == 4 && !strcmp(argv[1], "relative_path")) { + struct strbuf sb = STRBUF_INIT; const char *in, *prefix, *rel; normalize_argv_string(&in, argv[2]); normalize_argv_string(&prefix, argv[3]); - rel = relative_path(in, prefix); + rel = relative_path(in, prefix, &sb); if (!rel) puts("(null)"); else puts(strlen(rel) > 0 ? rel : "(empty)"); + strbuf_release(&sb); return 0; } -- cgit v1.2.1 From abd4284bc62127a2db69c8c81501a56bb29284c8 Mon Sep 17 00:00:00 2001 From: Jiang Xin Date: Tue, 25 Jun 2013 23:53:57 +0800 Subject: test: run testcases with POSIX absolute paths on Windows Some test cases are skipped on Windows by marking with POSIX prereq. This is because arguments look like absolute paths (such as /a/b) for regular Windows programs (*.exe executables, no bash scripts) are changed to Windows paths (like C:/msysgit/a/b). There is no cygpath nor equivalent on msysGit, but it is easy to write one. New subcommand "mingw_path" is added in test-path-utils, so that we can get the expected absolute paths on Windows. E.g. COMMAND LINE Linux output Windows output ================================== ============ =============== test-path-utils mingw_path / / C:/msysgit test-path-utils mingw_path /a/b/ /a/b/ C:/msysgit/a/b/ With this utility, most skipped test cases in t0060 can be turned on to be tested correctly on Windows. Signed-off-by: Jiang Xin Signed-off-by: Junio C Hamano --- test-path-utils.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'test-path-utils.c') diff --git a/test-path-utils.c b/test-path-utils.c index 1bf4730619..bb975e4d3e 100644 --- a/test-path-utils.c +++ b/test-path-utils.c @@ -116,6 +116,11 @@ int main(int argc, char **argv) return 0; } + if (argc == 3 && !strcmp(argv[1], "mingw_path")) { + puts(argv[2]); + return 0; + } + if (argc == 4 && !strcmp(argv[1], "relative_path")) { struct strbuf sb = STRBUF_INIT; const char *in, *prefix, *rel; -- cgit v1.2.1