Skip to content

Commit 952acce

Browse files
committed
git-wrapper: support COMSPEC better
The quoting rules of `cmd.exe` are really, really quirky. In particular, if there are more than two quotes, the entire set of rules changes. That is the reason why CMD /C "C:\Program Files\Git\usr\bin\bash.exe" -l -i works, but CMD /C "C:\Program Files\Git\usr\bin\bash.exe" -l -i "test.sh" fails with this error message: 'C:\Program' is not recognized as an internal or external command, operable program or batch file. The recommended fix is to pass the /S option to `cmd.exe` and surround the entire command-line by an extra set of quotes. And here lies the rub: for that to work, we have to append an extra quote. At the end of the command-line. *After* the last argument was appended, if any. This commit supports that use case by introducing the option "APPEND_QUOTE". The intended usage is to use the following string resource: SHOW_CONSOLE=1 APPEND_QUOTE=1 @@comspec@@ /S /C \"\"@@EXEPATH@@\\usr\\bin\\bash.exe\" --login -i (Note that there are only three quotes on that command-line, the fourth to be appended due to the `APPEND_QUOTE` setting.) This is (1/3) to fix #396 Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 96d2d2d commit 952acce

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

compat/win32/git-wrapper.c

+23-6
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static void setup_environment(LPWSTR top_level_path, int full_path)
124124
*/
125125
static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
126126
LPWSTR prefix_args, int prefix_args_len, int is_git_command,
127-
int skip_arguments)
127+
int skip_arguments, int append_quote_to_cmdline)
128128
{
129129
int wargc = 0;
130130
LPWSTR cmd = NULL, cmdline = NULL;
@@ -133,7 +133,8 @@ static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
133133
cmdline = GetCommandLine();
134134
wargv = CommandLineToArgvW(cmdline, &wargc);
135135
cmd = (LPWSTR)malloc(sizeof(WCHAR) *
136-
(wcslen(cmdline) + prefix_args_len + 1 + MAX_PATH));
136+
(wcslen(cmdline) + prefix_args_len + 1 + MAX_PATH +
137+
append_quote_to_cmdline));
137138
if (prefix_args) {
138139
if (is_git_command)
139140
_swprintf(cmd, L"\"%s\\%s\" %.*s", exepath, L"git.exe",
@@ -164,6 +165,9 @@ static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
164165
wcscat(cmd, p);
165166
}
166167

168+
if (append_quote_to_cmdline)
169+
wcscat(cmd, L"\"");
170+
167171
if (wargc > 1 && !wcscmp(wargv[1], L"gui"))
168172
*wait = 0;
169173

@@ -285,9 +289,11 @@ static void set_app_id(LPWSTR app_id)
285289
static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
286290
LPWSTR *prefix_args, int *prefix_args_len,
287291
int *is_git_command, LPWSTR *working_directory, int *full_path,
288-
int *skip_arguments, int *allocate_console, int *show_console)
292+
int *skip_arguments, int *allocate_console, int *show_console,
293+
int *append_quote_to_cmdline)
289294
{
290295
int i, id, minimal_search_path, needs_a_console, no_hide, wargc;
296+
int append_quote;
291297
LPWSTR *wargv;
292298
WCHAR *app_id;
293299

@@ -300,6 +306,7 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
300306
minimal_search_path = 0;
301307
needs_a_console = 0;
302308
no_hide = 0;
309+
append_quote = 0;
303310
app_id = NULL;
304311
len = LoadString(NULL, id, buf, BUFSIZE);
305312

@@ -325,6 +332,8 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
325332
needs_a_console = 1;
326333
else if (strip_prefix(buf, &len, L"SHOW_CONSOLE=1 "))
327334
no_hide = 1;
335+
else if (strip_prefix(buf, &len, L"APPEND_QUOTE=1 "))
336+
append_quote = 1;
328337
else if (strip_prefix(buf, &len, L"APP_ID=")) {
329338
LPWSTR space = wcschr(buf, L' ');
330339
size_t app_id_len = space - buf;
@@ -386,6 +395,10 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
386395
no_hide = 0;
387396
else if (!wcscmp(L"--no-hide", wargv[i]))
388397
no_hide = 1;
398+
else if (!wcscmp(L"--append-quote", wargv[i]))
399+
append_quote = 1;
400+
else if (!wcscmp(L"--no-append-quote", wargv[i]))
401+
append_quote = -1;
389402
else if (!wcsncmp(L"--command=", wargv[i], 10)) {
390403
LPWSTR expanded;
391404

@@ -415,6 +428,8 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
415428
*allocate_console = 1;
416429
if (no_hide)
417430
*show_console = 1;
431+
if (append_quote)
432+
*append_quote_to_cmdline = append_quote == 1;
418433
if (app_id)
419434
set_app_id(app_id);
420435
LocalFree(wargv);
@@ -466,7 +481,8 @@ int main(void)
466481
{
467482
int r = 1, wait = 1, prefix_args_len = -1, needs_env_setup = 1,
468483
is_git_command = 1, full_path = 1, skip_arguments = 0,
469-
allocate_console = 0, show_console = 0;
484+
allocate_console = 0, show_console = 0,
485+
append_quote_to_cmdline = 0;
470486
WCHAR exepath[MAX_PATH], exe[MAX_PATH], top_level_path[MAX_PATH];
471487
LPWSTR cmd = NULL, exep = exe, prefix_args = NULL, basename;
472488
LPWSTR working_directory = NULL;
@@ -487,7 +503,7 @@ int main(void)
487503
&prefix_args, &prefix_args_len,
488504
&is_git_command, &working_directory,
489505
&full_path, &skip_arguments, &allocate_console,
490-
&show_console)) {
506+
&show_console, &append_quote_to_cmdline)) {
491507
/* do nothing */
492508
}
493509
else if (!wcsicmp(basename, L"git-gui.exe")) {
@@ -571,7 +587,8 @@ int main(void)
571587
setup_environment(top_level_path, full_path);
572588
}
573589
cmd = fixup_commandline(exepath, &exep, &wait,
574-
prefix_args, prefix_args_len, is_git_command, skip_arguments);
590+
prefix_args, prefix_args_len, is_git_command, skip_arguments,
591+
append_quote_to_cmdline);
575592

576593
if (working_directory == (LPWSTR)1) {
577594
int len = GetEnvironmentVariable(L"HOME", NULL, 0);

0 commit comments

Comments
 (0)