Skip to content

Commit 81e2795

Browse files
committed
mingw: special-case arguments to sh
The MSYS2 runtime does its best to emulate the command-line expansion and de-quoting which would otherwise be performed by the calling shell. However, in Git we pass arguments to subprocesses that we do *not* want to be handled that way, e.g. when passing Windows paths. Note: this is only a problem when calling MSYS2 executables, not when calling MINGW executables such as git.exe. But sometimes we do call MSYS2 executables, most notably when setting the use_shell flag in the child_process structure. There is no elegant way to determine whether the .exe file to be executed is an MSYS2 program or a MINGW one. But since the use case of passing a command line through the shell is so prevalent, we need to work around this issue at least when executing sh.exe. Let's introduce an ugly, hard-coded test whether argv[0] is "sh" to determine whether we need to quote the arguments differently than usual. That still does not fix the issue completely, but at least it is something. Incidentally, this also fixes the problem where `git clone \\server\repo` failed due to incorrect handling of the backslashes when handing the path to the git-upload-pack process. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 2f1cb1d commit 81e2795

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

compat/mingw.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,7 @@ char *mingw_getcwd(char *pointer, int len)
10661066
* See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx
10671067
* (Parsing C++ Command-Line Arguments)
10681068
*/
1069-
static const char *quote_arg(const char *arg)
1069+
static const char *quote_arg_msvc(const char *arg)
10701070
{
10711071
/* count chars to quote */
10721072
int len = 0, n = 0;
@@ -1121,6 +1121,37 @@ static const char *quote_arg(const char *arg)
11211121
return q;
11221122
}
11231123

1124+
#include "quote.h"
1125+
1126+
static const char *quote_arg_sh(const char *arg)
1127+
{
1128+
struct strbuf buf = STRBUF_INIT;
1129+
const char *p2 = arg, *p;
1130+
1131+
for (p = arg; *p; p++) {
1132+
int ws = isspace(*p);
1133+
if (!ws && *p != '\\' && *p != '"')
1134+
continue;
1135+
if (!buf.len)
1136+
strbuf_addch(&buf, '"');
1137+
if (p != p2)
1138+
strbuf_add(&buf, p2, p - p2);
1139+
if (!ws)
1140+
strbuf_addch(&buf, '\\');
1141+
p2 = p;
1142+
}
1143+
1144+
if (p == arg)
1145+
strbuf_addch(&buf, '"');
1146+
else if (!buf.len)
1147+
return arg;
1148+
else
1149+
strbuf_add(&buf, p2, p - p2),
1150+
1151+
strbuf_addch(&buf, '"');
1152+
return strbuf_detach(&buf, 0);
1153+
}
1154+
11241155
static const char *parse_interpreter(const char *cmd)
11251156
{
11261157
static char buf[100];
@@ -1547,6 +1578,8 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
15471578
BOOL ret;
15481579
HANDLE cons;
15491580
const char *strace_env;
1581+
const char *(*quote_arg)(const char *arg) =
1582+
*argv && !strcmp("sh", *argv) ? quote_arg_sh : quote_arg_msvc;
15501583

15511584
if (!atexit_handler_initialized) {
15521585
atexit_handler_initialized = 1;

t/t5580-clone-push-unc.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ test_expect_success clone '
4343
git clone "file://$UNCPATH" clone
4444
'
4545

46-
test_expect_failure 'clone with backslashed path' '
46+
test_expect_success 'clone with backslashed path' '
4747
BACKSLASHED="$(echo "$UNCPATH" | tr / \\\\)" &&
4848
git clone "$BACKSLASHED" backslashed
4949
'

0 commit comments

Comments
 (0)