aboutsummaryrefslogtreecommitdiff
path: root/path.c
diff options
context:
space:
mode:
authorJohannes Sixt <j6t@kdbg.org>2016-12-14 20:37:38 +0100
committerJunio C Hamano <gitster@pobox.com>2016-12-16 13:10:43 -0800
commit7814fbe3f1e7cea1a675408df7b5dd1f5be731cc (patch)
treeef2f4a7e48adbaf3e170a0ea46eb8c23f765ddab /path.c
parent0202c411edc25940cc381bf317badcdf67670be4 (diff)
downloadgit-7814fbe3f1e7cea1a675408df7b5dd1f5be731cc.tar.gz
git-7814fbe3f1e7cea1a675408df7b5dd1f5be731cc.tar.xz
normalize_path_copy(): fix pushing to //server/share/dir on Windows
normalize_path_copy() is not prepared to keep the double-slash of a //server/share/dir kind of path, but treats it like a regular POSIX style path and transforms it to /server/share/dir. The bug manifests when 'git push //server/share/dir master' is run, because tmp_objdir_add_as_alternate() uses the path in normalized form when it registers the quarantine object database via link_alt_odb_entries(). Needless to say that the directory cannot be accessed using the wrongly normalized path. Fix it by skipping all of the root part, not just a potential drive prefix. offset_1st_component takes care of this, see the implementation in compat/mingw.c::mingw_offset_1st_component(). Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'path.c')
-rw-r--r--path.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/path.c b/path.c
index 17551c483..f4e5ffb44 100644
--- a/path.c
+++ b/path.c
@@ -961,7 +961,7 @@ const char *remove_leading_path(const char *in, const char *prefix)
*
* Performs the following normalizations on src, storing the result in dst:
* - Ensures that components are separated by '/' (Windows only)
- * - Squashes sequences of '/'.
+ * - Squashes sequences of '/' except "//server/share" on Windows
* - Removes "." components.
* - Removes ".." components, and the components the precede them.
* Returns failure (non-zero) if a ".." component appears as first path
@@ -984,17 +984,22 @@ const char *remove_leading_path(const char *in, const char *prefix)
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
{
char *dst0;
- int i;
+ const char *end;
- for (i = has_dos_drive_prefix(src); i > 0; i--)
- *dst++ = *src++;
+ /*
+ * Copy initial part of absolute path: "/", "C:/", "//server/share/".
+ */
+ end = src + offset_1st_component(src);
+ while (src < end) {
+ char c = *src++;
+ if (is_dir_sep(c))
+ c = '/';
+ *dst++ = c;
+ }
dst0 = dst;
- if (is_dir_sep(*src)) {
- *dst++ = '/';
- while (is_dir_sep(*src))
- src++;
- }
+ while (is_dir_sep(*src))
+ src++;
for (;;) {
char c = *src;