Merge branch 'js/var-git-shell-path'

"git var GIT_SHELL_PATH" should report the path to the shell used
to spawn external commands, but it didn't do so on Windows, which
has been corrected.

* js/var-git-shell-path:
  var(win32): do report the GIT_SHELL_PATH that is actually used
  run-command: declare the `git_shell_path()` function globally
  run-command(win32): resolve the path to the Unix shell early
  mingw(is_msys2_sh): handle forward slashes in the `sh.exe` path, too
  win32: override `fspathcmp()` with a directory separator-aware version
  strvec: declare the `strvec_push_nodup()` function globally
  run-command: refactor getting the Unix shell path into its own function
This commit is contained in:
Junio C Hamano 2024-07-17 10:47:27 -07:00
commit 76e018b9a1
12 changed files with 78 additions and 13 deletions

View File

@ -12,6 +12,7 @@
#include "refs.h"
#include "path.h"
#include "strbuf.h"
#include "run-command.h"
static const char var_usage[] = "git var (-l | <variable>)";
@ -51,7 +52,7 @@ static char *default_branch(int ident_flag UNUSED)
static char *shell_path(int ident_flag UNUSED)
{
return xstrdup(SHELL_PATH);
return git_shell_path();
}
static char *git_attr_val_system(int ident_flag UNUSED)

View File

@ -1546,7 +1546,7 @@ static int is_msys2_sh(const char *cmd)
return ret;
}
if (ends_with(cmd, "\\sh.exe")) {
if (ends_with(cmd, "\\sh.exe") || ends_with(cmd, "/sh.exe")) {
static char *sh;
if (!sh)

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

View File

@ -274,17 +274,24 @@ int sane_execvp(const char *file, char * const argv[])
return -1;
}
char *git_shell_path(void)
{
#ifndef GIT_WINDOWS_NATIVE
return xstrdup(SHELL_PATH);
#else
char *p = locate_in_PATH("sh");
convert_slashes(p);
return p;
#endif
}
static const char **prepare_shell_cmd(struct strvec *out, const char **argv)
{
if (!argv[0])
BUG("shell command is empty");
if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
#ifndef GIT_WINDOWS_NATIVE
strvec_push(out, SHELL_PATH);
#else
strvec_push(out, "sh");
#endif
strvec_push_nodup(out, git_shell_path());
strvec_push(out, "-c");
/*

View File

@ -195,6 +195,11 @@ int is_executable(const char *name);
*/
int exists_in_PATH(const char *command);
/**
* Return the path that is used to execute Unix shell command-lines.
*/
char *git_shell_path(void);
/**
* Start a sub-process. Takes a pointer to a `struct child_process`
* that specifies the details and returns pipe FDs (if requested).

View File

@ -10,7 +10,7 @@ void strvec_init(struct strvec *array)
memcpy(array, &blank, sizeof(*array));
}
static void strvec_push_nodup(struct strvec *array, const char *value)
void strvec_push_nodup(struct strvec *array, char *value)
{
if (array->v == empty_strvec)
array->v = NULL;

View File

@ -46,6 +46,9 @@ void strvec_init(struct strvec *);
/* Push a copy of a string onto the end of the array. */
const char *strvec_push(struct strvec *, const char *);
/* Push an allocated string onto the end of the array, taking ownership. */
void strvec_push_nodup(struct strvec *array, char *value);
/**
* Format a string and push it onto the end of the array. This is a
* convenience wrapper combining `strbuf_addf` and `strvec_push`.

View File

@ -157,7 +157,7 @@ test_expect_success POSIXPERM 'GIT_SHELL_PATH points to a valid executable' '
test_expect_success MINGW 'GIT_SHELL_PATH points to a suitable shell' '
shellpath=$(git var GIT_SHELL_PATH) &&
case "$shellpath" in
*sh) ;;
[A-Z]:/*/sh.exe) test -f "$shellpath";;
*) return 1;;
esac
'