Skip to content

Commit 59bd1a9

Browse files
committed
Merge branch 'git-wrapper--command'
This topic branch adds the --command=<command> option that allows starting the Git Bash (or Git CMD) with different terminal emulators than the one encoded via embedded string resources. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2 parents 118e2ac + ac6b03c commit 59bd1a9

File tree

1 file changed

+118
-55
lines changed

1 file changed

+118
-55
lines changed

compat/win32/git-wrapper.c

Lines changed: 118 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -184,16 +184,95 @@ static int strip_prefix(LPWSTR str, int *len, LPCWSTR prefix)
184184
return 0;
185185
}
186186

187+
static void extract_first_arg(LPWSTR command_line, LPWSTR exepath, LPWSTR buf)
188+
{
189+
LPWSTR *wargv;
190+
int wargc;
191+
192+
wargv = CommandLineToArgvW(command_line, &wargc);
193+
if (wargc < 1) {
194+
fwprintf(stderr, L"Invalid command-line: '%s'\n", command_line);
195+
exit(1);
196+
}
197+
if (*wargv[0] == L'\\' ||
198+
(isalpha(*wargv[0]) && wargv[0][1] == L':'))
199+
wcscpy(buf, wargv[0]);
200+
else {
201+
wcscpy(buf, exepath);
202+
PathAppend(buf, wargv[0]);
203+
}
204+
LocalFree(wargv);
205+
}
206+
207+
#define alloc_nr(x) (((x)+16)*3/2)
208+
209+
static LPWSTR expand_variables(LPWSTR buffer, size_t alloc)
210+
{
211+
LPWSTR buf = buffer;
212+
size_t len = wcslen(buf);
213+
214+
for (;;) {
215+
LPWSTR atat = wcsstr(buf, L"@@"), atat2;
216+
WCHAR save;
217+
int env_len, delta;
218+
219+
if (!atat)
220+
break;
221+
222+
atat2 = wcsstr(atat + 2, L"@@");
223+
if (!atat2)
224+
break;
225+
226+
*atat2 = L'\0';
227+
env_len = GetEnvironmentVariable(atat + 2, NULL, 0);
228+
delta = env_len - 1 - (atat2 + 2 - atat);
229+
if (len + delta >= alloc) {
230+
LPWSTR buf2;
231+
alloc = alloc_nr(alloc);
232+
if (alloc <= len + delta)
233+
alloc = len + delta + 1;
234+
if (buf != buffer)
235+
buf2 = realloc(buf, sizeof(WCHAR) * alloc);
236+
else {
237+
buf2 = malloc(sizeof(WCHAR) * alloc);
238+
if (buf2)
239+
memcpy(buf2, buf, sizeof(WCHAR)
240+
* (len + 1));
241+
}
242+
if (!buf2) {
243+
fwprintf(stderr,
244+
L"Substituting '%s' results in too "
245+
L"large a command-line\n", atat + 2);
246+
exit(1);
247+
}
248+
atat += buf2 - buf;
249+
atat2 += buf2 - buf;
250+
buf = buf2;
251+
}
252+
if (delta)
253+
memmove(atat2 + 2 + delta, atat2 + 2,
254+
sizeof(WCHAR) * (len + 1
255+
- (atat2 + 2 - buf)));
256+
len += delta;
257+
save = atat[env_len - 1];
258+
GetEnvironmentVariable(atat + 2, atat, env_len);
259+
atat[env_len - 1] = save;
260+
}
261+
262+
return buf;
263+
}
264+
187265
static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
188266
LPWSTR *prefix_args, int *prefix_args_len,
189267
int *is_git_command, LPWSTR *working_directory, int *full_path,
190268
int *skip_arguments, int *allocate_console, int *show_console)
191269
{
192-
int id, minimal_search_path, needs_a_console, no_hide, wargc;
270+
int i, id, minimal_search_path, needs_a_console, no_hide, wargc;
193271
LPWSTR *wargv;
194272

195273
#define BUFSIZE 65536
196274
static WCHAR buf[BUFSIZE];
275+
LPWSTR buf2 = buf;
197276
int len;
198277

199278
for (id = 0; ; id++) {
@@ -233,74 +312,58 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
233312
if (!id)
234313
SetEnvironmentVariable(L"EXEPATH", exepath);
235314

236-
for (;;) {
237-
LPWSTR atat = wcsstr(buf, L"@@"), atat2;
238-
WCHAR save;
239-
int env_len, delta;
240-
241-
if (!atat)
242-
break;
243-
244-
atat2 = wcsstr(atat + 2, L"@@");
245-
if (!atat2)
246-
break;
247-
248-
*atat2 = L'\0';
249-
env_len = GetEnvironmentVariable(atat + 2, NULL, 0);
250-
delta = env_len - 1 - (atat2 + 2 - atat);
251-
if (len + delta >= BUFSIZE) {
252-
fwprintf(stderr,
253-
L"Substituting '%s' results in too "
254-
L"large a command-line\n", atat + 2);
255-
exit(1);
256-
}
257-
if (delta)
258-
memmove(atat2 + 2 + delta, atat2 + 2,
259-
sizeof(WCHAR) * (len + 1
260-
- (atat2 + 2 - buf)));
261-
len += delta;
262-
save = atat[env_len - 1];
263-
GetEnvironmentVariable(atat + 2, atat, env_len);
264-
atat[env_len - 1] = save;
265-
}
315+
buf2 = expand_variables(buf, BUFSIZE);
266316

267-
/* parse first argument */
268-
wargv = CommandLineToArgvW(buf, &wargc);
269-
if (wargc < 1) {
270-
fwprintf(stderr, L"Invalid command-line: '%s'\n", buf);
271-
exit(1);
272-
}
273-
if (*wargv[0] == L'\\' ||
274-
(isalpha(*wargv[0]) && wargv[0][1] == L':'))
275-
wcscpy(exep, wargv[0]);
276-
else {
277-
wcscpy(exep, exepath);
278-
PathAppend(exep, wargv[0]);
279-
}
280-
LocalFree(wargv);
317+
extract_first_arg(buf2, exepath, exep);
281318

282319
if (_waccess(exep, 0) != -1)
283320
break;
284321
fwprintf(stderr,
285322
L"Skipping command-line '%s'\n('%s' not found)\n",
286-
buf, exep);
323+
buf2, exep);
287324
}
288325

