Skip to content

Commit

Permalink
Merge branch 'busybox-w32'
Browse files Browse the repository at this point in the history
Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
dscho authored and Git for Windows Build Agent committed Dec 17, 2024
2 parents 4c0b33d + 0b6ef64 commit cd3cc78
Show file tree
Hide file tree
Showing 41 changed files with 368 additions and 121 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*.pm text eol=lf diff=perl
*.py text eol=lf diff=python
*.bat text eol=crlf
*.png binary
CODE_OF_CONDUCT.md -whitespace
/Documentation/**/*.txt text eol=lf
/command-list.txt text eol=lf
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ TEST_BUILTINS_OBJS += test-hash-speed.o
TEST_BUILTINS_OBJS += test-hash.o
TEST_BUILTINS_OBJS += test-hashmap.o
TEST_BUILTINS_OBJS += test-hexdump.o
TEST_BUILTINS_OBJS += test-iconv.o
TEST_BUILTINS_OBJS += test-json-writer.o
TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o
TEST_BUILTINS_OBJS += test-match-trees.o
Expand Down
82 changes: 73 additions & 9 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "../repository.h"
#include "win32/fscache.h"
#include "../attr.h"
#include "../string-list.h"

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

Expand Down Expand Up @@ -1734,6 +1735,65 @@ static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
return NULL;
}

static char *path_lookup(const char *cmd, int exe_only);

static char *is_busybox_applet(const char *cmd)
{
static struct string_list applets = STRING_LIST_INIT_DUP;
static char *busybox_path;
static int busybox_path_initialized;

/* Avoid infinite loop */
if (!strncasecmp(cmd, "busybox", 7) &&
(!cmd[7] || !strcasecmp(cmd + 7, ".exe")))
return NULL;

if (!busybox_path_initialized) {
busybox_path = path_lookup("busybox.exe", 1);
busybox_path_initialized = 1;
}

/* Assume that sh is compiled in... */
if (!busybox_path || !strcasecmp(cmd, "sh"))
return xstrdup_or_null(busybox_path);

if (!applets.nr) {
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf buf = STRBUF_INIT;
char *p;

strvec_pushl(&cp.args, busybox_path, "--help", NULL);

if (capture_command(&cp, &buf, 2048)) {
string_list_append(&applets, "");
return NULL;
}

/* parse output */
p = strstr(buf.buf, "Currently defined functions:\n");
if (!p) {
warning("Could not parse output of busybox --help");
string_list_append(&applets, "");
return NULL;
}
p = strchrnul(p, '\n');
for (;;) {
size_t len;

p += strspn(p, "\n\t ,");
len = strcspn(p, "\n\t ,");
if (!len)
break;
p[len] = '\0';
string_list_insert(&applets, p);
p = p + len + 1;
}
}

return string_list_has_string(&applets, cmd) ?
xstrdup(busybox_path) : NULL;
}

/*
* Determines the absolute path of cmd using the split path in path.
* If cmd contains a slash or backslash, no lookup is performed.
Expand Down Expand Up @@ -1762,6 +1822,9 @@ static char *path_lookup(const char *cmd, int exe_only)
path = sep + 1;
}

if (!prog && !isexe)
prog = is_busybox_applet(cmd);

return prog;
}

Expand Down Expand Up @@ -1965,8 +2028,8 @@ static int is_msys2_sh(const char *cmd)
}

static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaenv,
const char *dir,
int prepend_cmd, int fhin, int fhout, int fherr)
const char *dir, const char *prepend_cmd,
int fhin, int fhout, int fherr)
{
static int restrict_handle_inheritance = -1;
STARTUPINFOEXW si;
Expand Down Expand Up @@ -2057,9 +2120,9 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
/* concatenate argv, quoting args as we go */
strbuf_init(&args, 0);
if (prepend_cmd) {
char *quoted = (char *)quote_arg(cmd);
char *quoted = (char *)quote_arg(prepend_cmd);
strbuf_addstr(&args, quoted);
if (quoted != cmd)
if (quoted != prepend_cmd)
free(quoted);
}
for (; *argv; argv++) {
Expand Down Expand Up @@ -2218,7 +2281,8 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
return (pid_t)pi.dwProcessId;
}

