Skip to content

Commit 051ef8f

Browse files
committed
Merge branch 'busybox-w32'
This topic branch brings slightly experimental changes supporting Git for Windows to use BusyBox-w32 to execute its shell scripts as well as its test suite. The test suite can be run by installing the test artifacts into a MinGit that has busybox.exe (and using Git for Windows' SDK's Perl for now, as the test suite requires Perl even when NO_PERL is set, go figure) by using the `install-mingit-test-artifacts` Makefile target with the DESTDIR variable pointing to the top-level directory of the MinGit installation. To facilitate running the test suite (without having `make` available, as `make.exe` is not part of MinGit), this branch brings an experimental patch to the `test-run-command` helper to run Git's test suite. It is still very experimental, though: in this developer's tests it seemed that the `poll()` emulation required for `run_parallel_processes()` to work sometimes hiccups on Windows, causing infinite "hangs". It is also possible that BusyBox itself has problems writing to the pipes opened by `test-run-command` (and merging this branch will help investigate further). Caveat emptor. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 3395974 + e70c979 commit 051ef8f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+645
-221
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
645645
TEST_PROGRAMS_NEED_X += test-fake-ssh
646646
TEST_PROGRAMS_NEED_X += test-genrandom
647647
TEST_PROGRAMS_NEED_X += test-hashmap
648+
TEST_PROGRAMS_NEED_X += test-helper
648649
TEST_PROGRAMS_NEED_X += test-index-version
649650
TEST_PROGRAMS_NEED_X += test-lazy-init-name-hash
650651
TEST_PROGRAMS_NEED_X += test-line-buffer

compat/mingw.c

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "../cache.h"
99
#include "win32/exit-process.h"
1010
#include "../config.h"
11+
#include "../string-list.h"
1112

1213
#define HCAST(type, handle) ((type)(intptr_t)handle)
1314

@@ -1216,6 +1217,65 @@ static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
12161217
return NULL;
12171218
}
12181219

1220+
static char *path_lookup(const char *cmd, int exe_only);
1221+
1222+
static char *is_busybox_applet(const char *cmd)
1223+
{
1224+
static struct string_list applets = STRING_LIST_INIT_DUP;
1225+
static char *busybox_path;
1226+
static int busybox_path_initialized;
1227+
1228+
/* Avoid infinite loop */
1229+
if (!strncasecmp(cmd, "busybox", 7) &&
1230+
(!cmd[7] || !strcasecmp(cmd + 7, ".exe")))
1231+
return NULL;
1232+
1233+
if (!busybox_path_initialized) {
1234+
busybox_path = path_lookup("busybox.exe", 1);
1235+
busybox_path_initialized = 1;
1236+
}
1237+
1238+
/* Assume that sh is compiled in... */
1239+
if (!busybox_path || !strcasecmp(cmd, "sh"))
1240+
return xstrdup_or_null(busybox_path);
1241+
1242+
if (!applets.nr) {
1243+
struct child_process cp = CHILD_PROCESS_INIT;
1244+
struct strbuf buf = STRBUF_INIT;
1245+
char *p;
1246+
1247+
argv_array_pushl(&cp.args, busybox_path, "--help", NULL);
1248+
1249+
if (capture_command(&cp, &buf, 2048)) {
1250+
string_list_append(&applets, "");
1251+
return NULL;
1252+
}
1253+
1254+
/* parse output */
1255+
p = strstr(buf.buf, "Currently defined functions:\n");
1256+
if (!p) {
1257+
warning("Could not parse output of busybox --help");
1258+
string_list_append(&applets, "");
1259+
return NULL;
1260+
}
1261+
p = strchrnul(p, '\n');
1262+
for (;;) {
1263+
size_t len;
1264+
1265+
p += strspn(p, "\n\t ,");
1266+
len = strcspn(p, "\n\t ,");
1267+
if (!len)
1268+
break;
1269+
p[len] = '\0';
1270+
string_list_insert(&applets, p);
1271+
p = p + len + 1;
1272+
}
1273+
}
1274+
1275+
return string_list_has_string(&applets, cmd) ?
1276+
xstrdup(busybox_path) : NULL;
1277+
}
1278+
12191279
/*
12201280
* Determines the absolute path of cmd using the split path in path.
12211281
* If cmd contains a slash or backslash, no lookup is performed.
@@ -1244,6 +1304,9 @@ static char *path_lookup(const char *cmd, int exe_only)
12441304
path = sep + 1;
12451305
}
12461306

1307+
if (!prog && !isexe)
1308+
prog = is_busybox_applet(cmd);
1309+
12471310
return prog;
12481311
}
12491312

@@ -1557,8 +1620,8 @@ static int is_msys2_sh(const char *cmd)
15571620
}
15581621

15591622
static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaenv,
1560-
const char *dir,
1561-
int prepend_cmd, int fhin, int fhout, int fherr)
1623+
const char *dir, const char *prepend_cmd,
1624+
int fhin, int fhout, int fherr)
15621625
{
15631626
static int atexit_handler_initialized;
15641627
STARTUPINFOW si;
@@ -1627,9 +1690,9 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
16271690
/* concatenate argv, quoting args as we go */
16281691
strbuf_init(&args, 0);
16291692
if (prepend_cmd) {
1630-
char *quoted = (char *)quote_arg(cmd);
1693+
char *quoted = (char *)quote_arg(prepend_cmd);
16311694
strbuf_addstr(&args, quoted);
1632-
if (quoted != cmd)
1695+
if (quoted != prepend_cmd)
16331696
free(quoted);
16341697
}
16351698
for (; *argv; argv++) {
@@ -1706,7 +1769,8 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
17061769
return (pid_t)pi.dwProcessId;
17071770
}
17081771

