Skip to content

Commit ee563f3

Browse files
committed
Merge pull request #2974 from derrickstolee/maintenance-and-headless
Include Windows-specific maintenance and headless-git
2 parents dd9b795 + 57dee28 commit ee563f3

File tree

5 files changed

+128
-1
lines changed

5 files changed

+128
-1
lines changed

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,6 +2550,13 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
25502550
compat/nedmalloc/nedmalloc.sp: SP_EXTRA_FLAGS += -Wno-non-pointer-null
25512551
endif
25522552

2553+
headless-git.o: compat/win32/headless.c
2554+
$(QUIET_CC)$(CC) $(ALL_CFLAGS) $(COMPAT_CFLAGS) \
2555+
-fno-stack-protector -o $@ -c -Wall -Wwrite-strings $<
2556+
2557+
headless-git$X: headless-git.o git.res
2558+
$(QUIET_LINK)$(CC) $(ALL_LDFLAGS) -mwindows $(COMPAT_CFLAGS) -o $@ $^
2559+
25532560
git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
25542561
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
25552562

builtin/gc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,7 +1797,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
17971797
"</Settings>\n"
17981798
"<Actions Context=\"Author\">\n"
17991799
"<Exec>\n"
1800-
"<Command>\"%s\\git.exe\"</Command>\n"
1800+
"<Command>\"%s\\headless-git.exe\"</Command>\n"
18011801
"<Arguments>--exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
18021802
"</Exec>\n"
18031803
"</Actions>\n"

compat/win32/headless.c

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* headless Git - run Git without opening a console window on Windows
3+
*/
4+
5+
#define STRICT
6+
#define WIN32_LEAN_AND_MEAN
7+
#define UNICODE
8+
#define _UNICODE
9+
#include <windows.h>
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
#include <wchar.h>
13+
14+
/*
15+
* If `dir` contains the path to a Git exec directory, extend `PATH` to
16+
* include the corresponding `bin/` directory (which is where all those
17+
* `.dll` files needed by `git.exe` are, on Windows).
18+
*/
19+
static int extend_path(wchar_t *dir, size_t dir_len)
20+
{
21+
const wchar_t *suffix = L"\\libexec\\git-core";
22+
size_t suffix_len = wcslen(suffix);
23+
wchar_t *env;
24+
DWORD len;
25+
26+
if (dir_len < suffix_len)
27+
return 0;
28+
29+
dir_len -= suffix_len;
30+
if (memcmp(dir + dir_len, suffix, suffix_len * sizeof(wchar_t)))
31+
return 0;
32+
33+
len = GetEnvironmentVariableW(L"PATH", NULL, 0);
34+
if (!len)
35+
return 0;
36+
37+
env = _alloca((dir_len + 5 + len) * sizeof(wchar_t));
38+
wcsncpy(env, dir, dir_len);
39+
wcscpy(env + dir_len, L"\\bin;");
40+
if (!GetEnvironmentVariableW(L"PATH", env + dir_len + 5, len))
41+
return 0;
42+
43+
SetEnvironmentVariableW(L"PATH", env);
44+
return 1;
45+
}
46+
47+
int WINAPI wWinMain(HINSTANCE instance, HINSTANCE previous_instance,
48+
wchar_t *command_line, int show)
49+
{
50+
wchar_t git_command_line[32768];
51+
size_t size = sizeof(git_command_line) / sizeof(wchar_t);
52+
const wchar_t *needs_quotes = L"";
53+
int slash = 0, i;
54+
55+
STARTUPINFO startup_info = {
56+
.dwFlags = STARTF_USESHOWWINDOW,
57+
.wShowWindow = SW_HIDE,
58+
};
59+
PROCESS_INFORMATION process_info = { 0 };
60+
DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT |
61+
CREATE_NEW_CONSOLE | CREATE_NO_WINDOW;
62+
DWORD exit_code;
63+
64+
/* First, determine the full path of argv[0] */
65+
for (i = 0; _wpgmptr[i]; i++)
66+
if (_wpgmptr[i] == L' ')
67+
needs_quotes = L"\"";
68+
else if (_wpgmptr[i] == L'\\')
69+
slash = i;
70+
71+
if (slash + 11 >= sizeof(git_command_line) / sizeof(wchar_t))
72+
return 127; /* Too long path */
73+
74+
/* If it is in Git's exec path, add the bin/ directory to the PATH */
75+
extend_path(_wpgmptr, slash);
76+
77+
/* Then, add the full path of `git.exe` as argv[0] */
78+
i = swprintf_s(git_command_line, size, L"%ls%.*ls\\git.exe%ls",
79+
needs_quotes, slash, _wpgmptr, needs_quotes);
80+
if (i < 0)
81+
return 127; /* Too long path */
82+
83+
if (*command_line) {
84+
/* Now, append the command-line arguments */
85+
i = swprintf_s(git_command_line + i, size - i,
86+
L" %ls", command_line);
87+
if (i < 0)
88+
return 127;
89+
}
90+
91+
startup_info.cb = sizeof(STARTUPINFO);
92+
93+
startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
94+
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
95+
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
96+
97+
if (!CreateProcess(NULL, /* infer argv[0] from the command line */
98+
git_command_line, /* modified command line */
99+
NULL, /* inherit process handles? */
100+
NULL, /* inherit thread handles? */
101+
FALSE, /* handles inheritable? */
102+
creation_flags,
103+
NULL, /* use this process' environment */
104+
NULL, /* use this process' working directory */
105+
&startup_info, &process_info))
106+
return 129; /* could not start */
107+
WaitForSingleObject(process_info.hProcess, INFINITE);
108+
if (!GetExitCodeProcess(process_info.hProcess, &exit_code)) {
109+
CloseHandle(process_info.hProcess);
110+
return 130; /* Could not determine exit code? */
111+
}
112+
113+
return (int)exit_code;
114+
}

config.mak.uname

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,8 @@ else
486486
endif
487487
X = .exe
488488

489+
EXTRA_PROGRAMS += headless-git$X
490+
489491
compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
490492
endif
491493
ifeq ($(uname_S),Interix)
@@ -627,6 +629,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
627629
RC = windres -O coff
628630
NATIVE_CRLF = YesPlease
629631
X = .exe
632+
EXTRA_PROGRAMS += headless-git$X
630633
ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
631634
htmldir = doc/git/html/
632635
prefix =

contrib/buildsystems/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,9 @@ if(WIN32)
648648
else()
649649
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
650650
endif()
651+
652+
add_executable(headless-git ${CMAKE_SOURCE_DIR}/compat/win32/headless.c)
653+
target_link_options(headless-git PUBLIC /NOLOGO /ENTRY:wWinMainCRTStartup /SUBSYSTEM:WINDOWS)
651654
elseif(UNIX)
652655
target_link_libraries(common-main pthread rt)
653656
endif()

0 commit comments

Comments
 (0)