static pid_t mingw_spawnv(const char *cmd, const char **argv, int prepend_cmd)
static pid_t mingw_spawnv(const char *cmd, const char **argv,
const char *prepend_cmd)
{
return mingw_spawnve_fd(cmd, argv, NULL, NULL, prepend_cmd, 0, 1, 2);
}
Expand Down Expand Up @@ -2246,14 +2310,14 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
pid = -1;
}
else {
pid = mingw_spawnve_fd(iprog, argv, deltaenv, dir, 1,
pid = mingw_spawnve_fd(iprog, argv, deltaenv, dir, interpr,
fhin, fhout, fherr);
free(iprog);
}
argv[0] = argv0;
}
else
pid = mingw_spawnve_fd(prog, argv, deltaenv, dir, 0,
pid = mingw_spawnve_fd(prog, argv, deltaenv, dir, NULL,
fhin, fhout, fherr);
free(prog);
}
Expand All @@ -2278,7 +2342,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
argv2[0] = (char *)cmd; /* full path to the script file */
COPY_ARRAY(&argv2[1], &argv[1], argc);
exec_id = trace2_exec(prog, (const char **)argv2);
pid = mingw_spawnv(prog, (const char **)argv2, 1);
pid = mingw_spawnv(prog, (const char **)argv2, interpr);
if (pid >= 0) {
int status;
if (waitpid(pid, &status, 0) < 0)
Expand All @@ -2302,7 +2366,7 @@ int mingw_execv(const char *cmd, char *const *argv)
int exec_id;

exec_id = trace2_exec(cmd, (const char **)argv);
pid = mingw_spawnv(cmd, (const char **)argv, 0);
pid = mingw_spawnv(cmd, (const char **)argv, NULL);
if (pid < 0) {
trace2_exec_result(exec_id, -1);
return -1;
Expand Down
56 changes: 56 additions & 0 deletions config.mak.uname
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,62 @@ ifeq ($(uname_S),MINGW)
ETC_GITCONFIG = ../etc/gitconfig
ETC_GITATTRIBUTES = ../etc/gitattributes
endif
ifeq (i686,$(uname_M))
MINGW_PREFIX := mingw32
endif
ifeq (x86_64,$(uname_M))
MINGW_PREFIX := mingw64
endif

DESTDIR_WINDOWS = $(shell cygpath -aw '$(DESTDIR_SQ)')
DESTDIR_MIXED = $(shell cygpath -am '$(DESTDIR_SQ)')
install-mingit-test-artifacts:
install -m755 -d '$(DESTDIR_SQ)/usr/bin'
printf '%s\n%s\n' >'$(DESTDIR_SQ)/usr/bin/perl' \
"#!/mingw64/bin/busybox sh" \
"exec \"$(shell cygpath -am /usr/bin/perl.exe)\" \"\$$@\""

install -m755 -d '$(DESTDIR_SQ)'
printf '%s%s\n%s\n%s\n%s\n%s\n' >'$(DESTDIR_SQ)/init.bat' \
"PATH=$(DESTDIR_WINDOWS)\\$(MINGW_PREFIX)\\bin;" \
"C:\\WINDOWS;C:\\WINDOWS\\system32" \
"@set GIT_TEST_INSTALLED=$(DESTDIR_MIXED)/$(MINGW_PREFIX)/bin" \
"@`echo "$(DESTDIR_WINDOWS)" | sed 's/:.*/:/'`" \
"@cd `echo "$(DESTDIR_WINDOWS)" | sed 's/^.://'`\\test-git\\t" \
"@echo Now, run 'helper\\test-run-command testsuite'"

install -m755 -d '$(DESTDIR_SQ)/test-git'
sed 's/^\(NO_PERL\|NO_PYTHON\)=.*/\1=YesPlease/' \
<GIT-BUILD-OPTIONS >'$(DESTDIR_SQ)/test-git/GIT-BUILD-OPTIONS'

install -m755 -d '$(DESTDIR_SQ)/test-git/t/helper'
install -m755 $(TEST_PROGRAMS) '$(DESTDIR_SQ)/test-git/t/helper'
(cd t && $(TAR) cf - t[0-9][0-9][0-9][0-9] lib-diff) | \
(cd '$(DESTDIR_SQ)/test-git/t' && $(TAR) xf -)
install -m755 t/t556x_common t/*.sh '$(DESTDIR_SQ)/test-git/t'

install -m755 -d '$(DESTDIR_SQ)/test-git/templates'
(cd templates && $(TAR) cf - blt) | \
(cd '$(DESTDIR_SQ)/test-git/templates' && $(TAR) xf -)

# po/build/locale for t0200
install -m755 -d '$(DESTDIR_SQ)/test-git/po/build/locale'
(cd po/build/locale && $(TAR) cf - .) | \
(cd '$(DESTDIR_SQ)/test-git/po/build/locale' && $(TAR) xf -)

# git-daemon.exe for t5802, git-http-backend.exe for t5560
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
install -m755 git-daemon.exe git-http-backend.exe \
'$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'

# git-upload-archive (dashed) for t5000
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'
install -m755 git-upload-archive.exe '$(DESTDIR_SQ)/$(MINGW_PREFIX)/bin'

# git-difftool--helper for t7800
install -m755 -d '$(DESTDIR_SQ)/$(MINGW_PREFIX)/libexec/git-core'
install -m755 git-difftool--helper \
'$(DESTDIR_SQ)/$(MINGW_PREFIX)/libexec/git-core'
endif
ifeq ($(uname_S),QNX)
COMPAT_CFLAGS += -DSA_RESTART=0
Expand Down
35 changes: 24 additions & 11 deletions git-sh-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -292,17 +292,30 @@ create_virtual_base() {
# Platform specific tweaks to work around some commands
case $(uname -s) in
*MINGW*)
# Windows has its own (incompatible) sort and find
sort () {
/usr/bin/sort "$@"
}
find () {
/usr/bin/find "$@"
}
# git sees Windows-style pwd
pwd () {
builtin pwd -W
}
if test -x /usr/bin/sort
then
# Windows has its own (incompatible) sort; override
sort () {
/usr/bin/sort "$@"
}
fi
if test -x /usr/bin/find
then
# Windows has its own (incompatible) find; override
find () {
/usr/bin/find "$@"
}
fi
# On Windows, Git wants Windows paths. But /usr/bin/pwd spits out
# Unix-style paths. At least in Bash, we have a builtin pwd that
# understands the -W option to force "mixed" paths, i.e. with drive
# prefix but still with forward slashes. Let's use that, if available.
if type builtin >/dev/null 2>&1
then
pwd () {
builtin pwd -W
}
fi
is_absolute_path () {
case "$1" in
[/\\]* | [A-Za-z]:*)
Expand Down
47 changes: 47 additions & 0 deletions t/helper/test-iconv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "test-tool.h"
#include "git-compat-util.h"
#include "strbuf.h"
#include "gettext.h"
#include "parse-options.h"
#include "utf8.h"

int cmd__iconv(int argc, const char **argv)
{
struct strbuf buf = STRBUF_INIT;
char *from = NULL, *to = NULL, *p;
size_t len;
int ret = 0;
const char * const iconv_usage[] = {
N_("test-helper --iconv [<options>]"),
NULL
};
struct option options[] = {
OPT_STRING('f', "from-code", &from, "encoding", "from"),
OPT_STRING('t', "to-code", &to, "encoding", "to"),
OPT_END()
};

argc = parse_options(argc, argv, NULL, options,
iconv_usage, 0);

if (argc > 1 || !from || !to)
usage_with_options(iconv_usage, options);

if (!argc) {
if (strbuf_read(&buf, 0, 2048) < 0)
die_errno("Could not read from stdin");
} else if (strbuf_read_file(&buf, argv[0], 2048) < 0)
die_errno("Could not read from '%s'", argv[0]);

p = reencode_string_len(buf.buf, buf.len, to, from, &len);
if (!p)
die_errno("Could not reencode");
if (write(1, p, len) < 0)
ret = !!error_errno("Could not write %"PRIuMAX" bytes",
(uintmax_t)len);

strbuf_release(&buf);
free(p);

return ret;
}
1 change: 1 addition & 0 deletions t/helper/test-tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static struct test_cmd cmds[] = {
{ "hashmap", cmd__hashmap },
{ "hash-speed", cmd__hash_speed },
{ "hexdump", cmd__hexdump },
{ "iconv", cmd__iconv },
{ "json-writer", cmd__json_writer },
{ "lazy-init-name-hash", cmd__lazy_init_name_hash },
{ "match-trees", cmd__match_trees },
Expand Down
1 change: 1 addition & 0 deletions t/helper/test-tool.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ int cmd__getcwd(int argc, const char **argv);
int cmd__hashmap(int argc, const char **argv);
int cmd__hash_speed(int argc, const char **argv);
int cmd__hexdump(int argc, const char **argv);
int cmd__iconv(int argc, const char **argv);
int cmd__json_writer(int argc, const char **argv);
int cmd__lazy_init_name_hash(int argc, const char **argv);
int cmd__match_trees(int argc, const char **argv);
Expand Down
8 changes: 6 additions & 2 deletions t/interop/interop-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
. ../../GIT-BUILD-OPTIONS
INTEROP_ROOT=$(pwd)
BUILD_ROOT=$INTEROP_ROOT/build
case "$PATH" in
*\;*) PATH_SEP=\; ;;
*) PATH_SEP=: ;;
esac

build_version () {
if test -z "$1"
Expand Down Expand Up @@ -57,7 +61,7 @@ wrap_git () {
write_script "$1" <<-EOF
GIT_EXEC_PATH="$2"
export GIT_EXEC_PATH
PATH="$2:\$PATH"
PATH="$2$PATH_SEP\$PATH"
export GIT_EXEC_PATH
exec git "\$@"
EOF
Expand All @@ -71,7 +75,7 @@ generate_wrappers () {
echo >&2 fatal: test tried to run generic git: $*
exit 1
EOF
PATH=$(pwd)/.bin:$PATH
PATH=$(pwd)/.bin$PATH_SEP$PATH
}

VERSION_A=${GIT_TEST_VERSION_A:-$VERSION_A}
Expand Down
File renamed without changes
File renamed without changes
2 changes: 1 addition & 1 deletion t/lib-proto-disable.sh
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ setup_ext_wrapper () {
cd "$TRASH_DIRECTORY/remote" &&
eval "$*"
EOF
PATH=$TRASH_DIRECTORY:$PATH &&
PATH=$TRASH_DIRECTORY$PATH_SEP$PATH &&
export TRASH_DIRECTORY
'
}
2 changes: 1 addition & 1 deletion t/t0014-alias.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ test_expect_success 'looping aliases - internal execution' '

test_expect_success 'run-command formats empty args properly' '
test_must_fail env GIT_TRACE=1 git frotz a "" b " " c 2>actual.raw &&
sed -ne "/run_command:/s/.*trace: run_command: //p" actual.raw >actual &&
sed -ne "/run_command: git-frotz/s/.*trace: run_command: //p" actual.raw >actual &&
echo "git-frotz a '\'''\'' b '\'' '\'' c" >expect &&
test_cmp expect actual
'
Expand Down
2 changes: 1 addition & 1 deletion t/t0021-conversion.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh

PATH=$PWD:$PATH
PATH=$PWD$PATH_SEP$PATH
TEST_ROOT="$(pwd)"

write_script <<\EOF "$TEST_ROOT/rot13.sh"
Expand Down
Loading

0 comments on commit cd3cc78

Please sign in to comment.