Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2779,6 +2779,13 @@ compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
compat/nedmalloc/nedmalloc.sp: SP_EXTRA_FLAGS += -Wno-non-pointer-null
endif

headless-git.o: compat/win32/headless.c GIT-CFLAGS
$(QUIET_CC)$(CC) $(ALL_CFLAGS) $(COMPAT_CFLAGS) \
-fno-stack-protector -o $@ -c -Wall -Wwrite-strings $<

headless-git$X: headless-git.o git.res GIT-LDFLAGS
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -mwindows -o $@ $< git.res

git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)

Expand Down Expand Up @@ -3652,6 +3659,7 @@ clean: profile-clean coverage-clean cocciclean
$(RM) po/git.pot po/git-core.pot
$(RM) git.res
$(RM) $(OBJECTS)
$(RM) headless-git.o
$(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS)
$(RM) $(TEST_PROGRAMS)
Expand Down Expand Up @@ -3680,6 +3688,7 @@ endif
$(RM) GIT-SCRIPT-DEFINES GIT-PERL-DEFINES GIT-PERL-HEADER GIT-PYTHON-VARS
ifdef MSVC
$(RM) $(patsubst %.o,%.o.pdb,$(OBJECTS))
$(RM) headless-git.o.pdb
$(RM) $(patsubst %.exe,%.pdb,$(OTHER_PROGRAMS))
$(RM) $(patsubst %.exe,%.iobj,$(OTHER_PROGRAMS))
$(RM) $(patsubst %.exe,%.ipdb,$(OTHER_PROGRAMS))
Expand Down
2 changes: 1 addition & 1 deletion builtin/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2068,7 +2068,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
"</Settings>\n"
"<Actions Context=\"Author\">\n"
"<Exec>\n"
"<Command>\"%s\\git.exe\"</Command>\n"
"<Command>\"%s\\headless-git.exe\"</Command>\n"
"<Arguments>--exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
"</Exec>\n"
"</Actions>\n"
Expand Down
115 changes: 115 additions & 0 deletions compat/win32/headless.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* headless Git - run Git without opening a console window on Windows
*/

#define STRICT
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>

/*
* If `dir` contains the path to a Git exec directory, extend `PATH` to
* include the corresponding `bin/` directory (which is where all those
* `.dll` files needed by `git.exe` are, on Windows).
*/
static int extend_path(wchar_t *dir, size_t dir_len)
{
const wchar_t *suffix = L"\\libexec\\git-core";
size_t suffix_len = wcslen(suffix);
wchar_t *env;
DWORD len;

if (dir_len < suffix_len)
return 0;

dir_len -= suffix_len;
if (memcmp(dir + dir_len, suffix, suffix_len * sizeof(wchar_t)))
return 0;

len = GetEnvironmentVariableW(L"PATH", NULL, 0);
if (!len)
return 0;

env = _alloca((dir_len + 5 + len) * sizeof(wchar_t));
wcsncpy(env, dir, dir_len);
wcscpy(env + dir_len, L"\\bin;");
if (!GetEnvironmentVariableW(L"PATH", env + dir_len + 5, len))
return 0;

SetEnvironmentVariableW(L"PATH", env);
return 1;
}

int WINAPI wWinMain(_In_ HINSTANCE instance,
_In_opt_ HINSTANCE previous_instance,
_In_ LPWSTR command_line, _In_ int show)
{
wchar_t git_command_line[32768];
size_t size = sizeof(git_command_line) / sizeof(wchar_t);
const wchar_t *needs_quotes = L"";
int slash = 0, i;

STARTUPINFO startup_info = {
.cb = sizeof(STARTUPINFO),
.dwFlags = STARTF_USESHOWWINDOW,
.wShowWindow = SW_HIDE,
};
PROCESS_INFORMATION process_info = { 0 };
DWORD creation_flags = CREATE_UNICODE_ENVIRONMENT |
CREATE_NEW_CONSOLE | CREATE_NO_WINDOW;
DWORD exit_code;

/* First, determine the full path of argv[0] */
for (i = 0; _wpgmptr[i]; i++)
if (_wpgmptr[i] == L' ')
needs_quotes = L"\"";
else if (_wpgmptr[i] == L'\\')
slash = i;

if (slash >= size - 11)
return 127; /* Too long path */

/* If it is in Git's exec path, add the bin/ directory to the PATH */
extend_path(_wpgmptr, slash);

/* Then, add the full path of `git.exe` as argv[0] */
i = swprintf_s(git_command_line, size, L"%ls%.*ls\\git.exe%ls",
needs_quotes, slash, _wpgmptr, needs_quotes);
if (i < 0)
return 127; /* Too long path */

if (*command_line) {
/* Now, append the command-line arguments */
i = swprintf_s(git_command_line + i, size - i,
L" %ls", command_line);
if (i < 0)
return 127;
}

startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);

