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>
This commit is contained in:
Johannes Schindelin 2024-07-13 21:08:20 +00:00 committed by Junio C Hamano
parent ce68178a0a
commit 193eda7507
5 changed files with 53 additions and 4 deletions

View 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);
}

View 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

4
dir.c
View File

@ -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);
}

4
dir.h
View File

@ -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);
/*

View 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