win32: override `fspathcmp()` with a directory separator-aware version
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>
Johannes Schindelin committedJul 13, 2024 at 21:08 UTC193eda7507d0ccb2fe6fd42b403c56ecc205e546
5 files changed+53-4
compat/win32/path-utils.c
+37
index ebf2f12eb6..b658ca3f81 100644--- a/compat/win32/path-utils.c+++ b/compat/win32/path-utils.c@@ -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);+}