if (!CreateProcess(NULL, /* infer argv[0] from the command line */
git_command_line, /* modified command line */
NULL, /* inherit process handles? */
NULL, /* inherit thread handles? */
FALSE, /* handles inheritable? */
creation_flags,
NULL, /* use this process' environment */
NULL, /* use this process' working directory */
&startup_info, &process_info))
return 129; /* could not start */
WaitForSingleObject(process_info.hProcess, INFINITE);
if (!GetExitCodeProcess(process_info.hProcess, &exit_code))
exit_code = 130; /* Could not determine exit code? */

CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);

return (int)exit_code;
}
3 changes: 3 additions & 0 deletions config.mak.uname
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ else
endif
X = .exe

EXTRA_PROGRAMS += headless-git$X

compat/msvc.o: compat/msvc.c compat/mingw.c GIT-CFLAGS
endif
ifeq ($(uname_S),Interix)
Expand Down Expand Up @@ -705,6 +707,7 @@ ifeq ($(uname_S),MINGW)
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY \
-fstack-protector-strong
EXTLIBS += -lntdll
EXTRA_PROGRAMS += headless-git$X
INSTALL = /bin/install
INTERNAL_QSORT = YesPlease
HAVE_LIBCHARSET_H = YesPlease
Expand Down
9 changes: 9 additions & 0 deletions contrib/buildsystems/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,15 @@ if(WIN32)
else()
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
endif()

add_executable(headless-git ${CMAKE_SOURCE_DIR}/compat/win32/headless.c)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
target_link_options(headless-git PUBLIC -municode -Wl,-subsystem,windows)
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
target_link_options(headless-git PUBLIC /NOLOGO /ENTRY:wWinMainCRTStartup /SUBSYSTEM:WINDOWS)
else()
message(FATAL_ERROR "Unhandled compiler: ${CMAKE_C_COMPILER_ID}")
endif()
elseif(UNIX)
target_link_libraries(common-main pthread rt)
endif()
Expand Down
4 changes: 2 additions & 2 deletions contrib/buildsystems/Generators/Vcxproj.pm
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ sub createProject {

my $libs_release = "\n ";
my $libs_debug = "\n ";
if (!$static_library) {
if (!$static_library && $name ne 'headless-git') {
$libs_release = join(";", sort(grep /^(?!libgit\.lib|xdiff\/lib\.lib|vcs-svn\/lib\.lib|reftable\/libreftable\.lib)/, @{$$build_structure{"$prefix${name}_LIBS"}}));
$libs_debug = $libs_release;
$libs_debug =~ s/zlib\.lib/zlibd\.lib/g;
Expand Down Expand Up @@ -230,7 +230,7 @@ EOM
print F << "EOM";
</ItemGroup>
EOM
if (!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') {
if ((!$static_library || $target =~ 'vcs-svn' || $target =~ 'xdiff') && !($name =~ /headless-git/)) {
my $uuid_libgit = $$build_structure{"LIBS_libgit_GUID"};
my $uuid_libreftable = $$build_structure{"LIBS_reftable/libreftable_GUID"};
my $uuid_xdiff_lib = $$build_structure{"LIBS_xdiff/lib_GUID"};
Expand Down
1 change: 1 addition & 0 deletions contrib/buildsystems/engine.pl
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ sub handleLinkLine
# exit(1);
foreach (@objfiles) {
my $sourcefile = $_;
$sourcefile =~ s/^headless-git\.o$/compat\/win32\/headless.c/;
$sourcefile =~ s/\.o$/.c/;
push(@sources, $sourcefile);
push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}});
Expand Down