1709-
static pid_t mingw_spawnv(const char *cmd, const char **argv, int prepend_cmd)
1772+
static pid_t mingw_spawnv(const char *cmd, const char **argv,
1773+
const char *prepend_cmd)
17101774
{
17111775
return mingw_spawnve_fd(cmd, argv, NULL, NULL, prepend_cmd, 0, 1, 2);
17121776
}
@@ -1734,14 +1798,14 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
17341798
pid = -1;
17351799
}
17361800
else {
1737-
pid = mingw_spawnve_fd(iprog, argv, deltaenv, dir, 1,
1801+
pid = mingw_spawnve_fd(iprog, argv, deltaenv, dir, interpr,
17381802
fhin, fhout, fherr);
17391803
free(iprog);
17401804
}
17411805
argv[0] = argv0;
17421806
}
17431807
else
1744-
pid = mingw_spawnve_fd(prog, argv, deltaenv, dir, 0,
1808+
pid = mingw_spawnve_fd(prog, argv, deltaenv, dir, NULL,
17451809
fhin, fhout, fherr);
17461810
free(prog);
17471811
}
@@ -1767,7 +1831,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
17671831
ALLOC_ARRAY(argv2, argc + 1);
17681832
argv2[0] = (char *)cmd; /* full path to the script file */
17691833
memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
1770-
pid = mingw_spawnv(prog, argv2, 1);
1834+
pid = mingw_spawnv(prog, argv2, interpr);
17711835
if (pid >= 0) {
17721836
int status;
17731837
if (waitpid(pid, &status, 0) < 0)
@@ -1787,7 +1851,7 @@ int mingw_execv(const char *cmd, char *const *argv)
17871851
if (!try_shell_exec(cmd, argv)) {
17881852
int pid, status;
17891853

1790-
pid = mingw_spawnv(cmd, (const char **)argv, 0);
1854+
pid = mingw_spawnv(cmd, (const char **)argv, NULL);
17911855
if (pid < 0)
17921856
return -1;
17931857
if (waitpid(pid, &status, 0) < 0)

config.mak.uname

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,72 @@ else
685685
NO_CURL = YesPlease
686686
endif
687687
endif
688+
ifeq (i686,$(uname_M))
689+
MINGW_PREFIX := mingw32
690+
endif
691+
ifeq (x86_64,$(uname_M))
692+
MINGW_PREFIX := mingw64
693+
endif
694+
695+
DESTDIR_WINDOWS = $(shell cygpath -aw '$(DESTDIR_SQ)')
696+
DESTDIR_MIXED = $(shell cygpath -am '$(DESTDIR_SQ)')
697+
install-mingit-test-artifacts:
698+
install -m755 -d '$(DESTDIR_SQ)/usr/bin'
699+
printf '%s\n%s\n' >'$(DESTDIR_SQ)/usr/bin/perl' \
700+
"#!/mingw64/bin/busybox sh" \
701+
"exec \"$(shell cygpath -am /usr/bin/perl.exe)\" \"\$$@\""
702+
703+
install -m755 -d '$(DESTDIR_SQ)'
704+
printf '%s%s\n%s\n%s\n%s\n%s\n' >'$(DESTDIR_SQ)/init.bat' \
705+
"PATH=$(DESTDIR_WINDOWS)\\$(MINGW_PREFIX)\\bin;" \
706+
"C:\\WINDOWS;C:\\WINDOWS\\system32" \
707+
"@set GIT_TEST_INSTALLED=$(DESTDIR_MIXED)/$(MINGW_PREFIX)/bin" \
708+
"@`echo "$(DESTDIR_WINDOWS)" | sed 's/:.*/:/'`" \
709+
"@cd `echo "$(DESTDIR_WINDOWS)" | sed 's/^.://'`\\test-git\\t" \
710+
"@echo Now, run 'helper\\test-run-command testsuite'"
711+
712+
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
713+
install -m755 git.exe git-credential-store.exe git-fast-import.exe \
714+
git-http-fetch.exe git-http-push.exe git-receive-pack.exe \
715+
git-remote-http.exe git-remote-https.exe \
716+
git-sh-i18n--envsubst.exe git-show-index.exe \
717+
git-upload-pack.exe '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
718+
719+
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/libexec/git-core'
720+
cp git-bisect git-difftool--helper git-filter-branch git-instaweb \
721+
git-merge-octopus git-merge-one-file git-merge-resolve \
722+
git-mergetool git-mergetool--lib git-parse-remote \
723+
git-quiltimport git-rebase git-rebase--am \
724+
git-rebase--interactive git-rebase--merge git-request-pull \
725+
git-sh-i18n git-sh-setup git-stash git-submodule \
726+
git-web--browse '$(DESTDIR_SQ)/$(MINGW_PREFIX)/libexec/git-core'
727+
728+
install -m755 -d '$(DESTDIR_SQ)/test-git'
729+
sed 's/^\(NO_PERL\|NO_PYTHON\)=.*/\1=YesPlease/' \
730+
<GIT-BUILD-OPTIONS >'$(DESTDIR_SQ)/test-git/GIT-BUILD-OPTIONS'
731+
732+
install -m755 -d '$(DESTDIR_SQ)/test-git/t/helper'
733+
install -m755 $(TEST_PROGRAMS) '$(DESTDIR_SQ)/test-git/t/helper'
734+
(cd t && $(TAR) cf - t[0-9][0-9][0-9][0-9] diff-lib) | \
735+
(cd '$(DESTDIR_SQ)/test-git/t' && $(TAR) xf -)
736+
install -m755 t/t556x_common t/*.sh '$(DESTDIR_SQ)/test-git/t'
737+
738+
install -m755 -d '$(DESTDIR_SQ)/test-git/templates'
739+
(cd templates && $(TAR) cf - blt) | \
740+
(cd '$(DESTDIR_SQ)/test-git/templates' && $(TAR) xf -)
741+
742+
# po/build/locale for t0200
743+
install -m755 -d '$(DESTDIR_SQ)/test-git/po/build/locale'
744+
(cd po/build/locale && $(TAR) cf - .) | \
745+
(cd '$(DESTDIR_SQ)/test-git/po/build/locale' && $(TAR) xf -)
746+
747+
# git-daemon.exe for t5802, git-http-backend.exe for t5560
748+
install -m755 git-daemon.exe git-http-backend.exe \
749+
'$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
750+
751+
# git-remote-testgit for t5801
752+
install -m755 git-remote-testgit \
753+
'$(DESTDIR_SQ)/$(MINGW_PREFIX)/libexec/git-core'
688754
endif
689755
ifeq ($(uname_S),QNX)
690756
COMPAT_CFLAGS += -DSA_RESTART=0

git-sh-setup.sh

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -332,17 +332,30 @@ create_virtual_base() {
332332
# Platform specific tweaks to work around some commands
333333
case $(uname -s) in
334334
*MINGW*)
335-
# Windows has its own (incompatible) sort and find
336-
sort () {
337-
/usr/bin/sort "$@"
338-
}
339-
find () {
340-
/usr/bin/find "$@"
341-
}
342-
# git sees Windows-style pwd
343-
pwd () {
344-
builtin pwd -W
345-
}
335+
if test -x /usr/bin/sort
336+
then
337+
# Windows has its own (incompatible) sort; override
338+
sort () {
339+
/usr/bin/sort "$@"
340+
}
341+
fi
342+
if test -x /usr/bin/find
343+
then
344+
# Windows has its own (incompatible) find; override
345+
find () {
346+
/usr/bin/find "$@"
347+
}
348+
fi
349+
# On Windows, Git wants Windows paths. But /usr/bin/pwd spits out
350+
# Unix-style paths. At least in Bash, we have a builtin pwd that
351+
# understands the -W option to force "mixed" paths, i.e. with drive
352+
# prefix but still with forward slashes. Let's use that, if available.
353+
if type builtin >/dev/null 2>&1
354+
then
355+
pwd () {
356+
builtin pwd -W
357+
}
358+
fi
346359
is_absolute_path () {
347360
case "$1" in
348361
[/\\]* | [A-Za-z]:*)

t/.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
t[0-9][0-9][0-9][0-9]/* -whitespace
22
/diff-lib/* eol=lf
3+
/diff-lib/*.png binary
34
/t0110/url-* binary
45
/t3900/*.txt eol=lf
56
/t3901/*.txt eol=lf
File renamed without changes.
File renamed without changes.

t/helper/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
/test-scrap-cache-tree
1111
/test-genrandom
1212
/test-hashmap
13+
/test-helper
1314
/test-index-version
1415
/test-lazy-init-name-hash
1516
/test-line-buffer

0 commit comments

Comments
 (0)