forked from msysgit/msysgit
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a compiled wrapper to replace the git.cmd script.
This addresses github issue msysgit#36 which points out problems in handling git commit notations of the form tag^{commit} and HEAD^. The windows command shell uses caret as a quote both on the command line and in batch scripts and this results in requiring double quoting. To be able to handle both "tag^{commit}" and tag^^{commit} (either style of command prompt quoting) the script needs replacing. This also makes it simpler to call git from batch scripts as it will no longer need to be prefixed with 'call'. Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>
- Loading branch information
Showing
4 changed files
with
201 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.exe | ||
*.o | ||
*~ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -Wwrite-strings | ||
LD = gcc | ||
LDFLAGS = -Wall -s | ||
LIBS =-lshell32 -lshlwapi | ||
|
||
all: git-wrapper | ||
|
||
git-wrapper: git-wrapper.o | ||
$(LD) $(LDFLAGS) -o $@ $^ $(LIBS) | ||
|
||
clean: | ||
-rm -f git-wrapper.o git-wrapper.exe | ||
|
||
%.o: %.c | ||
$(CC) $(CFLAGS) -c $^ -o $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/* | ||
* git-wrapper - replace cmd\git.cmd with an executable | ||
* | ||
* Copyright (C) 2012 Pat Thoyts <patthoyts@users.sourceforge.net> | ||
*/ | ||
|
||
#define STRICT | ||
#define WIN32_LEAN_AND_MEAN | ||
#define UNICODE | ||
#define _UNICODE | ||
#include <windows.h> | ||
#include <shlwapi.h> | ||
#include <shellapi.h> | ||
|
||
#ifdef __MSC_VER__ | ||
int __stdcall wmain(void) | ||
#else | ||
int main(void) | ||
#endif | ||
{ | ||
int r = 1, wait = 1; | ||
WCHAR exepath[MAX_PATH], exe[MAX_PATH]; | ||
LPWSTR cmd = NULL, path2 = NULL, exep = exe; | ||
UINT codepage = 0; | ||
int len; | ||
|
||
/* get the installation location */ | ||
GetModuleFileName(NULL, exepath, MAX_PATH); | ||
PathRemoveFileSpec(exepath); | ||
PathRemoveFileSpec(exepath); | ||
|
||
/* set the default exe module */ | ||
wcscpy(exe, exepath); | ||
PathAppend(exe, L"bin\\git.exe"); | ||
|
||
/* if not set, set TERM to msys */ | ||
if (GetEnvironmentVariable(L"TERM", NULL, 0) == 0) { | ||
SetEnvironmentVariable(L"TERM", L"msys"); | ||
} | ||
|
||
/* if not set, set PLINK_PROTOCOL to ssh */ | ||
if (GetEnvironmentVariable(L"PLINK_PROTOCOL", NULL, 0) == 0) { | ||
SetEnvironmentVariable(L"PLINK_PROTOCOL", L"ssh"); | ||
} | ||
|
||
/* set HOME to %HOMEDRIVE%%HOMEPATH% or %USERPROFILE% | ||
* With roaming profiles: HOMEPATH is the roaming location and | ||
* USERPROFILE is the local location | ||
*/ | ||
if (GetEnvironmentVariable(L"HOME", NULL, 0) == 0) { | ||
LPWSTR e = NULL; | ||
len = GetEnvironmentVariable(L"HOMEPATH", NULL, 0); | ||
if (len == 0) { | ||
len = GetEnvironmentVariable(L"USERPROFILE", NULL, 0); | ||
if (len != 0) { | ||
e = (LPWSTR)malloc(len * sizeof(WCHAR)); | ||
GetEnvironmentVariable(L"USERPROFILE", e, len); | ||
SetEnvironmentVariable(L"HOME", e); | ||
free(e); | ||
} | ||
} else { | ||
int n; | ||
len += GetEnvironmentVariable(L"HOMEDRIVE", NULL, 0); | ||
e = (LPWSTR)malloc(sizeof(WCHAR) * (len + 2)); | ||
n = GetEnvironmentVariable(L"HOMEDRIVE", e, len); | ||
GetEnvironmentVariable(L"HOMEPATH", &e[n], len-n); | ||
SetEnvironmentVariable(L"HOME", e); | ||
free(e); | ||
} | ||
} | ||
|
||
/* extend the PATH */ | ||
len = GetEnvironmentVariable(L"PATH", NULL, 0); | ||
len = sizeof(WCHAR) * (len + 2 * MAX_PATH); | ||
path2 = (LPWSTR)malloc(len); | ||
wcscpy(path2, exepath); | ||
PathAppend(path2, L"bin;"); | ||
/* should do this only if it exists */ | ||
wcscat(path2, exepath); | ||
PathAppend(path2, L"mingw\\bin;"); | ||
GetEnvironmentVariable(L"PATH", &path2[wcslen(path2)], | ||
(len/sizeof(WCHAR))-wcslen(path2)); | ||
SetEnvironmentVariable(L"PATH", path2); | ||
free(path2); | ||
|
||
|
||
/* fix up the command line to call git.exe | ||
* We have to be very careful about quoting here so we just | ||
* trim off the first argument and replace it leaving the rest | ||
* untouched. | ||
*/ | ||
{ | ||
int wargc = 0, gui = 0; | ||
LPWSTR cmdline = NULL; | ||
LPWSTR *wargv = NULL, p = NULL; | ||
cmdline = GetCommandLine(); | ||
wargv = CommandLineToArgvW(cmdline, &wargc); | ||
cmd = (LPWSTR)malloc(sizeof(WCHAR) * (wcslen(cmdline) + MAX_PATH)); | ||
if (wargc > 1 && wcsicmp(L"gui", wargv[1]) == 0) { | ||
wait = 0; | ||
if (wargc > 2 && wcsicmp(L"citool", wargv[2]) == 0) { | ||
wait = 1; | ||
wcscpy(cmd, L"git.exe"); | ||
} else { | ||
WCHAR script[MAX_PATH]; | ||
gui = 1; | ||
wcscat(script, exepath); | ||
PathAppend(script, L"libexec\\git-core\\git-gui"); | ||
PathQuoteSpaces(script); | ||
wcscpy(cmd, L"wish.exe "); | ||
wcscat(cmd, script); | ||
wcscat(cmd, L" --"); | ||
exep = NULL; /* find the module from the commandline */ | ||
} | ||
} else { | ||
wcscpy(cmd, L"git.exe"); | ||
} | ||
/* find the first space after the initial parameter then append all */ | ||
p = wcschr(&cmdline[wcslen(wargv[0])], L' '); | ||
if (p && *p) { | ||
/* for git gui subcommands, remove the 'gui' word */ | ||
if (gui) { | ||
while (*p == L' ') ++p; | ||
p = wcschr(p, L' '); | ||
} | ||
if (p && *p) | ||
wcscat(cmd, p); | ||
} | ||
LocalFree(wargv); | ||
} | ||
|
||
/* set the console to ANSI/GUI codepage */ | ||
codepage = GetConsoleCP(); | ||
SetConsoleCP(GetACP()); | ||
|
||
{ | ||
STARTUPINFO si; | ||
PROCESS_INFORMATION pi; | ||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); | ||
ZeroMemory(&si, sizeof(STARTUPINFO)); | ||
si.cb = sizeof(STARTUPINFO); | ||
CreateProcess(exep,/* module: null means use command line */ | ||
cmd, /* modified command line */ | ||
NULL, /* process handle inheritance */ | ||
NULL, /* thread handle inheritance */ | ||
TRUE, /* handles inheritable? */ | ||
CREATE_UNICODE_ENVIRONMENT, | ||
NULL, /* environment: use parent */ | ||
NULL, /* starting directory: use parent */ | ||
&si, &pi); | ||
if (wait) | ||
WaitForSingleObject(pi.hProcess, INFINITE); | ||
} | ||
|
||
free(cmd); | ||
|
||
/* reset the console codepage */ | ||
SetConsoleCP(codepage); | ||
ExitProcess(r); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#!/bin/sh | ||
|
||
cd "$(dirname "$0")" | ||
|
||
DEST=/cmd/git.exe | ||
|
||
die () { | ||
echo "$*" >&2 | ||
exit 1 | ||
} | ||
|
||
rmscript () { | ||
test -f /cmd/git.cmd && rm /cmd/git.cmd || true | ||
} | ||
|
||
make && | ||
index=$(/share/msysGit/pre-install.sh) && | ||
rmscript && | ||
install -m 775 git-wrapper.exe $DEST && | ||
/share/msysGit/post-install.sh $index "Updated git wrapper exe" || | ||
die "Failed to update git wrapper executable" |