289-
*prefix_args = buf;
290-
*prefix_args_len = wcslen(buf);
326+
*prefix_args = buf2;
327+
*prefix_args_len = wcslen(buf2);
291328

292329
*is_git_command = 0;
293330
*working_directory = (LPWSTR) 1;
294331
wargv = CommandLineToArgvW(GetCommandLine(), &wargc);
295-
if (wargc > 1) {
296-
if (!wcscmp(L"--no-cd", wargv[1])) {
332+
for (i = 1; i < wargc; i++) {
333+
if (!wcscmp(L"--no-cd", wargv[i]))
297334
*working_directory = NULL;
298-
*skip_arguments = 1;
299-
}
300-
else if (!wcsncmp(L"--cd=", wargv[1], 5)) {
301-
*working_directory = wcsdup(wargv[1] + 5);
302-
*skip_arguments = 1;
335+
else if (!wcsncmp(L"--cd=", wargv[i], 5))
336+
*working_directory = wcsdup(wargv[i] + 5);
337+
else if (!wcscmp(L"--minimal-search-path", wargv[i]))
338+
minimal_search_path = 1;
339+
else if (!wcscmp(L"--no-minimal-search-path", wargv[i]))
340+
minimal_search_path = 0;
341+
else if (!wcscmp(L"--needs-console", wargv[i]))
342+
needs_a_console = 1;
343+
else if (!wcscmp(L"--no-needs-console", wargv[i]))
344+
needs_a_console = 0;
345+
else if (!wcscmp(L"--hide", wargv[i]))
346+
no_hide = 0;
347+
else if (!wcscmp(L"--no-hide", wargv[i]))
348+
no_hide = 1;
349+
else if (!wcsncmp(L"--command=", wargv[i], 10)) {
350+
LPWSTR expanded;
351+
352+
wargv[i] += 10;
353+
expanded = expand_variables(wargv[i], wcslen(wargv[i]));
354+
if (expanded == wargv[i])
355+
expanded = wcsdup(expanded);
356+
357+
extract_first_arg(expanded, exepath, exep);
358+
359+
*prefix_args = expanded;
360+
*prefix_args_len = wcslen(*prefix_args);
361+
*skip_arguments = i;
362+
break;
303363
}
364+
else
365+
break;
366+
*skip_arguments = i;
304367
}
305368
if (minimal_search_path)
306369
*full_path = 0;

0 commit comments

Comments
 (0)