real_path: canonicalize directory separators in root parts

When an absolute path is resolved, resolution begins at the first path component after the root part. The root part is just copied verbatim, because it must not be inspected for symbolic links. For POSIX paths, this is just the initial slash, but on Windows, the root part has the forms c:\ or \\server\share. We do want to canonicalize the back-slashes in the root part because these parts are compared to the result of getcwd(), which does return a fully canonicalized path. Factor out a helper that splits off the root part, and have it canonicalize the copied part. This change was prompted because t1504-ceiling-dirs.sh caught a breakage in GIT_CEILING_DIRECTORIES handling on Windows. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Acked-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Sixt committed Dec 21, 2016 at 22:51 UTC e9a379c352b02ca560c58a56aa723994aa42666f
1 file changed +17 -12
abspath.c
+17 -12
@@ -48,6 +48,19 @@ static void get_next_component(struct strbuf *next, struct strbuf *remaining)
48 strbuf_remove(remaining, 0, end - remaining->buf);
49 }
50
51 +/* copies root part from remaining to resolved, canonicalizing it on the way */
52 +static void get_root_part(struct strbuf *resolved, struct strbuf *remaining)
53 +{
54 + int offset = offset_1st_component(remaining->buf);
55 +
56 + strbuf_reset(resolved);
57 + strbuf_add(resolved, remaining->buf, offset);
58 +#ifdef GIT_WINDOWS_NATIVE
59 + convert_slashes(resolved->buf);
60 +#endif
61 + strbuf_remove(remaining, 0, offset);
62 +}
63 +
64 /* We allow "recursive" symbolic links. Only within reason, though. */
65 #define MAXSYMLINKS 5
66
@@ -80,14 +93,10 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
93 goto error_out;
94 }
95
83 - strbuf_reset(resolved);
96 + strbuf_addstr(&remaining, path);
97 + get_root_part(resolved, &remaining);
98
85 - if (is_absolute_path(path)) {
86 - /* absolute path; start with only root as being resolved */
87 - int offset = offset_1st_component(path);
88 - strbuf_add(resolved, path, offset);
89 - strbuf_addstr(&remaining, path + offset);
90 - } else {
99 + if (!resolved->len) {
100 /* relative path; can use CWD as the initial resolved path */
101 if (strbuf_getcwd(resolved)) {
102 if (die_on_error)
@@ -95,7 +104,6 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
104 else
105 goto error_out;
106 }
98 - strbuf_addstr(&remaining, path);
107 }
108
109 /* Iterate over the remaining path components */
@@ -150,10 +158,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
158
159 if (is_absolute_path(symlink.buf)) {
160 /* absolute symlink; set resolved to root */
153 - int offset = offset_1st_component(symlink.buf);
154 - strbuf_reset(resolved);
155 - strbuf_add(resolved, symlink.buf, offset);
156 - strbuf_remove(&symlink, 0, offset);
161 + get_root_part(resolved, &symlink);
162 } else {
163 /*
164 * relative symlink