Skip to content

Commit 7f9a037

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 <[email protected]>
2 parents 9801f7b + f763cda commit 7f9a037

File tree

1 file changed

+120
-56
lines changed

1 file changed

+120
-56
lines changed

compat/win32/git-wrapper.c

Lines changed: 120 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -188,16 +188,95 @@ static int strip_prefix(LPWSTR str, int *len, LPCWSTR prefix)
188188
return 0;
189189
}
190190

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

199277
#define BUFSIZE 65536
200278
static WCHAR buf[BUFSIZE];
279+
LPWSTR buf2 = buf;
201280
int len;
202281

203282
for (id = 0; ; id++) {
@@ -237,74 +316,59 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
237316
if (!id)
238317
SetEnvironmentVariable(L"EXEPATH", exepath);
239318

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

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

286323
if (_waccess(exep, 0) != -1)
287324
break;
288325
fwprintf(stderr,
289326
L"Skipping command-line '%s'\n('%s' not found)\n",
290-
buf, exep);
327+
buf2, exep);
291328
}
292329

293-
*prefix_args = buf;
294-
*prefix_args_len = wcslen(buf);
330+
*prefix_args = buf2;
331+
*prefix_args_len = wcslen(buf2);
295332

296333
*is_git_command = 0;
297-
*working_directory = (LPWSTR) 1;
298334
wargv = CommandLineToArgvW(GetCommandLine(), &wargc);
299-
if (wargc > 1) {
300-
if (!wcscmp(L"--no-cd", wargv[1])) {
335+
for (i = 1; i < wargc; i++) {
336+
if (!wcscmp(L"--no-cd", wargv[i]))
301337
*working_directory = NULL;
302-
*skip_arguments = 1;
303-
}
304-
else if (!wcsncmp(L"--cd=", wargv[1], 5)) {
305-
*working_directory = wcsdup(wargv[1] + 5);
306-
*skip_arguments = 1;
338+
else if (!wcscmp(L"--cd-to-home", wargv[i]))
339+
*working_directory = (LPWSTR) 1;
340+
else if (!wcsncmp(L"--cd=", wargv[i], 5))
341+
*working_directory = wcsdup(wargv[i] + 5);
342+
else if (!wcscmp(L"--minimal-search-path", wargv[i]))
343+
minimal_search_path = 1;
344+
else if (!wcscmp(L"--no-minimal-search-path", wargv[i]))
345+
minimal_search_path = 0;
346+
else if (!wcscmp(L"--needs-console", wargv[i]))
347+
needs_a_console = 1;
348+
else if (!wcscmp(L"--no-needs-console", wargv[i]))
349+
needs_a_console = 0;
350+
else if (!wcscmp(L"--hide", wargv[i]))
351+
no_hide = 0;
352+
else if (!wcscmp(L"--no-hide", wargv[i]))
353+
no_hide = 1;
354+
else if (!wcsncmp(L"--command=", wargv[i], 10)) {
355+
LPWSTR expanded;
356+
357+
wargv[i] += 10;
358+
expanded = expand_variables(wargv[i], wcslen(wargv[i]));
359+
if (expanded == wargv[i])
360+
expanded = wcsdup(expanded);
361+
362+
extract_first_arg(expanded, exepath, exep);
363+
364+
*prefix_args = expanded;
365+
*prefix_args_len = wcslen(*prefix_args);
366+
*skip_arguments = i;
367+
break;
307368
}
369+
else
370+
break;
371+
*skip_arguments = i;
308372
}
309373
if (minimal_search_path)
310374
*full_path = 0;

0 commit comments

Comments
 (0)