diff --git a/compat/mingw.c b/compat/mingw.c index ef4556fe32..5f68d11830 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1066,6 +1066,16 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen free(quoted); } + if (getenv("GIT_STRACE_COMMANDS")) { + char **path = get_path_split(); + cmd = path_lookup("strace.exe", path, 1); + if (!cmd) + return error("strace not found!"); + if (xutftowcs_path(wcmd, cmd) < 0) + return -1; + strbuf_insert(&args, 0, "strace ", 7); + } + wargs = xmalloc((2 * args.len + 1) * sizeof(wchar_t)); xutftowcs(wargs, args.buf, 2 * args.len + 1); strbuf_release(&args); @@ -1639,7 +1649,12 @@ repeat: if (gle == ERROR_ACCESS_DENIED && (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) { if (attrs & FILE_ATTRIBUTE_DIRECTORY) { - errno = EISDIR; + DWORD attrsold = GetFileAttributesW(wpold); + if (attrsold == INVALID_FILE_ATTRIBUTES || + !(attrsold & FILE_ATTRIBUTE_DIRECTORY)) + errno = EISDIR; + else if (!_wrmdir(wpnew)) + goto repeat; return -1; } if ((attrs & FILE_ATTRIBUTE_READONLY) && @@ -2148,8 +2163,26 @@ void mingw_startup() __argv[0] = wcstoutfdup_startup(buffer, _wpgmptr, maxlen); for (i = 1; i < argc; i++) __argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen); - for (i = 0; wenv[i]; i++) + for (i = 0; wenv[i]; i++) { environ[i] = wcstoutfdup_startup(buffer, wenv[i], maxlen); + if (!strncasecmp(environ[i], "MSYS2_TZ=", 9)) { + char *to_free = environ[i]; + environ[i] = xstrdup(to_free + 6); + free(to_free); + } + if (!strncasecmp(environ[i], "TMP=", 4)) { + /* + * Convert all dir separators to forward slashes, + * to help shell commands called from the Git + * executable (by not mistaking the dir separators + * for escape characters. + */ + char *p; + for (p = environ[i]; *p; p++) + if (*p == '\\') + *p = '/'; + } + } environ[i] = NULL; free(buffer); diff --git a/compat/mingw.h b/compat/mingw.h index 5e499cfb71..629b5ec9ce 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -1,27 +1,34 @@ +#include +#include +#include +#ifndef _POSIX +typedef _sigset_t sigset_t; +#endif #include #include - /* * things that are not available in header files */ -typedef int pid_t; typedef int uid_t; typedef int socklen_t; -#define hstrerror strerror #define S_IFLNK 0120000 /* Symbolic link */ #define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK) #define S_ISSOCK(x) 0 +#ifndef S_IRWXG #define S_IRGRP 0 #define S_IWGRP 0 #define S_IXGRP 0 #define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP) +#endif +#ifndef S_IRWXO #define S_IROTH 0 #define S_IWOTH 0 #define S_IXOTH 0 #define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH) +#endif #define S_ISUID 0004000 #define S_ISGID 0002000 @@ -164,8 +171,10 @@ int pipe(int filedes[2]); unsigned int sleep (unsigned int seconds); int mkstemp(char *template); int gettimeofday(struct timeval *tv, void *tz); +#ifndef __MINGW64_VERSION_MAJOR struct tm *gmtime_r(const time_t *timep, struct tm *result); struct tm *localtime_r(const time_t *timep, struct tm *result); +#endif int getpagesize(void); /* defined in MinGW's libgcc.a */ struct passwd *getpwuid(uid_t uid); int setitimer(int type, struct itimerval *in, struct itimerval *out); @@ -213,6 +222,10 @@ char *mingw_mktemp(char *template); char *mingw_getcwd(char *pointer, int len); #define getcwd mingw_getcwd +#ifdef NO_UNSETENV +#error "NO_UNSETENV is incompatible with the MinGW startup code!" +#endif + char *mingw_getenv(const char *name); #define getenv mingw_getenv int mingw_putenv(const char *namevalue); @@ -285,8 +298,10 @@ static inline int getrlimit(int resource, struct rlimit *rlp) /* * Use mingw specific stat()/lstat()/fstat() implementations on Windows. */ +#ifndef __MINGW64_VERSION_MAJOR #define off_t off64_t #define lseek _lseeki64 +#endif /* use struct stat with 64 bit st_size */ #ifdef stat diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h index 8ad187344f..1ade961769 100644 --- a/compat/win32/pthread.h +++ b/compat/win32/pthread.h @@ -77,7 +77,7 @@ extern pthread_t pthread_self(void); static inline int pthread_exit(void *ret) { - ExitThread((DWORD)ret); + ExitThread((DWORD)(size_t)ret); } typedef DWORD pthread_key_t; diff --git a/compat/winansi.c b/compat/winansi.c index efc5bb3a4b..aac430a952 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -23,6 +23,7 @@ static HANDLE hthread, hread, hwrite; static HANDLE hconsole1, hconsole2; #ifdef __MINGW32__ +#if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 5 typedef struct _CONSOLE_FONT_INFOEX { ULONG cbSize; DWORD nFont; @@ -32,6 +33,7 @@ typedef struct _CONSOLE_FONT_INFOEX { WCHAR FaceName[LF_FACESIZE]; } CONSOLE_FONT_INFOEX, *PCONSOLE_FONT_INFOEX; #endif +#endif typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL, PCONSOLE_FONT_INFOEX); diff --git a/config.mak.uname b/config.mak.uname index b64b63c34c..00d0529ec7 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -495,7 +495,6 @@ ifneq (,$(findstring MINGW,$(uname_S))) NO_MKDTEMP = YesPlease NO_MKSTEMPS = YesPlease NO_SVN_TESTS = YesPlease - NO_PERL_MAKEMAKER = YesPlease RUNTIME_PREFIX = YesPlease NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease NO_NSEC = YesPlease @@ -512,13 +511,12 @@ ifneq (,$(findstring MINGW,$(uname_S))) NO_POSIX_GOODIES = UnfortunatelyYes DEFAULT_HELP_FORMAT = html NO_D_INO_IN_DIRENT = YesPlease - COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -D_USE_32BIT_TIME_T -DNOGDI -Icompat -Icompat/win32 + COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" COMPAT_OBJS += compat/mingw.o compat/winansi.o \ compat/win32/pthread.o compat/win32/syslog.o \ compat/win32/dirent.o BASIC_CFLAGS += -DPROTECT_NTFS_DEFAULT=1 - BASIC_LDFLAGS += -Wl,--large-address-aware EXTLIBS += -lws2_32 GITLIBS += git.res PTHREAD_LIBS = @@ -527,7 +525,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) X = .exe SPARSE_FLAGS = -Wno-one-bit-signed-bitfield ifneq (,$(wildcard ../THIS_IS_MSYSGIT)) - htmldir = doc/git/html/ + htmldir = share/doc/git/$(firstword $(subst -, ,$(GIT_VERSION)))/html prefix = INSTALL = /bin/install EXTLIBS += /mingw/lib/libz.a @@ -536,7 +534,33 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT)) HAVE_LIBCHARSET_H = YesPlease NO_GETTEXT = YesPlease else - NO_CURL = YesPlease + ifeq ($(shell expr "$(uname_R)" : '2\.'),2) + # MSys2 + prefix = /usr/ + ifeq (MINGW32,$(MSYSTEM)) + prefix = /mingw32/ + endif + ifeq (MINGW64,$(MSYSTEM)) + prefix = /mingw64/ + else + COMPAT_CFLAGS += -D_USE_32BIT_TIME_T + BASIC_LDFLAGS += -Wl,--large-address-aware + endif + CC = gcc + htmldir = share/doc/git/$(firstword $(subst -, ,$(GIT_VERSION)))/html + INSTALL = /bin/install + NO_R_TO_GCC_LINKER = YesPlease + INTERNAL_QSORT = YesPlease + HAVE_LIBCHARSET_H = YesPlease + NO_GETTEXT = + USE_GETTEXT_SCHEME = fallthrough + USE_LIBPCRE= YesPlease + NO_CURL = + USE_NED_ALLOCATOR = + NO_PYTHON = + else + NO_CURL = YesPlease + endif endif endif ifeq ($(uname_S),QNX) diff --git a/http.c b/http.c index 0153fb0b62..d50ead0088 100644 --- a/http.c +++ b/http.c @@ -8,6 +8,7 @@ #include "credential.h" #include "version.h" #include "pkt-line.h" +#include "exec_cmd.h" int active_requests; int http_is_verbose; @@ -180,6 +181,18 @@ static void process_curl_messages(void) } #endif +static int git_config_path(const char **result, + const char *var, const char *value) +{ + if (git_config_string(result, var, value)) + return 1; +#ifdef __MINGW32__ + if (**result == '/') + *result = system_path((*result) + 1); +#endif + return 0; +} + static int http_options(const char *var, const char *value, void *cb) { if (!strcmp("http.sslverify", var)) { @@ -187,17 +200,17 @@ static int http_options(const char *var, const char *value, void *cb) return 0; } if (!strcmp("http.sslcert", var)) - return git_config_string(&ssl_cert, var, value); + return git_config_path(&ssl_cert, var, value); #if LIBCURL_VERSION_NUM >= 0x070903 if (!strcmp("http.sslkey", var)) - return git_config_string(&ssl_key, var, value); + return git_config_path(&ssl_key, var, value); #endif #if LIBCURL_VERSION_NUM >= 0x070908 if (!strcmp("http.sslcapath", var)) - return git_config_string(&ssl_capath, var, value); + return git_config_path(&ssl_capath, var, value); #endif if (!strcmp("http.sslcainfo", var)) - return git_config_string(&ssl_cainfo, var, value); + return git_config_path(&ssl_cainfo, var, value); if (!strcmp("http.sslcertpasswordprotected", var)) { ssl_cert_password_required = git_config_bool(var, value); return 0; diff --git a/perl/Git.pm b/perl/Git.pm index 9026a7bb98..d1e4c48202 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -188,7 +188,8 @@ sub repository { }; if ($dir) { - $dir =~ m#^/# or $dir = $opts{Directory} . '/' . $dir; + _verify_require(); + File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir; $opts{Repository} = abs_path($dir); # If --git-dir went ok, this shouldn't die either. diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index 9a146f1335..04de03cad0 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -13,6 +13,7 @@ tree, index, and tree objects. HT=' ' +test_have_prereq MINGW || echo 2>/dev/null > "Name with an${HT}HT" if ! test -f "Name with an${HT}HT" then diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index e00d7d2b61..83b1df9e3c 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -14,7 +14,8 @@ test_expect_success \ git add -- foo bar baz 'space embedded' -q && git commit -m 'add normal files'" -if touch -- 'tab embedded' 'newline + +if ! test_have_prereq MINGW && touch -- 'tab embedded' 'newline embedded' 2>/dev/null then test_set_prereq FUNNYNAMES diff --git a/t/t3703-add-magic-pathspec.sh b/t/t3703-add-magic-pathspec.sh index 5115de7036..aaff784659 100755 --- a/t/t3703-add-magic-pathspec.sh +++ b/t/t3703-add-magic-pathspec.sh @@ -38,7 +38,7 @@ cat >expected </dev/null +if ! test_have_prereq MINGW && mkdir ":" 2>/dev/null then test_set_prereq COLON_DIR fi diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh index 892f567844..f528008c36 100755 --- a/t/t3902-quoted.sh +++ b/t/t3902-quoted.sh @@ -12,6 +12,7 @@ GN='純' HT=' ' DQ='"' +test_have_prereq MINGW || echo foo 2>/dev/null > "Name and an${HT}HT" if ! test -f "Name and an${HT}HT" then diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh index cd543ecc54..9c48e5c2c9 100755 --- a/t/t4016-diff-quote.sh +++ b/t/t4016-diff-quote.sh @@ -13,6 +13,7 @@ P1='pathname with HT' P2='pathname with SP' P3='pathname with LF' +test_have_prereq !MINGW && echo 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || { skip_all='Your filesystem does not allow tabs in filenames' test_done diff --git a/t/t4135-apply-weird-filenames.sh b/t/t4135-apply-weird-filenames.sh index bf5dc57286..6d6b96d5d3 100755 --- a/t/t4135-apply-weird-filenames.sh +++ b/t/t4135-apply-weird-filenames.sh @@ -19,7 +19,8 @@ test_expect_success 'setup' ' test_when_finished "rm -f \"tab embedded.txt\"" && test_when_finished "rm -f '\''\"quoteembedded\".txt'\''" && - if touch -- "tab embedded.txt" '\''"quoteembedded".txt'\'' + if ! test_have_prereq MINGW && + touch -- "tab embedded.txt" '\''"quoteembedded".txt'\'' then test_set_prereq FUNNYNAMES fi diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index e4436c1700..c9a6617237 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -16,6 +16,14 @@ This test checks the following functionality: . ./test-lib.sh +if test_have_prereq MINGW +then + # Avoid posix-to-windows path mangling + pwd () { + builtin pwd + } +fi + D=`pwd` mk_empty () { diff --git a/t/t9700/test.pl b/t/t9700/test.pl index 1140767b50..a01665473d 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -33,7 +33,9 @@ is($r->config_int("test.int"), 2048, "config_int: integer"); is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent"); ok($r->config_bool("test.booltrue"), "config_bool: true"); ok(!$r->config_bool("test.boolfalse"), "config_bool: false"); -is($r->config_path("test.path"), $r->config("test.pathexpanded"), +our $test_path = $r->config_path("test.path"); +$test_path =~ s/\\/\//g if ($^O eq 'msys'); +is($test_path, $r->config("test.pathexpanded"), "config_path: ~/foo expansion"); is_deeply([$r->config_path("test.pathmulti")], ["foo", "bar"], "config_path: multiple values"); diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index 51ecd3e4c1..c5bf838e9c 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -67,7 +67,7 @@ repo_with_newline='repo with newline' -if mkdir "$repo_with_newline" 2>/dev/null +if ! test_have_prereq MINGW && mkdir "$repo_with_newline" 2>/dev/null then test_set_prereq FUNNYNAMES else diff --git a/t/test-lib.sh b/t/test-lib.sh index c09677802c..4eb3ffc7fa 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -506,6 +506,20 @@ test_eval_ () { # # The test itself is run with stderr put back to &4 (so either to # /dev/null, or to the original stderr if --verbose was used). + if test -n "$TEST_NO_REDIRECT" + then + test_eval_inner_ "$@" + test_eval_ret_=$? + if test "$trace" = t + then + set +x + if test "$test_eval_ret_" != 0 + then + say_color error >&4 "error: last command exited with \$?=$test_eval_ret_" + fi + fi + return $test_eval_ret_ + fi { test_eval_inner_ "$@" &3 2>&4 test_eval_ret_=$? @@ -980,7 +994,7 @@ test_i18ngrep () { test_lazy_prereq PIPE ' # test whether the filesystem supports FIFOs case $(uname -s) in - CYGWIN*) + CYGWIN*|MINGW*) false ;; *)