Skip to content

Commit

Permalink
git-wrapper: support COMSPEC better
Browse files Browse the repository at this point in the history
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 <johannes.schindelin@gmx.de>
  • Loading branch information
dscho authored and Git for Windows Build Agent committed Aug 15, 2016
1 parent 290d5a2 commit 9dc5fe2
Showing 1 changed file with 23 additions and 6 deletions.
29 changes: 23 additions & 6 deletions compat/win32/git-wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ static void setup_environment(LPWSTR top_level_path, int full_path)
*/
static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
LPWSTR prefix_args, int prefix_args_len, int is_git_command,
int skip_arguments)
int skip_arguments, int append_quote_to_cmdline)
{
int wargc = 0;
LPWSTR cmd = NULL, cmdline = NULL;
Expand All @@ -133,7 +133,8 @@ static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
cmdline = GetCommandLine();
wargv = CommandLineToArgvW(cmdline, &wargc);
cmd = (LPWSTR)malloc(sizeof(WCHAR) *
(wcslen(cmdline) + prefix_args_len + 1 + MAX_PATH));
(wcslen(cmdline) + prefix_args_len + 1 + MAX_PATH +
append_quote_to_cmdline));
if (prefix_args) {
if (is_git_command)
_swprintf(cmd, L"\"%s\\%s\" %.*s", exepath, L"git.exe",
Expand Down Expand Up @@ -164,6 +165,9 @@ static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
wcscat(cmd, p);
}

if (append_quote_to_cmdline)
wcscat(cmd, L"\"");

if (wargc > 1 && !wcscmp(wargv[1], L"gui"))
*wait = 0;

Expand Down Expand Up @@ -285,9 +289,11 @@ static void set_app_id(LPWSTR app_id)
static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
LPWSTR *prefix_args, int *prefix_args_len,
int *is_git_command, LPWSTR *working_directory, int *full_path,
int *skip_arguments, int *allocate_console, int *show_console)
int *skip_arguments, int *allocate_console, int *show_console,
int *append_quote_to_cmdline)
{
int i, id, minimal_search_path, needs_a_console, no_hide, wargc;
int append_quote;
LPWSTR *wargv;
WCHAR *app_id;

Expand All @@ -300,6 +306,7 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
minimal_search_path = 0;
needs_a_console = 0;
no_hide = 0;
append_quote = 0;
app_id = NULL;
len = LoadString(NULL, id, buf, BUFSIZE);

Expand All @@ -325,6 +332,8 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
needs_a_console = 1;
else if (strip_prefix(buf, &len, L"SHOW_CONSOLE=1 "))
no_hide = 1;
else if (strip_prefix(buf, &len, L"APPEND_QUOTE=1 "))
append_quote = 1;
else if (strip_prefix(buf, &len, L"APP_ID=")) {
LPWSTR space = wcschr(buf, L' ');
size_t app_id_len = space - buf;
Expand Down Expand Up @@ -386,6 +395,10 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
no_hide = 0;
else if (!wcscmp(L"--no-hide", wargv[i]))
no_hide = 1;
else if (!wcscmp(L"--append-quote", wargv[i]))
append_quote = 1;
else if (!wcscmp(L"--no-append-quote", wargv[i]))
append_quote = -1;
else if (!wcsncmp(L"--command=", wargv[i], 10)) {
LPWSTR expanded;

Expand Down Expand Up @@ -415,6 +428,8 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
*allocate_console = 1;
if (no_hide)
*show_console = 1;
if (append_quote)
*append_quote_to_cmdline = append_quote == 1;
if (app_id)
set_app_id(app_id);
LocalFree(wargv);
Expand Down Expand Up @@ -466,7 +481,8 @@ int main(void)
{
int r = 1, wait = 1, prefix_args_len = -1, needs_env_setup = 1,
is_git_command = 1, full_path = 1, skip_arguments = 0,
allocate_console = 0, show_console = 0;
allocate_console = 0, show_console = 0,
append_quote_to_cmdline = 0;
WCHAR exepath[MAX_PATH], exe[MAX_PATH], top_level_path[MAX_PATH];
LPWSTR cmd = NULL, exep = exe, prefix_args = NULL, basename;
LPWSTR working_directory = NULL;
Expand All @@ -487,7 +503,7 @@ int main(void)
&prefix_args, &prefix_args_len,
&is_git_command, &working_directory,
&full_path, &skip_arguments, &allocate_console,
&show_console)) {
&show_console, &append_quote_to_cmdline)) {
/* do nothing */
}
else if (!wcsicmp(basename, L"git-gui.exe")) {
Expand Down Expand Up @@ -571,7 +587,8 @@ int main(void)
setup_environment(top_level_path, full_path);
}
cmd = fixup_commandline(exepath, &exep, &wait,
prefix_args, prefix_args_len, is_git_command, skip_arguments);
prefix_args, prefix_args_len, is_git_command, skip_arguments,
append_quote_to_cmdline);

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

0 comments on commit 9dc5fe2

Please sign in to comment.