2 * git-wrapper - replace cmd\git.cmd with an executable
4 * Copyright (C) 2012 Pat Thoyts <patthoyts@users.sourceforge.net>
8 #define WIN32_LEAN_AND_MEAN
17 PrintError(LPCWSTR wszPrefix
, DWORD dwError
)
22 cch
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
23 | FORMAT_MESSAGE_FROM_SYSTEM
24 | FORMAT_MESSAGE_IGNORE_INSERTS
,
25 NULL
, dwError
, LANG_NEUTRAL
,
26 (LPTSTR
)&lpsz
, 0, NULL
);
28 cch
= FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
29 | FORMAT_MESSAGE_FROM_STRING
30 | FORMAT_MESSAGE_ARGUMENT_ARRAY
,
32 0, LANG_NEUTRAL
, (LPTSTR
)&lpsz
, 0,
35 fwprintf(stderr
, L
"%s: %s", wszPrefix
, lpsz
);
36 LocalFree((HLOCAL
)lpsz
);
43 WCHAR exepath
[MAX_PATH
], exe
[MAX_PATH
];
44 LPWSTR cmd
= NULL
, path2
= NULL
, exep
= exe
;
48 /* get the installation location */
49 GetModuleFileName(NULL
, exepath
, MAX_PATH
);
50 PathRemoveFileSpec(exepath
);
51 PathRemoveFileSpec(exepath
);
53 /* set the default exe module */
55 PathAppend(exe
, L
"bin\\git.exe");
57 /* if not set, set TERM to msys */
58 if (GetEnvironmentVariable(L
"TERM", NULL
, 0) == 0) {
59 SetEnvironmentVariable(L
"TERM", L
"msys");
62 /* if not set, set PLINK_PROTOCOL to ssh */
63 if (GetEnvironmentVariable(L
"PLINK_PROTOCOL", NULL
, 0) == 0) {
64 SetEnvironmentVariable(L
"PLINK_PROTOCOL", L
"ssh");
67 /* set HOME to %HOMEDRIVE%%HOMEPATH% or %USERPROFILE%
68 * With roaming profiles: HOMEPATH is the roaming location and
69 * USERPROFILE is the local location
71 if (GetEnvironmentVariable(L
"HOME", NULL
, 0) == 0) {
73 len
= GetEnvironmentVariable(L
"HOMEPATH", NULL
, 0);
75 len
= GetEnvironmentVariable(L
"USERPROFILE", NULL
, 0);
77 e
= (LPWSTR
)malloc(len
* sizeof(WCHAR
));
78 GetEnvironmentVariable(L
"USERPROFILE", e
, len
);
79 SetEnvironmentVariable(L
"HOME", e
);
84 len
+= GetEnvironmentVariable(L
"HOMEDRIVE", NULL
, 0);
85 e
= (LPWSTR
)malloc(sizeof(WCHAR
) * (len
+ 2));
86 n
= GetEnvironmentVariable(L
"HOMEDRIVE", e
, len
);
87 GetEnvironmentVariable(L
"HOMEPATH", &e
[n
], len
-n
);
88 SetEnvironmentVariable(L
"HOME", e
);
94 len
= GetEnvironmentVariable(L
"PATH", NULL
, 0);
95 len
= sizeof(WCHAR
) * (len
+ 2 * MAX_PATH
);
96 path2
= (LPWSTR
)malloc(len
);
97 wcscpy(path2
, exepath
);
98 PathAppend(path2
, L
"bin;");
99 /* should do this only if it exists */
100 wcscat(path2
, exepath
);
101 PathAppend(path2
, L
"mingw\\bin;");
102 GetEnvironmentVariable(L
"PATH", &path2
[wcslen(path2
)],
103 (len
/sizeof(WCHAR
))-wcslen(path2
));
104 SetEnvironmentVariable(L
"PATH", path2
);
108 /* fix up the command line to call git.exe
109 * We have to be very careful about quoting here so we just
110 * trim off the first argument and replace it leaving the rest
114 int wargc
= 0, gui
= 0;
115 LPWSTR cmdline
= NULL
;
116 LPWSTR
*wargv
= NULL
, p
= NULL
;
117 cmdline
= GetCommandLine();
118 wargv
= CommandLineToArgvW(cmdline
, &wargc
);
119 cmd
= (LPWSTR
)malloc(sizeof(WCHAR
) * (wcslen(cmdline
) + MAX_PATH
));
120 if (wargc
> 1 && wcsicmp(L
"gui", wargv
[1]) == 0) {
122 if (wargc
> 2 && wcsicmp(L
"citool", wargv
[2]) == 0) {
124 wcscpy(cmd
, L
"git.exe");
126 WCHAR script
[MAX_PATH
];
128 wcscpy(script
, exepath
);
129 PathAppend(script
, L
"libexec\\git-core\\git-gui");
130 PathQuoteSpaces(script
);
131 wcscpy(cmd
, L
"wish.exe ");
134 exep
= NULL
; /* find the module from the commandline */
137 wcscpy(cmd
, L
"git.exe");
139 /* find the first space after the initial parameter then append all */
140 p
= wcschr(&cmdline
[wcslen(wargv
[0])], L
' ');
142 /* for git gui subcommands, remove the 'gui' word */
144 while (*p
== L
' ') ++p
;
153 /* set the console to ANSI/GUI codepage */
154 codepage
= GetConsoleCP();
155 SetConsoleCP(GetACP());
159 PROCESS_INFORMATION pi
;
161 ZeroMemory(&pi
, sizeof(PROCESS_INFORMATION
));
162 ZeroMemory(&si
, sizeof(STARTUPINFO
));
163 si
.cb
= sizeof(STARTUPINFO
);
164 br
= CreateProcess(exep
,/* module: null means use command line */
165 cmd
, /* modified command line */
166 NULL
, /* process handle inheritance */
167 NULL
, /* thread handle inheritance */
168 TRUE
, /* handles inheritable? */
169 CREATE_UNICODE_ENVIRONMENT
,
170 NULL
, /* environment: use parent */
171 NULL
, /* starting directory: use parent */
175 WaitForSingleObject(pi
.hProcess
, INFINITE
);
176 if (!GetExitCodeProcess(pi
.hProcess
, (DWORD
*)&r
))
177 PrintError(L
"error reading exit code", GetLastError());
178 CloseHandle(pi
.hProcess
);
180 PrintError(L
"error launching git", GetLastError());
187 /* reset the console codepage */
188 SetConsoleCP(codepage
);
195 * indent-tabs-mode: nil