diff --git a/Documentation/config.txt b/Documentation/config.txt
index ef0768b91a..01cc9c0d32 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -432,6 +432,8 @@ include::config/reset.txt[]
include::config/sendemail.txt[]
+include::config/sendpack.txt[]
+
include::config/sequencer.txt[]
include::config/showbranch.txt[]
diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt
index 3968fbb697..4d7fef1ba1 100644
--- a/Documentation/config/http.txt
+++ b/Documentation/config/http.txt
@@ -173,11 +173,13 @@ http.sslBackend::
http.schannelCheckRevoke::
Used to enforce or disable certificate revocation checks in cURL
- when http.sslBackend is set to "schannel". Defaults to `true` if
- unset. Only necessary to disable this if Git consistently errors
- and the message is about checking the revocation status of a
- certificate. This option is ignored if cURL lacks support for
- setting the relevant SSL option at runtime.
+ when http.sslBackend is set to "schannel" via "true" and "false",
+ respectively. Another accepted value is "best-effort" (the default)
+ in which case revocation checks are performed, but errors due to
+ revocation list distribution points that are offline are silently
+ ignored, as well as errors due to certificates missing revocation
+ list distribution points. This option is ignored if cURL lacks
+ support for setting the relevant SSL option at runtime.
http.schannelUseSSLCAInfo::
As of cURL v7.60.0, the Secure Channel backend can use the
diff --git a/Documentation/config/sendpack.txt b/Documentation/config/sendpack.txt
new file mode 100644
index 0000000000..e306f657fb
--- /dev/null
+++ b/Documentation/config/sendpack.txt
@@ -0,0 +1,5 @@
+sendpack.sideband::
+ Allows to disable the side-band-64k capability for send-pack even
+ when it is advertised by the server. Makes it possible to work
+ around a limitation in the git for windows implementation together
+ with the dump git protocol. Defaults to true.
diff --git a/Makefile b/Makefile
index 90aa329eb7..83ee789e87 100644
--- a/Makefile
+++ b/Makefile
@@ -2728,6 +2728,11 @@ ifdef GIT_INTEROP_MAKE_OPTS
endif
ifdef GIT_TEST_INDEX_VERSION
@echo GIT_TEST_INDEX_VERSION=\''$(subst ','\'',$(subst ','\'',$(GIT_TEST_INDEX_VERSION)))'\' >>$@+
+endif
+ifdef RUNTIME_PREFIX
+ @echo RUNTIME_PREFIX=\'true\' >>$@+
+else
+ @echo RUNTIME_PREFIX=\'false\' >>$@+
endif
@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
diff --git a/abspath.c b/abspath.c
index 6f15a418bb..8a14e61c2c 100644
--- a/abspath.c
+++ b/abspath.c
@@ -95,6 +95,9 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
goto error_out;
}
+ if (platform_strbuf_realpath(resolved, path))
+ return resolved->buf;
+
strbuf_addstr(&remaining, path);
get_root_part(resolved, &remaining);
diff --git a/archive-tar.c b/archive-tar.c
index 5ceec3684b..9bee3f72d5 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -17,6 +17,8 @@ static unsigned long offset;
static int tar_umask = 002;
+static gzFile gzip;
+
static int write_tar_filter_archive(const struct archiver *ar,
struct archiver_args *args);
@@ -38,11 +40,21 @@ static int write_tar_filter_archive(const struct archiver *ar,
#define USTAR_MAX_MTIME 077777777777ULL
#endif
+/* writes out the whole block, or dies if fails */
+static void write_block_or_die(const char *block) {
+ if (gzip) {
+ if (gzwrite(gzip, block, (unsigned) BLOCKSIZE) != BLOCKSIZE)
+ die(_("gzwrite failed"));
+ } else {
+ write_or_die(1, block, BLOCKSIZE);
+ }
+}
+
/* writes out the whole block, but only if it is full */
static void write_if_needed(void)
{
if (offset == BLOCKSIZE) {
- write_or_die(1, block, BLOCKSIZE);
+ write_block_or_die(block);
offset = 0;
}
}
@@ -66,7 +78,7 @@ static void do_write_blocked(const void *data, unsigned long size)
write_if_needed();
}
while (size >= BLOCKSIZE) {
- write_or_die(1, buf, BLOCKSIZE);
+ write_block_or_die(buf);
size -= BLOCKSIZE;
buf += BLOCKSIZE;
}
@@ -101,10 +113,10 @@ static void write_trailer(void)
{
int tail = BLOCKSIZE - offset;
memset(block + offset, 0, tail);
- write_or_die(1, block, BLOCKSIZE);
+ write_block_or_die(block);
if (tail < 2 * RECORDSIZE) {
memset(block, 0, offset);
- write_or_die(1, block, BLOCKSIZE);
+ write_block_or_die(block);
}
}
@@ -461,18 +473,34 @@ static int write_tar_filter_archive(const struct archiver *ar,
filter.use_shell = 1;
filter.in = -1;
- if (start_command(&filter) < 0)
- die_errno(_("unable to start '%s' filter"), argv[0]);
- close(1);
- if (dup2(filter.in, 1) < 0)
- die_errno(_("unable to redirect descriptor"));
- close(filter.in);
+ if (!strcmp("gzip -cn", ar->data)) {
+ char outmode[4] = "wb\0";
+
+ if (args->compression_level >= 0 && args->compression_level <= 9)
+ outmode[2] = '0' + args->compression_level;
+
+ gzip = gzdopen(fileno(stdout), outmode);
+ if (!gzip)
+ die(_("Could not gzdopen stdout"));
+ } else {
+ if (start_command(&filter) < 0)
+ die_errno(_("unable to start '%s' filter"), argv[0]);
+ close(1);
+ if (dup2(filter.in, 1) < 0)
+ die_errno(_("unable to redirect descriptor"));
+ close(filter.in);
+ }
r = write_tar_archive(ar, args);
- close(1);
- if (finish_command(&filter) != 0)
- die(_("'%s' filter reported error"), argv[0]);
+ if (gzip) {
+ if (gzclose(gzip) != Z_OK)
+ die(_("gzclose failed"));
+ } else {
+ close(1);
+ if (finish_command(&filter) != 0)
+ die(_("'%s' filter reported error"), argv[0]);
+ }
strbuf_release(&cmd);
return r;
diff --git a/builtin/clean.c b/builtin/clean.c
index 4ca12bc0c0..b0cef56f8e 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -34,6 +34,10 @@ static const char *msg_remove = N_("Removing %s\n");
static const char *msg_would_remove = N_("Would remove %s\n");
static const char *msg_skip_git_dir = N_("Skipping repository %s\n");
static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
+#ifndef CAN_UNLINK_MOUNT_POINTS
+static const char *msg_skip_mount_point = N_("Skipping mount point %s\n");
+static const char *msg_would_skip_mount_point = N_("Would skip mount point %s\n");
+#endif
static const char *msg_warn_remove_failed = N_("failed to remove %s");
static const char *msg_warn_lstat_failed = N_("could not lstat %s\n");
@@ -171,6 +175,29 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
goto out;
}
+ if (is_mount_point(path)) {
+#ifndef CAN_UNLINK_MOUNT_POINTS
+ if (!quiet) {
+ quote_path_relative(path->buf, prefix, "ed);
+ printf(dry_run ?
+ _(msg_would_skip_mount_point) :
+ _(msg_skip_mount_point), quoted.buf);
+ }
+ *dir_gone = 0;
+#else
+ if (!dry_run && unlink(path->buf)) {
+ int saved_errno = errno;
+ quote_path_relative(path->buf, prefix, "ed);
+ errno = saved_errno;
+ warning_errno(_(msg_warn_remove_failed), quoted.buf);
+ *dir_gone = 0;
+ ret = -1;
+ }
+#endif
+
+ goto out;
+ }
+
dir = opendir(path->buf);
if (!dir) {
/* an empty dir could be removed even if it is unreadble */
diff --git a/builtin/clone.c b/builtin/clone.c
index cb48a291ca..f83701be52 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -1235,7 +1235,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
}
if (!is_local && !complete_refs_before_fetch)
- transport_fetch_refs(transport, mapped_refs);
+ if (transport_fetch_refs(transport, mapped_refs))
+ die(_("could not fetch refs from %s"),
+ transport->url);
remote_head = find_ref_by_name(refs, "HEAD");
remote_head_points_at =
diff --git a/cache.h b/cache.h
index 0f0485ecfe..f98ae3d093 100644
--- a/cache.h
+++ b/cache.h
@@ -1327,6 +1327,7 @@ int normalize_path_copy_len(char *dst, const char *src, int *prefix_len);
int normalize_path_copy(char *dst, const char *src);
int longest_ancestor_length(const char *path, struct string_list *prefixes);
char *strip_path_suffix(const char *path, const char *suffix);
+int is_mount_point_via_stat(struct strbuf *path);
int daemon_avoid_alias(const char *path);
/*
diff --git a/compat/mingw.c b/compat/mingw.c
index 8ee0b6408e..d7a620fe85 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -290,6 +290,9 @@ int mingw_unlink(const char *pathname)
if (xutftowcs_path(wpathname, pathname) < 0)
return -1;
+ if (DeleteFileW(wpathname))
+ return 0;
+
/* read-only files cannot be removed */
_wchmod(wpathname, 0666);
while ((ret = _wunlink(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
@@ -1002,11 +1005,19 @@ unsigned int sleep (unsigned int seconds)
char *mingw_mktemp(char *template)
{
wchar_t wtemplate[MAX_PATH];
+ int offset = 0;
+
if (xutftowcs_path(wtemplate, template) < 0)
return NULL;
+
+ if (is_dir_sep(template[0]) && !is_dir_sep(template[1]) &&
+ iswalpha(wtemplate[0]) && wtemplate[1] == L':') {
+ /* We have an absolute path missing the drive prefix */
+ offset = 2;
+ }
if (!_wmktemp(wtemplate))
return NULL;
- if (xwcstoutf(template, wtemplate, strlen(template) + 1) < 0)
+ if (xwcstoutf(template, wtemplate + offset, strlen(template) + 1) < 0)
return NULL;
return template;
}
@@ -1069,33 +1080,65 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
return NULL;
}
+char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path)
+{
+ wchar_t wpath[MAX_PATH];
+ HANDLE h;
+ DWORD ret;
+ int len;
+
+ if (xutftowcs_path(wpath, path) < 0)
+ return NULL;
+
+ h = CreateFileW(wpath, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return NULL;
+
+ ret = GetFinalPathNameByHandleW(h, wpath, ARRAY_SIZE(wpath), 0);
+ CloseHandle(h);
+ if (!ret || ret >= ARRAY_SIZE(wpath))
+ return NULL;
+
+ len = wcslen(wpath) * 3;
+ strbuf_grow(resolved, len);
+ len = xwcstoutf(resolved->buf, normalize_ntpath(wpath), len);
+ if (len < 0)
+ return NULL;
+ resolved->len = len;
+ return resolved->buf;
+
+}
+
char *mingw_getcwd(char *pointer, int len)
{
wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);
+ HANDLE hnd;
if (!ret || ret >= ARRAY_SIZE(cwd)) {
errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
return NULL;
}
- ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
- if (!ret && GetLastError() == ERROR_ACCESS_DENIED) {
- HANDLE hnd = CreateFileW(cwd, 0,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
- if (hnd == INVALID_HANDLE_VALUE)
- return NULL;
+ hnd = CreateFileW(cwd, 0,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (hnd != INVALID_HANDLE_VALUE) {
ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
CloseHandle(hnd);
- if (!ret || ret >= ARRAY_SIZE(wpointer))
- return NULL;
+ if (!ret || ret >= ARRAY_SIZE(wpointer)) {
+ ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
+ if (!ret || ret >= ARRAY_SIZE(wpointer)) {
+ errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
+ return NULL;
+ }
+ }
if (xwcstoutf(pointer, normalize_ntpath(wpointer), len) < 0)
return NULL;
return pointer;
}
- if (!ret || ret >= ARRAY_SIZE(wpointer))
- return NULL;
- if (xwcstoutf(pointer, wpointer, len) < 0)
+ if (xwcstoutf(pointer, cwd, len) < 0)
return NULL;
convert_slashes(pointer);
return pointer;
@@ -1968,18 +2011,150 @@ static void ensure_socket_initialization(void)
initialized = 1;
}
+static int winsock_error_to_errno(DWORD err)
+{
+ switch (err) {
+ case WSAEINTR: return EINTR;
+ case WSAEBADF: return EBADF;
+ case WSAEACCES: return EACCES;
+ case WSAEFAULT: return EFAULT;
+ case WSAEINVAL: return EINVAL;
+ case WSAEMFILE: return EMFILE;
+ case WSAEWOULDBLOCK: return EWOULDBLOCK;
+ case WSAEINPROGRESS: return EINPROGRESS;
+ case WSAEALREADY: return EALREADY;
+ case WSAENOTSOCK: return ENOTSOCK;
+ case WSAEDESTADDRREQ: return EDESTADDRREQ;
+ case WSAEMSGSIZE: return EMSGSIZE;
+ case WSAEPROTOTYPE: return EPROTOTYPE;
+ case WSAENOPROTOOPT: return ENOPROTOOPT;
+ case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT;
+ case WSAEOPNOTSUPP: return EOPNOTSUPP;
+ case WSAEAFNOSUPPORT: return EAFNOSUPPORT;
+ case WSAEADDRINUSE: return EADDRINUSE;
+ case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL;
+ case WSAENETDOWN: return ENETDOWN;
+ case WSAENETUNREACH: return ENETUNREACH;
+ case WSAENETRESET: return ENETRESET;
+ case WSAECONNABORTED: return ECONNABORTED;
+ case WSAECONNRESET: return ECONNRESET;
+ case WSAENOBUFS: return ENOBUFS;
+ case WSAEISCONN: return EISCONN;
+ case WSAENOTCONN: return ENOTCONN;
+ case WSAETIMEDOUT: return ETIMEDOUT;
+ case WSAECONNREFUSED: return ECONNREFUSED;
+ case WSAELOOP: return ELOOP;
+ case WSAENAMETOOLONG: return ENAMETOOLONG;
+ case WSAEHOSTUNREACH: return EHOSTUNREACH;
+ case WSAENOTEMPTY: return ENOTEMPTY;
+ /* No errno equivalent; default to EIO */
+ case WSAESOCKTNOSUPPORT:
+ case WSAEPFNOSUPPORT:
+ case WSAESHUTDOWN:
+ case WSAETOOMANYREFS:
+ case WSAEHOSTDOWN:
+ case WSAEPROCLIM:
+ case WSAEUSERS:
+ case WSAEDQUOT:
+ case WSAESTALE:
+ case WSAEREMOTE:
+ case WSASYSNOTREADY:
+ case WSAVERNOTSUPPORTED:
+ case WSANOTINITIALISED:
+ case WSAEDISCON:
+ case WSAENOMORE:
+ case WSAECANCELLED:
+ case WSAEINVALIDPROCTABLE:
+ case WSAEINVALIDPROVIDER:
+ case WSAEPROVIDERFAILEDINIT:
+ case WSASYSCALLFAILURE:
+ case WSASERVICE_NOT_FOUND:
+ case WSATYPE_NOT_FOUND:
+ case WSA_E_NO_MORE:
+ case WSA_E_CANCELLED:
+ case WSAEREFUSED:
+ case WSAHOST_NOT_FOUND:
+ case WSATRY_AGAIN:
+ case WSANO_RECOVERY:
+ case WSANO_DATA:
+ case WSA_QOS_RECEIVERS:
+ case WSA_QOS_SENDERS:
+ case WSA_QOS_NO_SENDERS:
+ case WSA_QOS_NO_RECEIVERS:
+ case WSA_QOS_REQUEST_CONFIRMED:
+ case WSA_QOS_ADMISSION_FAILURE:
+ case WSA_QOS_POLICY_FAILURE:
+ case WSA_QOS_BAD_STYLE:
+ case WSA_QOS_BAD_OBJECT:
+ case WSA_QOS_TRAFFIC_CTRL_ERROR:
+ case WSA_QOS_GENERIC_ERROR:
+ case WSA_QOS_ESERVICETYPE:
+ case WSA_QOS_EFLOWSPEC:
+ case WSA_QOS_EPROVSPECBUF:
+ case WSA_QOS_EFILTERSTYLE:
+ case WSA_QOS_EFILTERTYPE:
+ case WSA_QOS_EFILTERCOUNT:
+ case WSA_QOS_EOBJLENGTH:
+ case WSA_QOS_EFLOWCOUNT:
+#ifndef _MSC_VER
+ case WSA_QOS_EUNKNOWNPSOBJ:
+#endif
+ case WSA_QOS_EPOLICYOBJ:
+ case WSA_QOS_EFLOWDESC:
+ case WSA_QOS_EPSFLOWSPEC:
+ case WSA_QOS_EPSFILTERSPEC:
+ case WSA_QOS_ESDMODEOBJ:
+ case WSA_QOS_ESHAPERATEOBJ:
+ case WSA_QOS_RESERVED_PETYPE:
+ default: return EIO;
+ }
+}
+
+/*
+ * On Windows, `errno` is a global macro to a function call.
+ * This makes it difficult to debug and single-step our mappings.
+ */
+static inline void set_wsa_errno(void)
+{
+ DWORD wsa = WSAGetLastError();
+ int e = winsock_error_to_errno(wsa);
+ errno = e;
+
+#ifdef DEBUG_WSA_ERRNO
+ fprintf(stderr, "winsock error: %d -> %d\n", wsa, e);
+ fflush(stderr);
+#endif
+}
+
+static inline int winsock_return(int ret)
+{
+ if (ret < 0)
+ set_wsa_errno();
+
+ return ret;
+}
+
+#define WINSOCK_RETURN(x) do { return winsock_return(x); } while (0)
+
#undef gethostname
int mingw_gethostname(char *name, int namelen)
{
- ensure_socket_initialization();
- return gethostname(name, namelen);
+ ensure_socket_initialization();
+ WINSOCK_RETURN(gethostname(name, namelen));
}
#undef gethostbyname
struct hostent *mingw_gethostbyname(const char *host)
{
+ struct hostent *ret;
+
ensure_socket_initialization();
- return gethostbyname(host);
+
+ ret = gethostbyname(host);
+ if (!ret)
+ set_wsa_errno();
+
+ return ret;
}
#undef getaddrinfo
@@ -1987,7 +2162,7 @@ int mingw_getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res)
{
ensure_socket_initialization();
- return getaddrinfo(node, service, hints, res);
+ WINSOCK_RETURN(getaddrinfo(node, service, hints, res));
}
int mingw_socket(int domain, int type, int protocol)
@@ -2007,7 +2182,7 @@ int mingw_socket(int domain, int type, int protocol)
* in errno so that _if_ someone looks up the code somewhere,
* then it is at least the number that are usually listed.
*/
- errno = WSAGetLastError();
+ set_wsa_errno();
return -1;
}
/* convert into a file descriptor */
@@ -2023,35 +2198,35 @@ int mingw_socket(int domain, int type, int protocol)
int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
{
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
- return connect(s, sa, sz);
+ WINSOCK_RETURN(connect(s, sa, sz));
}
#undef bind
int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)
{
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
- return bind(s, sa, sz);
+ WINSOCK_RETURN(bind(s, sa, sz));
}
#undef setsockopt
int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)
{
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
- return setsockopt(s, lvl, optname, (const char*)optval, optlen);
+ WINSOCK_RETURN(setsockopt(s, lvl, optname, (const char*)optval, optlen));
}
#undef shutdown
int mingw_shutdown(int sockfd, int how)
{
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
- return shutdown(s, how);
+ WINSOCK_RETURN(shutdown(s, how));
}
#undef listen
int mingw_listen(int sockfd, int backlog)
{
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
- return listen(s, backlog);
+ WINSOCK_RETURN(listen(s, backlog));
}
#undef accept
@@ -2062,6 +2237,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
SOCKET s2 = accept(s1, sa, sz);
+ if (s2 == INVALID_SOCKET) {
+ set_wsa_errno();
+ return -1;
+ }
+
/* convert into a file descriptor */
if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {
int err = errno;
@@ -2456,6 +2636,28 @@ pid_t waitpid(pid_t pid, int *status, int options)
return -1;
}
+int mingw_is_mount_point(struct strbuf *path)
+{
+ WIN32_FIND_DATAW findbuf = { 0 };
+ HANDLE handle;
+ wchar_t wfilename[MAX_PATH];
+ int wlen = xutftowcs_path(wfilename, path->buf);
+ if (wlen < 0)
+ die(_("could not get long path for '%s'"), path->buf);
+
+ /* remove trailing slash, if any */
+ if (wlen > 0 && wfilename[wlen - 1] == L'/')
+ wfilename[--wlen] = L'\0';
+
+ handle = FindFirstFileW(wfilename, &findbuf);
+ if (handle == INVALID_HANDLE_VALUE)
+ return 0;
+ FindClose(handle);
+
+ return (findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
+ (findbuf.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT);
+}
+
int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
{
int upos = 0, wpos = 0;
@@ -2541,6 +2743,47 @@ int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
return -1;
}
+#ifdef ENSURE_MSYSTEM_IS_SET
+static size_t append_system_bin_dirs(char *path, size_t size)
+{
+#if !defined(RUNTIME_PREFIX) || !defined(HAVE_WPGMPTR)
+ return 0;
+#else
+ char prefix[32768];
+ const char *slash;
+ size_t len = xwcstoutf(prefix, _wpgmptr, sizeof(prefix)), off = 0;
+
+ if (len == 0 || len >= sizeof(prefix) ||
+ !(slash = find_last_dir_sep(prefix)))
+ return 0;
+ /* strip trailing `git.exe` */
+ len = slash - prefix;
+
+ /* strip trailing `cmd` or `mingw64\bin` or `mingw32\bin` or `bin` or `libexec\git-core` */
+ if (strip_suffix_mem(prefix, &len, "\\mingw64\\libexec\\git-core") ||
+ strip_suffix_mem(prefix, &len, "\\mingw64\\bin"))
+ off += xsnprintf(path + off, size - off,
+ "%.*s\\mingw64\\bin;", (int)len, prefix);
+ else if (strip_suffix_mem(prefix, &len, "\\mingw32\\libexec\\git-core") ||
+ strip_suffix_mem(prefix, &len, "\\mingw32\\bin"))
+ off += xsnprintf(path + off, size - off,
+ "%.*s\\mingw32\\bin;", (int)len, prefix);
+ else if (strip_suffix_mem(prefix, &len, "\\cmd") ||
+ strip_suffix_mem(prefix, &len, "\\bin") ||
+ strip_suffix_mem(prefix, &len, "\\libexec\\git-core"))
+ off += xsnprintf(path + off, size - off,
+ "%.*s\\mingw%d\\bin;", (int)len, prefix,
+ (int)(sizeof(void *) * 8));
+ else
+ return 0;
+
+ off += xsnprintf(path + off, size - off,
+ "%.*s\\usr\\bin;", (int)len, prefix);
+ return off;
+#endif
+}
+#endif
+
static void setup_windows_environment(void)
{
char *tmp = getenv("TMPDIR");
@@ -2592,6 +2835,37 @@ static void setup_windows_environment(void)
if (!tmp && (tmp = getenv("USERPROFILE")))
setenv("HOME", tmp, 1);
}
+
+ if (!getenv("PLINK_PROTOCOL"))
+ setenv("PLINK_PROTOCOL", "ssh", 0);
+
+#ifdef ENSURE_MSYSTEM_IS_SET
+ if (!(tmp = getenv("MSYSTEM")) || !tmp[0]) {
+ const char *home = getenv("HOME"), *path = getenv("PATH");
+ char buf[32768];
+ size_t off = 0;
+
+ xsnprintf(buf, sizeof(buf),
+ "MINGW%d", (int)(sizeof(void *) * 8));
+ setenv("MSYSTEM", buf, 1);
+
+ if (home)
+ off += xsnprintf(buf + off, sizeof(buf) - off,
+ "%s\\bin;", home);
+ off += append_system_bin_dirs(buf + off, sizeof(buf) - off);
+ if (path)
+ off += xsnprintf(buf + off, sizeof(buf) - off,
+ "%s", path);
+ else if (off > 0)
+ buf[off - 1] = '\0';
+ else
+ buf[0] = '\0';
+ setenv("PATH", buf, 1);
+ }
+#endif
+
+ if (!getenv("LC_ALL") && !getenv("LC_CTYPE") && !getenv("LANG"))
+ setenv("LC_CTYPE", "C", 1);
}
int is_valid_win32_path(const char *path, int allow_literal_nul)
@@ -2836,6 +3110,7 @@ int wmain(int argc, const wchar_t **wargv)
#endif
maybe_redirect_std_handles();
+ fsync_object_files = 1;
/* determine size of argv and environ conversion buffer */
maxlen = wcslen(wargv[0]);
diff --git a/compat/mingw.h b/compat/mingw.h
index e6fe810ba9..03b4ec5c2f 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -442,9 +442,15 @@ static inline void convert_slashes(char *path)
if (*path == '\\')
*path = '/';
}
+struct strbuf;
+int mingw_is_mount_point(struct strbuf *path);
+#define is_mount_point mingw_is_mount_point
+#define CAN_UNLINK_MOUNT_POINTS 1
#define PATH_SEP ';'
char *mingw_query_user_email(void);
#define query_user_email mingw_query_user_email
+char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path);
+#define platform_strbuf_realpath mingw_strbuf_realpath
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
#define PRIuMAX "I64u"
#define PRId64 "I64d"
diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl
index d9f71b7cbb..d6959a8441 100755
--- a/compat/vcbuild/scripts/clink.pl
+++ b/compat/vcbuild/scripts/clink.pl
@@ -54,7 +54,8 @@ while (@ARGV) {
# need to use that instead?
foreach my $flag (@lflags) {
if ($flag =~ /^-LIBPATH:(.*)/) {
- foreach my $l ("libcurl_imp.lib", "libcurl.lib") {
+ my $libcurl = $is_debug ? "libcurl-d.lib" : "libcurl.lib";
+ foreach my $l ("libcurl_imp.lib", $libcurl) {
if (-f "$1/$l") {
$lib = $l;
last;
diff --git a/compat/vcbuild/vcpkg_install.bat b/compat/vcbuild/vcpkg_install.bat
index ebd0bad242..8330d8120f 100644
--- a/compat/vcbuild/vcpkg_install.bat
+++ b/compat/vcbuild/vcpkg_install.bat
@@ -36,6 +36,13 @@ REM ================================================================
dir vcpkg\vcpkg.exe >nul 2>nul && GOTO :install_libraries
+ git.exe version 2>nul
+ IF ERRORLEVEL 1 (
+ echo "***"
+ echo "Git not found. Please adjust your CMD path or Git install option."
+ echo "***"
+ EXIT /B 1 )
+
echo Fetching vcpkg in %cwd%vcpkg
git.exe clone https://github.com/Microsoft/vcpkg vcpkg
IF ERRORLEVEL 1 ( EXIT /B 1 )
@@ -73,6 +80,12 @@ REM ================================================================
:sub__install_one
echo Installing package %1...
+ REM vcpkg may not be reliable on slow, intermittent or proxy
+ REM connections, see e.g.
+ REM https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/4a8f7be5-5e15-4213-a7bb-ddf424a954e6/winhttpsendrequest-ends-with-12002-errorhttptimeout-after-21-seconds-no-matter-what-timeout?forum=windowssdk
+ REM which explains the hidden 21 second timeout
+ REM (last post by Dave : Microsoft - Windows Networking team)
+
.\vcpkg.exe install %1:%arch%
IF ERRORLEVEL 1 ( EXIT /B 1 )
diff --git a/config.c b/config.c
index 8db9c77098..59c2bda33b 100644
--- a/config.c
+++ b/config.c
@@ -1678,9 +1678,11 @@ static int git_config_from_blob_ref(config_fn_t fn,
const char *git_etc_gitconfig(void)
{
- static const char *system_wide;
- if (!system_wide)
+ static char *system_wide;
+ if (!system_wide) {
system_wide = system_path(ETC_GITCONFIG);
+ normalize_path_copy(system_wide, system_wide);
+ }
return system_wide;
}
diff --git a/config.mak.uname b/config.mak.uname
index c7eba69e54..188281c5ff 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -433,6 +433,11 @@ ifeq ($(uname_S),Windows)
NO_POSIX_GOODIES = UnfortunatelyYes
NATIVE_CRLF = YesPlease
DEFAULT_HELP_FORMAT = html
+ifeq (/mingw64,$(subst 32,64,$(prefix)))
+ # Move system config into top-level /etc/
+ ETC_GITCONFIG = ../etc/gitconfig
+ ETC_GITATTRIBUTES = ../etc/gitattributes
+endif
CC = compat/vcbuild/scripts/clink.pl
AR = compat/vcbuild/scripts/lib.pl
@@ -443,7 +448,7 @@ ifeq ($(uname_S),Windows)
compat/win32/pthread.o compat/win32/syslog.o \
compat/win32/trace2_win32_process_info.o \
compat/win32/dirent.o
- COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
+ COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DDETECT_MSYS_TTY -DENSURE_MSYSTEM_IS_SET -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -ENTRY:wmainCRTStartup -SUBSYSTEM:CONSOLE
# invalidcontinue.obj allows Git's source code to close the same file
# handle twice, or to access the osfhandle of an already-closed stdout
@@ -666,7 +671,7 @@ else
endif
CC = gcc
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0 -DDETECT_MSYS_TTY \
- -fstack-protector-strong
+ -DENSURE_MSYSTEM_IS_SET -fstack-protector-strong
EXTLIBS += -lntdll
INSTALL = /bin/install
NO_R_TO_GCC_LINKER = YesPlease
@@ -674,10 +679,15 @@ else
HAVE_LIBCHARSET_H = YesPlease
NO_GETTEXT =
USE_GETTEXT_SCHEME = fallthrough
- USE_LIBPCRE= YesPlease
- NO_LIBPCRE1_JIT = UnfortunatelyYes
+ USE_LIBPCRE = YesPlease
NO_CURL =
USE_NED_ALLOCATOR = YesPlease
+ NO_PYTHON =
+ ifeq (/mingw64,$(subst 32,64,$(prefix)))
+ # Move system config into top-level /etc/
+ ETC_GITCONFIG = ../etc/gitconfig
+ ETC_GITATTRIBUTES = ../etc/gitattributes
+ endif
else
COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO
NO_CURL = YesPlease
@@ -709,7 +719,7 @@ vcxproj:
# Make .vcxproj files and add them
unset QUIET_GEN QUIET_BUILT_IN; \
perl contrib/buildsystems/generate -g Vcxproj
- git add -f git.sln {*,*/lib,t/helper/*}/*.vcxproj
+ git add -f git.sln {*,*/lib.proj,t/helper/*}/*.vcxproj
# Generate the LinkOrCopyBuiltins.targets and LinkOrCopyRemoteHttp.targets file
(echo '' && \
@@ -719,7 +729,7 @@ vcxproj:
echo ' '; \
done && \
echo ' ' && \
- echo '') >git/LinkOrCopyBuiltins.targets
+ echo '') >git.proj/LinkOrCopyBuiltins.targets
(echo '' && \
echo ' ' && \
for name in $(REMOTE_CURL_ALIASES); \
@@ -727,8 +737,8 @@ vcxproj:
echo ' '; \
done && \
echo ' ' && \
- echo '') >git-remote-http/LinkOrCopyRemoteHttp.targets
- git add -f git/LinkOrCopyBuiltins.targets git-remote-http/LinkOrCopyRemoteHttp.targets
+ echo '') >git-remote-http.proj/LinkOrCopyRemoteHttp.targets
+ git add -f git.proj/LinkOrCopyBuiltins.targets git-remote-http.proj/LinkOrCopyRemoteHttp.targets
# Add command-list.h and config-list.h
$(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 config-list.h command-list.h
diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm
index 5c666f9ac0..4944ba6bd4 100644
--- a/contrib/buildsystems/Generators/Vcxproj.pm
+++ b/contrib/buildsystems/Generators/Vcxproj.pm
@@ -58,8 +58,8 @@ sub createProject {
my $uuid = generate_guid($name);
$$build_structure{"$prefix${target}_GUID"} = $uuid;
my $vcxproj = $target;
- $vcxproj =~ s/(.*\/)?(.*)/$&\/$2.vcxproj/;
- $vcxproj =~ s/([^\/]*)(\/lib)\/(lib.vcxproj)/$1$2\/$1_$3/;
+ $vcxproj =~ s/(.*\/)?(.*)/$&.proj\/$2.vcxproj/;
+ $vcxproj =~ s/([^\/]*)(\/lib\.proj)\/(lib.vcxproj)/$1$2\/$1_$3/;
$$build_structure{"$prefix${target}_VCXPROJ"} = $vcxproj;
my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"$prefix${name}_SOURCES"}}));
@@ -88,7 +88,9 @@ sub createProject {
$defines =~ s/>/>/g;
$defines =~ s/\'//g;
- die "Could not create the directory $target for $label project!\n" unless (-d "$target" || mkdir "$target");
+ my $dir = $vcxproj;
+ $dir =~ s/\/[^\/]*$//;
+ die "Could not create the directory $dir for $label project!\n" unless (-d "$dir" || mkdir "$dir");
open F, ">$vcxproj" or die "Could not open $vcxproj for writing!\n";
binmode F, ":crlf :utf8";
@@ -235,14 +237,14 @@ EOM
print F << "EOM";
-
+
$uuid_libgit
false
EOM
if (!($name =~ 'xdiff')) {
print F << "EOM";
-
+
$uuid_xdiff_lib
false
@@ -251,7 +253,7 @@ EOM
if ($name =~ /(test-(line-buffer|svn-fe)|^git-remote-testsvn)\.exe$/) {
my $uuid_vcs_svn_lib = $$build_structure{"LIBS_vcs-svn/lib_GUID"};
print F << "EOM";
-
+
$uuid_vcs_svn_lib
false
@@ -328,7 +330,7 @@ sub createGlueProject {
my $vcxproj = $build_structure{"APPS_${appname}_VCXPROJ"};
$vcxproj =~ s/\//\\/g;
$appname =~ s/.*\///;
- print F "\"${appname}\", \"${vcxproj}\", \"${uuid}\"";
+ print F "\"${appname}.proj\", \"${vcxproj}\", \"${uuid}\"";
print F "$SLN_POST";
}
foreach (@libs) {
@@ -338,7 +340,7 @@ sub createGlueProject {
my $vcxproj = $build_structure{"LIBS_${libname}_VCXPROJ"};
$vcxproj =~ s/\//\\/g;
$libname =~ s/\//_/g;
- print F "\"${libname}\", \"${vcxproj}\", \"${uuid}\"";
+ print F "\"${libname}.proj\", \"${vcxproj}\", \"${uuid}\"";
print F "$SLN_POST";
}
diff --git a/credential.c b/credential.c
index d8d226b97e..2acb3bcd9e 100644
--- a/credential.c
+++ b/credential.c
@@ -202,7 +202,7 @@ int credential_read(struct credential *c, FILE *fp)
{
struct strbuf line = STRBUF_INIT;
- while (strbuf_getline_lf(&line, fp) != EOF) {
+ while (strbuf_getline(&line, fp) != EOF) {
char *key = line.buf;
char *value = strchr(key, '=');
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 99e63e90f8..7b12f42a7a 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -84,6 +84,18 @@ static struct diff_rename_src *register_rename_src(struct diff_filepair *p)
first = 0;
last = rename_src_nr;
+
+ if (last > 0) {
+ struct diff_rename_src *src = &(rename_src[last-1]);
+ int cmp = strcmp(one->path, src->p->one->path);
+ if (!cmp)
+ return src;
+ if (cmp > 0) {
+ first = last;
+ goto append_it;
+ }
+ }
+
while (last > first) {
int next = first + ((last - first) >> 1);
struct diff_rename_src *src = &(rename_src[next]);
@@ -97,6 +109,7 @@ static struct diff_rename_src *register_rename_src(struct diff_filepair *p)
first = next+1;
}
+append_it:
/* insert to make it at "first" */
ALLOC_GROW(rename_src, rename_src_nr + 1, rename_src_alloc);
rename_src_nr++;
diff --git a/git-compat-util.h b/git-compat-util.h
index a73632e8e4..3d7a1094bc 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -397,10 +397,18 @@ static inline int git_has_dir_sep(const char *path)
#define has_dir_sep(path) git_has_dir_sep(path)
#endif
+#ifndef is_mount_point
+#define is_mount_point is_mount_point_via_stat
+#endif
+
#ifndef query_user_email
#define query_user_email() NULL
#endif
+#ifndef platform_strbuf_realpath
+#define platform_strbuf_realpath(resolved, path) NULL
+#endif
+
#ifdef __TANDEM
#include
#include
diff --git a/gitk-git/gitk b/gitk-git/gitk
index abe4805ade..2d5065b88b 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -354,6 +354,16 @@ proc parseviewrevs {view revs} {
return $ret
}
+# Escapes a list of filter paths to be passed to git log via stdin. Note that
+# paths must not be quoted.
+proc escape_filter_paths {paths} {
+ set escaped [list]
+ foreach path $paths {
+ lappend escaped [string map {\\ \\\\ "\ " "\\\ "} $path]
+ }
+ return $escaped
+}
+
# Start off a git log process and arrange to read its output
proc start_rev_list {view} {
global startmsecs commitidx viewcomplete curview
@@ -406,14 +416,17 @@ proc start_rev_list {view} {
if {$revs eq {}} {
return 0
}
- set args [concat $vflags($view) $revs]
+ set args $vflags($view)
} else {
+ set revs {}
set args $vorigargs($view)
}
if {[catch {
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
- --parents --boundary $args "--" $files] r]
+ --parents --boundary $args --stdin \
+ "<<[join [concat $revs "--" \
+ [escape_filter_paths $files]] "\\n"]"] r]
} err]} {
error_popup "[mc "Error executing git log:"] $err"
return 0
@@ -555,13 +568,20 @@ proc updatecommits {} {
set revs $newrevs
set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
}
- set args [concat $vflags($view) $revs --not $oldpos]
+ set args $vflags($view)
+ foreach r $oldpos {
+ lappend revs "^$r"
+ }
} else {
+ set revs {}
set args $vorigargs($view)
}
if {[catch {
set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
- --parents --boundary $args "--" $vfilelimit($view)] r]
+ --parents --boundary $args --stdin \
+ "<<[join [concat $revs "--" \
+ [escape_filter_paths \
+ $vfilelimit($view)]] "\\n"]"] r]
} err]} {
error_popup "[mc "Error executing git log:"] $err"
return
@@ -10210,10 +10230,16 @@ proc getallcommits {} {
foreach id $seeds {
lappend ids "^$id"
}
+ lappend ids "--"
}
}
if {$ids ne {}} {
- set fd [open [concat $cmd $ids] r]
+ if {$ids eq "--all"} {
+ set cmd [concat $cmd "--all"]
+ } else {
+ set cmd [concat $cmd --stdin "<<[join $ids "\\n"]"]
+ }
+ set fd [open $cmd r]
fconfigure $fd -blocking 0
incr allcommits
nowbusy allcommits
@@ -12599,7 +12625,9 @@ set cdup {}
if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
set cdup [exec git rev-parse --show-cdup]
}
-set worktree [exec git rev-parse --show-toplevel]
+if {$hasworktree} {
+ set worktree [exec git rev-parse --show-toplevel]
+}
setcoords
makewindow
catch {
diff --git a/http.c b/http.c
index 62aa995245..0e041102b3 100644
--- a/http.c
+++ b/http.c
@@ -165,7 +165,13 @@ static char *cached_accept_language;
static char *http_ssl_backend;
-static int http_schannel_check_revoke = 1;
+static int http_schannel_check_revoke_mode =
+#ifdef CURLSSLOPT_REVOKE_BEST_EFFORT
+ CURLSSLOPT_REVOKE_BEST_EFFORT;
+#else
+ CURLSSLOPT_NO_REVOKE;
+#endif
+
/*
* With the backend being set to `schannel`, setting sslCAinfo would override
* the Certificate Store in cURL v7.60.0 and later, which is not what we want
@@ -330,7 +336,19 @@ static int http_options(const char *var, const char *value, void *cb)
}
if (!strcmp("http.schannelcheckrevoke", var)) {
- http_schannel_check_revoke = git_config_bool(var, value);
+ if (value && !strcmp(value, "best-effort")) {
+ http_schannel_check_revoke_mode =
+#ifdef CURLSSLOPT_REVOKE_BEST_EFFORT
+ CURLSSLOPT_REVOKE_BEST_EFFORT;
+#else
+ CURLSSLOPT_NO_REVOKE;
+ warning(_("%s=%s unsupported by current cURL"),
+ var, value);
+#endif
+ } else
+ http_schannel_check_revoke_mode =
+ (git_config_bool(var, value) ?
+ 0 : CURLSSLOPT_NO_REVOKE);
return 0;
}
@@ -907,9 +925,9 @@ static CURL *get_curl_handle(void)
#endif
if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
- !http_schannel_check_revoke) {
+ http_schannel_check_revoke_mode) {
#if LIBCURL_VERSION_NUM >= 0x072c00
- curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+ curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, http_schannel_check_revoke_mode);
#else
warning(_("CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0"));
#endif
diff --git a/path.c b/path.c
index 8b2c753191..51b2a448fd 100644
--- a/path.c
+++ b/path.c
@@ -12,6 +12,7 @@
#include "packfile.h"
#include "object-store.h"
#include "lockfile.h"
+#include "exec-cmd.h"
static int get_st_mode_bits(const char *path, int *mode)
{
@@ -732,6 +733,10 @@ char *expand_user_path(const char *path, int real_home)
if (path == NULL)
goto return_null;
+#ifdef __MINGW32__
+ if (path[0] == '/')
+ return system_path(path + 1);
+#endif
if (path[0] == '~') {
const char *first_slash = strchrnul(path, '/');
const char *username = path + 1;
@@ -1289,6 +1294,45 @@ char *strip_path_suffix(const char *path, const char *suffix)
return offset == -1 ? NULL : xstrndup(path, offset);
}
+int is_mount_point_via_stat(struct strbuf *path)
+{
+ size_t len = path->len;
+ unsigned int current_dev;
+ struct stat st;
+
+ if (!strcmp("/", path->buf))
+ return 1;
+
+ strbuf_addstr(path, "/.");
+ if (lstat(path->buf, &st)) {
+ /*
+ * If we cannot access the current directory, we cannot say
+ * that it is a bind mount.
+ */
+ strbuf_setlen(path, len);
+ return 0;
+ }
+ current_dev = st.st_dev;
+
+ /* Now look at the parent directory */
+ strbuf_addch(path, '.');
+ if (lstat(path->buf, &st)) {
+ /*
+ * If we cannot access the parent directory, we cannot say
+ * that it is a bind mount.
+ */
+ strbuf_setlen(path, len);
+ return 0;
+ }
+ strbuf_setlen(path, len);
+
+ /*
+ * If the device ID differs between current and parent directory,
+ * then it is a bind mount.
+ */
+ return current_dev != st.st_dev;
+}
+
int daemon_avoid_alias(const char *p)
{
int sl, ndot;
diff --git a/send-pack.c b/send-pack.c
index 0abee22283..a91b250211 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -39,6 +39,16 @@ int option_parse_push_signed(const struct option *opt,
die("bad %s argument: %s", opt->long_name, arg);
}
+static int config_use_sideband = 1;
+
+static int send_pack_config(const char *var, const char *value, void *unused)
+{
+ if (!strcmp("sendpack.sideband", var))
+ config_use_sideband = git_config_bool(var, value);
+
+ return 0;
+}
+
static void feed_object(const struct object_id *oid, FILE *fh, int negative)
{
if (negative &&
@@ -369,6 +379,8 @@ int send_pack(struct send_pack_args *args,
const char *push_cert_nonce = NULL;
struct packet_reader reader;
+ git_config(send_pack_config, NULL);
+
/* Does the other end support the reporting? */
if (server_supports("report-status"))
status_report = 1;
@@ -376,7 +388,7 @@ int send_pack(struct send_pack_args *args,
allow_deleting_refs = 1;
if (server_supports("ofs-delta"))
args->use_ofs_delta = 1;
- if (server_supports("side-band-64k"))
+ if (config_use_sideband && server_supports("side-band-64k"))
use_sideband = 1;
if (server_supports("quiet"))
quiet_supported = 1;
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 56db5c8aba..ada3e5b72d 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -495,4 +495,42 @@ test_expect_success MINGW 'is_valid_path() on Windows' '
"PRN./abc"
'
+test_expect_success MINGW 'MSYSTEM/PATH is adjusted if necessary' '
+ mkdir -p "$HOME"/bin pretend/mingw64/bin \
+ pretend/mingw64/libexec/git-core pretend/usr/bin &&
+ cp "$GIT_EXEC_PATH"/git.exe pretend/mingw64/bin/ &&
+ cp "$GIT_EXEC_PATH"/git.exe pretend/mingw64/libexec/git-core/ &&
+ echo "env | grep MSYSTEM=" | write_script "$HOME"/bin/git-test-home &&
+ echo "echo mingw64" | write_script pretend/mingw64/bin/git-test-bin &&
+ echo "echo usr" | write_script pretend/usr/bin/git-test-bin2 &&
+
+ (
+ MSYSTEM= &&
+ GIT_EXEC_PATH= &&
+ pretend/mingw64/libexec/git-core/git.exe test-home >actual &&
+ pretend/mingw64/libexec/git-core/git.exe test-bin >>actual &&
+ pretend/mingw64/bin/git.exe test-bin2 >>actual
+ ) &&
+ test_write_lines MSYSTEM=$MSYSTEM mingw64 usr >expect &&
+ test_cmp expect actual
+'
+
+test_lazy_prereq RUNTIME_PREFIX '
+ test true = "$RUNTIME_PREFIX"
+'
+
+test_lazy_prereq CAN_EXEC_IN_PWD '
+ cp "$GIT_EXEC_PATH"/git$X ./ &&
+ ./git rev-parse
+'
+
+test_expect_success RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX works' '
+ mkdir -p pretend/git pretend/libexec/git-core &&
+ echo "echo HERE" | write_script pretend/libexec/git-core/git-here &&
+ cp "$GIT_EXEC_PATH"/git$X pretend/git/ &&
+ GIT_EXEC_PATH= ./pretend/git/git here >actual &&
+ echo HERE >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index b7d4ba608c..d12aebd233 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -423,4 +423,15 @@ test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' '
git add "$downcased"
'
+test_expect_success MINGW 'can add files via NTFS junctions' '
+ test_when_finished "cmd //c rmdir junction && rm -rf target" &&
+ test_create_repo target &&
+ cmd //c "mklink /j junction target" &&
+ >target/via-junction &&
+ git -C junction add "$(pwd)/junction/via-junction" &&
+ echo via-junction >expect &&
+ git -C target diff --cached --name-only >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index dda81b7d07..fa755405ec 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -721,8 +721,8 @@ test_expect_success '"remote show" does not show symbolic refs' '
(
cd three &&
git remote show origin >output &&
- ! grep "^ *HEAD$" < output &&
- ! grep -i stale < output
+ ! grep "^ *HEAD$"