]> git.ipfire.org Git - thirdparty/git.git/commitdiff
win32: override `fspathcmp()` with a directory separator-aware version
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Sat, 13 Jul 2024 21:08:20 +0000 (21:08 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sat, 13 Jul 2024 23:23:36 +0000 (16:23 -0700)
On Windows, the backslash is the directory separator, even if the
forward slash can be used, too, at least since Windows NT.

This means that the paths `a/b` and `a\b` are equivalent, and
`fspathcmp()` needs to be made aware of that fact.

Note that we have to override both `fspathcmp()` and `fspathncmp()`, and
the former cannot be a mere pre-processor constant that transforms calls
to `fspathcmp(a, b)` into `fspathncmp(a, b, (size_t)-1)` because the
function `report_collided_checkout()` in `unpack-trees.c` wants to
assign `list.cmp = fspathcmp`.

Also note that `fspatheq()` does _not_ need to be overridden because it
calls `fspathcmp()` internally.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
compat/win32/path-utils.c
compat/win32/path-utils.h
dir.c
dir.h
git-compat-util.h

index ebf2f12eb666910eede5a7e04ee2ab5b0dddb0f8..b658ca3f811717fcdf5910af02163a29103e2891 100644 (file)
@@ -1,4 +1,5 @@
 #include "../../git-compat-util.h"
+#include "../../environment.h"
 
 int win32_has_dos_drive_prefix(const char *path)
 {
@@ -50,3 +51,39 @@ int win32_offset_1st_component(const char *path)
 
        return pos + is_dir_sep(*pos) - path;
 }
+
+int win32_fspathncmp(const char *a, const char *b, size_t count)
+{
+       int diff;
+
+       for (;;) {
+               if (!count--)
+                       return 0;
+               if (!*a)
+                       return *b ? -1 : 0;
+               if (!*b)
+                       return +1;
+
+               if (is_dir_sep(*a)) {
+                       if (!is_dir_sep(*b))
+                               return -1;
+                       a++;
+                       b++;
+                       continue;
+               } else if (is_dir_sep(*b))
+                       return +1;
+
+               diff = ignore_case ?
+                       (unsigned char)tolower(*a) - (int)(unsigned char)tolower(*b) :
+                       (unsigned char)*a - (int)(unsigned char)*b;
+               if (diff)
+                       return diff;
+               a++;
+               b++;
+       }
+}
+
+int win32_fspathcmp(const char *a, const char *b)
+{
+       return win32_fspathncmp(a, b, (size_t)-1);
+}
index 65fa3b9263a47c2dfaad4a110c253cbaae88fc7b..a561c700e7571313320476a82a37ea9254667f1e 100644 (file)
@@ -29,5 +29,9 @@ static inline int win32_has_dir_sep(const char *path)
 #define has_dir_sep(path) win32_has_dir_sep(path)
 int win32_offset_1st_component(const char *path);
 #define offset_1st_component win32_offset_1st_component
+int win32_fspathcmp(const char *a, const char *b);
+#define fspathcmp win32_fspathcmp
+int win32_fspathncmp(const char *a, const char *b, size_t count);
+#define fspathncmp win32_fspathncmp
 
 #endif
diff --git a/dir.c b/dir.c
index b7a6625ebda526bf4ba7d3397fbf09feb27ec94e..5a23376bdaec3a7811677e7ca83e76ababa60a52 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -95,7 +95,7 @@ int count_slashes(const char *s)
        return cnt;
 }
 
-int fspathcmp(const char *a, const char *b)
+int git_fspathcmp(const char *a, const char *b)
 {
        return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
 }
@@ -105,7 +105,7 @@ int fspatheq(const char *a, const char *b)
        return !fspathcmp(a, b);
 }
 
-int fspathncmp(const char *a, const char *b, size_t count)
+int git_fspathncmp(const char *a, const char *b, size_t count)
 {
        return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
 }
diff --git a/dir.h b/dir.h
index 69a76d8bdd30a3c0e5108780a69c55eeca6e5dbe..a3a2f00f5d927346cd712bc5a08fd02d762adc6f 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -541,9 +541,9 @@ int remove_dir_recursively(struct strbuf *path, int flag);
  */
 int remove_path(const char *path);
 
-int fspathcmp(const char *a, const char *b);
+int git_fspathcmp(const char *a, const char *b);
 int fspatheq(const char *a, const char *b);
-int fspathncmp(const char *a, const char *b, size_t count);
+int git_fspathncmp(const char *a, const char *b, size_t count);
 unsigned int fspathhash(const char *str);
 
 /*
index ca7678a379dcbcc4e77b1d1e590ea936fa7ac10f..71b4d23f0386b2136b01c99120854523fd384c2e 100644 (file)
@@ -506,6 +506,14 @@ static inline int git_offset_1st_component(const char *path)
 #define offset_1st_component git_offset_1st_component
 #endif
 
+#ifndef fspathcmp
+#define fspathcmp git_fspathcmp
+#endif
+
+#ifndef fspathncmp
+#define fspathncmp git_fspathncmp
+#endif
+
 #ifndef is_valid_path
 #define is_valid_path(path) 1
 #endif