mirror of
https://github.com/git/git.git
synced 2026-01-27 19:12:01 +00:00
Merge 'git-wrapper' into HEAD
Use msysGit's `git-wrapper` instead of the builtins. This works around two issues: - when the file system does not allow hard links, we would waste over 800 megabyte by having 109 copies of a multi-megabyte executable - even when the file system allows hard links, the Windows Explorer counts the disk usage as if it did not. Many users complained about Git for Windows using too much space (when it actually did not). We can easily avoid those user complaints by merging this branch. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This commit is contained in:
34
Makefile
34
Makefile
@@ -1732,11 +1732,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
|
||||
|
||||
@@ -2303,6 +2309,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 "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
|
||||
ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
|
||||
cp "$$execdir/git$X" "$$execdir/$$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)'
|
||||
@@ -2341,17 +2365,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 \
|
||||
|
||||
503
compat/win32/git-wrapper.c
Normal file
503
compat/win32/git-wrapper.c
Normal file
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* 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>
|
||||
#include <wchar.h>
|
||||
|
||||
static WCHAR msystem_bin[64];
|
||||
|
||||
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 full_path)
|
||||
{
|
||||
WCHAR msystem[64];
|
||||
LPWSTR path2 = NULL;
|
||||
int len;
|
||||
|
||||
/* Set MSYSTEM */
|
||||
swprintf(msystem, sizeof(msystem),
|
||||
L"MINGW%d", (int) sizeof(void *) * 8);
|
||||
SetEnvironmentVariable(L"MSYSTEM", msystem);
|
||||
|
||||
/* 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) {
|
||||
DWORD attr, drvlen = GetEnvironmentVariable(L"HOMEDRIVE", NULL, 0);
|
||||
e = (LPWSTR)malloc(sizeof(WCHAR) * (drvlen + len));
|
||||
drvlen = GetEnvironmentVariable(L"HOMEDRIVE", e, drvlen);
|
||||
GetEnvironmentVariable(L"HOMEPATH", e + drvlen, len);
|
||||
/* check if the path exists */
|
||||
attr = GetFileAttributesW(e);
|
||||
if (attr != INVALID_FILE_ATTRIBUTES
|
||||
&& (attr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
SetEnvironmentVariable(L"HOME", e);
|
||||
else
|
||||
len = 0; /* use USERPROFILE */
|
||||
free(e);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* extend the PATH */
|
||||
len = GetEnvironmentVariable(L"PATH", NULL, 0);
|
||||
len = sizeof(WCHAR) * (len + 2 * MAX_PATH);
|
||||
path2 = (LPWSTR)malloc(len);
|
||||
wcscpy(path2, exepath);
|
||||
if (!full_path)
|
||||
PathAppend(path2, L"cmd;");
|
||||
else {
|
||||
PathAppend(path2, msystem_bin);
|
||||
if (_waccess(path2, 0) != -1) {
|
||||
/* We are in an MSys2-based setup */
|
||||
wcscat(path2, L";");
|
||||
wcscat(path2, exepath);
|
||||
PathAppend(path2, L"usr\\bin;");
|
||||
}
|
||||
else {
|
||||
/* Fall back to MSys1 paths */
|
||||
wcscpy(path2, exepath);
|
||||
PathAppend(path2, L"bin;");
|
||||
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 prefix_args, int prefix_args_len, int is_git_command,
|
||||
int skip_arguments)
|
||||
{
|
||||
int wargc = 0;
|
||||
LPWSTR cmd = NULL, cmdline = NULL;
|
||||
LPWSTR *wargv = NULL, p = NULL;
|
||||
|
||||
cmdline = GetCommandLine();
|
||||
wargv = CommandLineToArgvW(cmdline, &wargc);
|
||||
cmd = (LPWSTR)malloc(sizeof(WCHAR) *
|
||||
(wcslen(cmdline) + prefix_args_len + 1 + MAX_PATH));
|
||||
if (prefix_args) {
|
||||
if (is_git_command)
|
||||
_swprintf(cmd, L"\"%s\\%s\" %.*s", exepath, L"git.exe",
|
||||
prefix_args_len, prefix_args);
|
||||
else
|
||||
_swprintf(cmd, L"%.*s", prefix_args_len, prefix_args);
|
||||
|
||||
}
|
||||
else
|
||||
wcscpy(cmd, L"git.exe");
|
||||
|
||||
/* skip wargv[0], append the remaining arguments */
|
||||
++skip_arguments;
|
||||
if (skip_arguments < wargc) {
|
||||
int i;
|
||||
for (i = 0, p = cmdline; p && *p && i < skip_arguments; i++) {
|
||||
if (i)
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
if (*p == L'"')
|
||||
p++;
|
||||
p += wcslen(wargv[i]);
|
||||
if (*p == L'"')
|
||||
p++;
|
||||
while (*p && !isspace(*p))
|
||||
p++;
|
||||
}
|
||||
wcscat(cmd, p);
|
||||
}
|
||||
|
||||
if (wargc > 1 && !wcscmp(wargv[1], L"gui"))
|
||||
*wait = 0;
|
||||
|
||||
LocalFree(wargv);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static int strip_prefix(LPWSTR str, int *len, LPCWSTR prefix)
|
||||
{
|
||||
LPWSTR start = str;
|
||||
do {
|
||||
if (str - start > *len)
|
||||
return 0;
|
||||
if (!*prefix) {
|
||||
*len -= str - start;
|
||||
memmove(start, str,
|
||||
sizeof(WCHAR) * (wcslen(str) + 1));
|
||||
return 1;
|
||||
}
|
||||
} while (*str++ == *prefix++);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep,
|
||||
LPWSTR *prefix_args, int *prefix_args_len,
|
||||
int *is_git_command, LPWSTR *working_directory, int *full_path,
|
||||
int *skip_arguments, int *allocate_console, int *show_console)
|
||||
{
|
||||
int id, minimal_search_path, needs_a_console, no_hide, wargc;
|
||||
LPWSTR *wargv;
|
||||
|
||||
#define BUFSIZE 65536
|
||||
static WCHAR buf[BUFSIZE];
|
||||
int len;
|
||||
|
||||
for (id = 0; ; id++) {
|
||||
minimal_search_path = 0;
|
||||
needs_a_console = 0;
|
||||
no_hide = 0;
|
||||
len = LoadString(NULL, id, buf, BUFSIZE);
|
||||
|
||||
if (!len) {
|
||||
if (!id)
|
||||
return 0; /* no resources found */
|
||||
|
||||
fwprintf(stderr, L"Need a valid command-line; "
|
||||
L"Edit the string resources accordingly\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (len >= BUFSIZE) {
|
||||
fwprintf(stderr,
|
||||
L"Could not read resource (too large)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (strip_prefix(buf, &len, L"MINIMAL_PATH=1 "))
|
||||
minimal_search_path = 1;
|
||||
else if (strip_prefix(buf, &len, L"ALLOC_CONSOLE=1 "))
|
||||
needs_a_console = 1;
|
||||
else if (strip_prefix(buf, &len, L"SHOW_CONSOLE=1 "))
|
||||
no_hide = 1;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
buf[len] = L'\0';
|
||||
|
||||
if (!id)
|
||||
SetEnvironmentVariable(L"EXEPATH", exepath);
|
||||
|
||||
for (;;) {
|
||||
LPWSTR atat = wcsstr(buf, L"@@"), atat2;
|
||||
WCHAR save;
|
||||
int env_len, delta;
|
||||
|
||||
if (!atat)
|
||||
break;
|
||||
|
||||
atat2 = wcsstr(atat + 2, L"@@");
|
||||
if (!atat2)
|
||||
break;
|
||||
|
||||
*atat2 = L'\0';
|
||||
env_len = GetEnvironmentVariable(atat + 2, NULL, 0);
|
||||
delta = env_len - 1 - (atat2 + 2 - atat);
|
||||
if (len + delta >= BUFSIZE) {
|
||||
fwprintf(stderr,
|
||||
L"Substituting '%s' results in too "
|
||||
L"large a command-line\n", atat + 2);
|
||||
exit(1);
|
||||
}
|
||||
if (delta)
|
||||
memmove(atat2 + 2 + delta, atat2 + 2,
|
||||
sizeof(WCHAR) * (len + 1
|
||||
- (atat2 + 2 - buf)));
|
||||
len += delta;
|
||||
save = atat[env_len - 1];
|
||||
GetEnvironmentVariable(atat + 2, atat, env_len);
|
||||
atat[env_len - 1] = save;
|
||||
}
|
||||
|
||||
/* parse first argument */
|
||||
wargv = CommandLineToArgvW(buf, &wargc);
|
||||
if (wargc < 1) {
|
||||
fwprintf(stderr, L"Invalid command-line: '%s'\n", buf);
|
||||
exit(1);
|
||||
}
|
||||
if (*wargv[0] == L'\\' ||
|
||||
(isalpha(*wargv[0]) && wargv[0][1] == L':'))
|
||||
wcscpy(exep, wargv[0]);
|
||||
else {
|
||||
wcscpy(exep, exepath);
|
||||
PathAppend(exep, wargv[0]);
|
||||
}
|
||||
LocalFree(wargv);
|
||||
|
||||
if (_waccess(exep, 0) != -1)
|
||||
break;
|
||||
fwprintf(stderr,
|
||||
L"Skipping command-line '%s'\n('%s' not found)\n",
|
||||
buf, exep);
|
||||
}
|
||||
|
||||
*prefix_args = buf;
|
||||
*prefix_args_len = wcslen(buf);
|
||||
|
||||
*is_git_command = 0;
|
||||
*working_directory = (LPWSTR) 1;
|
||||
wargv = CommandLineToArgvW(GetCommandLine(), &wargc);
|
||||
if (wargc > 1) {
|
||||
if (!wcscmp(L"--no-cd", wargv[1])) {
|
||||
*working_directory = NULL;
|
||||
*skip_arguments = 1;
|
||||
}
|
||||
else if (!wcsncmp(L"--cd=", wargv[1], 5)) {
|
||||
*working_directory = wcsdup(wargv[1] + 5);
|
||||
*skip_arguments = 1;
|
||||
}
|
||||
}
|
||||
if (minimal_search_path)
|
||||
*full_path = 0;
|
||||
if (needs_a_console)
|
||||
*allocate_console = 1;
|
||||
if (no_hide)
|
||||
*show_console = 1;
|
||||
LocalFree(wargv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int r = 1, wait = 1, prefix_args_len = -1, needs_env_setup = 1,
|
||||
is_git_command = 1, full_path = 1, skip_arguments = 0,
|
||||
allocate_console = 0, show_console = 0;
|
||||
WCHAR exepath[MAX_PATH], exe[MAX_PATH];
|
||||
LPWSTR cmd = NULL, exep = exe, prefix_args = NULL, basename;
|
||||
LPWSTR working_directory = NULL;
|
||||
|
||||
/* Determine MSys2-based Git path. */
|
||||
swprintf(msystem_bin, sizeof(msystem_bin),
|
||||
L"mingw%d\\bin", (int) sizeof(void *) * 8);
|
||||
|
||||
/* 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 (configure_via_resource(basename, exepath, exep,
|
||||
&prefix_args, &prefix_args_len,
|
||||
&is_git_command, &working_directory,
|
||||
&full_path, &skip_arguments, &allocate_console,
|
||||
&show_console)) {
|
||||
/* do nothing */
|
||||
}
|
||||
else if (!wcsicmp(basename, L"git-gui.exe")) {
|
||||
static WCHAR buffer[BUFSIZE];
|
||||
wait = 0;
|
||||
allocate_console = 1;
|
||||
if (!PathRemoveFileSpec(exepath)) {
|
||||
fwprintf(stderr,
|
||||
L"Invalid executable path: %s\n", exepath);
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
/* set the default exe module */
|
||||
wcscpy(exe, exepath);
|
||||
PathAppend(exe, msystem_bin);
|
||||
PathAppend(exe, L"wish.exe");
|
||||
if (_waccess(exe, 0) != -1)
|
||||
swprintf(buffer, BUFSIZE,
|
||||
L"\"%s\\%.*s\\libexec\\git-core\"",
|
||||
exepath, wcslen(msystem_bin) - 4, msystem_bin);
|
||||
else {
|
||||
wcscpy(exe, exepath);
|
||||
PathAppend(exe, L"mingw\\bin\\wish.exe");
|
||||
swprintf(buffer, BUFSIZE,
|
||||
L"\"%s\\mingw\\libexec\\git-core\"", exepath);
|
||||
}
|
||||
PathAppend(buffer, L"git-gui");
|
||||
prefix_args = buffer;
|
||||
prefix_args_len = wcslen(buffer);
|
||||
}
|
||||
else if (!wcsnicmp(basename, L"git-", 4)) {
|
||||
needs_env_setup = 0;
|
||||
|
||||
/* Call a builtin */
|
||||
prefix_args = basename + 4;
|
||||
prefix_args_len = wcslen(prefix_args);
|
||||
if (!wcsicmp(prefix_args + prefix_args_len - 4, L".exe"))
|
||||
prefix_args_len -= 4;
|
||||
|
||||
/* set the default exe module */
|
||||
wcscpy(exe, exepath);
|
||||
PathAppend(exe, L"git.exe");
|
||||
}
|
||||
else if (!wcsicmp(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, msystem_bin);
|
||||
PathAppend(exe, L"git.exe");
|
||||
if (_waccess(exe, 0) == -1) {
|
||||
wcscpy(exe, exepath);
|
||||
PathAppend(exe, L"bin\\git.exe");
|
||||
}
|
||||
}
|
||||
else if (!wcsicmp(basename, L"gitk.exe")) {
|
||||
static WCHAR buffer[BUFSIZE];
|
||||
allocate_console = 1;
|
||||
if (!PathRemoveFileSpec(exepath)) {
|
||||
fwprintf(stderr,
|
||||
L"Invalid executable path: %s\n", exepath);
|
||||
ExitProcess(1);
|
||||
}
|
||||
|
||||
/* set the default exe module */
|
||||
wcscpy(exe, exepath);
|
||||
swprintf(buffer, BUFSIZE, L"\"%s\"", exepath);
|
||||
PathAppend(exe, msystem_bin);
|
||||
PathAppend(exe, L"wish.exe");
|
||||
if (_waccess(exe, 0) != -1)
|
||||
PathAppend(buffer, msystem_bin);
|
||||
else {
|
||||
wcscpy(exe, exepath);
|
||||
PathAppend(exe, L"mingw\\bin\\wish.exe");
|
||||
PathAppend(buffer, L"mingw\\bin");
|
||||
}
|
||||
PathAppend(buffer, L"gitk");
|
||||
prefix_args = buffer;
|
||||
prefix_args_len = wcslen(buffer);
|
||||
}
|
||||
|
||||
if (needs_env_setup)
|
||||
setup_environment(exepath, full_path);
|
||||
cmd = fixup_commandline(exepath, &exep, &wait,
|
||||
prefix_args, prefix_args_len, is_git_command, skip_arguments);
|
||||
|
||||
if (working_directory == (LPWSTR)1) {
|
||||
int len = GetEnvironmentVariable(L"HOME", NULL, 0);
|
||||
|
||||
if (len) {
|
||||
working_directory = malloc(sizeof(WCHAR) * len);
|
||||
GetEnvironmentVariable(L"HOME", working_directory, len);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT;
|
||||
HANDLE console_handle;
|
||||
BOOL br = FALSE;
|
||||
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
|
||||
if (allocate_console | show_console)
|
||||
creation_flags |= CREATE_NEW_CONSOLE;
|
||||
else if ((console_handle = CreateFile(L"CONOUT$", GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL)) !=
|
||||
INVALID_HANDLE_VALUE)
|
||||
CloseHandle(console_handle);
|
||||
else {
|
||||
#define STD_HANDLE(field, id) si.hStd##field = GetStdHandle(STD_##id); if (!si.hStd##field) si.hStd##field = INVALID_HANDLE_VALUE
|
||||
STD_HANDLE(Input, INPUT_HANDLE);
|
||||
STD_HANDLE(Output, OUTPUT_HANDLE);
|
||||
STD_HANDLE(Error, ERROR_HANDLE);
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
|
||||
|
||||
creation_flags |= CREATE_NO_WINDOW;
|
||||
}
|
||||
if (show_console) {
|
||||
si.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_SHOW;
|
||||
}
|
||||
br = CreateProcess(/* module: null means use command line */
|
||||
exep,
|
||||
cmd, /* modified command line */
|
||||
NULL, /* process handle inheritance */
|
||||
NULL, /* thread handle inheritance */
|
||||
/* handles inheritable? */
|
||||
allocate_console ? FALSE : TRUE,
|
||||
creation_flags,
|
||||
NULL, /* environment: use parent */
|
||||
working_directory, /* use parent's */
|
||||
&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);
|
||||
|
||||
ExitProcess(r);
|
||||
}
|
||||
@@ -580,6 +580,17 @@ else
|
||||
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO
|
||||
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) $(ALL_LDFLAGS) $(COMPAT_CFLAGS) \
|
||||
-fno-stack-protector -Wall -s -o $@ $^ -lshell32 -lshlwapi
|
||||
|
||||
compat/win32/git-wrapper.o: %.o: %.c GIT-PREFIX
|
||||
$(QUIET_CC)$(CC) $(ALL_CFLAGS) $(COMPAT_CFLAGS) \
|
||||
-fno-stack-protector -o $*.o -c -Wall -Wwrite-strings $<
|
||||
|
||||
endif
|
||||
endif
|
||||
ifeq ($(uname_S),QNX)
|
||||
|
||||
Reference in New Issue
Block a user