mirror of
https://github.com/git/git.git
synced 2026-02-07 00:05:02 +00:00
Merge pull request #34 from dscho/git-wrapper
Use msysGit's `git-wrapper` instead of the builtins
This commit is contained in:
34
Makefile
34
Makefile
@@ -1655,11 +1655,17 @@ version.sp version.s version.o: EXTRA_CPPFLAGS = \
|
||||
'-DGIT_VERSION="$(GIT_VERSION)"' \
|
||||
'-DGIT_USER_AGENT=$(GIT_USER_AGENT_CQ_SQ)'
|
||||
|
||||
ifeq (,$(BUILT_IN_WRAPPER))
|
||||
$(BUILT_INS): git$X
|
||||
$(QUIET_BUILT_IN)$(RM) $@ && \
|
||||
ln $< $@ 2>/dev/null || \
|
||||
ln -s $< $@ 2>/dev/null || \
|
||||
cp $< $@
|
||||
else
|
||||
$(BUILT_INS): $(BUILT_IN_WRAPPER)
|
||||
$(QUIET_BUILT_IN)$(RM) $@ && \
|
||||
cp $< $@
|
||||
endif
|
||||
|
||||
common-cmds.h: ./generate-cmdlist.sh command-list.txt
|
||||
|
||||
@@ -2222,6 +2228,24 @@ profile-install: profile
|
||||
profile-fast-install: profile-fast
|
||||
$(MAKE) install
|
||||
|
||||
ifeq (,$(BUILT_IN_WRAPPER))
|
||||
LN_OR_CP_BUILT_IN_BINDIR = \
|
||||
test -z "$(NO_INSTALL_HARDLINKS)" && \
|
||||
ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
|
||||
ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
|
||||
cp "$$bindir/git$X" "$$bindir/$$p" || exit;
|
||||
LN_OR_CP_BUILT_IN_EXECDIR = \
|
||||
test -z "$(NO_INSTALL_HARDLINKS)" && \
|
||||
ln "$$exectir/git$X" "$$exectir/$$p" 2>/dev/null || \
|
||||
ln -s "git$X" "$$exectir/$$p" 2>/dev/null || \
|
||||
cp "$$exectir/git$X" "$$exectir/$$p" || exit;
|
||||
else
|
||||
LN_OR_CP_BUILT_IN_BINDIR = \
|
||||
cp "$(BUILT_IN_WRAPPER)" "$$bindir/$$p" || exit;
|
||||
LN_OR_CP_BUILT_IN_EXECDIR = \
|
||||
cp "$(BUILT_IN_WRAPPER)" "$$execdir/$$p" || exit;
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
|
||||
@@ -2260,17 +2284,11 @@ endif
|
||||
} && \
|
||||
for p in $(filter $(install_bindir_programs),$(BUILT_INS)); do \
|
||||
$(RM) "$$bindir/$$p" && \
|
||||
test -z "$(NO_INSTALL_HARDLINKS)" && \
|
||||
ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
|
||||
ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
|
||||
cp "$$bindir/git$X" "$$bindir/$$p" || exit; \
|
||||
$(LN_OR_CP_BUILT_IN_BINDIR) \
|
||||
done && \
|
||||
for p in $(BUILT_INS); do \
|
||||
$(RM) "$$execdir/$$p" && \
|
||||
test -z "$(NO_INSTALL_HARDLINKS)" && \
|
||||
ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
|
||||
ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
|
||||
cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
|
||||
$(LN_OR_CP_BUILT_IN_EXECDIR) \
|
||||
done && \
|
||||
remote_curl_aliases="$(REMOTE_CURL_ALIASES)" && \
|
||||
for p in $$remote_curl_aliases; do \
|
||||
|
||||
233
compat/win32/git-wrapper.c
Normal file
233
compat/win32/git-wrapper.c
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <stdio.h>
|
||||
|
||||
static void print_error(LPCWSTR prefix, DWORD error_number)
|
||||
{
|
||||
LPWSTR buffer = NULL;
|
||||
DWORD count = 0;
|
||||
|
||||
count = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
| FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, error_number, LANG_NEUTRAL,
|
||||
(LPTSTR)&buffer, 0, NULL);
|
||||
if (count < 1)
|
||||
count = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
| FORMAT_MESSAGE_FROM_STRING
|
||||
| FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||||
L"Code 0x%1!08x!",
|
||||
0, LANG_NEUTRAL, (LPTSTR)&buffer, 0,
|
||||
(va_list*)&error_number);
|
||||
fwprintf(stderr, L"%s: %s", prefix, buffer);
|
||||
LocalFree((HLOCAL)buffer);
|
||||
}
|
||||
|
||||
static void setup_environment(LPWSTR exepath)
|
||||
{
|
||||
int len;
|
||||
LPWSTR path2 = NULL;
|
||||
|
||||
/* if not set, set TERM to msys */
|
||||
if (!GetEnvironmentVariable(L"TERM", NULL, 0))
|
||||
SetEnvironmentVariable(L"TERM", L"msys");
|
||||
|
||||
/* if not set, set PLINK_PROTOCOL to ssh */
|
||||
if (!GetEnvironmentVariable(L"PLINK_PROTOCOL", NULL, 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)) {
|
||||
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.
|
||||
*/
|
||||
static LPWSTR fixup_commandline(LPWSTR exepath, LPWSTR *exep, int *wait,
|
||||
LPWSTR builtin, int builtin_len)
|
||||
{
|
||||
int wargc = 0, gui = 0;
|
||||
LPWSTR cmd = NULL, cmdline = NULL;
|
||||
LPWSTR *wargv = NULL, p = NULL;
|
||||
|
||||
cmdline = GetCommandLine();
|
||||
wargv = CommandLineToArgvW(cmdline, &wargc);
|
||||
cmd = (LPWSTR)malloc(sizeof(WCHAR) *
|
||||
(wcslen(cmdline) + builtin_len + 1 + 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;
|
||||
wcscpy(script, exepath);
|
||||
PathAppend(script,
|
||||
L"libexec\\git-core\\git-gui");
|
||||
PathQuoteSpaces(script);
|
||||
wcscpy(cmd, L"wish.exe ");
|
||||
wcscat(cmd, script);
|
||||
wcscat(cmd, L" --");
|
||||
/* find the module from the commandline */
|
||||
*exep = NULL;
|
||||
}
|
||||
}
|
||||
else if (builtin)
|
||||
_swprintf(cmd, L"%s\\%s %.*s",
|
||||
exepath, L"git.exe", builtin_len, builtin);
|
||||
else
|
||||
wcscpy(cmd, L"git.exe");
|
||||
|
||||
/* append all after first space after the initial parameter */
|
||||
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);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int r = 1, wait = 1, builtin_len = -1;
|
||||
WCHAR exepath[MAX_PATH], exe[MAX_PATH];
|
||||
LPWSTR cmd = NULL, exep = exe, builtin = NULL, basename;
|
||||
UINT codepage = 0;
|
||||
|
||||
/* get the installation location */
|
||||
GetModuleFileName(NULL, exepath, MAX_PATH);
|
||||
if (!PathRemoveFileSpec(exepath)) {
|
||||
fwprintf(stderr, L"Invalid executable path: %s\n", exepath);
|
||||
ExitProcess(1);
|
||||
}
|
||||
basename = exepath + wcslen(exepath) + 1;
|
||||
if (!wcsncmp(basename, L"git-", 4)) {
|
||||
/* Call a builtin */
|
||||
builtin = basename + 4;
|
||||
builtin_len = wcslen(builtin);
|
||||
if (!wcscmp(builtin + builtin_len - 4, L".exe"))
|
||||
builtin_len -= 4;
|
||||
|
||||
/* set the default exe module */
|
||||
wcscpy(exe, exepath);
|
||||
PathAppend(exe, L"git.exe");
|
||||
}
|
||||
else if (!wcscmp(basename, L"git.exe")) {
|
||||
if (!PathRemoveFileSpec(exepath)) {
|
||||
fwprintf(stderr,
|
||||
L"Invalid executable path: %s\n", exepath);
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
/* set the default exe module */
|
||||
wcscpy(exe, exepath);
|
||||
PathAppend(exe, L"bin\\git.exe");
|
||||
}
|
||||
|
||||
if (!builtin)
|
||||
setup_environment(exepath);
|
||||
cmd = fixup_commandline(exepath, &exep, &wait, builtin, builtin_len);
|
||||
|
||||
/* set the console to ANSI/GUI codepage */
|
||||
codepage = GetConsoleCP();
|
||||
SetConsoleCP(GetACP());
|
||||
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
BOOL br = FALSE;
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
br = CreateProcess(/* module: null means use command line */
|
||||
exep,
|
||||
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 (br) {
|
||||
if (wait)
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
if (!GetExitCodeProcess(pi.hProcess, (DWORD *)&r))
|
||||
print_error(L"error reading exit code",
|
||||
GetLastError());
|
||||
CloseHandle(pi.hProcess);
|
||||
}
|
||||
else {
|
||||
print_error(L"error launching git", GetLastError());
|
||||
r = 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(cmd);
|
||||
|
||||
/* reset the console codepage */
|
||||
SetConsoleCP(codepage);
|
||||
ExitProcess(r);
|
||||
}
|
||||
@@ -561,6 +561,15 @@ else
|
||||
else
|
||||
NO_CURL = YesPlease
|
||||
endif
|
||||
OTHER_PROGRAMS += git-wrapper$(X)
|
||||
BUILT_IN_WRAPPER = git-wrapper$(X)
|
||||
|
||||
git-wrapper$(X): compat/win32/git-wrapper.o git.res
|
||||
$(QUIET_LINK)$(CC) -Wall -s -o $@ $^ -lshell32 -lshlwapi
|
||||
|
||||
compat/win32/git-wrapper.o: %.o: %.c
|
||||
$(QUIET_CC)$(CC) -o $*.o -c -Wall -Wwrite-strings $<
|
||||
|
||||
endif
|
||||
endif
|
||||
ifeq ($(uname_S),QNX)
|
||||
|
||||
Reference in New Issue
Block a user