git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 3/7] win32: override `fspathcmp()` with a directory separator-aware version

From
PWPhillip Wood <phillip.wood123@gmail.com>
Date
Jul 12, 2024, 13:46 UTC
Message-ID
<a1913542-ea19-49d7-a694-42540c71df03@gmail.com>
In-Reply-To
<a718183bb3b8eabd5ced274d8db124909bcdf493.1720739496.git.gitgitgadget@gmail.com>
Hi Johannes
On 12/07/2024 00:11, Johannes Schindelin via GitGitGadget wrote:
Show 7 quoted lines
> From: Johannes Schindelin <johannes.schindelin@gmx.de>
> 
> 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.

How does fspathncmp() behave? It would be good for the two to match. I've left a couple of thoughts below but I'm not sure they're worth re-rolling for

Show 25 quoted lines
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
>   compat/win32/path-utils.c | 25 +++++++++++++++++++++++++
>   compat/win32/path-utils.h |  2 ++
>   dir.c                     |  2 +-
>   dir.h                     |  2 +-
>   git-compat-util.h         |  5 +++++
>   5 files changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c
> index ebf2f12eb66..af7ef957bbf 100644
> --- a/compat/win32/path-utils.c
> +++ b/compat/win32/path-utils.c
> @@ -50,3 +50,28 @@ int win32_offset_1st_component(const char *path)
>   
>   	return pos + is_dir_sep(*pos) - path;
>   }
> +
> +int win32_fspathcmp(const char *a, const char *b)
> +{
> +	int diff;
> +
> +	for (;;) {
> +		if (!*a)
> +			return !*b ? 0 : -1;
Personally I'd find this easier to read as
	return *b ? -1 : 0;
Show 13 quoted lines
> +		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 = (unsigned char)tolower(*(a++)) - (unsigned char)tolower(*(b++));

There is a subtle difference between this and strcasecmp() because the latter is locale dependent but our tolower() is not because we override the standard library's version. As they're both useless on multibyte locales it probably doesn't make much difference in practice.

Thanks
Phillip
Show 58 quoted lines
> +		if (diff)
> +			return diff;
> +	}
> +}
> diff --git a/compat/win32/path-utils.h b/compat/win32/path-utils.h
> index 65fa3b9263a..e3c2a79df74 100644
> --- a/compat/win32/path-utils.h
> +++ b/compat/win32/path-utils.h
> @@ -29,5 +29,7 @@ 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
>   
>   #endif
> diff --git a/dir.c b/dir.c
> index b7a6625ebda..37d8e266b2c 100644
> --- 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);
>   }
> diff --git a/dir.h b/dir.h
> index 69a76d8bdd3..947e3d77442 100644
> --- a/dir.h
> +++ b/dir.h
> @@ -541,7 +541,7 @@ 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);
>   unsigned int fspathhash(const char *str);
> diff --git a/git-compat-util.h b/git-compat-util.h
> index ca7678a379d..ac564a68987 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -506,6 +506,11 @@ 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 is_valid_path
>   #define is_valid_path(path) 1
>   #endif
Previous: Johannes Schindelin via GitGitGadgetNext: Johannes Schindelin via GitGitGadget
Message 16 of 35 in “var(win32): do report the GIT_SHELL_PATH that is actually used”
  1. var(win32): do report the GIT_SHELL_PATH that is actually usedJohannes Schindelin via GitGitGadget, Jul 8, 2024
  2. Junio C HamanoJul 8, 2024
  3. brian m. carlsonJul 8, 2024
  4. Junio C HamanoJul 8, 2024
  5. brian m. carlsonJul 9, 2024
  6. Junio C HamanoJul 9, 2024
  7. Phillip WoodJul 9, 2024
  8. Junio C HamanoJul 8, 2024
  9. Phillip WoodJul 9, 2024
  10. Johannes SchindelinJul 11, 2024
  11. phillip.wood123@gmail.comJul 17, 2024
  12. 0/7 var(win32): do report the GIT_SHELL_PATH that is actually usedJohannes Schindelin via GitGitGadget, Jul 11, 2024
  13. 1/7 run-command: refactor getting the Unix shell path into its own functionJohannes Schindelin via GitGitGadget, Jul 11, 2024
  14. 2/7 strvec: declare the `strvec_push_nodup()` function globallyJohannes Schindelin via GitGitGadget, Jul 11, 2024
  15. 3/7 win32: override `fspathcmp()` with a directory separator-aware versionJohannes Schindelin via GitGitGadget, Jul 11, 2024
  16. Phillip WoodJul 12, 2024
  17. 4/7 mingw(is_msys2_sh): handle forward slashes in the `sh.exe` path, tooJohannes Schindelin via GitGitGadget, Jul 11, 2024
  18. Phillip WoodJul 12, 2024
  19. 5/7 run-command(win32): resolve the path to the Unix shell earlyJohannes Schindelin via GitGitGadget, Jul 11, 2024
  20. 6/7 run-command: declare the `git_shell_path()` function globallyJohannes Schindelin via GitGitGadget, Jul 11, 2024
  21. 7/7 var(win32): do report the GIT_SHELL_PATH that is actually usedJohannes Schindelin via GitGitGadget, Jul 11, 2024
  22. Junio C HamanoJul 12, 2024
  23. Phillip WoodJul 12, 2024
  24. Junio C HamanoJul 12, 2024
  25. 0/7 var(win32): do report the GIT_SHELL_PATH that is actually usedJohannes Schindelin via GitGitGadget, Jul 13, 2024
  26. 1/7 run-command: refactor getting the Unix shell path into its own functionJohannes Schindelin via GitGitGadget, Jul 13, 2024
  27. 2/7 strvec: declare the `strvec_push_nodup()` function globallyJohannes Schindelin via GitGitGadget, Jul 13, 2024
  28. 3/7 win32: override `fspathcmp()` with a directory separator-aware versionJohannes Schindelin via GitGitGadget, Jul 13, 2024
  29. 4/7 mingw(is_msys2_sh): handle forward slashes in the `sh.exe` path, tooJohannes Schindelin via GitGitGadget, Jul 13, 2024
  30. 5/7 run-command(win32): resolve the path to the Unix shell earlyJohannes Schindelin via GitGitGadget, Jul 13, 2024
  31. 6/7 run-command: declare the `git_shell_path()` function globallyJohannes Schindelin via GitGitGadget, Jul 13, 2024
  32. 7/7 var(win32): do report the GIT_SHELL_PATH that is actually usedJohannes Schindelin via GitGitGadget, Jul 13, 2024
  33. Phillip WoodJul 17, 2024
  34. brian m. carlsonJul 17, 2024
  35. Junio C HamanoJul 17, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.