From 1708a00fded64243bc45ef64f071031512a93a38 Mon Sep 17 00:00:00 2001 From: Sverre Rabbelier Date: Sun, 24 Jul 2011 15:54:04 +0200 Subject: [PATCH 001/105] t9350: point out that refs are not updated correctly This happens only when the corresponding commits are not exported in the current fast-export run. This can happen either when the relevant commit is already marked, or when the commit is explicitly marked as UNINTERESTING with a negative ref by another argument. This breaks fast-export basec remote helpers. Signed-off-by: Sverre Rabbelier --- t/t9350-fast-export.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index fc99703fc5..2f203d41f0 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -789,4 +789,15 @@ test_expect_success 'fast-export --first-parent outputs all revisions output by ) ' +cat > expected << EOF +reset refs/heads/master +from $(git rev-parse master) + +EOF + +test_expect_failure 'refs are updated even if no commits need to be exported' ' + git fast-export master..master > actual && + test_cmp expected actual +' + test_done From c83b82761931c620ae44fe9c8fb0d2ba9580545a Mon Sep 17 00:00:00 2001 From: Sverre Rabbelier Date: Sat, 28 Aug 2010 20:49:01 -0500 Subject: [PATCH 002/105] transport-helper: add trailing -- [PT: ensure we add an additional element to the argv array] Signed-off-by: Sverre Rabbelier Signed-off-by: Johannes Schindelin --- transport-helper.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/transport-helper.c b/transport-helper.c index 322c722478..ceca807c74 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -478,6 +478,8 @@ static int get_exporter(struct transport *transport, for (i = 0; i < revlist_args->nr; i++) strvec_push(&fastexport->args, revlist_args->items[i].string); + strvec_push(&fastexport->args, "--"); + fastexport->git_cmd = 1; return start_command(fastexport); } From 2ff614f41187e4be48bf686dca0af21abf598d6f Mon Sep 17 00:00:00 2001 From: Sverre Rabbelier Date: Sun, 24 Jul 2011 00:06:00 +0200 Subject: [PATCH 003/105] remote-helper: check helper status after import/export Signed-off-by: Johannes Schindelin Signed-off-by: Sverre Rabbelier --- t/t5801-remote-helpers.sh | 2 +- transport-helper.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index d386076dbd..b5d69b0c50 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -239,7 +239,7 @@ test_expect_success 'push update refs failure' ' echo "update fail" >>file && git commit -a -m "update fail" && git rev-parse --verify testgit/origin/heads/update >expect && - test_expect_code 1 env GIT_REMOTE_TESTGIT_FAILURE="non-fast forward" \ + test_must_fail env GIT_REMOTE_TESTGIT_FAILURE="non-fast forward" \ git push origin update && git rev-parse --verify testgit/origin/heads/update >actual && test_cmp expect actual diff --git a/transport-helper.c b/transport-helper.c index ceca807c74..ce9dc05ac7 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -484,6 +484,19 @@ static int get_exporter(struct transport *transport, return start_command(fastexport); } +static void check_helper_status(struct helper_data *data) +{ + int pid, status; + + pid = waitpid(data->helper->pid, &status, WNOHANG); + if (pid < 0) + die("Could not retrieve status of remote helper '%s'", + data->name); + if (pid > 0 && WIFEXITED(status)) + die("Remote helper '%s' died with %d", + data->name, WEXITSTATUS(status)); +} + static int fetch_with_import(struct transport *transport, int nr_heads, struct ref **to_fetch) { @@ -520,6 +533,7 @@ static int fetch_with_import(struct transport *transport, if (finish_command(&fastimport)) die(_("error while running fast-import")); + check_helper_status(data); /* * The fast-import stream of a remote helper that advertises @@ -1124,6 +1138,7 @@ static int push_refs_with_export(struct transport *transport, if (finish_command(&exporter)) die(_("error while running fast-export")); + check_helper_status(data); if (push_update_refs_status(data, remote_refs, flags)) return 1; From 92def8de339d689331a32a2dcaf50b2a903045f0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 9 Apr 2012 13:04:35 -0500 Subject: [PATCH 004/105] Always auto-gc after calling a fast-import transport After importing anything with fast-import, we should always let the garbage collector do its job, since the objects are written to disk inefficiently. This brings down an initial import of http://selenic.com/hg from about 230 megabytes to about 14. In the future, we may want to make this configurable on a per-remote basis, or maybe teach fast-import about it in the first place. Signed-off-by: Johannes Schindelin --- transport-helper.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/transport-helper.c b/transport-helper.c index ce9dc05ac7..b50275aabc 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -16,6 +16,8 @@ #include "protocol.h" static int debug; +/* TODO: put somewhere sensible, e.g. git_transport_options? */ +static int auto_gc = 1; struct helper_data { const char *name; @@ -567,6 +569,12 @@ static int fetch_with_import(struct transport *transport, } } strbuf_release(&buf); + if (auto_gc) { + const char *argv_gc_auto[] = { + "gc", "--auto", "--quiet", NULL, + }; + run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); + } return 0; } From 62c8341ca2ed686c4ce814b9cc49d16f20d00f31 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 18 Apr 2017 12:09:08 +0200 Subject: [PATCH 005/105] mingw: demonstrate a problem with certain absolute paths On Windows, there are several categories of absolute paths. One such category starts with a backslash and is implicitly relative to the drive associated with the current working directory. Example: c: git clone https://github.com/git-for-windows/git \G4W should clone into C:\G4W. There is currently a problem with that, in that mingw_mktemp() does not expect the _wmktemp() function to prefix the absolute path with the drive prefix, and as a consequence, the resulting path does not fit into the originally-passed string buffer. The symptom is a "Result too large" error. Reported by Juan Carlos Arevalo Baeza. Signed-off-by: Johannes Schindelin --- t/t5580-unc-paths.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/t/t5580-unc-paths.sh b/t/t5580-unc-paths.sh index cd7604fff9..116204b59d 100755 --- a/t/t5580-unc-paths.sh +++ b/t/t5580-unc-paths.sh @@ -21,14 +21,11 @@ fi UNCPATH="$(winpwd)" case "$UNCPATH" in [A-Z]:*) + WITHOUTDRIVE="${UNCPATH#?:}" # Use administrative share e.g. \\localhost\C$\git-sdk-64\usr\src\git # (we use forward slashes here because MSYS2 and Git accept them, and # they are easier on the eyes) - UNCPATH="//localhost/${UNCPATH%%:*}\$/${UNCPATH#?:}" - test -d "$UNCPATH" || { - skip_all='could not access administrative share; skipping' - test_done - } + UNCPATH="//localhost/${UNCPATH%%:*}\$$WITHOUTDRIVE" ;; *) skip_all='skipping UNC path tests, cannot determine current path as UNC' @@ -36,6 +33,18 @@ case "$UNCPATH" in ;; esac +test_expect_failure 'clone into absolute path lacking a drive prefix' ' + USINGBACKSLASHES="$(echo "$WITHOUTDRIVE"/without-drive-prefix | + tr / \\\\)" && + git clone . "$USINGBACKSLASHES" && + test -f without-drive-prefix/.git/HEAD +' + +test -d "$UNCPATH" || { + skip_all='could not access administrative share; skipping' + test_done +} + test_expect_success setup ' test_commit initial ' From 9f4e4376e5d9484c2b744cd06199ad13bb990082 Mon Sep 17 00:00:00 2001 From: Rohit Ashiwal Date: Fri, 15 Feb 2019 19:03:57 +0530 Subject: [PATCH 006/105] archive: replace write_or_die() calls with write_block_or_die() MinGit for Windows comes without `gzip` bundled inside, git-archive uses `gzip -cn` to compress tar files but for this to work, gzip needs to be present on the host system. In the next commit, we will change the gzip compression so that we no longer spawn `gzip` but let zlib perform the compression in the same process instead. In preparation for this, we consolidate all the block writes into a single function. This closes https://github.com/git-for-windows/git/issues/1970 Signed-off-by: Rohit Ashiwal Signed-off-by: Johannes Schindelin --- archive-tar.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/archive-tar.c b/archive-tar.c index 042feb66d2..74dfc635b8 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); } } From 5ed5ff7fa0da233a0c17852617e0f9afc27b6a3f Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 25 Apr 2019 12:05:29 -0400 Subject: [PATCH 007/105] gitk: prevent overly long command lines To avoid running into command line limitations, some of Git's commands support the `--stdin` option. Let's use exactly this option in the three rev-list/log invocations in gitk that would otherwise possibly run the danger of trying to invoke a too-long command line. While it is easy to redirect either stdin or stdout in Tcl/Tk scripts, what we need here is both. We need to capture the output, yet we also need to pipe in the revs/files arguments via stdin (because stdin does not have any limit, unlike the command line). To help this, we use the neat Tcl feature where you can capture stdout and at the same time feed a fixed string as stdin to the spawned process. One non-obvious aspect about this change is that the `--stdin` option allows to specify revs, the double-dash, and files, but *no* other options such as `--not`. This is addressed by prefixing the "negative" revs with `^` explicitly rather than relying on the `--not` option (thanks for coming up with that idea, Max!). This fixes https://github.com/git-for-windows/git/issues/1987 Analysis-and-initial-patch-by: Max Kirillov Signed-off-by: Johannes Schindelin --- gitk-git/gitk | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/gitk-git/gitk b/gitk-git/gitk index 0ae7d68590..92375ca6a2 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -405,14 +405,16 @@ 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 "--" $files] "\\n"]"] r] } err]} { error_popup "[mc "Error executing git log:"] $err" return 0 @@ -554,13 +556,19 @@ 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 "--" \ + $vfilelimit($view)] "\\n"]"] r] } err]} { error_popup "[mc "Error executing git log:"] $err" return @@ -10231,10 +10239,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 From b1bbf97d944aa1fa4d1299433efe3068a98ce3c9 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 7 Dec 2018 13:39:30 +0100 Subject: [PATCH 008/105] clean: do not traverse mount points It seems to be not exactly rare on Windows to install NTFS junction points (the equivalent of "bind mounts" on Linux/Unix) in worktrees, e.g. to map some development tools into a subdirectory. In such a scenario, it is pretty horrible if `git clean -dfx` traverses into the mapped directory and starts to "clean up". Let's just not do that. Let's make sure before we traverse into a directory that it is not a mount point (or junction). This addresses https://github.com/git-for-windows/git/issues/607 Signed-off-by: Johannes Schindelin --- builtin/clean.c | 14 ++++++++++++++ cache.h | 1 + compat/mingw.c | 22 ++++++++++++++++++++++ compat/mingw.h | 3 +++ git-compat-util.h | 4 ++++ path.c | 39 +++++++++++++++++++++++++++++++++++++++ t/t7300-clean.sh | 9 +++++++++ 7 files changed, 92 insertions(+) diff --git a/builtin/clean.c b/builtin/clean.c index 5466636e66..34d56426d7 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -34,6 +34,8 @@ 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"); +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"); 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"); static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n"); @@ -175,6 +177,18 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, goto out; } + if (is_mount_point(path)) { + if (!quiet) { + quote_path(path->buf, prefix, "ed, 0); + printf(dry_run ? + _(msg_would_skip_mount_point) : + _(msg_skip_mount_point), quoted.buf); + } + *dir_gone = 0; + + goto out; + } + dir = opendir(path->buf); if (!dir) { /* an empty dir could be removed even if it is unreadble */ diff --git a/cache.h b/cache.h index ac5ab4ef9d..7a9ee4e44b 100644 --- a/cache.h +++ b/cache.h @@ -1306,6 +1306,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 2607de93af..dd0b44e43c 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2508,6 +2508,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; diff --git a/compat/mingw.h b/compat/mingw.h index a74da68f31..b3304f4eb5 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -449,6 +449,9 @@ 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 PATH_SEP ';' char *mingw_query_user_email(void); #define query_user_email mingw_query_user_email diff --git a/git-compat-util.h b/git-compat-util.h index fd36d3bfdc..9d51debaad 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -521,6 +521,10 @@ 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 diff --git a/path.c b/path.c index a3cfcd8a6e..b41c645c89 100644 --- a/path.c +++ b/path.c @@ -1300,6 +1300,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/t/t7300-clean.sh b/t/t7300-clean.sh index 0399701e62..6439e0f723 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -788,4 +788,13 @@ test_expect_success 'traverse into directories that may have ignored entries' ' ) ' +test_expect_success MINGW 'clean does not traverse mount points' ' + mkdir target && + >target/dont-clean-me && + git init with-mountpoint && + cmd //c "mklink /j with-mountpoint\\mountpoint target" && + git -C with-mountpoint clean -dfx && + test_path_is_file target/dont-clean-me +' + test_done From 97b15773e976f8d5e21d96584fbc64de60a1a0d6 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 18 Apr 2017 12:38:30 +0200 Subject: [PATCH 009/105] mingw: allow absolute paths without drive prefix When specifying an absolute path without a drive prefix, we convert that path internally. Let's make sure that we handle that case properly, too ;-) This fixes the command git clone https://github.com/git-for-windows/git \G4W Signed-off-by: Johannes Schindelin --- compat/mingw.c | 10 +++++++++- t/t5580-unc-paths.sh | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..30b0f78a3d 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1048,11 +1048,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; } diff --git a/t/t5580-unc-paths.sh b/t/t5580-unc-paths.sh index 116204b59d..2c5b410048 100755 --- a/t/t5580-unc-paths.sh +++ b/t/t5580-unc-paths.sh @@ -33,7 +33,7 @@ case "$UNCPATH" in ;; esac -test_expect_failure 'clone into absolute path lacking a drive prefix' ' +test_expect_success 'clone into absolute path lacking a drive prefix' ' USINGBACKSLASHES="$(echo "$WITHOUTDRIVE"/without-drive-prefix | tr / \\\\)" && git clone . "$USINGBACKSLASHES" && From f73dbb687f94173d3c6a2606aa9d95570d8b59f8 Mon Sep 17 00:00:00 2001 From: Rohit Ashiwal Date: Tue, 19 Feb 2019 22:28:41 +0530 Subject: [PATCH 010/105] archive: avoid spawning `gzip` As we already link to the zlib library, we can perform the compression without even requiring gzip on the host machine. Signed-off-by: Rohit Ashiwal Signed-off-by: Johannes Schindelin --- archive-tar.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/archive-tar.c b/archive-tar.c index 74dfc635b8..ae87fe646e 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -455,18 +455,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"), cmd.buf); - 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"), cmd.buf); + 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"), cmd.buf); + if (gzip) { + if (gzclose(gzip) != Z_OK) + die(_("gzclose failed")); + } else { + close(1); + if (finish_command(&filter) != 0) + die(_("'%s' filter reported error"), cmd.buf); + } strbuf_release(&cmd); return r; From 4b8247221ecde434b8418b99a40d26b22c891530 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 4 Sep 2017 11:59:45 +0200 Subject: [PATCH 011/105] mingw: change core.fsyncObjectFiles = 1 by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the documentation of said setting: This boolean will enable fsync() when writing object files. This is a total waste of time and effort on a filesystem that orders data writes properly, but can be useful for filesystems that do not use journalling (traditional UNIX filesystems) or that only journal metadata and not file contents (OS X’s HFS+, or Linux ext3 with "data=writeback"). The most common file system on Windows (NTFS) does not guarantee that order, therefore a sudden loss of power (or any other event causing an unclean shutdown) would cause corrupt files (i.e. files filled with NULs). Therefore we need to change the default. Note that the documentation makes it sound as if this causes really bad performance. In reality, writing loose objects is something that is done only rarely, and only a handful of files at a time. Signed-off-by: Johannes Schindelin --- compat/mingw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..b13b976674 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2974,6 +2974,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]); From b7a2d103f28c7c7168be7ff511711c647cfe02cf Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Mon, 19 Aug 2019 20:46:12 +0200 Subject: [PATCH 012/105] gitk: Escape file paths before piping to git log Fixes https://github.com/git-for-windows/git/issues/2293 Signed-off-by: Nico Rieck --- gitk-git/gitk | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/gitk-git/gitk b/gitk-git/gitk index 92375ca6a2..df3ba2ea99 100755 --- a/gitk-git/gitk +++ b/gitk-git/gitk @@ -353,6 +353,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 @@ -414,7 +424,8 @@ proc start_rev_list {view} { if {[catch { set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \ --parents --boundary $args --stdin \ - "<<[join [concat $revs "--" $files] "\\n"]"] r] + "<<[join [concat $revs "--" \ + [escape_filter_paths $files]] "\\n"]"] r] } err]} { error_popup "[mc "Error executing git log:"] $err" return 0 @@ -568,7 +579,8 @@ proc updatecommits {} { set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \ --parents --boundary $args --stdin \ "<<[join [concat $revs "--" \ - $vfilelimit($view)] "\\n"]"] r] + [escape_filter_paths \ + $vfilelimit($view)]] "\\n"]"] r] } err]} { error_popup "[mc "Error executing git log:"] $err" return From 7c65717fc2d78f3029d08f699bad9d728c0522d6 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 11 Dec 2018 12:55:26 +0100 Subject: [PATCH 013/105] clean: remove mount points when possible Windows' equivalent to "bind mounts", NTFS junction points, can be unlinked without affecting the mount target. This is clearly what users expect to happen when they call `git clean -dfx` in a worktree that contains NTFS junction points: the junction should be removed, and the target directory of said junction should be left alone (unless it is inside the worktree). Signed-off-by: Johannes Schindelin --- builtin/clean.c | 13 +++++++++++++ compat/mingw.h | 1 + t/t7300-clean.sh | 1 + 3 files changed, 15 insertions(+) diff --git a/builtin/clean.c b/builtin/clean.c index 34d56426d7..cb55e8956b 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -34,8 +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"); static const char *msg_skip_cwd = N_("Refusing to remove current working directory\n"); @@ -178,6 +180,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, } if (is_mount_point(path)) { +#ifndef CAN_UNLINK_MOUNT_POINTS if (!quiet) { quote_path(path->buf, prefix, "ed, 0); printf(dry_run ? @@ -185,6 +188,16 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag, _(msg_skip_mount_point), quoted.buf); } *dir_gone = 0; +#else + if (!dry_run && unlink(path->buf)) { + int saved_errno = errno; + quote_path(path->buf, prefix, "ed, 0); + errno = saved_errno; + warning_errno(_(msg_warn_remove_failed), quoted.buf); + *dir_gone = 0; + ret = -1; + } +#endif goto out; } diff --git a/compat/mingw.h b/compat/mingw.h index b3304f4eb5..84e007bcf5 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -452,6 +452,7 @@ static inline void convert_slashes(char *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 diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 6439e0f723..336f41c742 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -794,6 +794,7 @@ test_expect_success MINGW 'clean does not traverse mount points' ' git init with-mountpoint && cmd //c "mklink /j with-mountpoint\\mountpoint target" && git -C with-mountpoint clean -dfx && + test_path_is_missing with-mountpoint/mountpoint && test_path_is_file target/dont-clean-me ' From c1d2666978a3baff908285b0bad3d04e22f1141d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 16 Feb 2015 14:06:59 +0100 Subject: [PATCH 014/105] mingw: include the Python parts in the build While Git for Windows does not _ship_ Python (in order to save on bandwidth), MSYS2 provides very fine Python interpreters that users can easily take advantage of, by using Git for Windows within its SDK. Signed-off-by: Johannes Schindelin --- config.mak.uname | 1 + 1 file changed, 1 insertion(+) diff --git a/config.mak.uname b/config.mak.uname index ce83cad47a..7fc924d036 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -722,6 +722,7 @@ else 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 From 34ad2f8a0b216744c10d3e0e5c716c03f266a20f Mon Sep 17 00:00:00 2001 From: Thomas Braun Date: Thu, 8 May 2014 21:43:24 +0200 Subject: [PATCH 015/105] Config option to disable side-band-64k for transport Since commit 0c499ea60f the send-pack builtin uses the side-band-64k capability if advertised by the server. Unfortunately this breaks pushing over the dump git protocol if used over a network connection. The detailed reasons for this breakage are (by courtesy of Jeff Preshing, quoted from ttps://groups.google.com/d/msg/msysgit/at8D7J-h7mw/eaLujILGUWoJ): ---------------------------------------------------------------------------- MinGW wraps Windows sockets in CRT file descriptors in order to mimic the functionality of POSIX sockets. This causes msvcrt.dll to treat sockets as Installable File System (IFS) handles, calling ReadFile, WriteFile, DuplicateHandle and CloseHandle on them. This approach works well in simple cases on recent versions of Windows, but does not support all usage patterns. In particular, using this approach, any attempt to read & write concurrently on the same socket (from one or more processes) will deadlock in a scenario where the read waits for a response from the server which is only invoked after the write. This is what send_pack currently attempts to do in the use_sideband codepath. ---------------------------------------------------------------------------- The new config option "sendpack.sideband" allows to override the side-band-64k capability of the server, and thus makes the dump git protocol work. Other transportation methods like ssh and http/https still benefit from the sideband channel, therefore the default value of "sendpack.sideband" is still true. [jes: split out the documentation into Documentation/config/] Signed-off-by: Thomas Braun Signed-off-by: Johannes Schindelin Signed-off-by: Oliver Schneider --- Documentation/config.txt | 2 ++ Documentation/config/sendpack.txt | 5 +++++ send-pack.c | 14 +++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 Documentation/config/sendpack.txt diff --git a/Documentation/config.txt b/Documentation/config.txt index e284b042f2..c662bf86e0 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -499,6 +499,8 @@ include::config/safe.txt[] include::config/sendemail.txt[] +include::config/sendpack.txt[] + include::config/sequencer.txt[] include::config/showbranch.txt[] 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/send-pack.c b/send-pack.c index bc0fcdbb00..a5821515b3 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 && @@ -494,6 +504,8 @@ int send_pack(struct send_pack_args *args, return 0; } + git_config(send_pack_config, NULL); + git_config_get_bool("push.negotiate", &push_negotiate); if (push_negotiate) get_commons_through_negotiation(args->url, remote_refs, &commons); @@ -509,7 +521,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; From cdf6778c5d098c161abfc41f21a10c046c92fae3 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 14 Nov 2019 20:09:23 +0100 Subject: [PATCH 016/105] mingw: make sure `errno` is set correctly when socket operations fail The winsock2 library provides functions that work on different data types than file descriptors, therefore we wrap them. But that is not the only difference: they also do not set `errno` but expect the callers to enquire about errors via `WSAGetLastError()`. Let's translate that into appropriate `errno` values whenever the socket operations fail so that Git's code base does not have to change its expectations. This closes https://github.com/git-for-windows/git/issues/2404 Helped-by: Jeff Hostetler Signed-off-by: Johannes Schindelin --- compat/mingw.c | 157 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 147 insertions(+), 10 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..49679fdcf0 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2020,18 +2020,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 @@ -2039,7 +2171,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) @@ -2059,7 +2191,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 */ @@ -2075,35 +2207,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 @@ -2114,6 +2246,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; From b18c43ce2a390ac8822b435fc1eda17ce61b5f79 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 31 Jan 2020 12:02:47 +0100 Subject: [PATCH 017/105] mingw: demonstrate a `git add` issue with NTFS junctions NTFS junctions are somewhat similar in spirit to Unix bind mounts: they point to a different directory and are resolved by the filesystem driver. As such, they appear to `lstat()` as if they are directories, not as if they are symbolic links. _Any_ user can create junctions, while symbolic links can only be created by non-administrators in Developer Mode on Windows 10. Hence NTFS junctions are much more common "in the wild" than NTFS symbolic links. It was reported in https://github.com/git-for-windows/git/issues/2481 that adding files via an absolute path that traverses an NTFS junction: since 1e64d18 (mingw: do resolve symlinks in `getcwd()`), we resolve not only symbolic links but also NTFS junctions when determining the absolute path of the current directory. The same is not true for `git add `, where symbolic links are resolved in ``, but not NTFS junctions. Signed-off-by: Johannes Schindelin --- t/t3700-add.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 8979c8a5f0..a3659ecd16 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -498,4 +498,15 @@ test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' ' git add "$downcased" ' +test_expect_failure 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 From 0f40f18c2cb4304530cfb4efb4d8a10877e9d577 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 31 Jan 2020 11:44:31 +0100 Subject: [PATCH 018/105] strbuf_realpath(): use platform-dependent API if available Some platforms (e.g. Windows) provide API functions to resolve paths much quicker. Let's offer a way to short-cut `strbuf_realpath()` on those platforms. Signed-off-by: Johannes Schindelin --- abspath.c | 3 +++ git-compat-util.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/abspath.c b/abspath.c index 39e06b5848..7a5f114382 100644 --- a/abspath.c +++ b/abspath.c @@ -91,6 +91,9 @@ static char *strbuf_realpath_1(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/git-compat-util.h b/git-compat-util.h index fd36d3bfdc..ba745b4389 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -525,6 +525,10 @@ static inline int git_has_dir_sep(const char *path) #define query_user_email() NULL #endif +#ifndef platform_strbuf_realpath +#define platform_strbuf_realpath(resolved, path) NULL +#endif + #ifdef __TANDEM #include #include From 33201fb1143e5c93d34af36a691c63ed69d1a614 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 1 Jan 2020 21:07:22 +0100 Subject: [PATCH 019/105] mingw: do resolve symlinks in `getcwd()` As pointed out in https://github.com/git-for-windows/git/issues/1676, the `git rev-parse --is-inside-work-tree` command currently fails when the current directory's path contains symbolic links. The underlying reason for this bug is that `getcwd()` is supposed to resolve symbolic links, but our `mingw_getcwd()` implementation did not. We do have all the building blocks for that, though: the `GetFinalPathByHandleW()` function will resolve symbolic links. However, we only called that function if `GetLongPathNameW()` failed, for historical reasons: the latter function was supported for a long time, but the former API function was introduced only with Windows Vista, and we used to support also Windows XP. With that support having been dropped, we are free to call the symbolic link-resolving function right away. Signed-off-by: Johannes Schindelin --- compat/mingw.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..a8be954bce 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1121,18 +1121,16 @@ 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)) @@ -1141,13 +1139,11 @@ char *mingw_getcwd(char *pointer, int len) return NULL; return pointer; } - if (!ret || ret >= ARRAY_SIZE(wpointer)) - return NULL; - if (GetFileAttributesW(wpointer) == INVALID_FILE_ATTRIBUTES) { + if (GetFileAttributesW(cwd) == INVALID_FILE_ATTRIBUTES) { errno = ENOENT; return NULL; } - if (xwcstoutf(pointer, wpointer, len) < 0) + if (xwcstoutf(pointer, cwd, len) < 0) return NULL; convert_slashes(pointer); return pointer; From 1939dc02b9d9f15b2119ab723f1afc6929f92014 Mon Sep 17 00:00:00 2001 From: Bjoern Mueller Date: Wed, 22 Jan 2020 13:49:13 +0100 Subject: [PATCH 020/105] mingw: fix fatal error working on mapped network drives on Windows In 1e64d18 (mingw: do resolve symlinks in `getcwd()`) a problem was introduced that causes git for Windows to stop working with certain mapped network drives (in particular, drives that are mapped to locations with long path names). Error message was "fatal: Unable to read current working directory: No such file or directory". Present change fixes this issue as discussed in https://github.com/git-for-windows/git/issues/2480 Signed-off-by: Bjoern Mueller --- compat/mingw.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..865b86c45f 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1135,8 +1135,13 @@ char *mingw_getcwd(char *pointer, int len) return NULL; 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; From a77a855620f0e7896f362eee8052fc0300671639 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Thu, 30 Jan 2020 14:22:27 -0500 Subject: [PATCH 021/105] clink.pl: fix MSVC compile script to handle libcurl-d.lib Update clink.pl to link with either libcurl.lib or libcurl-d.lib depending on whether DEBUG=1 is set. Signed-off-by: Jeff Hostetler Signed-off-by: Johannes Schindelin --- compat/vcbuild/scripts/clink.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl index 3bd824154b..c4c99d1a11 100755 --- a/compat/vcbuild/scripts/clink.pl +++ b/compat/vcbuild/scripts/clink.pl @@ -56,7 +56,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; From a7a0f0aa9d509140388004d5dc90e1a3d6760a80 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 31 Jan 2020 11:49:04 +0100 Subject: [PATCH 022/105] mingw: implement a platform-specific `strbuf_realpath()` There is a Win32 API function to resolve symbolic links, and we can use that instead of resolving them manually. Even better, this function also resolves NTFS junction points (which are somewhat similar to bind mounts). This fixes https://github.com/git-for-windows/git/issues/2481. Signed-off-by: Johannes Schindelin --- compat/mingw.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ compat/mingw.h | 3 +++ t/t3700-add.sh | 2 +- t/t5601-clone.sh | 7 ++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..2764204c55 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1117,6 +1117,69 @@ struct tm *localtime_r(const time_t *timep, struct tm *result) } #endif +char *mingw_strbuf_realpath(struct strbuf *resolved, const char *path) +{ + wchar_t wpath[MAX_PATH]; + HANDLE h; + DWORD ret; + int len; + const char *last_component = NULL; + + 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); + + /* + * strbuf_realpath() allows the last path component to not exist. If + * that is the case, now it's time to try without last component. + */ + if (h == INVALID_HANDLE_VALUE && + GetLastError() == ERROR_FILE_NOT_FOUND) { + /* cut last component off of `wpath` */ + wchar_t *p = wpath + wcslen(wpath); + + while (p != wpath) + if (*(--p) == L'/' || *p == L'\\') + break; /* found start of last component */ + + if (p != wpath && (last_component = find_last_dir_sep(path))) { + last_component++; /* skip directory separator */ + *p = L'\0'; + 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; + + if (last_component) { + /* Use forward-slash, like `normalize_ntpath()` */ + strbuf_addch(resolved, '/'); + strbuf_addstr(resolved, last_component); + } + + return resolved->buf; + +} + char *mingw_getcwd(char *pointer, int len) { wchar_t cwd[MAX_PATH], wpointer[MAX_PATH]; diff --git a/compat/mingw.h b/compat/mingw.h index a74da68f31..3bbb11e3ed 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -452,6 +452,9 @@ static inline void convert_slashes(char *path) #define PATH_SEP ';' char *mingw_query_user_email(void); #define query_user_email mingw_query_user_email +struct strbuf; +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/t/t3700-add.sh b/t/t3700-add.sh index a3659ecd16..208f9a5ac3 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -498,7 +498,7 @@ test_expect_success CASE_INSENSITIVE_FS 'path is case-insensitive' ' git add "$downcased" ' -test_expect_failure MINGW 'can add files via NTFS junctions' ' +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" && diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index d2f046b4b9..2d3f734b35 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -94,6 +94,13 @@ test_expect_success 'clone does not detect username:password when it is https:// ! grep "uses plaintext credentials" err ' +test_expect_success CASE_INSENSITIVE_FS 'core.worktree is not added due to path case' ' + + mkdir UPPERCASE && + git clone src "$(pwd)/uppercase" && + test "unset" = "$(git -C UPPERCASE config --default unset core.worktree)" +' + test_expect_success 'clone from hooks' ' test_create_repo r0 && From 42d8cb0afa22fc9669986a3d2521a6c5f6a13326 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 21 Feb 2017 13:28:58 +0100 Subject: [PATCH 023/105] mingw: ensure valid CTYPE A change between versions 2.4.1 and 2.6.0 of the MSYS2 runtime modified how Cygwin's runtime (and hence Git for Windows' MSYS2 runtime derivative) handles locales: d16a56306d (Consolidate wctomb/mbtowc calls for POSIX-1.2008, 2016-07-20). An unintended side-effect is that "cold-calling" into the POSIX emulation will start with a locale based on the current code page, something that Git for Windows is very ill-prepared for, as it expects to be able to pass a command-line containing non-ASCII characters to the shell without having those characters munged. One symptom of this behavior: when `git clone` or `git fetch` shell out to call `git-upload-pack` with a path that contains non-ASCII characters, the shell tried to interpret the entire command-line (including command-line parameters) as executable path, which obviously must fail. This fixes https://github.com/git-for-windows/git/issues/1036 Signed-off-by: Johannes Schindelin --- compat/mingw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..c59246ba0a 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2644,6 +2644,9 @@ static void setup_windows_environment(void) if (!tmp && (tmp = getenv("USERPROFILE"))) setenv("HOME", tmp, 1); } + + if (!getenv("LC_ALL") && !getenv("LC_CTYPE") && !getenv("LANG")) + setenv("LC_CTYPE", "C.UTF-8", 1); } static PSID get_current_user_sid(void) From e630a272e13abb88699b079170f60e3cb04914dd Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 9 May 2020 14:08:36 +0200 Subject: [PATCH 024/105] vcxproj: unclash project directories with build outputs It already caused problems with the test suite that the directory containing `git.vcxproj` is called the same as the Git executable without its file extension: `./git` is ambiguous, it could refer both to the directory `git/` as well as to `git.exe`. Now there is one more problem: when our GitHub workflow runs on the `vs/master` branch, it fails in all but the Windows builds, as they want to write the file `git` but there is already a directory in the way. Let's just go ahead and append `.proj` to all of those directories, e.g. `git.proj/` instead of `git/`. Signed-off-by: Johannes Schindelin --- config.mak.uname | 8 ++++---- contrib/buildsystems/Generators/Vcxproj.pm | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/config.mak.uname b/config.mak.uname index ce83cad47a..fa088a255d 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -756,7 +756,7 @@ vcxproj: # Make .vcxproj files and add them 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 '' && \ @@ -766,7 +766,7 @@ vcxproj: echo ' '; \ done && \ echo ' ' && \ - echo '') >git/LinkOrCopyBuiltins.targets + echo '') >git.proj/LinkOrCopyBuiltins.targets (echo '' && \ echo ' ' && \ for name in $(REMOTE_CURL_ALIASES); \ @@ -774,8 +774,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 generated headers $(MAKE) MSVC=1 SKIP_VCPKG=1 prefix=/mingw64 $(GENERATED_H) diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm index 1a25789d28..81ee2f5a4a 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"}})); @@ -89,7 +89,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"; @@ -237,7 +239,7 @@ EOM print F << "EOM"; - + $uuid_libgit false @@ -252,7 +254,7 @@ EOM } if (!($name =~ 'xdiff')) { print F << "EOM"; - + $uuid_xdiff_lib false @@ -261,7 +263,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 @@ -338,7 +340,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) { @@ -348,7 +350,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"; } From df6a8ac48dee24d4ad7bb5f90a6c1fc4d1d225c0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 1 Feb 2020 00:31:16 +0100 Subject: [PATCH 025/105] mingw: allow `git.exe` to be used instead of the "Git wrapper" Git for Windows wants to add `git.exe` to the users' `PATH`, without cluttering the latter with unnecessary executables such as `wish.exe`. To that end, it invented the concept of its "Git wrapper", i.e. a tiny executable located in `C:\Program Files\Git\cmd\git.exe` (originally a CMD script) whose sole purpose is to set up a couple of environment variables and then spawn the _actual_ `git.exe` (which nowadays lives in `C:\Program Files\Git\mingw64\bin\git.exe` for 64-bit, and the obvious equivalent for 32-bit installations). Currently, the following environment variables are set unless already initialized: - `MSYSTEM`, to make sure that the MSYS2 Bash and the MSYS2 Perl interpreter behave as expected, and - `PLINK_PROTOCOL`, to force PuTTY's `plink.exe` to use the SSH protocol instead of Telnet, - `PATH`, to make sure that the `bin` folder in the user's home directory, as well as the `/mingw64/bin` and the `/usr/bin` directories are included. The trick here is that the `/mingw64/bin/` and `/usr/bin/` directories are relative to the top-level installation directory of Git for Windows (which the included Bash interprets as `/`, i.e. as the MSYS pseudo root directory). Using the absence of `MSYSTEM` as a tell-tale, we can detect in `git.exe` whether these environment variables have been initialized properly. Therefore we can call `C:\Program Files\Git\mingw64\bin\git` in-place after this change, without having to call Git through the Git wrapper. Obviously, above-mentioned directories must be _prepended_ to the `PATH` variable, otherwise we risk picking up executables from unrelated Git installations. We do that by constructing the new `PATH` value from scratch, appending `$HOME/bin` (if `HOME` is set), then the MSYS2 system directories, and then appending the original `PATH`. Side note: this modification of the `PATH` variable is independent of the modification necessary to reach the executables and scripts in `/mingw64/libexec/git-core/`, i.e. the `GIT_EXEC_PATH`. That modification is still performed by Git, elsewhere, long after making the changes described above. While we _still_ cannot simply hard-link `mingw64\bin\git.exe` to `cmd` (because the former depends on a couple of `.dll` files that are only in `mingw64\bin`, i.e. calling `...\cmd\git.exe` would fail to load due to missing dependencies), at least we can now avoid that extra process of running the Git wrapper (which then has to wait for the spawned `git.exe` to finish) by calling `...\mingw64\bin\git.exe` directly, via its absolute path. Testing this is in Git's test suite tricky: we set up a "new" MSYS pseudo-root and copy the `git.exe` file into the appropriate location, then verify that `MSYSTEM` is set properly, and also that the `PATH` is modified so that scripts can be found in `$HOME/bin`, `/mingw64/bin/` and `/usr/bin/`. This addresses https://github.com/git-for-windows/git/issues/2283 Signed-off-by: Johannes Schindelin --- compat/mingw.c | 69 +++++++++++++++++++++++++++++++++++++++++++ config.mak.uname | 4 +-- t/t0060-path-utils.sh | 23 ++++++++++++++- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/compat/mingw.c b/compat/mingw.c index c59246ba0a..5bc515bcdd 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2593,6 +2593,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"); @@ -2645,6 +2686,34 @@ static void setup_windows_environment(void) 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.UTF-8", 1); } diff --git a/config.mak.uname b/config.mak.uname index ce83cad47a..6a1ca33ea9 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -487,7 +487,7 @@ endif 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 @@ -712,7 +712,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 INTERNAL_QSORT = YesPlease diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index aa35350b6f..5eefa5ddb1 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -548,7 +548,8 @@ test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD 'RUNTIME_PREFIX wor cp "$GIT_EXEC_PATH"/git$X pretend/bin/ && GIT_EXEC_PATH= ./pretend/bin/git here >actual && echo HERE >expect && - test_cmp expect actual' + test_cmp expect actual +' test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works' ' mkdir -p pretend/bin && @@ -559,4 +560,24 @@ test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works' test_cmp expect actual ' +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_done From 17c5d7dc7f839aa359bf9feae40fff1da90ac9e7 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 9 May 2020 16:19:06 +0200 Subject: [PATCH 026/105] t5505/t5516: allow running without `.git/branches/` in the templates When we commit the template directory as part of `make vcxproj`, the `branches/` directory is not actually commited, as it is empty. Two tests were not prepared for that situation. This developer tried to get rid of the support for `.git/branches/` a long time ago, but that effort did not bear fruit, so the best we can do is work around in these here tests. Signed-off-by: Johannes Schindelin --- t/t5505-remote.sh | 2 ++ t/t5516-fetch-push.sh | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index fff14e13ed..6c1581e530 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -962,6 +962,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' ( cd six && git remote rm origin && + mkdir -p .git/branches && echo "$origin_url#main" >.git/branches/origin && git remote rename origin origin && test_path_is_missing .git/branches/origin && @@ -976,6 +977,7 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' ( cd seven && git remote rm origin && + mkdir -p .git/branches && echo "quux#foom" > .git/branches/origin && git remote rename origin origin && test_path_is_missing .git/branches/origin && diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index dedca106a7..09337b8716 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -937,6 +937,7 @@ test_expect_success 'fetch with branches' ' mk_empty testrepo && git branch second $the_first_commit && git checkout second && + mkdir -p testrepo/.git/branches && echo ".." > testrepo/.git/branches/branch1 && ( cd testrepo && @@ -950,6 +951,7 @@ test_expect_success 'fetch with branches' ' test_expect_success 'fetch with branches containing #' ' mk_empty testrepo && + mkdir -p testrepo/.git/branches && echo "..#second" > testrepo/.git/branches/branch2 && ( cd testrepo && @@ -964,6 +966,7 @@ test_expect_success 'fetch with branches containing #' ' test_expect_success 'push with branches' ' mk_empty testrepo && git checkout second && + mkdir -p .git/branches && echo "testrepo" > .git/branches/branch1 && git push branch1 && ( @@ -976,6 +979,7 @@ test_expect_success 'push with branches' ' test_expect_success 'push with branches containing #' ' mk_empty testrepo && + mkdir -p .git/branches && echo "testrepo#branch3" > .git/branches/branch2 && git push branch2 && ( From 2803e58b8d4b8ae84d4286c54445e8f418bbf69c Mon Sep 17 00:00:00 2001 From: Kelly Heller Date: Wed, 27 May 2015 14:51:43 -0700 Subject: [PATCH 027/105] Allow `add -p` and `add -i` with a large number of files This fixes https://github.com/msysgit/git/issues/182. Inspired by Pull Request 218 using code from @PhilipDavis. [jes: simplified code quite a bit] Signed-off-by: Kelly Heller Signed-off-by: Johannes Schindelin --- git-add--interactive.perl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/git-add--interactive.perl b/git-add--interactive.perl index 95887fd8e5..63dd89a651 100755 --- a/git-add--interactive.perl +++ b/git-add--interactive.perl @@ -174,6 +174,24 @@ sub run_cmd_pipe { die "$^O does not support: @invalid\n" if @invalid; my @args = map { m/ /o ? "\"$_\"": $_ } @_; return qx{@args}; + } elsif (($^O eq 'MSWin32' || $^O eq 'msys') && (scalar @_ > 200) && + grep $_ eq '--', @_) { + use File::Temp qw(tempfile); + my ($fhargs, $filename) = + tempfile('git-args-XXXXXX', UNLINK => 1); + + my $cmd = 'cat '.$filename.' | xargs -0 -s 20000 '; + while ($_[0] ne '--') { + $cmd = $cmd . shift(@_) . ' '; + } + + shift(@_); + print $fhargs join("\0", @_); + close($fhargs); + + my $fh = undef; + open($fh, '-|', $cmd) or die; + return <$fh>; } else { my $fh = undef; open($fh, '-|', @_) or die; From 9211a398d318c17de287c7dd8028e1427493a45a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 25 Aug 2020 12:13:26 +0200 Subject: [PATCH 028/105] mingw: ignore HOMEDRIVE/HOMEPATH if it points to Windows' system directory Internally, Git expects the environment variable `HOME` to be set, and to point to the current user's home directory. This environment variable is not set by default on Windows, and therefore Git tries its best to construct one if it finds `HOME` unset. There are actually two different approaches Git tries: first, it looks at `HOMEDRIVE`/`HOMEPATH` because this is widely used in corporate environments with roaming profiles, and a user generally wants their global Git settings to be in a roaming profile. Only when `HOMEDRIVE`/`HOMEPATH` is either unset or does not point to a valid location, Git will fall back to using `USERPROFILE` instead. However, starting with Windows Vista, for secondary logons and services, the environment variables `HOMEDRIVE`/`HOMEPATH` point to Windows' system directory (usually `C:\Windows\system32`). That is undesirable, and that location is usually write-protected anyway. So let's verify that the `HOMEDRIVE`/`HOMEPATH` combo does not point to Windows' system directory before using it, falling back to `USERPROFILE` if it does. This fixes git-for-windows#2709 Initial-Path-by: Ivan Pozdeev Signed-off-by: Johannes Schindelin --- compat/mingw.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/compat/mingw.c b/compat/mingw.c index 5bc515bcdd..7ed2b804a9 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -2634,6 +2634,18 @@ static size_t append_system_bin_dirs(char *path, size_t size) } #endif +static int is_system32_path(const char *path) +{ + WCHAR system32[MAX_PATH], wpath[MAX_PATH]; + + if (xutftowcs_path(wpath, path) < 0 || + !GetSystemDirectoryW(system32, ARRAY_SIZE(system32)) || + _wcsicmp(system32, wpath)) + return 0; + + return 1; +} + static void setup_windows_environment(void) { char *tmp = getenv("TMPDIR"); @@ -2674,7 +2686,8 @@ static void setup_windows_environment(void) strbuf_addstr(&buf, tmp); if ((tmp = getenv("HOMEPATH"))) { strbuf_addstr(&buf, tmp); - if (is_directory(buf.buf)) + if (!is_system32_path(buf.buf) && + is_directory(buf.buf)) setenv("HOME", buf.buf, 1); else tmp = NULL; /* use $USERPROFILE */ From ed6426238ceac1a8e8c997e53e6700754afd3c46 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 4 Mar 2020 21:55:28 +0100 Subject: [PATCH 029/105] http: use new "best effort" strategy for Secure Channel revoke checking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The native Windows HTTPS backend is based on Secure Channel which lets the caller decide how to handle revocation checking problems caused by missing information in the certificate or offline CRL distribution points. Unfortunately, cURL chose to handle these problems differently than OpenSSL by default: while OpenSSL happily ignores those problems (essentially saying "¯\_(ツ)_/¯"), the Secure Channel backend will error out instead. As a remedy, the "no revoke" mode was introduced, which turns off revocation checking altogether. This is a bit heavy-handed. We support this via the `http.schannelCheckRevoke` setting. In https://github.com/curl/curl/pull/4981, we contributed an opt-in "best effort" strategy that emulates what OpenSSL seems to do. In Git for Windows, we actually want this to be the default. This patch makes it so, introducing it as a new value for the `http.schannelCheckRevoke" setting, which now becmes a tristate: it accepts the values "false", "true" or "best-effort" (defaulting to the last one). Signed-off-by: Johannes Schindelin --- Documentation/config/http.txt | 12 +++++++----- http.c | 26 ++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt index 179d03e57b..ebdee6dc09 100644 --- a/Documentation/config/http.txt +++ b/Documentation/config/http.txt @@ -189,11 +189,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/http.c b/http.c index 11c6f69fac..1ad95be438 100644 --- a/http.c +++ b/http.c @@ -136,7 +136,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 @@ -287,7 +293,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; } @@ -819,9 +837,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) { #ifdef GIT_CURL_HAVE_CURLSSLOPT_NO_REVOKE - 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 From 4c72664ab7e33171d92d42a547d034e6a7e3575c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 9 May 2020 19:24:23 +0200 Subject: [PATCH 030/105] t5505/t5516: fix white-space around redirectors The convention in Git project's shell scripts is to have white-space _before_, but not _after_ the `>` (or `<`). Signed-off-by: Johannes Schindelin --- t/t5505-remote.sh | 6 +++--- t/t5516-fetch-push.sh | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 6c1581e530..4747f6f87c 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -769,8 +769,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$" .git/branches/origin && + echo "quux#foom" >.git/branches/origin && git remote rename origin origin && test_path_is_missing .git/branches/origin && test "$(git config remote.origin.url)" = "quux" && diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 09337b8716..5841f48d79 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -938,7 +938,7 @@ test_expect_success 'fetch with branches' ' git branch second $the_first_commit && git checkout second && mkdir -p testrepo/.git/branches && - echo ".." > testrepo/.git/branches/branch1 && + echo ".." >testrepo/.git/branches/branch1 && ( cd testrepo && git fetch branch1 && @@ -952,7 +952,7 @@ test_expect_success 'fetch with branches' ' test_expect_success 'fetch with branches containing #' ' mk_empty testrepo && mkdir -p testrepo/.git/branches && - echo "..#second" > testrepo/.git/branches/branch2 && + echo "..#second" >testrepo/.git/branches/branch2 && ( cd testrepo && git fetch branch2 && @@ -967,7 +967,7 @@ test_expect_success 'push with branches' ' mk_empty testrepo && git checkout second && mkdir -p .git/branches && - echo "testrepo" > .git/branches/branch1 && + echo "testrepo" >.git/branches/branch1 && git push branch1 && ( cd testrepo && @@ -980,7 +980,7 @@ test_expect_success 'push with branches' ' test_expect_success 'push with branches containing #' ' mk_empty testrepo && mkdir -p .git/branches && - echo "testrepo#branch3" > .git/branches/branch2 && + echo "testrepo#branch3" >.git/branches/branch2 && git push branch2 && ( cd testrepo && @@ -1508,7 +1508,7 @@ EOF git init no-thin && git --git-dir=no-thin/.git config receive.unpacklimit 0 && git push no-thin/.git refs/heads/main:refs/heads/foo && - echo modified >> path1 && + echo modified >>path1 && git commit -am modified && git repack -adf && rcvpck="git receive-pack --reject-thin-pack-for-testing" && From 12b33ce72791479d7b9fd7dc03a8759c7c209a2b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 12 Sep 2015 12:25:47 +0200 Subject: [PATCH 031/105] t3701: verify that we can add *lots* of files interactively Signed-off-by: Johannes Schindelin --- t/t3701-add-interactive.sh | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 94537a6b40..369203f7e0 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -991,6 +991,27 @@ test_expect_success 'checkout -p patch editing of added file' ' ) ' +test_expect_success EXPENSIVE 'add -i with a lot of files' ' + git reset --hard && + x160=0123456789012345678901234567890123456789 && + x160=$x160$x160$x160$x160 && + y= && + i=0 && + while test $i -le 200 + do + name=$(printf "%s%03d" $x160 $i) && + echo $name >$name && + git add -N $name && + y="${y}y$LF" && + i=$(($i+1)) || + break + done && + echo "$y" | git add -p -- . && + git diff --cached >staged && + test_line_count = 1407 staged && + git reset --hard +' + test_expect_success 'show help from add--helper' ' git reset --hard && cat >expect <<-EOF && From aa383f7db8c74241e8061b9c31728cd8f27faf0c Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Tue, 30 Mar 2021 14:25:31 -0400 Subject: [PATCH 032/105] clink.pl: fix libexpatd.lib link error when using MSVC When building with `make MSVC=1 DEBUG=1`, link to `libexpatd.lib` rather than `libexpat.lib`. It appears that the `vcpkg` package for "libexpat" has changed and now creates `libexpatd.lib` for debug mode builds. Previously, both debug and release builds created a ".lib" with the same basename. Signed-off-by: Jeff Hostetler --- compat/vcbuild/scripts/clink.pl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl index 3bd824154b..2768ae15f1 100755 --- a/compat/vcbuild/scripts/clink.pl +++ b/compat/vcbuild/scripts/clink.pl @@ -66,7 +66,11 @@ while (@ARGV) { } push(@args, $lib); } elsif ("$arg" eq "-lexpat") { + if ($is_debug) { + push(@args, "libexpatd.lib"); + } else { push(@args, "libexpat.lib"); + } } elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") { $arg =~ s/^-L/-LIBPATH:/; push(@lflags, $arg); From ce5bfd73d3e35f849f518ed2668593dfd9e5c188 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Mon, 5 Apr 2021 15:27:38 -0400 Subject: [PATCH 033/105] Makefile: clean up .ilk files when MSVC=1 Signed-off-by: Jeff Hostetler --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 04d0fd1fe6..b38b4eda91 100644 --- a/Makefile +++ b/Makefile @@ -3440,12 +3440,15 @@ endif ifdef MSVC $(RM) $(patsubst %.o,%.o.pdb,$(OBJECTS)) $(RM) $(patsubst %.exe,%.pdb,$(OTHER_PROGRAMS)) + $(RM) $(patsubst %.exe,%.ilk,$(OTHER_PROGRAMS)) $(RM) $(patsubst %.exe,%.iobj,$(OTHER_PROGRAMS)) $(RM) $(patsubst %.exe,%.ipdb,$(OTHER_PROGRAMS)) $(RM) $(patsubst %.exe,%.pdb,$(PROGRAMS)) + $(RM) $(patsubst %.exe,%.ilk,$(PROGRAMS)) $(RM) $(patsubst %.exe,%.iobj,$(PROGRAMS)) $(RM) $(patsubst %.exe,%.ipdb,$(PROGRAMS)) $(RM) $(patsubst %.exe,%.pdb,$(TEST_PROGRAMS)) + $(RM) $(patsubst %.exe,%.ilk,$(TEST_PROGRAMS)) $(RM) $(patsubst %.exe,%.iobj,$(TEST_PROGRAMS)) $(RM) $(patsubst %.exe,%.ipdb,$(TEST_PROGRAMS)) $(RM) compat/vcbuild/MSVC-DEFS-GEN From 9dfd8ed79ee3a6fd655d9dad69eff58b1fa59cc7 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Mon, 5 Apr 2021 14:08:22 -0400 Subject: [PATCH 034/105] vcbuild: add support for compiling Windows resource files Create a wrapper for the Windows Resource Compiler (RC.EXE) for use by the MSVC=1 builds. This is similar to the CL.EXE and LIB.EXE wrappers used for the MSVC=1 builds. Signed-off-by: Jeff Hostetler --- compat/vcbuild/find_vs_env.bat | 7 ++++++ compat/vcbuild/scripts/rc.pl | 46 ++++++++++++++++++++++++++++++++++ config.mak.uname | 3 ++- 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 compat/vcbuild/scripts/rc.pl diff --git a/compat/vcbuild/find_vs_env.bat b/compat/vcbuild/find_vs_env.bat index b35d264c0e..379b16296e 100644 --- a/compat/vcbuild/find_vs_env.bat +++ b/compat/vcbuild/find_vs_env.bat @@ -99,6 +99,7 @@ REM ================================================================ SET sdk_dir=%WindowsSdkDir% SET sdk_ver=%WindowsSDKVersion% + SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%%tgt% SET si=%sdk_dir%Include\%sdk_ver% SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared" SET sl=%sdk_dir%lib\%sdk_ver% @@ -130,6 +131,7 @@ REM ================================================================ SET sdk_dir=%WindowsSdkDir% SET sdk_ver=%WindowsSDKVersion% + SET sdk_ver_bin_dir=%WindowsSdkVerBinPath%bin\amd64 SET si=%sdk_dir%Include\%sdk_ver% SET sdk_includes=-I"%si%ucrt" -I"%si%um" -I"%si%shared" -I"%si%winrt" SET sl=%sdk_dir%lib\%sdk_ver% @@ -160,6 +162,11 @@ REM ================================================================ echo msvc_includes=%msvc_includes% echo msvc_libs=%msvc_libs% + echo sdk_ver_bin_dir=%sdk_ver_bin_dir% + SET X1=%sdk_ver_bin_dir:C:=/C% + SET X2=%X1:\=/% + echo sdk_ver_bin_dir_msys=%X2% + echo sdk_includes=%sdk_includes% echo sdk_libs=%sdk_libs% diff --git a/compat/vcbuild/scripts/rc.pl b/compat/vcbuild/scripts/rc.pl new file mode 100644 index 0000000000..7bca4cd81c --- /dev/null +++ b/compat/vcbuild/scripts/rc.pl @@ -0,0 +1,46 @@ +#!/usr/bin/perl -w +###################################################################### +# Compile Resources on Windows +# +# This is a wrapper to facilitate the compilation of Git with MSVC +# using GNU Make as the build system. So, instead of manipulating the +# Makefile into something nasty, just to support non-space arguments +# etc, we use this wrapper to fix the command line options +# +###################################################################### +use strict; +my @args = (); +my @input = (); + +while (@ARGV) { + my $arg = shift @ARGV; + if ("$arg" =~ /^-[dD]/) { + # GIT_VERSION gets passed with too many + # layers of dquote escaping. + $arg =~ s/\\"/"/g; + + push(@args, $arg); + + } elsif ("$arg" eq "-i") { + my $arg = shift @ARGV; + # TODO complain if NULL or is dashed ?? + push(@input, $arg); + + } elsif ("$arg" eq "-o") { + my $arg = shift @ARGV; + # TODO complain if NULL or is dashed ?? + push(@args, "-fo$arg"); + + } else { + push(@args, $arg); + } +} + +push(@args, "-nologo"); +push(@args, "-v"); +push(@args, @input); + +unshift(@args, "rc.exe"); +printf("**** @args\n"); + +exit (system(@args) != 0); diff --git a/config.mak.uname b/config.mak.uname index 53d9ad3144..5fb76dde33 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -425,7 +425,7 @@ ifeq ($(uname_S),Windows) # link.exe next to, and required by, cl.exe, we have to prepend this # onto the existing $PATH. # - SANE_TOOL_PATH ?= $(msvc_bin_dir_msys) + SANE_TOOL_PATH ?= $(msvc_bin_dir_msys):$(sdk_ver_bin_dir_msys) HAVE_ALLOCA_H = YesPlease NO_PREAD = YesPlease NEEDS_CRYPTO_WITH_SSL = YesPlease @@ -494,6 +494,7 @@ endif # See https://msdn.microsoft.com/en-us/library/ms235330.aspx EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj kernel32.lib ntdll.lib PTHREAD_LIBS = + RC = compat/vcbuild/scripts/rc.pl lib = BASIC_CFLAGS += $(vcpkg_inc) $(sdk_includes) $(msvc_includes) ifndef DEBUG From 0f08a68d8fa80ec71f5179e05819bf1e33dd13d6 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 2 Jul 2020 16:35:05 +0200 Subject: [PATCH 035/105] git add -i: handle CR/LF line endings in the interactive input As of Git for Windows v2.27.0, there is an option to use Windows' newly-introduced Pseudo Console support. When running an interactive add operation with this support enabled, Git will receive CR/LF line endings. Therefore, let's not pretend that we are expecting Unix line endings. This fixes https://github.com/git-for-windows/git/issues/2729 Signed-off-by: Johannes Schindelin --- prompt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prompt.c b/prompt.c index 50df17279d..c546e43737 100644 --- a/prompt.c +++ b/prompt.c @@ -77,7 +77,7 @@ int git_read_line_interactively(struct strbuf *line) int ret; fflush(stdout); - ret = strbuf_getline_lf(line, stdin); + ret = strbuf_getline(line, stdin); if (ret != EOF) strbuf_trim_trailing_newline(line); From 4ef05608fe164a964b450b27f282ae5a81612098 Mon Sep 17 00:00:00 2001 From: Luke Bonanomi Date: Wed, 24 Jun 2020 07:45:52 -0400 Subject: [PATCH 036/105] commit: accept "scissors" with CR/LF line endings This change enhances `git commit --cleanup=scissors` by detecting scissors lines ending in either LF (UNIX-style) or CR/LF (DOS-style). Regression tests are included to specifically test for trailing comments after a CR/LF-terminated scissors line. Signed-off-by: Luke Bonanomi Signed-off-by: Johannes Schindelin --- t/t7502-commit-porcelain.sh | 42 +++++++++++++++++++++++++++++++++++++ wt-status.c | 13 +++++++++--- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh index 38a532d81c..b643375fa5 100755 --- a/t/t7502-commit-porcelain.sh +++ b/t/t7502-commit-porcelain.sh @@ -586,6 +586,48 @@ test_expect_success 'cleanup commit messages (scissors option,-F,-e, scissors on test_must_be_empty actual ' +test_expect_success 'helper-editor' ' + + write_script lf-to-crlf.sh <<-\EOF + sed "s/\$/Q/" <"$1" | tr Q "\\015" >"$1".new && + mv -f "$1".new "$1" + EOF +' + +test_expect_success 'cleanup commit messages (scissors option,-F,-e, CR/LF line endings)' ' + + test_config core.editor "\"$PWD/lf-to-crlf.sh\"" && + scissors="# ------------------------ >8 ------------------------" && + + test_write_lines >text \ + "# Keep this comment" "" " $scissors" \ + "# Keep this comment, too" "$scissors" \ + "# Remove this comment" "$scissors" \ + "Remove this comment, too" && + + test_write_lines >expect \ + "# Keep this comment" "" " $scissors" \ + "# Keep this comment, too" && + + git commit --cleanup=scissors -e -F text --allow-empty && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup commit messages (scissors option,-F,-e, scissors on first line, CR/LF line endings)' ' + + scissors="# ------------------------ >8 ------------------------" && + test_write_lines >text \ + "$scissors" \ + "# Remove this comment and any following lines" && + cp text /tmp/test2-text && + git commit --cleanup=scissors -e -F text --allow-empty --allow-empty-message && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && + test_must_be_empty actual +' + test_expect_success 'cleanup commit messages (strip option,-F)' ' echo >>negative && diff --git a/wt-status.c b/wt-status.c index 867e3e417e..e9fb389994 100644 --- a/wt-status.c +++ b/wt-status.c @@ -22,7 +22,7 @@ #define AB_DELAY_WARNING_IN_MS (2 * 1000) static const char cut_line[] = -"------------------------ >8 ------------------------\n"; +"------------------------ >8 ------------------------"; static char default_wt_status_colors[][COLOR_MAXLEN] = { GIT_COLOR_NORMAL, /* WT_STATUS_HEADER */ @@ -1068,15 +1068,22 @@ conclude: status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); } +static inline int starts_with_newline(const char *p) +{ + return *p == '\n' || (*p == '\r' && p[1] == '\n'); +} + size_t wt_status_locate_end(const char *s, size_t len) { const char *p; struct strbuf pattern = STRBUF_INIT; strbuf_addf(&pattern, "\n%c %s", comment_line_char, cut_line); - if (starts_with(s, pattern.buf + 1)) + if (starts_with(s, pattern.buf + 1) && + starts_with_newline(s + pattern.len - 1)) len = 0; - else if ((p = strstr(s, pattern.buf))) + else if ((p = strstr(s, pattern.buf)) && + starts_with_newline(p + pattern.len)) len = p - s + 1; strbuf_release(&pattern); return len; From 0607914ec3d159638207a38b3610c545b2eb7e66 Mon Sep 17 00:00:00 2001 From: Jens Glathe Date: Tue, 2 Jun 2020 12:12:25 +0200 Subject: [PATCH 037/105] t0014: fix indentation For some reason, this test case was indented with 4 spaces instead of 1 horizontal tab. The other test cases in the same test script are fine. Signed-off-by: Jens Glathe Signed-off-by: Johannes Schindelin --- t/t0014-alias.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh index 8d3d9144c0..288e08299a 100755 --- a/t/t0014-alias.sh +++ b/t/t0014-alias.sh @@ -38,10 +38,10 @@ 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 && - echo "git-frotz a '\'''\'' b '\'' '\'' c" >expect && - test_cmp expect actual + 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 && + echo "git-frotz a '\'''\'' b '\'' '\'' c" >expect && + test_cmp expect actual ' test_done From af361ab3712484e2f528596bd8429e9fe0237331 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 12 Aug 2020 15:06:17 +0000 Subject: [PATCH 038/105] git-gui: accommodate for intent-to-add files As of Git v2.28.0, the diff for files staged via `git add -N` marks them as new files. Git GUI was ill-prepared for that, and this patch teaches Git GUI about them. Please note that this will not even fix things with v2.28.0, as the `rp/apply-cached-with-i-t-a` patches are required on Git's side, too. This fixes https://github.com/git-for-windows/git/issues/2779 Signed-off-by: Johannes Schindelin Signed-off-by: Pratyush Yadav --- git-gui/git-gui.sh | 2 ++ git-gui/lib/diff.tcl | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh index 201524c34e..3fe9bd9f47 100755 --- a/git-gui/git-gui.sh +++ b/git-gui/git-gui.sh @@ -2087,6 +2087,7 @@ set all_icons(U$ui_index) file_merge set all_icons(T$ui_index) file_statechange set all_icons(_$ui_workdir) file_plain +set all_icons(A$ui_workdir) file_plain set all_icons(M$ui_workdir) file_mod set all_icons(D$ui_workdir) file_question set all_icons(U$ui_workdir) file_merge @@ -2113,6 +2114,7 @@ foreach i { {A_ {mc "Staged for commit"}} {AM {mc "Portions staged for commit"}} {AD {mc "Staged for commit, missing"}} + {AA {mc "Intended to be added"}} {_D {mc "Missing"}} {D_ {mc "Staged for removal"}} diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl index 871ad488c2..36d3715f7b 100644 --- a/git-gui/lib/diff.tcl +++ b/git-gui/lib/diff.tcl @@ -582,7 +582,8 @@ proc apply_or_revert_hunk {x y revert} { if {$current_diff_side eq $ui_index} { set failed_msg [mc "Failed to unstage selected hunk."] lappend apply_cmd --reverse --cached - if {[string index $mi 0] ne {M}} { + set file_state [string index $mi 0] + if {$file_state ne {M} && $file_state ne {A}} { unlock_index return } @@ -595,7 +596,8 @@ proc apply_or_revert_hunk {x y revert} { lappend apply_cmd --cached } - if {[string index $mi 1] ne {M}} { + set file_state [string index $mi 1] + if {$file_state ne {M} && $file_state ne {A}} { unlock_index return } @@ -687,7 +689,8 @@ proc apply_or_revert_range_or_line {x y revert} { set failed_msg [mc "Failed to unstage selected line."] set to_context {+} lappend apply_cmd --reverse --cached - if {[string index $mi 0] ne {M}} { + set file_state [string index $mi 0] + if {$file_state ne {M} && $file_state ne {A}} { unlock_index return } @@ -702,7 +705,8 @@ proc apply_or_revert_range_or_line {x y revert} { lappend apply_cmd --cached } - if {[string index $mi 1] ne {M}} { + set file_state [string index $mi 1] + if {$file_state ne {M} && $file_state ne {A}} { unlock_index return } From de623adaa7606896e7d8c0a78ebecb7767f235a7 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Mon, 5 Apr 2021 14:12:14 -0400 Subject: [PATCH 039/105] config.mak.uname: add git.rc to MSVC builds Teach MSVC=1 builds to depend on the `git.rc` file so that the resulting executables have Windows-style resources and version number information within them. Signed-off-by: Jeff Hostetler --- config.mak.uname | 1 + 1 file changed, 1 insertion(+) diff --git a/config.mak.uname b/config.mak.uname index 5fb76dde33..967a31f3b7 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -493,6 +493,7 @@ endif # handle twice, or to access the osfhandle of an already-closed stdout # See https://msdn.microsoft.com/en-us/library/ms235330.aspx EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib invalidcontinue.obj kernel32.lib ntdll.lib + GITLIBS += git.res PTHREAD_LIBS = RC = compat/vcbuild/scripts/rc.pl lib = From 06a1611f44aa710c3489e0d59f7c4a5252937b80 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Mon, 5 Apr 2021 14:24:52 -0400 Subject: [PATCH 040/105] clink.pl: ignore no-stack-protector arg on MSVC=1 builds Ignore the `-fno-stack-protector` compiler argument when building with MSVC. This will be used in a later commit that needs to build a Win32 GUI app. Signed-off-by: Jeff Hostetler --- compat/vcbuild/scripts/clink.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl index 2768ae15f1..73c8a2b184 100755 --- a/compat/vcbuild/scripts/clink.pl +++ b/compat/vcbuild/scripts/clink.pl @@ -122,6 +122,8 @@ while (@ARGV) { push(@cflags, "-wd4996"); } elsif ("$arg" =~ /^-W[a-z]/) { # let's ignore those + } elsif ("$arg" eq "-fno-stack-protector") { + # eat this } else { push(@args, $arg); } From 845c04b3c2ce8a20795d95af3bd75ddeb21212a2 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Mon, 5 Apr 2021 14:39:33 -0400 Subject: [PATCH 041/105] clink.pl: move default linker options for MSVC=1 builds Move the default `-ENTRY` and `-SUBSYSTEM` arguments for MSVC=1 builds from `config.mak.uname` into `clink.pl`. These args are constant for console-mode executables. Add support to `clink.pl` for generating a Win32 GUI application using the `-mwindows` argument (to match how GCC does it). This changes the `-ENTRY` and `-SUBSYSTEM` arguments accordingly. Signed-off-by: Jeff Hostetler --- compat/vcbuild/scripts/clink.pl | 11 +++++++++++ config.mak.uname | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl index 73c8a2b184..a38b360015 100755 --- a/compat/vcbuild/scripts/clink.pl +++ b/compat/vcbuild/scripts/clink.pl @@ -15,6 +15,7 @@ my @cflags = (); my @lflags = (); my $is_linking = 0; my $is_debug = 0; +my $is_gui = 0; while (@ARGV) { my $arg = shift @ARGV; if ("$arg" eq "-DDEBUG") { @@ -124,11 +125,21 @@ while (@ARGV) { # let's ignore those } elsif ("$arg" eq "-fno-stack-protector") { # eat this + } elsif ("$arg" eq "-mwindows") { + $is_gui = 1; } else { push(@args, $arg); } } if ($is_linking) { + if ($is_gui) { + push(@args, "-ENTRY:wWinMainCRTStartup"); + push(@args, "-SUBSYSTEM:WINDOWS"); + } else { + push(@args, "-ENTRY:wmainCRTStartup"); + push(@args, "-SUBSYSTEM:CONSOLE"); + } + push(@args, @lflags); unshift(@args, "link.exe"); } else { diff --git a/config.mak.uname b/config.mak.uname index 967a31f3b7..aaeb495566 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -488,7 +488,7 @@ endif compat/win32/trace2_win32_process_info.o \ compat/win32/dirent.o 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 + BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO # invalidcontinue.obj allows Git's source code to close the same file # handle twice, or to access the osfhandle of an already-closed stdout # See https://msdn.microsoft.com/en-us/library/ms235330.aspx From 499338325e31e5fe61c6670e383410eac74092d0 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 7 Apr 2021 15:29:21 +0200 Subject: [PATCH 042/105] buildsystems: remove duplicate clause This seems to have been there since 259d87c35495 (Add scripts to generate projects for other buildsystems (MSVC vcproj, QMake), 2009-09-16), i.e. since the beginning of that file. Signed-off-by: Johannes Schindelin --- contrib/buildsystems/engine.pl | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl index ed6c45988a..37b0b026f2 100755 --- a/contrib/buildsystems/engine.pl +++ b/contrib/buildsystems/engine.pl @@ -265,7 +265,6 @@ sub handleCompileLine shift @parts; } elsif ("$part" eq "-c") { # ignore compile flag - } elsif ("$part" eq "-c") { } elsif ($part =~ /^.?-I/) { push(@incpaths, $part); } elsif ($part =~ /^.?-D/) { From cb90bcb58496818e2664b3e7dc661e728cf74076 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 7 Apr 2021 15:15:08 +0200 Subject: [PATCH 043/105] vcxproj: handle resource files, too On Windows, we also compile a "resource" file, which is similar to source code, but contains metadata (such as the program version). So far, we did not compile it in `MSVC` mode, only when compiling Git for Windows with the GNU C Compiler. In preparation for including it also when compiling with MS Visual C, let's teach our `vcxproj` generator to handle those sort of files, too. Signed-off-by: Johannes Schindelin --- contrib/buildsystems/Generators/Vcxproj.pm | 17 ++++++++++++++++- contrib/buildsystems/engine.pl | 9 +++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm index 81ee2f5a4a..58a48233c5 100644 --- a/contrib/buildsystems/Generators/Vcxproj.pm +++ b/contrib/buildsystems/Generators/Vcxproj.pm @@ -89,6 +89,9 @@ sub createProject { $defines =~ s/>/>/g; $defines =~ s/\'//g; + my $rcdefines = $defines; + $rcdefines =~ s/(?WIN32;_DEBUG;$defines;%(PreprocessorDefinitions) MultiThreadedDebugDLL + + WIN32;_DEBUG;$rcdefines;%(PreprocessorDefinitions) + true @@ -216,6 +222,9 @@ EOM true Speed + + WIN32;NDEBUG;$rcdefines;%(PreprocessorDefinitions) + true true @@ -225,9 +234,15 @@ EOM EOM foreach(@sources) { - print F << "EOM"; + if (/\.rc$/) { + print F << "EOM"; + +EOM + } else { + print F << "EOM"; EOM + } } print F << "EOM"; diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl index 37b0b026f2..441059a737 100755 --- a/contrib/buildsystems/engine.pl +++ b/contrib/buildsystems/engine.pl @@ -165,7 +165,7 @@ sub parseMakeOutput next; } - if($text =~ / -c /) { + if($text =~ / -c / || $text =~ / -i \S+\.rc /) { # compilation handleCompileLine($text, $line); @@ -263,7 +263,7 @@ sub handleCompileLine if ("$part" eq "-o") { # ignore object file shift @parts; - } elsif ("$part" eq "-c") { + } elsif ("$part" eq "-c" || "$part" eq "-i") { # ignore compile flag } elsif ($part =~ /^.?-I/) { push(@incpaths, $part); @@ -271,7 +271,7 @@ sub handleCompileLine push(@defines, $part); } elsif ($part =~ /^-/) { push(@cflags, $part); - } elsif ($part =~ /\.(c|cc|cpp)$/) { + } elsif ($part =~ /\.(c|cc|cpp|rc)$/) { $sourcefile = $part; } else { die "Unhandled compiler option @ line $lineno: $part"; @@ -358,7 +358,7 @@ sub handleLinkLine push(@libs, $part); } elsif ($part eq 'invalidcontinue.obj') { # ignore - known to MSVC - } elsif ($part =~ /\.o$/) { + } elsif ($part =~ /\.(o|res)$/) { push(@objfiles, $part); } elsif ($part =~ /\.obj$/) { # do nothing, 'make' should not be producing .obj, only .o files @@ -371,6 +371,7 @@ sub handleLinkLine foreach (@objfiles) { my $sourcefile = $_; $sourcefile =~ s/\.o$/.c/; + $sourcefile =~ s/\.res$/.rc/; push(@sources, $sourcefile); push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}}); push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}}); From d5e86e19854a0573346106355c2833fdff756503 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 7 Apr 2021 21:57:31 +0200 Subject: [PATCH 044/105] vcxproj: ignore -fno-stack-protector and -fno-common An upcoming commit will introduce those compile options; MSVC does not understand them, so let's suppress them when generating the Visual Studio project files. Signed-off-by: Johannes Schindelin --- contrib/buildsystems/engine.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl index 441059a737..7453bc9697 100755 --- a/contrib/buildsystems/engine.pl +++ b/contrib/buildsystems/engine.pl @@ -263,7 +263,7 @@ sub handleCompileLine if ("$part" eq "-o") { # ignore object file shift @parts; - } elsif ("$part" eq "-c" || "$part" eq "-i") { + } elsif ("$part" eq "-c" || "$part" eq "-i" || "$part" =~ /^-fno-/) { # ignore compile flag } elsif ($part =~ /^.?-I/) { push(@incpaths, $part); From 95a0ec94150796245c5ef35b601a3f510ed69b64 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 7 Apr 2021 15:48:50 +0200 Subject: [PATCH 045/105] vcxproj: handle GUI programs, too So far, we only built Console programs, but we are about to introduce a program that targets the Windows subsystem (i.e. it is a so-called "GUI" program). Let's handle this preemptively in the script that generates the Visual Studio files. Signed-off-by: Johannes Schindelin --- contrib/buildsystems/Generators/Vcxproj.pm | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm index 58a48233c5..1cabe69bff 100644 --- a/contrib/buildsystems/Generators/Vcxproj.pm +++ b/contrib/buildsystems/Generators/Vcxproj.pm @@ -92,6 +92,13 @@ sub createProject { my $rcdefines = $defines; $rcdefines =~ s/(?\$(VCPKGLibDirectory);%(AdditionalLibraryDirectories) \$(VCPKGLibs);\$(AdditionalDependencies) invalidcontinue.obj %(AdditionalOptions) - wmainCRTStartup + $entrypoint $cdup\\compat\\win32\\git.manifest - Console + $subsystem EOM if ($target eq 'libgit') { From 76415ce1cd800ca5e8aa6a4bbb27dea5bb54f1ef Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 3 Dec 2020 22:44:24 +0100 Subject: [PATCH 046/105] win32: add a helper to run `git.exe` without a foreground window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows, there are two kinds of executables, console ones and non-console ones. Git's executables are all console ones. When launching the former e.g. in a scheduled task, a CMD window pops up. This is not what we want for the tasks installed via the `git maintenance` command. To work around this, let's introduce `headless-git.exe`, which is a non-console program that does _not_ pop up any window. All it does is to re-launch `git.exe`, suppressing that console window, passing through all command-line arguments as-are. Helped-by: Carlo Marcelo Arenas Belón Helped-by: Yuyi Wang Signed-off-by: Johannes Schindelin Signed-off-by: Derrick Stolee --- Makefile | 9 ++ compat/win32/headless.c | 115 +++++++++++++++++++++ config.mak.uname | 3 + contrib/buildsystems/CMakeLists.txt | 9 ++ contrib/buildsystems/Generators/Vcxproj.pm | 4 +- contrib/buildsystems/engine.pl | 1 + 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 compat/win32/headless.c diff --git a/Makefile b/Makefile index b38b4eda91..59c95f5c48 100644 --- a/Makefile +++ b/Makefile @@ -2654,6 +2654,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) @@ -3410,6 +3417,7 @@ clean: profile-clean coverage-clean cocciclean $(RM) po/git.pot po/git-core.pot $(RM) *.res $(RM) $(OBJECTS) + $(RM) headless-git.o $(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB) $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X $(RM) $(TEST_PROGRAMS) @@ -3439,6 +3447,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,%.ilk,$(OTHER_PROGRAMS)) $(RM) $(patsubst %.exe,%.iobj,$(OTHER_PROGRAMS)) diff --git a/compat/win32/headless.c b/compat/win32/headless.c new file mode 100644 index 0000000000..8b00dfe3bd --- /dev/null +++ b/compat/win32/headless.c @@ -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 +#include +#include +#include + +/* + * 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; +} diff --git a/config.mak.uname b/config.mak.uname index aaeb495566..b41e272daa 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -527,6 +527,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) @@ -680,6 +682,7 @@ ifeq ($(uname_S),MINGW) RC = windres -O coff NATIVE_CRLF = YesPlease X = .exe + EXTRA_PROGRAMS += headless-git$X ifneq (,$(wildcard ../THIS_IS_MSYSGIT)) htmldir = doc/git/html/ prefix = diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt index 1b23f2440d..71d9ad8ee2 100644 --- a/contrib/buildsystems/CMakeLists.txt +++ b/contrib/buildsystems/CMakeLists.txt @@ -734,6 +734,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() diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm index 1cabe69bff..a6d1c6b8d0 100644 --- a/contrib/buildsystems/Generators/Vcxproj.pm +++ b/contrib/buildsystems/Generators/Vcxproj.pm @@ -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; @@ -254,7 +254,7 @@ EOM print F << "EOM"; 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"}; diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl index 7453bc9697..417ae71d44 100755 --- a/contrib/buildsystems/engine.pl +++ b/contrib/buildsystems/engine.pl @@ -370,6 +370,7 @@ sub handleLinkLine # exit(1); foreach (@objfiles) { my $sourcefile = $_; + $sourcefile =~ s/^headless-git\.o$/compat\/win32\/headless.c/; $sourcefile =~ s/\.o$/.c/; $sourcefile =~ s/\.res$/.rc/; push(@sources, $sourcefile); From ce544d68f628706567aaa995cdf9286baeb98190 Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Sun, 6 Oct 2019 18:40:55 +0100 Subject: [PATCH 047/105] vcpkg_install: detect lack of Git The vcpkg_install batch file depends on the availability of a working Git on the CMD path. This may not be present if the user has selected the 'bash only' option during Git-for-Windows install. Detect and tell the user about their lack of a working Git in the CMD window. Fixes #2348. A separate PR https://github.com/git-for-windows/build-extra/pull/258 now highlights the recommended path setting during install. Signed-off-by: Philip Oakley --- compat/vcbuild/vcpkg_install.bat | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compat/vcbuild/vcpkg_install.bat b/compat/vcbuild/vcpkg_install.bat index ebd0bad242..bcbbf536af 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 ) From 42acd0046d945f8203a6fe9821c540a9f2ac3ac5 Mon Sep 17 00:00:00 2001 From: Ian Bearman Date: Fri, 31 Jan 2020 15:37:27 -0800 Subject: [PATCH 048/105] vcxproj: support building Windows/ARM64 binaries Signed-off-by: Ian Bearman Signed-off-by: Dennis Ameling Signed-off-by: Johannes Schindelin --- contrib/buildsystems/Generators/Vcxproj.pm | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm index 1a25789d28..548766fa9d 100644 --- a/contrib/buildsystems/Generators/Vcxproj.pm +++ b/contrib/buildsystems/Generators/Vcxproj.pm @@ -114,12 +114,21 @@ sub createProject { Release x64 + + Debug + ARM64 + + + Release + ARM64 + $uuid Win32Proj x86-windows - x64-windows + x64-windows + arm64-windows $cdup\\compat\\vcbuild\\vcpkg\\installed\\\$(VCPKGArch) \$(VCPKGArchDirectory)\\debug\\bin \$(VCPKGArchDirectory)\\debug\\lib @@ -140,7 +149,7 @@ sub createProject { $config_type - v140 + v142 ..\\ @@ -355,8 +364,10 @@ sub createGlueProject { print F << "EOM"; Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection @@ -367,10 +378,14 @@ EOM foreach (@apps) { my $appname = $_; my $uuid = $build_structure{"APPS_${appname}_GUID"}; + print F "\t\t${uuid}.Debug|ARM64.ActiveCfg = Debug|ARM64\n"; + print F "\t\t${uuid}.Debug|ARM64.Build.0 = Debug|ARM64\n"; print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n"; print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n"; print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n"; print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n"; + print F "\t\t${uuid}.Release|ARM64.ActiveCfg = Release|ARM64\n"; + print F "\t\t${uuid}.Release|ARM64.Build.0 = Release|ARM64\n"; print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n"; print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n"; print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n"; @@ -379,10 +394,14 @@ EOM foreach (@libs) { my $libname = $_; my $uuid = $build_structure{"LIBS_${libname}_GUID"}; + print F "\t\t${uuid}.Debug|ARM64.ActiveCfg = Debug|ARM64\n"; + print F "\t\t${uuid}.Debug|ARM64.Build.0 = Debug|ARM64\n"; print F "\t\t${uuid}.Debug|x64.ActiveCfg = Debug|x64\n"; print F "\t\t${uuid}.Debug|x64.Build.0 = Debug|x64\n"; print F "\t\t${uuid}.Debug|x86.ActiveCfg = Debug|Win32\n"; print F "\t\t${uuid}.Debug|x86.Build.0 = Debug|Win32\n"; + print F "\t\t${uuid}.Release|ARM64.ActiveCfg = Release|ARM64\n"; + print F "\t\t${uuid}.Release|ARM64.Build.0 = Release|ARM64\n"; print F "\t\t${uuid}.Release|x64.ActiveCfg = Release|x64\n"; print F "\t\t${uuid}.Release|x64.Build.0 = Release|x64\n"; print F "\t\t${uuid}.Release|x86.ActiveCfg = Release|Win32\n"; From b562a7e3b877cb10a899c251c27bcc8e60fb2226 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 3 Dec 2020 22:54:11 +0100 Subject: [PATCH 049/105] git maintenance: avoid console window in scheduled tasks on Windows We just introduced a helper to avoid showing a console window when the scheduled task runs `git.exe`. Let's actually use it. Signed-off-by: Johannes Schindelin Signed-off-by: Derrick Stolee --- builtin/gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/gc.c b/builtin/gc.c index 4ea70089c9..4d2c0366bf 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -1969,7 +1969,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority "\n" "\n" "\n" - "\"%s\\git.exe\"\n" + "\"%s\\headless-git.exe\"\n" "--exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s\n" "\n" "\n" From bcd43af8d22dd74415743818561ff0663e1e5be9 Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Sun, 6 Oct 2019 18:43:57 +0100 Subject: [PATCH 050/105] vcpkg_install: add comment regarding slow network connections The vcpkg downloads may not succeed. Warn careful readers of the time out. A simple retry will usually resolve the issue. Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- compat/vcbuild/vcpkg_install.bat | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compat/vcbuild/vcpkg_install.bat b/compat/vcbuild/vcpkg_install.bat index bcbbf536af..8330d8120f 100644 --- a/compat/vcbuild/vcpkg_install.bat +++ b/compat/vcbuild/vcpkg_install.bat @@ -80,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 ) From 13947f37cbe3bf7130dc6f1431d1bebd58827213 Mon Sep 17 00:00:00 2001 From: Ian Bearman Date: Fri, 31 Jan 2020 16:00:25 -0800 Subject: [PATCH 051/105] vcbuild: install ARM64 dependencies when building ARM64 binaries Co-authored-by: Dennis Ameling Signed-off-by: Ian Bearman Signed-off-by: Dennis Ameling Signed-off-by: Johannes Schindelin --- compat/vcbuild/README | 6 +++++- compat/vcbuild/vcpkg_copy_dlls.bat | 7 ++++++- compat/vcbuild/vcpkg_install.bat | 9 +++++++-- contrib/buildsystems/Generators/Vcxproj.pm | 2 +- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/compat/vcbuild/README b/compat/vcbuild/README index 29ec1d0f10..1df1cabb1e 100644 --- a/compat/vcbuild/README +++ b/compat/vcbuild/README @@ -6,7 +6,11 @@ The Steps to Build Git with VS2015 or VS2017 from the command line. Prompt or from an SDK bash window: $ cd - $ ./compat/vcbuild/vcpkg_install.bat + $ ./compat/vcbuild/vcpkg_install.bat x64-windows + + or + + $ ./compat/vcbuild/vcpkg_install.bat arm64-windows The vcpkg tools and all of the third-party sources will be installed in this folder: diff --git a/compat/vcbuild/vcpkg_copy_dlls.bat b/compat/vcbuild/vcpkg_copy_dlls.bat index 13661c14f8..8bea0cbf83 100644 --- a/compat/vcbuild/vcpkg_copy_dlls.bat +++ b/compat/vcbuild/vcpkg_copy_dlls.bat @@ -15,7 +15,12 @@ REM ================================================================ @FOR /F "delims=" %%D IN ("%~dp0") DO @SET cwd=%%~fD cd %cwd% - SET arch=x64-windows + SET arch=%2 + IF NOT DEFINED arch ( + echo defaulting to 'x64-windows`. Invoke %0 with 'x86-windows', 'x64-windows', or 'arm64-windows' + set arch=x64-windows + ) + SET inst=%cwd%vcpkg\installed\%arch% IF [%1]==[release] ( diff --git a/compat/vcbuild/vcpkg_install.bat b/compat/vcbuild/vcpkg_install.bat index 8330d8120f..cacef18c11 100644 --- a/compat/vcbuild/vcpkg_install.bat +++ b/compat/vcbuild/vcpkg_install.bat @@ -31,6 +31,12 @@ REM ================================================================ SETLOCAL EnableDelayedExpansion + SET arch=%1 + IF NOT DEFINED arch ( + echo defaulting to 'x64-windows`. Invoke %0 with 'x86-windows', 'x64-windows', or 'arm64-windows' + set arch=x64-windows + ) + @FOR /F "delims=" %%D IN ("%~dp0") DO @SET cwd=%%~fD cd %cwd% @@ -55,9 +61,8 @@ REM ================================================================ echo Successfully installed %cwd%vcpkg\vcpkg.exe :install_libraries - SET arch=x64-windows - echo Installing third-party libraries... + echo Installing third-party libraries(%arch%)... FOR %%i IN (zlib expat libiconv openssl libssh2 curl) DO ( cd %cwd%vcpkg IF NOT EXIST "packages\%%i_%arch%" CALL :sub__install_one %%i diff --git a/contrib/buildsystems/Generators/Vcxproj.pm b/contrib/buildsystems/Generators/Vcxproj.pm index 548766fa9d..7a92599946 100644 --- a/contrib/buildsystems/Generators/Vcxproj.pm +++ b/contrib/buildsystems/Generators/Vcxproj.pm @@ -193,7 +193,7 @@ EOM Initialize VCPKG del "$cdup\\compat\\vcbuild\\vcpkg" - call "$cdup\\compat\\vcbuild\\vcpkg_install.bat" + call "$cdup\\compat\\vcbuild\\vcpkg_install.bat" \$(VCPKGArch) EOM } From 62e3c627bafe059baf4df4079b62f12edf223ff1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 10 Apr 2020 23:39:40 +0200 Subject: [PATCH 052/105] Add a GitHub workflow to generate Git for Windows' Pacman package Git for Windows uses MSYS2 as base system, and therefore the Git binaries are bundled as Pacman package. This workflow allows building the 64-bit version of this package (which is called `mingw-w64-x86_64-git`). Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 141 ++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 .github/workflows/git-artifacts.yml diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml new file mode 100644 index 0000000000..837015d7f7 --- /dev/null +++ b/.github/workflows/git-artifacts.yml @@ -0,0 +1,141 @@ +name: mingw-w64-x86_64-git + +on: + # This workflow can be triggered manually in the Actions tab, see + # https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/ + - workflow_dispatch + +env: + HOME: "${{github.workspace}}\\home" + MSYSTEM: MINGW64 + USERPROFILE: "${{github.workspace}}\\home" + +jobs: + bundle-artifacts: + runs-on: windows-latest + steps: + - name: Configure user + shell: bash + run: + USER_NAME="${{github.actor}}" && + USER_EMAIL="${{github.actor}}@users.noreply.github.com" && + mkdir "$HOME" && + git config --global user.name "$USER_NAME" && + git config --global user.email "$USER_EMAIL" && + echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV + - name: Download git-sdk-64-build-installers + shell: bash + run: | + # Use Git Bash to download and unpack the artifact + + ## Get artifact + urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds + id=$(curl "$urlbase?definitions=29&statusFilter=completed&resultFilter=succeeded&\$top=1" | + jq -r '.value[0].id') + download_url=$(curl "$urlbase/$id/artifacts" | + jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl') + + curl -o artifacts.zip "$download_url" + + ## Unpack artifact + unzip artifacts.zip + - name: Clone build-extra + shell: bash + run: | + d=git-sdk-64-build-installers/usr/src/build-extra && + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d + - name: Generate bundle artifacts + shell: powershell + run: | + & .\git-sdk-64-build-installers\git-cmd.exe --command=usr\bin\bash.exe -lc @" + printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "`$@"\n' >/usr/bin/git && + mkdir -p bundle-artifacts && + + git -c init.defaultBranch=main init --bare && + git remote add -f origin https://github.com/git-for-windows/git && + git fetch https://github.com/${{github.repository}} ${{github.ref}}:${{github.ref}} && + + tag_name=\"`$(git describe --match 'v[0-9]*' FETCH_HEAD)-`$(date +%Y%m%d%H%M%S)\" && + echo \"prerelease-`${tag_name#v}\" >bundle-artifacts/ver && + echo \"`${tag_name#v}\" >bundle-artifacts/display_version && + echo \"`$tag_name\" >bundle-artifacts/next_version && + git tag -m \"Snapshot build\" \"`$tag_name\" FETCH_HEAD && + git bundle create bundle-artifacts/git.bundle origin/main..\"`$tag_name\" && + + sh -x /usr/src/build-extra/please.sh mention feature \"Snapshot of `$(git show -s --pretty='tformat:%h (%s, %ad)' --date=short FETCH_HEAD)\" && + git -C /usr/src/build-extra bundle create \"`$PWD/bundle-artifacts/build-extra.bundle\" origin/main..main + "@ + - name: 'Publish Pipeline Artifact: bundle-artifacts' + uses: actions/upload-artifact@v1 + with: + name: bundle-artifacts + path: bundle-artifacts + pkg-x86_64: + runs-on: windows-latest + needs: bundle-artifacts + steps: + - name: Configure user + shell: bash + run: + USER_NAME="${{github.actor}}" && + USER_EMAIL="${{github.actor}}@users.noreply.github.com" && + mkdir "$HOME" && + git config --global user.name "$USER_NAME" && + git config --global user.email "$USER_EMAIL" && + echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV + - name: Download git-sdk-64-makepkg-git + shell: bash + run: | + # Use Git Bash to download and unpack the artifact + + ## Get artifact + urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds + id=${{ needs.bundle-artifacts.outputs.latest-sdk64-extra-build-id }} + download_url="$(curl "$urlbase/$id/artifacts" | + jq -r '.value[] | select(.name == "git-sdk-64-makepkg-git").resource.downloadUrl')" + + curl -o artifacts.zip "$download_url" + + ## Unpack artifact + unzip artifacts.zip + - name: Download bundle-artifacts + uses: actions/download-artifact@v1 + with: + name: bundle-artifacts + path: bundle-artifacts + - name: Clone and update build-extra + shell: bash + run: | + d=git-sdk-64-makepkg-git/usr/src/build-extra && + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && + git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main + - name: Check out git/git + shell: bash + run: | + git -c init.defaultBranch=main init && + git remote add -f origin https://github.com/git-for-windows/git && + git fetch --tags bundle-artifacts/git.bundle $(cat bundle-artifacts/next_version) && + git reset --hard $(cat bundle-artifacts/next_version) + - name: Build mingw-w64-x86_64-git + shell: powershell + run: | + & git-sdk-64-makepkg-git\usr\bin\sh.exe -lc @" + set -x + # Let `cv2pdb` find the DLLs + PATH=\"`$PATH:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\" + type -p mspdb140.dll || exit 1 + sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-64-bit --build-src-pkg -o artifacts HEAD && + cp bundle-artifacts/ver artifacts/ && + + b=`$PWD/artifacts && + version=`$(cat bundle-artifacts/next_version) && + (cd /usr/src/MINGW-packages/mingw-w64-git && + cp PKGBUILD.`$version PKGBUILD && + git commit -s -m \"mingw-w64-git: new version (`$version)\" PKGBUILD && + git bundle create \"`$b\"/MINGW-packages.bundle origin/main..main) + "@ + - name: Publish mingw-w64-x86_64-git + uses: actions/upload-artifact@v1 + with: + name: pkg-x86_64 + path: artifacts From 53770d9659ef99a9a34b80c3d0f26996539d8f02 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 12 Apr 2020 00:24:49 +0200 Subject: [PATCH 053/105] git-artifacts: if GPG secrets are available, use them This expects the `GPGKEY` and `PRIVGPGKEY` secrets to be set in the respective GitHub repository. The `GPGKEY` value should be of the form --passphrase --yes --batch --no-tty --pinentry-mode loopback --digest-algo SHA256 and the `PRIVGPGKEY` should be generated via gpg --export-secret-keys | base64 | tr '\n' % Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 837015d7f7..b5dbf6c4bc 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -6,6 +6,7 @@ on: - workflow_dispatch env: + GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" HOME: "${{github.workspace}}\\home" MSYSTEM: MINGW64 USERPROFILE: "${{github.workspace}}\\home" @@ -44,7 +45,21 @@ jobs: run: | d=git-sdk-64-build-installers/usr/src/build-extra && git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d + - name: Prepare home directory for GPG signing + if: env.GPGKEY != '' + shell: bash + run: | + echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import && + mkdir -p home && + git config --global gpg.program "$PWD/git-sdk-64-build-installers/usr/src/build-extra/gnupg-with-gpgkey.sh" && + info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" && + git config --global user.name "${info% <*}" && + git config --global user.email "<${info#*<}" + env: + GPGKEY: ${{secrets.GPGKEY}} - name: Generate bundle artifacts + env: + GPGKEY: ${{secrets.GPGKEY}} shell: powershell run: | & .\git-sdk-64-build-installers\git-cmd.exe --command=usr\bin\bash.exe -lc @" @@ -59,12 +74,16 @@ jobs: echo \"prerelease-`${tag_name#v}\" >bundle-artifacts/ver && echo \"`${tag_name#v}\" >bundle-artifacts/display_version && echo \"`$tag_name\" >bundle-artifacts/next_version && - git tag -m \"Snapshot build\" \"`$tag_name\" FETCH_HEAD && + git tag `$(test -z \"`$GPGKEY\" || echo \" -s\") -m \"Snapshot build\" \"`$tag_name\" FETCH_HEAD && git bundle create bundle-artifacts/git.bundle origin/main..\"`$tag_name\" && sh -x /usr/src/build-extra/please.sh mention feature \"Snapshot of `$(git show -s --pretty='tformat:%h (%s, %ad)' --date=short FETCH_HEAD)\" && git -C /usr/src/build-extra bundle create \"`$PWD/bundle-artifacts/build-extra.bundle\" origin/main..main "@ + - name: Clean up temporary files + if: always() + shell: bash + run: rm -rf home - name: 'Publish Pipeline Artifact: bundle-artifacts' uses: actions/upload-artifact@v1 with: @@ -116,7 +135,19 @@ jobs: git remote add -f origin https://github.com/git-for-windows/git && git fetch --tags bundle-artifacts/git.bundle $(cat bundle-artifacts/next_version) && git reset --hard $(cat bundle-artifacts/next_version) + - name: Prepare home directory for GPG signing + if: env.GPGKEY != '' + shell: bash + run: | + echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import && + info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" && + git config --global user.name "${info% <*}" && + git config --global user.email "<${info#*<}" + env: + GPGKEY: ${{secrets.GPGKEY}} - name: Build mingw-w64-x86_64-git + env: + GPGKEY: "${{secrets.GPGKEY}}" shell: powershell run: | & git-sdk-64-makepkg-git\usr\bin\sh.exe -lc @" @@ -126,6 +157,13 @@ jobs: type -p mspdb140.dll || exit 1 sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-64-bit --build-src-pkg -o artifacts HEAD && cp bundle-artifacts/ver artifacts/ && + if test -n \"`$GPGKEY\" + then + for tar in artifacts/*.tar* + do + /usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor `$tar + done + fi && b=`$PWD/artifacts && version=`$(cat bundle-artifacts/next_version) && @@ -134,6 +172,10 @@ jobs: git commit -s -m \"mingw-w64-git: new version (`$version)\" PKGBUILD && git bundle create \"`$b\"/MINGW-packages.bundle origin/main..main) "@ + - name: Clean up temporary files + if: always() + shell: bash + run: rm -rf home - name: Publish mingw-w64-x86_64-git uses: actions/upload-artifact@v1 with: From 74e7c024fde50e013917b3d8b24b178625f371e3 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 12 Apr 2020 00:34:56 +0200 Subject: [PATCH 054/105] git-artifacts: also code-sign, if configured via the secrets When the secrets `CODESIGN_P12` and `CODESIGN_PASS` are set, the workflow will now code-sign the `.exe` files contained in the package. This should help with a few anti-malware programs, at least when the certificate saw some action and gained trust. Note: `CODESIGN_P12` needs to be generated via cat .p12 | base64 | tr '\n' % Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index b5dbf6c4bc..7faeac0fcc 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -135,6 +135,18 @@ jobs: git remote add -f origin https://github.com/git-for-windows/git && git fetch --tags bundle-artifacts/git.bundle $(cat bundle-artifacts/next_version) && git reset --hard $(cat bundle-artifacts/next_version) + - name: Prepare home directory for code-signing + env: + CODESIGN_P12: ${{secrets.CODESIGN_P12}} + CODESIGN_PASS: ${{secrets.CODESIGN_PASS}} + if: env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' + shell: bash + run: | + cd home && + mkdir -p .sig && + echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >.sig/codesign.p12 && + echo -n "$CODESIGN_PASS" >.sig/codesign.pass + git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' - name: Prepare home directory for GPG signing if: env.GPGKEY != '' shell: bash From cd4ee14c22e276cd2d42a8c63831a531ed418876 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 12 Apr 2020 00:43:19 +0200 Subject: [PATCH 055/105] git-artifacts: also build the installer While at it, we might just as well build the Git for Windows installer ;-) Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 75 ++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 7faeac0fcc..380dc00b86 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -1,4 +1,4 @@ -name: mingw-w64-x86_64-git +name: git-artifacts on: # This workflow can be triggered manually in the Actions tab, see @@ -193,3 +193,76 @@ jobs: with: name: pkg-x86_64 path: artifacts + installer-x86_64: + runs-on: windows-latest + needs: pkg-x86_64 + env: + MSYSTEM: MINGW64 + steps: + - name: Download pkg-x86_64 + uses: actions/download-artifact@v1 + with: + name: pkg-x86_64 + path: pkg-x86_64 + - name: Download bundle-artifacts + uses: actions/download-artifact@v1 + with: + name: bundle-artifacts + path: bundle-artifacts + - name: Download git-sdk-64-build-installers + shell: bash + run: | + # Use Git Bash to download and unpack the artifact + + ## Get artifact + urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds + id=${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} + download_url="$(curl "$urlbase/$id/artifacts" | + jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl')" + + curl -o artifacts.zip "$download_url" + + ## Unpack artifact + unzip artifacts.zip + - name: Clone and update build-extra + shell: bash + run: | + d=git-sdk-64-build-installers/usr/src/build-extra && + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && + git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main + - name: Prepare home directory for code-signing + env: + CODESIGN_P12: ${{secrets.CODESIGN_P12}} + CODESIGN_PASS: ${{secrets.CODESIGN_PASS}} + if: (matrix.artifact.name == 'installer' || matrix.artifact.name == 'portable') && env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' + shell: bash + run: | + mkdir -p home/.sig && + echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >home/.sig/codesign.p12 && + echo -n "$CODESIGN_PASS" >home/.sig/codesign.pass && + git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' + - name: Build 64-bit installer + shell: powershell + run: | + & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" + set -x + /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --installer --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && + openssl dgst -sha256 artifacts/Git-*.exe | sed \"s/.* //\" >artifacts/sha-256.txt && + cp /usr/src/build-extra/installer/package-versions.txt artifacts/ && + + a=`$PWD/artifacts && + p=`$PWD/pkg-x86_64 && + (cd /usr/src/build-extra && + mkdir -p cached-source-packages && + cp \"`$p\"/*-pdb* cached-source-packages/ && + GIT_CONFIG_PARAMETERS=\"'windows.sdk64.path='\" ./please.sh bundle_pdbs --arch=x86_64 --directory=\"`$a\" installer/package-versions.txt) + "@ + - name: Clean up temporary files + if: always() + shell: bash + run: rm -rf home + - name: Publish installer-x86_64 + uses: actions/upload-artifact@v1 + with: + name: installer-x86_64 + path: artifacts From 98b6dc396a0697e3519db63c79ce7d597c1e0a4d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 12 Apr 2020 00:51:00 +0200 Subject: [PATCH 056/105] git-artifacts: also build portable, mingit and mingit-busybox ... because we can. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 43 ++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 380dc00b86..ed7c7e4a26 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -193,9 +193,28 @@ jobs: with: name: pkg-x86_64 path: artifacts - installer-x86_64: + artifacts: runs-on: windows-latest - needs: pkg-x86_64 + needs: pkg + strategy: + matrix: + artifact: + - name: installer + fileprefix: Git + fileextension: exe + - name: portable + fileprefix: PortableGit + fileextension: exe + - name: archive + fileprefix: Git + fileextension: tar.bz2 + - name: mingit + fileprefix: MinGit + fileextension: zip + - name: mingit-busybox + fileprefix: MinGit + fileextension: zip + fail-fast: false env: MSYSTEM: MINGW64 steps: @@ -241,13 +260,23 @@ jobs: echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >home/.sig/codesign.p12 && echo -n "$CODESIGN_PASS" >home/.sig/codesign.pass && git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' - - name: Build 64-bit installer + - name: Build 64-bit ${{matrix.artifact.name}} shell: powershell run: | & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" set -x - /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --installer --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && - openssl dgst -sha256 artifacts/Git-*.exe | sed \"s/.* //\" >artifacts/sha-256.txt && + /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && + if test portable = '${{matrix.artifact.name}}' && test -n \"`$(git config alias.signtool)\" + then + git signtool artifacts/PortableGit-*.exe + fi && + openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.${{matrix.artifact.fileextension}} | sed \"s/.* //\" >artifacts/sha-256.txt + "@ + - name: Copy package-versions and pdbs + if: matrix.artifact.name == 'installer' + shell: powershell + run: | + & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" cp /usr/src/build-extra/installer/package-versions.txt artifacts/ && a=`$PWD/artifacts && @@ -261,8 +290,8 @@ jobs: if: always() shell: bash run: rm -rf home - - name: Publish installer-x86_64 + - name: Publish ${{matrix.artifact.name}}-x86_64 uses: actions/upload-artifact@v1 with: - name: installer-x86_64 + name: ${{matrix.artifact.name}}-x86_64 path: artifacts From b4a8d15d226b6f61f33d4398a6458573df561967 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 12 Apr 2020 00:57:23 +0200 Subject: [PATCH 057/105] git-artifacts: also build 32-bit versions Just in case that we need to generate those real quick. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index ed7c7e4a26..2b2ef6ebab 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -89,9 +89,18 @@ jobs: with: name: bundle-artifacts path: bundle-artifacts - pkg-x86_64: + pkg: runs-on: windows-latest needs: bundle-artifacts + strategy: + matrix: + arch: + - name: x86_64 + bitness: 64 + bin: /amd64 + - name: i686 + bitness: 32 + bin: '' steps: - name: Configure user shell: bash @@ -157,7 +166,7 @@ jobs: git config --global user.email "<${info#*<}" env: GPGKEY: ${{secrets.GPGKEY}} - - name: Build mingw-w64-x86_64-git + - name: Build mingw-w64-${{matrix.arch.name}}-git env: GPGKEY: "${{secrets.GPGKEY}}" shell: powershell @@ -165,9 +174,9 @@ jobs: & git-sdk-64-makepkg-git\usr\bin\sh.exe -lc @" set -x # Let `cv2pdb` find the DLLs - PATH=\"`$PATH:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64\" + PATH=\"`$PATH:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin${{matrix.arch.bin}}\" type -p mspdb140.dll || exit 1 - sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-64-bit --build-src-pkg -o artifacts HEAD && + sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-${{matrix.arch.bitness}}-bit --build-src-pkg -o artifacts HEAD && cp bundle-artifacts/ver artifacts/ && if test -n \"`$GPGKEY\" then @@ -188,10 +197,10 @@ jobs: if: always() shell: bash run: rm -rf home - - name: Publish mingw-w64-x86_64-git + - name: Publish mingw-w64-${{matrix.arch.name}}-git uses: actions/upload-artifact@v1 with: - name: pkg-x86_64 + name: pkg-${{matrix.arch.name}} path: artifacts artifacts: runs-on: windows-latest @@ -214,21 +223,27 @@ jobs: - name: mingit-busybox fileprefix: MinGit fileextension: zip + arch: + - name: x86_64 + bitness: 64 + - name: i686 + bitness: 32 fail-fast: false env: - MSYSTEM: MINGW64 + MSYSTEM: MINGW${{matrix.arch.bitness}} steps: - - name: Download pkg-x86_64 + - name: Download pkg-${{matrix.arch.name}} uses: actions/download-artifact@v1 with: - name: pkg-x86_64 - path: pkg-x86_64 + name: pkg-${{matrix.arch.name}} + path: pkg-${{matrix.arch.name}} - name: Download bundle-artifacts uses: actions/download-artifact@v1 with: name: bundle-artifacts path: bundle-artifacts - name: Download git-sdk-64-build-installers + if: matrix.arch.bitness == '64' shell: bash run: | # Use Git Bash to download and unpack the artifact @@ -241,12 +256,29 @@ jobs: curl -o artifacts.zip "$download_url" + ## Unpack artifact + unzip artifacts.zip + - name: Download git-sdk-32-build-installers + if: matrix.arch.bitness == '32' + shell: bash + run: | + # Use Git Bash to download and unpack the artifact + + ## Get artifact + urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds + id=$(curl "$urlbase?definitions=30&statusFilter=completed&resultFilter=succeeded&\$top=1" | + jq -r '.value[0].id') + download_url=$(curl "$urlbase/$id/artifacts" | + jq -r '.value[] | select(.name == "git-sdk-32-build-installers").resource.downloadUrl') + + curl -o artifacts.zip "$download_url" + ## Unpack artifact unzip artifacts.zip - name: Clone and update build-extra shell: bash run: | - d=git-sdk-64-build-installers/usr/src/build-extra && + d=git-sdk-${{matrix.arch.bitness}}-build-installers/usr/src/build-extra && git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main - name: Prepare home directory for code-signing @@ -260,12 +292,12 @@ jobs: echo -n "$CODESIGN_P12" | tr % '\n' | base64 -d >home/.sig/codesign.p12 && echo -n "$CODESIGN_PASS" >home/.sig/codesign.pass && git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' - - name: Build 64-bit ${{matrix.artifact.name}} + - name: Build ${{matrix.arch.bitness}}-bit ${{matrix.artifact.name}} shell: powershell run: | - & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" + & .\git-sdk-${{matrix.arch.bitness}}-build-installers\usr\bin\bash.exe -lc @" set -x - /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && + /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-${{matrix.arch.name}}/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-[0-9]*.tar.xz --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-doc-html-[0-9]*.tar.xz && if test portable = '${{matrix.artifact.name}}' && test -n \"`$(git config alias.signtool)\" then git signtool artifacts/PortableGit-*.exe @@ -276,22 +308,22 @@ jobs: if: matrix.artifact.name == 'installer' shell: powershell run: | - & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" + & .\git-sdk-${{matrix.arch.bitness}}-build-installers\usr\bin\bash.exe -lc @" cp /usr/src/build-extra/installer/package-versions.txt artifacts/ && a=`$PWD/artifacts && - p=`$PWD/pkg-x86_64 && + p=`$PWD/pkg-${{matrix.arch.name}} && (cd /usr/src/build-extra && mkdir -p cached-source-packages && cp \"`$p\"/*-pdb* cached-source-packages/ && - GIT_CONFIG_PARAMETERS=\"'windows.sdk64.path='\" ./please.sh bundle_pdbs --arch=x86_64 --directory=\"`$a\" installer/package-versions.txt) + GIT_CONFIG_PARAMETERS=\"'windows.sdk${{matrix.arch.bitness}}.path='\" ./please.sh bundle_pdbs --arch=${{matrix.arch.name}} --directory=\"`$a\" installer/package-versions.txt) "@ - name: Clean up temporary files if: always() shell: bash run: rm -rf home - - name: Publish ${{matrix.artifact.name}}-x86_64 + - name: Publish ${{matrix.artifact.name}}-${{matrix.arch.name}} uses: actions/upload-artifact@v1 with: - name: ${{matrix.artifact.name}}-x86_64 + name: ${{matrix.artifact.name}}-${{matrix.arch.name}} path: artifacts From 009e2c4c53fc6622dc8a06d812c9c7731bd2a187 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sun, 12 Apr 2020 00:52:22 +0200 Subject: [PATCH 058/105] git-artifacts: also build the nuget package The two NuGet artifact exists only in the 64-bit version. So let's make them in a separate, non-matrix job. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 2b2ef6ebab..2f521175d2 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -327,3 +327,52 @@ jobs: with: name: ${{matrix.artifact.name}}-${{matrix.arch.name}} path: artifacts + nuget: + runs-on: windows-latest + needs: pkg + steps: + - name: Download pkg-x86_64 + uses: actions/download-artifact@v1 + with: + name: pkg-x86_64 + path: pkg-x86_64 + - name: Download bundle-artifacts + uses: actions/download-artifact@v1 + with: + name: bundle-artifacts + path: bundle-artifacts + - name: Download git-sdk-64-build-installers + shell: bash + run: | + # Use Git Bash to download and unpack the artifact + + ## Get artifact + urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds + id=${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} + download_url=$(curl "$urlbase/$id/artifacts" | + jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl') + + curl -o artifacts.zip "$download_url" + + ## Unpack artifact + unzip artifacts.zip + - name: Clone and update build-extra + shell: bash + run: | + d=git-sdk-64-build-installers/usr/src/build-extra && + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && + git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main + - uses: nuget/setup-nuget@v1 + - name: Build 64-bit NuGet packages + shell: powershell + run: | + & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" + /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --nuget --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && + /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --nuget-mingit && + openssl dgst -sha256 artifacts/Git*.nupkg | sed \"s/.* //\" >artifacts/sha-256.txt + "@ + - name: Publish nuget-x86_64 + uses: actions/upload-artifact@v1 + with: + name: nuget-x86_64 + path: artifacts From 8231bb4b8c73fcce8d8f62fe9c7a1f98915031cb Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 11 Apr 2020 23:43:55 +0200 Subject: [PATCH 059/105] git-artifacts: allow restricting which artifacts are built Users can now specify which artifacts they want to build, via the `build_only` input, which is a space-separated list of artifacts. For example, `installer portable` will build `installer-x86_64`, `installer-i686`, `portable-x86_64` and `portable-i686`, and an empty or unset value will build all artifacts. Please note that the `mingw-w64-git` packages are built always, as it would be tricky to figure out when they need to be built (for example, `build_only=portable-x86_64` technically does not need `pkg-i686` to be built, while `build_only=portable` does). Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 44 +++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 2f521175d2..6700e7ef26 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -3,13 +3,17 @@ name: git-artifacts on: # This workflow can be triggered manually in the Actions tab, see # https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/ - - workflow_dispatch + workflow_dispatch: + inputs: + build_only: + description: 'Optionally restrict what artifacts to build' env: GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" HOME: "${{github.workspace}}\\home" MSYSTEM: MINGW64 USERPROFILE: "${{github.workspace}}\\home" + BUILD_ONLY: "${{github.event.inputs.build_only}}" jobs: bundle-artifacts: @@ -232,18 +236,28 @@ jobs: env: MSYSTEM: MINGW${{matrix.arch.bitness}} steps: + - name: Determine whether this job should be skipped + shell: bash + run: | + case " $BUILD_ONLY " in + ' ') ;; # not set; build all + *" ${{matrix.artifact.name}} "*|*" ${{matrix.artifact.name}}-${{matrix.arch.name}} "*) ;; # build this artifact + *) echo "SKIP=true" >>$GITHUB_ENV;; + esac - name: Download pkg-${{matrix.arch.name}} + if: env.SKIP != 'true' uses: actions/download-artifact@v1 with: name: pkg-${{matrix.arch.name}} path: pkg-${{matrix.arch.name}} - name: Download bundle-artifacts + if: env.SKIP != 'true' uses: actions/download-artifact@v1 with: name: bundle-artifacts path: bundle-artifacts - name: Download git-sdk-64-build-installers - if: matrix.arch.bitness == '64' + if: env.SKIP != 'true' && matrix.arch.bitness == '64' shell: bash run: | # Use Git Bash to download and unpack the artifact @@ -259,7 +273,7 @@ jobs: ## Unpack artifact unzip artifacts.zip - name: Download git-sdk-32-build-installers - if: matrix.arch.bitness == '32' + if: env.SKIP != 'true' && matrix.arch.bitness == '32' shell: bash run: | # Use Git Bash to download and unpack the artifact @@ -276,6 +290,7 @@ jobs: ## Unpack artifact unzip artifacts.zip - name: Clone and update build-extra + if: env.SKIP != 'true' shell: bash run: | d=git-sdk-${{matrix.arch.bitness}}-build-installers/usr/src/build-extra && @@ -285,7 +300,7 @@ jobs: env: CODESIGN_P12: ${{secrets.CODESIGN_P12}} CODESIGN_PASS: ${{secrets.CODESIGN_PASS}} - if: (matrix.artifact.name == 'installer' || matrix.artifact.name == 'portable') && env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' + if: env.SKIP != 'true' && (matrix.artifact.name == 'installer' || matrix.artifact.name == 'portable') && env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' shell: bash run: | mkdir -p home/.sig && @@ -293,6 +308,7 @@ jobs: echo -n "$CODESIGN_PASS" >home/.sig/codesign.pass && git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' - name: Build ${{matrix.arch.bitness}}-bit ${{matrix.artifact.name}} + if: env.SKIP != 'true' shell: powershell run: | & .\git-sdk-${{matrix.arch.bitness}}-build-installers\usr\bin\bash.exe -lc @" @@ -305,7 +321,7 @@ jobs: openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.${{matrix.artifact.fileextension}} | sed \"s/.* //\" >artifacts/sha-256.txt "@ - name: Copy package-versions and pdbs - if: matrix.artifact.name == 'installer' + if: env.SKIP != 'true' && matrix.artifact.name == 'installer' shell: powershell run: | & .\git-sdk-${{matrix.arch.bitness}}-build-installers\usr\bin\bash.exe -lc @" @@ -319,10 +335,11 @@ jobs: GIT_CONFIG_PARAMETERS=\"'windows.sdk${{matrix.arch.bitness}}.path='\" ./please.sh bundle_pdbs --arch=${{matrix.arch.name}} --directory=\"`$a\" installer/package-versions.txt) "@ - name: Clean up temporary files - if: always() + if: always() && env.SKIP != 'true' shell: bash run: rm -rf home - name: Publish ${{matrix.artifact.name}}-${{matrix.arch.name}} + if: env.SKIP != 'true' uses: actions/upload-artifact@v1 with: name: ${{matrix.artifact.name}}-${{matrix.arch.name}} @@ -331,17 +348,28 @@ jobs: runs-on: windows-latest needs: pkg steps: + - name: Determine whether this job should be skipped + shell: bash + run: | + case " $BUILD_ONLY " in + ' ') ;; # not set; build all + *" nuget "*) ;; # build this artifact + *) echo "SKIP=true" >>$GITHUB_ENV;; + esac - name: Download pkg-x86_64 + if: env.SKIP != 'true' uses: actions/download-artifact@v1 with: name: pkg-x86_64 path: pkg-x86_64 - name: Download bundle-artifacts + if: env.SKIP != 'true' uses: actions/download-artifact@v1 with: name: bundle-artifacts path: bundle-artifacts - name: Download git-sdk-64-build-installers + if: env.SKIP != 'true' shell: bash run: | # Use Git Bash to download and unpack the artifact @@ -357,13 +385,16 @@ jobs: ## Unpack artifact unzip artifacts.zip - name: Clone and update build-extra + if: env.SKIP != 'true' shell: bash run: | d=git-sdk-64-build-installers/usr/src/build-extra && git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main - uses: nuget/setup-nuget@v1 + if: env.SKIP != 'true' - name: Build 64-bit NuGet packages + if: env.SKIP != 'true' shell: powershell run: | & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" @@ -372,6 +403,7 @@ jobs: openssl dgst -sha256 artifacts/Git*.nupkg | sed \"s/.* //\" >artifacts/sha-256.txt "@ - name: Publish nuget-x86_64 + if: env.SKIP != 'true' uses: actions/upload-artifact@v1 with: name: nuget-x86_64 From 7c95922f52fe5801c9f5d2c31f751bb5de30d329 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 11 Apr 2020 23:58:47 +0200 Subject: [PATCH 060/105] git-artifacts: allow specifying repo/ref via workflow_dispatch With this change, users can specify the branch and repository from which they want to build Git for Windows' artifacts, via the `ref` and `repository` inputs. This allows e.g. building `refs/heads/seen` of `git/git` (even if no `git-artifacts` workflow is configured in that repository), or `refs/pull//merge` for a given Pull Request. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 6700e7ef26..0090941ce0 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -7,6 +7,10 @@ on: inputs: build_only: description: 'Optionally restrict what artifacts to build' + ref: + description: 'Optionally override which branch to build' + repository: + description: 'Optionally override from where to fetch the specified ref' env: GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" @@ -14,6 +18,8 @@ env: MSYSTEM: MINGW64 USERPROFILE: "${{github.workspace}}\\home" BUILD_ONLY: "${{github.event.inputs.build_only}}" + REPOSITORY: "${{github.event.inputs.repository}}" + REF: "${{github.event.inputs.ref}}" jobs: bundle-artifacts: @@ -70,9 +76,11 @@ jobs: printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "`$@"\n' >/usr/bin/git && mkdir -p bundle-artifacts && + { test -n \"`$REPOSITORY\" || REPOSITORY='${{github.repository}}'; } && + { test -n \"`$REF\" || REF='${{github.ref}}'; } && git -c init.defaultBranch=main init --bare && git remote add -f origin https://github.com/git-for-windows/git && - git fetch https://github.com/${{github.repository}} ${{github.ref}}:${{github.ref}} && + git fetch \"https://github.com/`$REPOSITORY\" \"`$REF:`$REF\" && tag_name=\"`$(git describe --match 'v[0-9]*' FETCH_HEAD)-`$(date +%Y%m%d%H%M%S)\" && echo \"prerelease-`${tag_name#v}\" >bundle-artifacts/ver && From 2e62f99d1e538b0962652aa1648492a5904cf95c Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 25 Feb 2021 00:06:41 +0100 Subject: [PATCH 061/105] git-artifacts(arm64): avoid hard-linking the dashed built-ins The archive and MinGit variants really get bloated because they handle those as straight copies instead of hard-links. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 327683f35f..630a3e17b5 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -288,7 +288,7 @@ jobs: run: | cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/arm64-windows \ -DNO_GETTEXT=YesPlease -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON -DCMAKE_GENERATOR_PLATFORM=arm64 -DVCPKG_ARCH=arm64-windows \ - -DCMAKE_INSTALL_PREFIX="`pwd`/git-arm64" + -DCMAKE_INSTALL_PREFIX="`pwd`/git-arm64" -DSKIP_DASHED_BUILT_INS=ON - name: MSBuild run: msbuild git.sln -property:Configuration=Release - name: Link the Git executables From 29277cecc947b8881a9302dc5b63c5642d28a552 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 23 Feb 2021 11:39:15 +0100 Subject: [PATCH 062/105] git-artifacts: use a narrower `PATH` GitHub workflows run in agents that have quite a bit of stuff in their `PATH`, e.g. Chocolatey. To make sure that those bits and pieces are _not_ used to build the artifacts, let's whittle down the `PATH` to contain the bare minimum. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 630a3e17b5..f1b0426779 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -224,8 +224,10 @@ jobs: run: | & git-sdk-64-build-installers\usr\bin\sh.exe -lc @" set -x - # Let `cv2pdb` find the DLLs - PATH=\"`$PATH:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin${{matrix.arch.bin}}\" + + # Restrict `PATH` to MSYS2 and to Visual Studio (to let `cv2pdb` find the relevant DLLs) + PATH=\"`/mingw64/bin:/usr/bin:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin${{matrix.arch.bin}}:/C/Windows/system32\" + type -p mspdb140.dll || exit 1 sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-${{matrix.arch.bitness}}-bit --build-src-pkg -o artifacts HEAD && cp bundle-artifacts/ver artifacts/ && From 17ee3dab7194e9315c392d67be52f1826c830755 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 23 Feb 2021 12:25:34 +0100 Subject: [PATCH 063/105] git-artifacts: fix BUILD_ONLY handling for ARM64 The workflow allows users to restrict what parts are being built. For example, `installer-i686` will build only the 32-bit installer, not the 64-bit one nor any MinGit flavor. However, this logic was not extended when introducing support for ARM64: Instead, we _also_ built the ARM64 installer when the user asked for `installer-i686`. Let's allow restricting to `installer-i686` _without_ building the ARM64 version, and allow restricting to `installer-arm64` _just_ for the ARM64 version. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index f1b0426779..8b47fa4c3e 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -338,9 +338,14 @@ jobs: - name: Determine whether this job should be skipped shell: bash run: | + suffix=${{matrix.arch.name}} + if test true = ${{matrix.arch.arm64}} + then + suffix=arm64 + fi case " $BUILD_ONLY " in ' ') ;; # not set; build all - *" ${{matrix.artifact.name}} "*|*" ${{matrix.artifact.name}}-${{matrix.arch.name}} "*) ;; # build this artifact + *" ${{matrix.artifact.name}} "*|*" ${{matrix.artifact.name}}-$suffix "*) ;; # build this artifact *) echo "SKIP=true" >>$GITHUB_ENV;; esac - name: Download pkg-${{matrix.arch.name}} From e239535d715799065db2439d9b452e21910c5e24 Mon Sep 17 00:00:00 2001 From: Dennis Ameling Date: Thu, 28 Jan 2021 21:31:05 +0100 Subject: [PATCH 064/105] git-artifacts: cache the build-installers artifact It is a bit expensive to fetch just the git-sdk-64-build-installers artifact from Azure Pipelines and then to unpack it (takes some 6-7 minutes, typically). Let's cache it if possible. Signed-off-by: Dennis Ameling Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 89 +++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 10 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 0090941ce0..c2767fe266 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -24,6 +24,8 @@ env: jobs: bundle-artifacts: runs-on: windows-latest + outputs: + latest-sdk64-extra-build-id: ${{ steps.determine-latest-sdk64-extra-build-id.outputs.id }} steps: - name: Configure user shell: bash @@ -34,15 +36,31 @@ jobs: git config --global user.name "$USER_NAME" && git config --global user.email "$USER_EMAIL" && echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV + - name: Determine latest git-sdk-64-extra-artifacts build ID + id: determine-latest-sdk64-extra-build-id + shell: bash + run: | + urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds + id=$(curl "$urlbase?definitions=29&statusFilter=completed&resultFilter=succeeded&\$top=1" | + jq -r '.value[0].id') + + echo "Latest ID is ${id}" + echo "::set-output name=id::$id" + - name: Cache git-sdk-64-build-installers + id: cache-sdk-build-installers + uses: actions/cache@v2 + with: + path: git-sdk-64-build-installers + key: build-installers-64-${{ steps.determine-latest-sdk64-extra-build-id.outputs.id }} - name: Download git-sdk-64-build-installers + if: steps.cache-sdk-build-installers.outputs.cache-hit != 'true' shell: bash run: | # Use Git Bash to download and unpack the artifact ## Get artifact urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=$(curl "$urlbase?definitions=29&statusFilter=completed&resultFilter=succeeded&\$top=1" | - jq -r '.value[0].id') + id=${{ steps.determine-latest-sdk64-extra-build-id.outputs.id }} download_url=$(curl "$urlbase/$id/artifacts" | jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl') @@ -54,7 +72,13 @@ jobs: shell: bash run: | d=git-sdk-64-build-installers/usr/src/build-extra && - git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d + if test ! -d $d/.git + then + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d + else + git -C $d fetch https://github.com/git-for-windows/build-extra main && + git -C $d switch -C main FETCH_HEAD + fi - name: Prepare home directory for GPG signing if: env.GPGKEY != '' shell: bash @@ -104,6 +128,8 @@ jobs: pkg: runs-on: windows-latest needs: bundle-artifacts + outputs: + latest-sdk64-extra-build-id: ${{ needs.bundle-artifacts.outputs.latest-sdk64-extra-build-id }} strategy: matrix: arch: @@ -264,8 +290,15 @@ jobs: with: name: bundle-artifacts path: bundle-artifacts - - name: Download git-sdk-64-build-installers + - name: Cache git-sdk-64-build-installers if: env.SKIP != 'true' && matrix.arch.bitness == '64' + id: cache-sdk64-build-installers + uses: actions/cache@v2 + with: + path: git-sdk-64-build-installers + key: build-installers-64-${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} + - name: Download git-sdk-64-build-installers + if: env.SKIP != 'true' && matrix.arch.bitness == '64' && steps.cache-sdk64-build-installers.outputs.cache-hit != 'true' shell: bash run: | # Use Git Bash to download and unpack the artifact @@ -280,16 +313,33 @@ jobs: ## Unpack artifact unzip artifacts.zip - - name: Download git-sdk-32-build-installers + - name: Determine latest git-sdk-32-extra-artifacts build ID if: env.SKIP != 'true' && matrix.arch.bitness == '32' + id: determine-latest-sdk32-extra-build-id + shell: bash + run: | + urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds + id=$(curl "$urlbase?definitions=30&statusFilter=completed&resultFilter=succeeded&\$top=1" | + jq -r '.value[0].id') + + echo "Latest ID is ${id}" + echo "::set-output name=id::$id" + - name: Cache git-sdk-32-build-installers + if: env.SKIP != 'true' && matrix.arch.bitness == '32' + id: cache-sdk32-build-installers + uses: actions/cache@v2 + with: + path: git-sdk-32-build-installers + key: build-installers-32-${{ steps.determine-latest-sdk32-extra-build-id.outputs.id }} + - name: Download git-sdk-32-build-installers + if: env.SKIP != 'true' && matrix.arch.bitness == '32' && steps.cache-sdk32-build-installers.outputs.cache-hit != 'true' shell: bash run: | # Use Git Bash to download and unpack the artifact ## Get artifact urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=$(curl "$urlbase?definitions=30&statusFilter=completed&resultFilter=succeeded&\$top=1" | - jq -r '.value[0].id') + id=${{ steps.determine-latest-sdk32-extra-build-id.outputs.id }} download_url=$(curl "$urlbase/$id/artifacts" | jq -r '.value[] | select(.name == "git-sdk-32-build-installers").resource.downloadUrl') @@ -302,7 +352,13 @@ jobs: shell: bash run: | d=git-sdk-${{matrix.arch.bitness}}-build-installers/usr/src/build-extra && - git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && + if test ! -d $d/.git + then + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d + else + git -C $d fetch https://github.com/git-for-windows/build-extra main && + git -C $d switch -C main FETCH_HEAD + fi && git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main - name: Prepare home directory for code-signing env: @@ -376,8 +432,15 @@ jobs: with: name: bundle-artifacts path: bundle-artifacts - - name: Download git-sdk-64-build-installers + - name: Cache git-sdk-64-build-installers if: env.SKIP != 'true' + id: cache-sdk-build-installers + uses: actions/cache@v2 + with: + path: git-sdk-64-build-installers + key: build-installers-64-${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} + - name: Download git-sdk-64-build-installers + if: env.SKIP != 'true' && steps.cache-sdk-build-installers.outputs.cache-hit != 'true' shell: bash run: | # Use Git Bash to download and unpack the artifact @@ -397,7 +460,13 @@ jobs: shell: bash run: | d=git-sdk-64-build-installers/usr/src/build-extra && - git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && + if test ! -d $d/.git + then + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d + else + git -C $d fetch https://github.com/git-for-windows/build-extra main && + git -C $d switch -C main FETCH_HEAD + fi && git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main - uses: nuget/setup-nuget@v1 if: env.SKIP != 'true' From e1d7cb226744195fd1ee74b7f2370a6e7a096ddc Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 23 Feb 2021 12:31:24 +0100 Subject: [PATCH 065/105] git-artifacts: extend the `SKIP` logic to handle `pkg` and `build-arm64` When the user asked for `installer-x86_64`, there is no point in building `pkg-i686` or `build-arm64`; Let's be a bit smarter about this. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 50 ++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 8b47fa4c3e..f6537f6c5a 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -140,7 +140,21 @@ jobs: bitness: 32 bin: '' steps: + - name: Determine whether this job should be skipped + shell: bash + run: | + for e in ${BUILD_ONLY:-pkg} + do + case $e in + *-${{matrix.arch.name}}) exit 0;; # build this artifact + *-arm64) test i686 != ${{matrix.arch.name}} || exit 0;; # pkg-i686 is required for the ARM64 version + *-*) ;; # not this build artifact, keep looking + *) exit 0;; # build this artifact + esac + done + echo "SKIP=true" >>$GITHUB_ENV - name: Configure user + if: env.SKIP != 'true' shell: bash run: USER_NAME="${{github.actor}}" && @@ -150,13 +164,14 @@ jobs: git config --global user.email "$USER_EMAIL" && echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV - name: Cache git-sdk-64-build-installers + if: env.SKIP != 'true' id: cache-sdk-build-installers uses: actions/cache@v2 with: path: git-sdk-64-build-installers key: build-installers-64-${{ needs.bundle-artifacts.outputs.latest-sdk64-extra-build-id }} - name: Download git-sdk-64-build-installers - if: steps.cache-sdk-build-installers.outputs.cache-hit != 'true' + if: env.SKIP != 'true' && steps.cache-sdk-build-installers.outputs.cache-hit != 'true' shell: bash run: | # Use Git Bash to download and unpack the artifact @@ -172,11 +187,13 @@ jobs: ## Unpack artifact unzip artifacts.zip - name: Download bundle-artifacts + if: env.SKIP != 'true' uses: actions/download-artifact@v1 with: name: bundle-artifacts path: bundle-artifacts - name: Clone and update build-extra + if: env.SKIP != 'true' shell: bash run: | d=git-sdk-64-build-installers/usr/src/build-extra && @@ -189,6 +206,7 @@ jobs: fi && git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main - name: Check out git/git + if: env.SKIP != 'true' shell: bash run: | git -c init.defaultBranch=main init && @@ -199,7 +217,7 @@ jobs: env: CODESIGN_P12: ${{secrets.CODESIGN_P12}} CODESIGN_PASS: ${{secrets.CODESIGN_PASS}} - if: env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' + if: env.SKIP != 'true' && env.CODESIGN_P12 != '' && env.CODESIGN_PASS != '' shell: bash run: | cd home && @@ -208,7 +226,7 @@ jobs: echo -n "$CODESIGN_PASS" >.sig/codesign.pass git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' - name: Prepare home directory for GPG signing - if: env.GPGKEY != '' + if: env.SKIP != 'true' && env.GPGKEY != '' shell: bash run: | echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import && @@ -218,6 +236,7 @@ jobs: env: GPGKEY: ${{secrets.GPGKEY}} - name: Build mingw-w64-${{matrix.arch.name}}-git + if: env.SKIP != 'true' env: GPGKEY: "${{secrets.GPGKEY}}" shell: powershell @@ -247,10 +266,11 @@ jobs: git bundle create \"`$b\"/MINGW-packages.bundle origin/main..main) "@ - name: Clean up temporary files - if: always() + if: always() && env.SKIP != 'true' shell: bash run: rm -rf home - name: Publish mingw-w64-${{matrix.arch.name}}-git + if: env.SKIP != 'true' uses: actions/upload-artifact@v1 with: name: pkg-${{matrix.arch.name}} @@ -259,7 +279,20 @@ jobs: needs: bundle-artifacts runs-on: windows-latest steps: + - name: Determine whether this job should be skipped + shell: bash + run: | + for e in ${BUILD_ONLY:-pkg} + do + case $e in + *-arm64) exit 0;; # build this artifact + *-*) ;; # not this build artifact, keep looking + *) exit 0;; # build this artifact + esac + done + echo "SKIP=true" >>$GITHUB_ENV - name: Configure user + if: env.SKIP != 'true' shell: bash run: USER_NAME="${{github.actor}}" && @@ -268,34 +301,43 @@ jobs: git config --global user.name "$USER_NAME" && git config --global user.email "$USER_EMAIL" - uses: actions/checkout@v2 + if: env.SKIP != 'true' - name: initialize vcpkg + if: env.SKIP != 'true' uses: actions/checkout@v2 with: repository: 'microsoft/vcpkg' path: 'compat/vcbuild/vcpkg' - name: download vcpkg artifacts + if: env.SKIP != 'true' uses: git-for-windows/get-azure-pipelines-artifact@v0 with: repository: git/git definitionId: 9 - name: add msbuild to PATH + if: env.SKIP != 'true' uses: microsoft/setup-msbuild@v1 - name: copy dlls to root + if: env.SKIP != 'true' shell: powershell run: | & compat\vcbuild\vcpkg_copy_dlls.bat release arm64-windows if (!$?) { exit(1) } - name: generate Visual Studio solution + if: env.SKIP != 'true' shell: bash run: | cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/arm64-windows \ -DNO_GETTEXT=YesPlease -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON -DCMAKE_GENERATOR_PLATFORM=arm64 -DVCPKG_ARCH=arm64-windows \ -DCMAKE_INSTALL_PREFIX="`pwd`/git-arm64" -DSKIP_DASHED_BUILT_INS=ON - name: MSBuild + if: env.SKIP != 'true' run: msbuild git.sln -property:Configuration=Release - name: Link the Git executables + if: env.SKIP != 'true' run: msbuild INSTALL.vcxproj -property:Configuration=Release - name: upload build artifacts + if: env.SKIP != 'true' uses: actions/upload-artifact@v1 with: name: arm64-artifacts From fb8c21b3854de5be8d0fff9492da3ae78f7d180f Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 3 Feb 2021 15:52:58 +0100 Subject: [PATCH 066/105] git-artifacts: use the cached build-installers instead of makepkg-git When building the Pacman packages, we technically do not need the full `build-installers` artifact (which is substantially larger than the `makepkg-git` artifact). However, the former is already cached and includes the latter's files. And it is _so_ much faster to download the cached (larger) artifact than to download the smaller `makepkg-git` artifact from Azure Pipelines. Suggested-by: Dennis Ameling Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index c2767fe266..ba95460584 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -149,16 +149,23 @@ jobs: git config --global user.name "$USER_NAME" && git config --global user.email "$USER_EMAIL" && echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV - - name: Download git-sdk-64-makepkg-git + - name: Cache git-sdk-64-build-installers + id: cache-sdk-build-installers + uses: actions/cache@v2 + with: + path: git-sdk-64-build-installers + key: build-installers-64-${{ needs.bundle-artifacts.outputs.latest-sdk64-extra-build-id }} + - name: Download git-sdk-64-build-installers + if: steps.cache-sdk-build-installers.outputs.cache-hit != 'true' shell: bash run: | # Use Git Bash to download and unpack the artifact ## Get artifact urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=${{ needs.bundle-artifacts.outputs.latest-sdk64-extra-build-id }} - download_url="$(curl "$urlbase/$id/artifacts" | - jq -r '.value[] | select(.name == "git-sdk-64-makepkg-git").resource.downloadUrl')" + id=${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} + download_url=$(curl "$urlbase/$id/artifacts" | + jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl') curl -o artifacts.zip "$download_url" @@ -172,8 +179,14 @@ jobs: - name: Clone and update build-extra shell: bash run: | - d=git-sdk-64-makepkg-git/usr/src/build-extra && - git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d && + d=git-sdk-64-build-installers/usr/src/build-extra && + if test ! -d $d/.git + then + git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d + else + git -C $d fetch https://github.com/git-for-windows/build-extra main && + git -C $d switch -C main FETCH_HEAD + fi && git -C $d pull "$PWD"/bundle-artifacts/build-extra.bundle main - name: Check out git/git shell: bash @@ -209,7 +222,7 @@ jobs: GPGKEY: "${{secrets.GPGKEY}}" shell: powershell run: | - & git-sdk-64-makepkg-git\usr\bin\sh.exe -lc @" + & git-sdk-64-build-installers\usr\bin\sh.exe -lc @" set -x # Let `cv2pdb` find the DLLs PATH=\"`$PATH:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin${{matrix.arch.bin}}\" From 8b6fa642c597fbec82d97c24f5b545ff70cfbe1a Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 23 Feb 2021 12:44:29 +0100 Subject: [PATCH 067/105] git-artifacts: mark all inputs as "not required" This workflow needs to be triggered manually, and it offers to specify a couple input parameters. But none of them are required. Make that explicit. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index f6537f6c5a..04ce234988 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -7,10 +7,13 @@ on: inputs: build_only: description: 'Optionally restrict what artifacts to build' + required: false ref: description: 'Optionally override which branch to build' + required: false repository: description: 'Optionally override from where to fetch the specified ref' + required: false env: GPG_OPTIONS: "--batch --yes --no-tty --list-options no-show-photos --verify-options no-show-photos --pinentry-mode loopback" From 0c1d0cb31b9badbacc9c5f5abd8067131849db28 Mon Sep 17 00:00:00 2001 From: Dennis Ameling Date: Thu, 4 Feb 2021 16:49:01 +0100 Subject: [PATCH 068/105] git-artifacts: add ARM64 artifacts Adds ARM64 artifacts to the git-artifacts GitHub Action workflow. Signed-off-by: Dennis Ameling Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 75 +++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index ba95460584..327683f35f 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -253,9 +253,54 @@ jobs: with: name: pkg-${{matrix.arch.name}} path: artifacts + build-arm64: + needs: bundle-artifacts + runs-on: windows-latest + steps: + - name: Configure user + shell: bash + run: + USER_NAME="${{github.actor}}" && + USER_EMAIL="${{github.actor}}@users.noreply.github.com" && + mkdir -p "$HOME" && + git config --global user.name "$USER_NAME" && + git config --global user.email "$USER_EMAIL" + - uses: actions/checkout@v2 + - name: initialize vcpkg + uses: actions/checkout@v2 + with: + repository: 'microsoft/vcpkg' + path: 'compat/vcbuild/vcpkg' + - name: download vcpkg artifacts + uses: git-for-windows/get-azure-pipelines-artifact@v0 + with: + repository: git/git + definitionId: 9 + - name: add msbuild to PATH + uses: microsoft/setup-msbuild@v1 + - name: copy dlls to root + shell: powershell + run: | + & compat\vcbuild\vcpkg_copy_dlls.bat release arm64-windows + if (!$?) { exit(1) } + - name: generate Visual Studio solution + shell: bash + run: | + cmake `pwd`/contrib/buildsystems/ -DCMAKE_PREFIX_PATH=`pwd`/compat/vcbuild/vcpkg/installed/arm64-windows \ + -DNO_GETTEXT=YesPlease -DPERL_TESTS=OFF -DPYTHON_TESTS=OFF -DCURL_NO_CURL_CMAKE=ON -DCMAKE_GENERATOR_PLATFORM=arm64 -DVCPKG_ARCH=arm64-windows \ + -DCMAKE_INSTALL_PREFIX="`pwd`/git-arm64" + - name: MSBuild + run: msbuild git.sln -property:Configuration=Release + - name: Link the Git executables + run: msbuild INSTALL.vcxproj -property:Configuration=Release + - name: upload build artifacts + uses: actions/upload-artifact@v1 + with: + name: arm64-artifacts + path: ./git-arm64 artifacts: runs-on: windows-latest - needs: pkg + needs: [pkg, build-arm64] strategy: matrix: artifact: @@ -277,8 +322,13 @@ jobs: arch: - name: x86_64 bitness: 64 + arm64: false - name: i686 bitness: 32 + arm64: false + - name: i686 + bitness: 32 + arm64: true fail-fast: false env: MSYSTEM: MINGW${{matrix.arch.bitness}} @@ -360,6 +410,12 @@ jobs: ## Unpack artifact unzip artifacts.zip + - name: Download arm64 artifact + if: env.SKIP != 'true' && matrix.arch.arm64 == true + uses: actions/download-artifact@v1 + with: + name: arm64-artifacts + path: ${{github.workspace}}/arm64 - name: Clone and update build-extra if: env.SKIP != 'true' shell: bash @@ -390,7 +446,14 @@ jobs: run: | & .\git-sdk-${{matrix.arch.bitness}}-build-installers\usr\bin\bash.exe -lc @" set -x - /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-${{matrix.arch.name}}/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-[0-9]*.tar.xz --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-doc-html-[0-9]*.tar.xz && + if test "${{matrix.arch.arm64}}" = true + then + ARM64="--include-arm64-artifacts=\"$PWD/arm64\"" + else + ARM64= + fi + + eval /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git `$ARM64 --version=`$(cat pkg-${{matrix.arch.name}}/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-[0-9]*.tar.xz --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-doc-html-[0-9]*.tar.xz && if test portable = '${{matrix.artifact.name}}' && test -n \"`$(git config alias.signtool)\" then git signtool artifacts/PortableGit-*.exe @@ -416,11 +479,17 @@ jobs: shell: bash run: rm -rf home - name: Publish ${{matrix.artifact.name}}-${{matrix.arch.name}} - if: env.SKIP != 'true' + if: env.SKIP != 'true' && matrix.arch.arm64 != true uses: actions/upload-artifact@v1 with: name: ${{matrix.artifact.name}}-${{matrix.arch.name}} path: artifacts + - name: Publish ${{matrix.artifact.name}}-arm64 + if: env.SKIP != 'true' && matrix.arch.arm64 == true + uses: actions/upload-artifact@v1 + with: + name: ${{matrix.artifact.name}}-arm64 + path: artifacts nuget: runs-on: windows-latest needs: pkg From 4b64e06c6d7030e248f268451abcc3d20263d7af Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 23 Feb 2021 13:32:31 +0100 Subject: [PATCH 069/105] git-artifacts(build-arm64): build artifacts using the intended Git revision We cannot just check out the current revision: The user might have overridden `REPOSITORY` and `REF` via the workflow dispatch. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 04ce234988..35dd92fc52 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -303,8 +303,20 @@ jobs: mkdir -p "$HOME" && git config --global user.name "$USER_NAME" && git config --global user.email "$USER_EMAIL" - - uses: actions/checkout@v2 + - name: Download bundle-artifacts if: env.SKIP != 'true' + uses: actions/download-artifact@v1 + with: + name: bundle-artifacts + path: bundle-artifacts + - name: Check out git/git + if: env.SKIP != 'true' + shell: bash + run: | + git -c init.defaultBranch=main init && + git remote add -f origin https://github.com/git-for-windows/git && + git fetch --tags bundle-artifacts/git.bundle $(cat bundle-artifacts/next_version) && + git reset --hard $(cat bundle-artifacts/next_version) - name: initialize vcpkg if: env.SKIP != 'true' uses: actions/checkout@v2 From 74f1d06501abdab7710ba1fbc13167edc555d847 Mon Sep 17 00:00:00 2001 From: Dennis Ameling Date: Wed, 3 Mar 2021 11:59:05 +0100 Subject: [PATCH 070/105] git-artifacts: add workaround for GCM Core on ARM64 Since there is no GCM Core for ARM64, let's just install a simple shell script that calls the i686 version for now. Signed-off-by: Dennis Ameling Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 327683f35f..64dc1dbcef 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -416,6 +416,13 @@ jobs: with: name: arm64-artifacts path: ${{github.workspace}}/arm64 + # Workaround for Git Credential Manager Core on ARM64: https://github.com/git-for-windows/git/issues/3015 + - name: Create git-credential-manager-core wrapper for ARM64 + if: env.SKIP != 'true' && matrix.arch.arm64 == true + shell: bash + run: | + printf '%s\n' '#!/bin/sh' 'exec /mingw32/libexec/git-core/git-credential-manager-core.exe "$@"' > arm64/libexec/git-core/git-credential-manager-core + chmod +x arm64/libexec/git-core/git-credential-manager-core - name: Clone and update build-extra if: env.SKIP != 'true' shell: bash From b6cd36f75a5427fd276992566c0da7f240f7e7ab Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 23 Feb 2021 11:35:47 +0100 Subject: [PATCH 071/105] git-artifacts: use the `setup-git-for-windows-sdk` Action This simplifies the workflow dramatically, as well as accelerating it because the Action recently learned to use the partial clone/parallel checkout features of Git. Note that we have to reinstate that `/usr/bin/git` hack (a shell script that simply redirects to `/mingw64/bin/git.exe`) in the `pkg` job manually, since we no longer cache the `build-installers` artifact _after_ installing that hack in `bundle-artifacts`. Signed-off-by: Johannes Schindelin --- .github/workflows/git-artifacts.yml | 288 ++++++++-------------------- 1 file changed, 81 insertions(+), 207 deletions(-) diff --git a/.github/workflows/git-artifacts.yml b/.github/workflows/git-artifacts.yml index 35dd92fc52..4352cb126c 100644 --- a/.github/workflows/git-artifacts.yml +++ b/.github/workflows/git-artifacts.yml @@ -27,8 +27,6 @@ env: jobs: bundle-artifacts: runs-on: windows-latest - outputs: - latest-sdk64-extra-build-id: ${{ steps.determine-latest-sdk64-extra-build-id.outputs.id }} steps: - name: Configure user shell: bash @@ -39,42 +37,13 @@ jobs: git config --global user.name "$USER_NAME" && git config --global user.email "$USER_EMAIL" && echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV - - name: Determine latest git-sdk-64-extra-artifacts build ID - id: determine-latest-sdk64-extra-build-id - shell: bash - run: | - urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=$(curl "$urlbase?definitions=29&statusFilter=completed&resultFilter=succeeded&\$top=1" | - jq -r '.value[0].id') - - echo "Latest ID is ${id}" - echo "::set-output name=id::$id" - - name: Cache git-sdk-64-build-installers - id: cache-sdk-build-installers - uses: actions/cache@v2 + - uses: git-for-windows/setup-git-for-windows-sdk@v1 with: - path: git-sdk-64-build-installers - key: build-installers-64-${{ steps.determine-latest-sdk64-extra-build-id.outputs.id }} - - name: Download git-sdk-64-build-installers - if: steps.cache-sdk-build-installers.outputs.cache-hit != 'true' - shell: bash - run: | - # Use Git Bash to download and unpack the artifact - - ## Get artifact - urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=${{ steps.determine-latest-sdk64-extra-build-id.outputs.id }} - download_url=$(curl "$urlbase/$id/artifacts" | - jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl') - - curl -o artifacts.zip "$download_url" - - ## Unpack artifact - unzip artifacts.zip + flavor: build-installers - name: Clone build-extra shell: bash run: | - d=git-sdk-64-build-installers/usr/src/build-extra && + d=/usr/src/build-extra && if test ! -d $d/.git then git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d @@ -88,7 +57,7 @@ jobs: run: | echo '${{secrets.PRIVGPGKEY}}' | tr % '\n' | gpg $GPG_OPTIONS --import && mkdir -p home && - git config --global gpg.program "$PWD/git-sdk-64-build-installers/usr/src/build-extra/gnupg-with-gpgkey.sh" && + git config --global gpg.program "/usr/src/build-extra/gnupg-with-gpgkey.sh" && info="$(gpg --list-keys --with-colons "${GPGKEY%% *}" | cut -d : -f 1,10 | sed -n '/^uid/{s|uid:||p;q}')" && git config --global user.name "${info% <*}" && git config --global user.email "<${info#*<}" @@ -97,28 +66,26 @@ jobs: - name: Generate bundle artifacts env: GPGKEY: ${{secrets.GPGKEY}} - shell: powershell + shell: bash run: | - & .\git-sdk-64-build-installers\git-cmd.exe --command=usr\bin\bash.exe -lc @" - printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "`$@"\n' >/usr/bin/git && - mkdir -p bundle-artifacts && + printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "$@"\n' >/usr/bin/git && + mkdir -p bundle-artifacts && - { test -n \"`$REPOSITORY\" || REPOSITORY='${{github.repository}}'; } && - { test -n \"`$REF\" || REF='${{github.ref}}'; } && - git -c init.defaultBranch=main init --bare && - git remote add -f origin https://github.com/git-for-windows/git && - git fetch \"https://github.com/`$REPOSITORY\" \"`$REF:`$REF\" && + { test -n "$REPOSITORY" || REPOSITORY='${{github.repository}}'; } && + { test -n "$REF" || REF='${{github.ref}}'; } && + git -c init.defaultBranch=main init --bare && + git remote add -f origin https://github.com/git-for-windows/git && + git fetch "https://github.com/$REPOSITORY" "$REF:$REF" && - tag_name=\"`$(git describe --match 'v[0-9]*' FETCH_HEAD)-`$(date +%Y%m%d%H%M%S)\" && - echo \"prerelease-`${tag_name#v}\" >bundle-artifacts/ver && - echo \"`${tag_name#v}\" >bundle-artifacts/display_version && - echo \"`$tag_name\" >bundle-artifacts/next_version && - git tag `$(test -z \"`$GPGKEY\" || echo \" -s\") -m \"Snapshot build\" \"`$tag_name\" FETCH_HEAD && - git bundle create bundle-artifacts/git.bundle origin/main..\"`$tag_name\" && + tag_name="$(git describe --match 'v[0-9]*' FETCH_HEAD)-$(date +%Y%m%d%H%M%S)" && + echo "prerelease-${tag_name#v}" >bundle-artifacts/ver && + echo "${tag_name#v}" >bundle-artifacts/display_version && + echo "$tag_name" >bundle-artifacts/next_version && + git tag $(test -z "$GPGKEY" || echo " -s") -m "Snapshot build" "$tag_name" FETCH_HEAD && + git bundle create bundle-artifacts/git.bundle origin/main.."$tag_name" && - sh -x /usr/src/build-extra/please.sh mention feature \"Snapshot of `$(git show -s --pretty='tformat:%h (%s, %ad)' --date=short FETCH_HEAD)\" && - git -C /usr/src/build-extra bundle create \"`$PWD/bundle-artifacts/build-extra.bundle\" origin/main..main - "@ + sh -x /usr/src/build-extra/please.sh mention feature "Snapshot of $(git show -s --pretty='tformat:%h (%s, %ad)' --date=short FETCH_HEAD)" && + git -C /usr/src/build-extra bundle create "$PWD/bundle-artifacts/build-extra.bundle" origin/main..main - name: Clean up temporary files if: always() shell: bash @@ -131,8 +98,6 @@ jobs: pkg: runs-on: windows-latest needs: bundle-artifacts - outputs: - latest-sdk64-extra-build-id: ${{ needs.bundle-artifacts.outputs.latest-sdk64-extra-build-id }} strategy: matrix: arch: @@ -166,29 +131,10 @@ jobs: git config --global user.name "$USER_NAME" && git config --global user.email "$USER_EMAIL" && echo "PACKAGER=$USER_NAME <$USER_EMAIL>" >>$GITHUB_ENV - - name: Cache git-sdk-64-build-installers + - uses: git-for-windows/setup-git-for-windows-sdk@v1 if: env.SKIP != 'true' - id: cache-sdk-build-installers - uses: actions/cache@v2 with: - path: git-sdk-64-build-installers - key: build-installers-64-${{ needs.bundle-artifacts.outputs.latest-sdk64-extra-build-id }} - - name: Download git-sdk-64-build-installers - if: env.SKIP != 'true' && steps.cache-sdk-build-installers.outputs.cache-hit != 'true' - shell: bash - run: | - # Use Git Bash to download and unpack the artifact - - ## Get artifact - urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} - download_url=$(curl "$urlbase/$id/artifacts" | - jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl') - - curl -o artifacts.zip "$download_url" - - ## Unpack artifact - unzip artifacts.zip + flavor: build-installers - name: Download bundle-artifacts if: env.SKIP != 'true' uses: actions/download-artifact@v1 @@ -199,7 +145,7 @@ jobs: if: env.SKIP != 'true' shell: bash run: | - d=git-sdk-64-build-installers/usr/src/build-extra && + d=/usr/src/build-extra && if test ! -d $d/.git then git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d @@ -242,32 +188,33 @@ jobs: if: env.SKIP != 'true' env: GPGKEY: "${{secrets.GPGKEY}}" - shell: powershell + shell: bash run: | - & git-sdk-64-build-installers\usr\bin\sh.exe -lc @" - set -x + set -x - # Restrict `PATH` to MSYS2 and to Visual Studio (to let `cv2pdb` find the relevant DLLs) - PATH=\"`/mingw64/bin:/usr/bin:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin${{matrix.arch.bin}}:/C/Windows/system32\" + # Make sure that there is a `/usr/bin/git` that can be used by `makepkg-mingw` + printf '#!/bin/sh\n\nexec /mingw64/bin/git.exe "$@"\n' >/usr/bin/git && - type -p mspdb140.dll || exit 1 - sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-${{matrix.arch.bitness}}-bit --build-src-pkg -o artifacts HEAD && - cp bundle-artifacts/ver artifacts/ && - if test -n \"`$GPGKEY\" - then - for tar in artifacts/*.tar* - do - /usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor `$tar - done - fi && + # Restrict `PATH` to MSYS2 and to Visual Studio (to let `cv2pdb` find the relevant DLLs) + PATH="/mingw64/bin:/usr/bin:/c/Program Files/Microsoft Visual Studio/2022/Enterprise/Common7/IDE/:/C/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin${{matrix.arch.bin}}:/C/Windows/system32" - b=`$PWD/artifacts && - version=`$(cat bundle-artifacts/next_version) && - (cd /usr/src/MINGW-packages/mingw-w64-git && - cp PKGBUILD.`$version PKGBUILD && - git commit -s -m \"mingw-w64-git: new version (`$version)\" PKGBUILD && - git bundle create \"`$b\"/MINGW-packages.bundle origin/main..main) - "@ + type -p mspdb140.dll || exit 1 + sh -x /usr/src/build-extra/please.sh build-mingw-w64-git --only-${{matrix.arch.bitness}}-bit --build-src-pkg -o artifacts HEAD && + cp bundle-artifacts/ver artifacts/ && + if test -n "$GPGKEY" + then + for tar in artifacts/*.tar* + do + /usr/src/build-extra/gnupg-with-gpgkey.sh --detach-sign --no-armor $tar + done + fi && + + b=$PWD/artifacts && + version=$(cat bundle-artifacts/next_version) && + (cd /usr/src/MINGW-packages/mingw-w64-git && + cp PKGBUILD.$version PKGBUILD && + git commit -s -m "mingw-w64-git: new version ($version)" PKGBUILD && + git bundle create "$b"/MINGW-packages.bundle origin/main..main) - name: Clean up temporary files if: always() && env.SKIP != 'true' shell: bash @@ -417,63 +364,15 @@ jobs: with: name: bundle-artifacts path: bundle-artifacts - - name: Cache git-sdk-64-build-installers + - uses: git-for-windows/setup-git-for-windows-sdk@v1 if: env.SKIP != 'true' && matrix.arch.bitness == '64' - id: cache-sdk64-build-installers - uses: actions/cache@v2 with: - path: git-sdk-64-build-installers - key: build-installers-64-${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} - - name: Download git-sdk-64-build-installers - if: env.SKIP != 'true' && matrix.arch.bitness == '64' && steps.cache-sdk64-build-installers.outputs.cache-hit != 'true' - shell: bash - run: | - # Use Git Bash to download and unpack the artifact - - ## Get artifact - urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} - download_url="$(curl "$urlbase/$id/artifacts" | - jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl')" - - curl -o artifacts.zip "$download_url" - - ## Unpack artifact - unzip artifacts.zip - - name: Determine latest git-sdk-32-extra-artifacts build ID + flavor: build-installers + - uses: git-for-windows/setup-git-for-windows-sdk@v1 if: env.SKIP != 'true' && matrix.arch.bitness == '32' - id: determine-latest-sdk32-extra-build-id - shell: bash - run: | - urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=$(curl "$urlbase?definitions=30&statusFilter=completed&resultFilter=succeeded&\$top=1" | - jq -r '.value[0].id') - - echo "Latest ID is ${id}" - echo "::set-output name=id::$id" - - name: Cache git-sdk-32-build-installers - if: env.SKIP != 'true' && matrix.arch.bitness == '32' - id: cache-sdk32-build-installers - uses: actions/cache@v2 with: - path: git-sdk-32-build-installers - key: build-installers-32-${{ steps.determine-latest-sdk32-extra-build-id.outputs.id }} - - name: Download git-sdk-32-build-installers - if: env.SKIP != 'true' && matrix.arch.bitness == '32' && steps.cache-sdk32-build-installers.outputs.cache-hit != 'true' - shell: bash - run: | - # Use Git Bash to download and unpack the artifact - - ## Get artifact - urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=${{ steps.determine-latest-sdk32-extra-build-id.outputs.id }} - download_url=$(curl "$urlbase/$id/artifacts" | - jq -r '.value[] | select(.name == "git-sdk-32-build-installers").resource.downloadUrl') - - curl -o artifacts.zip "$download_url" - - ## Unpack artifact - unzip artifacts.zip + flavor: build-installers + architecture: i686 - name: Download arm64 artifact if: env.SKIP != 'true' && matrix.arch.arm64 == true uses: actions/download-artifact@v1 @@ -484,7 +383,7 @@ jobs: if: env.SKIP != 'true' shell: bash run: | - d=git-sdk-${{matrix.arch.bitness}}-build-installers/usr/src/build-extra && + d=/usr/src/build-extra && if test ! -d $d/.git then git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d @@ -506,38 +405,34 @@ jobs: git config --global alias.signtool '!sh "/usr/src/build-extra/signtool.sh"' - name: Build ${{matrix.arch.bitness}}-bit ${{matrix.artifact.name}} if: env.SKIP != 'true' - shell: powershell + shell: bash run: | - & .\git-sdk-${{matrix.arch.bitness}}-build-installers\usr\bin\bash.exe -lc @" - set -x - if test "${{matrix.arch.arm64}}" = true - then - ARM64="--include-arm64-artifacts=\"$PWD/arm64\"" - else - ARM64= - fi + set -x + if test "${{matrix.arch.arm64}}" = true + then + ARM64="--include-arm64-artifacts=\"$PWD/arm64\"" + else + ARM64= + fi - eval /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git `$ARM64 --version=`$(cat pkg-${{matrix.arch.name}}/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-[0-9]*.tar.xz --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-doc-html-[0-9]*.tar.xz && - if test portable = '${{matrix.artifact.name}}' && test -n \"`$(git config alias.signtool)\" - then - git signtool artifacts/PortableGit-*.exe - fi && - openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.${{matrix.artifact.fileextension}} | sed \"s/.* //\" >artifacts/sha-256.txt - "@ + eval /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git $ARM64 --version=$(cat pkg-${{matrix.arch.name}}/ver) -o artifacts --${{matrix.artifact.name}} --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-[0-9]*.tar.xz --pkg=pkg-${{matrix.arch.name}}/mingw-w64-${{matrix.arch.name}}-git-doc-html-[0-9]*.tar.xz && + if test portable = '${{matrix.artifact.name}}' && test -n "$(git config alias.signtool)" + then + git signtool artifacts/PortableGit-*.exe + fi && + openssl dgst -sha256 artifacts/${{matrix.artifact.fileprefix}}-*.${{matrix.artifact.fileextension}} | sed "s/.* //" >artifacts/sha-256.txt - name: Copy package-versions and pdbs if: env.SKIP != 'true' && matrix.artifact.name == 'installer' - shell: powershell + shell: bash run: | - & .\git-sdk-${{matrix.arch.bitness}}-build-installers\usr\bin\bash.exe -lc @" - cp /usr/src/build-extra/installer/package-versions.txt artifacts/ && + cp /usr/src/build-extra/installer/package-versions.txt artifacts/ && - a=`$PWD/artifacts && - p=`$PWD/pkg-${{matrix.arch.name}} && - (cd /usr/src/build-extra && - mkdir -p cached-source-packages && - cp \"`$p\"/*-pdb* cached-source-packages/ && - GIT_CONFIG_PARAMETERS=\"'windows.sdk${{matrix.arch.bitness}}.path='\" ./please.sh bundle_pdbs --arch=${{matrix.arch.name}} --directory=\"`$a\" installer/package-versions.txt) - "@ + a=$PWD/artifacts && + p=$PWD/pkg-${{matrix.arch.name}} && + (cd /usr/src/build-extra && + mkdir -p cached-source-packages && + cp "$p"/*-pdb* cached-source-packages/ && + GIT_CONFIG_PARAMETERS="'windows.sdk${{matrix.arch.bitness}}.path='" ./please.sh bundle_pdbs --arch=${{matrix.arch.name}} --directory="$a" installer/package-versions.txt) - name: Clean up temporary files if: always() && env.SKIP != 'true' shell: bash @@ -578,34 +473,15 @@ jobs: with: name: bundle-artifacts path: bundle-artifacts - - name: Cache git-sdk-64-build-installers + - uses: git-for-windows/setup-git-for-windows-sdk@v1 if: env.SKIP != 'true' - id: cache-sdk-build-installers - uses: actions/cache@v2 with: - path: git-sdk-64-build-installers - key: build-installers-64-${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} - - name: Download git-sdk-64-build-installers - if: env.SKIP != 'true' && steps.cache-sdk-build-installers.outputs.cache-hit != 'true' - shell: bash - run: | - # Use Git Bash to download and unpack the artifact - - ## Get artifact - urlbase=https://dev.azure.com/git-for-windows/git/_apis/build/builds - id=${{ needs.pkg.outputs.latest-sdk64-extra-build-id }} - download_url=$(curl "$urlbase/$id/artifacts" | - jq -r '.value[] | select(.name == "git-sdk-64-build-installers").resource.downloadUrl') - - curl -o artifacts.zip "$download_url" - - ## Unpack artifact - unzip artifacts.zip + flavor: build-installers - name: Clone and update build-extra if: env.SKIP != 'true' shell: bash run: | - d=git-sdk-64-build-installers/usr/src/build-extra && + d=/usr/src/build-extra && if test ! -d $d/.git then git clone --single-branch -b main https://github.com/git-for-windows/build-extra $d @@ -618,13 +494,11 @@ jobs: if: env.SKIP != 'true' - name: Build 64-bit NuGet packages if: env.SKIP != 'true' - shell: powershell + shell: bash run: | - & .\git-sdk-64-build-installers\usr\bin\bash.exe -lc @" - /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --nuget --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && - /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=`$(cat pkg-x86_64/ver) -o artifacts --nuget-mingit && - openssl dgst -sha256 artifacts/Git*.nupkg | sed \"s/.* //\" >artifacts/sha-256.txt - "@ + /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=$(cat pkg-x86_64/ver) -o artifacts --nuget --pkg=pkg-x86_64/mingw-w64-x86_64-git-[0-9]*.tar.xz --pkg=pkg-x86_64/mingw-w64-x86_64-git-doc-html-[0-9]*.tar.xz && + /usr/src/build-extra/please.sh make_installers_from_mingw_w64_git --version=$(cat pkg-x86_64/ver) -o artifacts --nuget-mingit && + openssl dgst -sha256 artifacts/Git*.nupkg | sed "s/.* //" >artifacts/sha-256.txt - name: Publish nuget-x86_64 if: env.SKIP != 'true' uses: actions/upload-artifact@v1 From 2ef79219ebbd85c6ac6355c0d07319054a1fa7ea Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 19 Feb 2021 11:39:37 +0100 Subject: [PATCH 072/105] ci(vs-build): download the vcpkg artifacts using a dedicated Action We now have a GitHub Action to download and cache Azure Pipelines artifacts (such as the `vcpkg` artifacts), hiding gnarly internals, and also providing some robustness against network glitches. Let's use it. Signed-off-by: Johannes Schindelin --- .github/workflows/main.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3fa88b78b6..513c93f945 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -142,14 +142,10 @@ jobs: repository: 'microsoft/vcpkg' path: 'compat/vcbuild/vcpkg' - name: download vcpkg artifacts - shell: powershell - run: | - $urlbase = "https://dev.azure.com/git/git/_apis/build/builds" - $id = ((Invoke-WebRequest -UseBasicParsing "${urlbase}?definitions=9&statusFilter=completed&resultFilter=succeeded&`$top=1").content | ConvertFrom-JSON).value[0].id - $downloadUrl = ((Invoke-WebRequest -UseBasicParsing "${urlbase}/$id/artifacts").content | ConvertFrom-JSON).value[0].resource.downloadUrl - (New-Object Net.WebClient).DownloadFile($downloadUrl, "compat.zip") - Expand-Archive compat.zip -DestinationPath . -Force - Remove-Item compat.zip + uses: git-for-windows/get-azure-pipelines-artifact@v0 + with: + repository: git/git + definitionId: 9 - name: add msbuild to PATH uses: microsoft/setup-msbuild@v1 - name: copy dlls to root From 8e006ac50c44a80d90adbc67c74775327fc32a01 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 2 Apr 2021 22:50:54 +0200 Subject: [PATCH 073/105] mingw: allow for longer paths in `parse_interpreter()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As reported in https://github.com/newren/git-filter-repo/pull/225, it looks like 99 bytes is not really sufficient to represent e.g. the full path to Python when installed via Windows Store (and this path is used in the hasb bang line when installing scripts via `pip`). Let's increase it to what is probably the maximum sensible path size: MAX_PATH. This makes `parse_interpreter()` in line with what `lookup_prog()` handles. Signed-off-by: Johannes Schindelin Signed-off-by: Vilius Šumskas --- compat/mingw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compat/mingw.c b/compat/mingw.c index 2607de93af..83be86c3a8 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1249,7 +1249,7 @@ static const char *quote_arg_msys2(const char *arg) static const char *parse_interpreter(const char *cmd) { - static char buf[100]; + static char buf[MAX_PATH]; char *p, *opt; int n, fd; From 5ba2775ad8d3e5dce19b372bd4fc9f7153eb9cb3 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 17 May 2021 10:46:52 +0200 Subject: [PATCH 074/105] compat/vcbuild: document preferred way to build in Visual Studio We used to have that `make vcxproj` hack, but a hack it is. In the meantime, we have a much cleaner solution: using CMake, either explicitly, or even more conveniently via Visual Studio's built-in CMake support (simply open Git's top-level directory via File>Open>Folder...). Let's let the `README` reflect this. Signed-off-by: Johannes Schindelin --- compat/vcbuild/README | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/compat/vcbuild/README b/compat/vcbuild/README index 29ec1d0f10..5c71ea2daa 100644 --- a/compat/vcbuild/README +++ b/compat/vcbuild/README @@ -37,27 +37,17 @@ The Steps to Build Git with VS2015 or VS2017 from the command line. ================================================================ -Alternatively, run `make vcxproj` and then load the generated `git.sln` in -Visual Studio. The initial build will install the vcpkg system and build the +Alternatively, just open Git's top-level directory in Visual Studio, via +`File>Open>Folder...`. This will use CMake internally to generate the +project definitions. It will also install the vcpkg system and build the dependencies automatically. This will take a while. -Instead of generating the `git.sln` file yourself (which requires a full Git -for Windows SDK), you may want to consider fetching the `vs/master` branch of -https://github.com/git-for-windows/git instead (which is updated automatically -via CI running `make vcxproj`). The `vs/master` branch does not require a Git -for Windows to build, but you can run the test scripts in a regular Git Bash. +You can also generate the Visual Studio solution manually by downloading +and running CMake explicitly rather than letting Visual Studio doing +that implicitly. -Note that `make vcxproj` will automatically add and commit the generated `.sln` -and `.vcxproj` files to the repo. This is necessary to allow building a -fully-testable Git in Visual Studio, where a regular Git Bash can be used to -run the test scripts (as opposed to a full Git for Windows SDK): a number of -build targets, such as Git commands implemented as Unix shell scripts (where -`@@SHELL_PATH@@` and other placeholders are interpolated) require a full-blown -Git for Windows SDK (which is about 10x the size of a regular Git for Windows -installation). - -If your plan is to open a Pull Request with Git for Windows, it is a good idea -to drop this commit before submitting. +Another, deprecated option is to run `make vcxproj`. This option is +superseded by the CMake-based build, and will be removed at some point. ================================================================ The Steps of Build Git with VS2008 From 36a34aeab9b233fa6acfe1e227f13fa544071fc3 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Thu, 5 Aug 2021 19:04:13 -0400 Subject: [PATCH 075/105] subtree: update `contrib/subtree` `test` target The intention of this change is to align with how the top-level git `Makefile` defines its own test target (which also internally calls `$(MAKE) -C t/ all`). This change also ensures the consistency of `make -C contrib/subtree test` with other testing in CI executions (which rely on `$DEFAULT_TEST_TARGET` being defined as `prove`). Signed-off-by: Victoria Dye --- contrib/subtree/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/subtree/Makefile b/contrib/subtree/Makefile index 6fa7496bfd..6f6e90c4cb 100644 --- a/contrib/subtree/Makefile +++ b/contrib/subtree/Makefile @@ -94,7 +94,7 @@ $(GIT_SUBTREE_TEST): $(GIT_SUBTREE) cp $< $@ test: $(GIT_SUBTREE_TEST) - $(MAKE) -C t/ test + $(MAKE) -C t/ all clean: $(RM) $(GIT_SUBTREE) From 12625e01bd6df27880fac9ed62e0327f3794d5d9 Mon Sep 17 00:00:00 2001 From: Pascal Muller Date: Wed, 23 Jun 2021 21:21:10 +0200 Subject: [PATCH 076/105] http: optionally send SSL client certificate This adds support for a new http.sslAutoClientCert config value. In cURL 7.77 or later the schannel backend does not automatically send client certificates from the Windows Certificate Store anymore. This config value is only used if http.sslBackend is set to "schannel", and can be used to opt in to the old behavior and force cURL to send client certificates. This fixes https://github.com/git-for-windows/git/issues/3292 Signed-off-by: Pascal Muller --- Documentation/config/http.txt | 5 +++++ git-curl-compat.h | 8 ++++++++ http.c | 26 ++++++++++++++++++++++---- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt index ebdee6dc09..c526ad07cb 100644 --- a/Documentation/config/http.txt +++ b/Documentation/config/http.txt @@ -205,6 +205,11 @@ http.schannelUseSSLCAInfo:: when the `schannel` backend was configured via `http.sslBackend`, unless `http.schannelUseSSLCAInfo` overrides this behavior. +http.sslAutoClientCert:: + As of cURL v7.77.0, the Secure Channel backend won't automatically + send client certificates from the Windows Certificate Store anymore. + To opt in to the old behavior, http.sslAutoClientCert can be set. + http.pinnedpubkey:: Public key of the https service. It may either be the filename of a PEM or DER encoded public key file or a string starting with diff --git a/git-curl-compat.h b/git-curl-compat.h index 56a83b6bbd..f9f784220f 100644 --- a/git-curl-compat.h +++ b/git-curl-compat.h @@ -126,4 +126,12 @@ #define GIT_CURL_HAVE_CURLSSLSET_NO_BACKENDS #endif +/** + * CURLSSLOPT_AUTO_CLIENT_CERT was added in 7.77.0, released in May + * 2021. + */ +#if LIBCURL_VERSION_NUM >= 0x074d00 +#define GIT_CURL_HAVE_CURLSSLOPT_AUTO_CLIENT_CERT +#endif + #endif diff --git a/http.c b/http.c index 1ad95be438..2f1021a1ba 100644 --- a/http.c +++ b/http.c @@ -150,6 +150,8 @@ static int http_schannel_check_revoke_mode = */ static int http_schannel_use_ssl_cainfo; +static int http_auto_client_cert; + size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_) { size_t size = eltsize * nmemb; @@ -314,6 +316,11 @@ static int http_options(const char *var, const char *value, void *cb) return 0; } + if (!strcmp("http.sslautoclientcert", var)) { + http_auto_client_cert = git_config_bool(var, value); + return 0; + } + if (!strcmp("http.minsessions", var)) { min_curl_sessions = git_config_int(var, value); if (min_curl_sessions > 1) @@ -836,13 +843,24 @@ static CURL *get_curl_handle(void) } #endif - if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) && - http_schannel_check_revoke_mode) { + if (http_ssl_backend && !strcmp("schannel", http_ssl_backend)) { + long ssl_options = 0; + if (http_schannel_check_revoke_mode) { #ifdef GIT_CURL_HAVE_CURLSSLOPT_NO_REVOKE - curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, http_schannel_check_revoke_mode); + ssl_options |= http_schannel_check_revoke_mode; #else - warning(_("CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0")); + warning(_("CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0")); #endif + } + + if (http_auto_client_cert) { +#ifdef GIT_CURL_HAVE_CURLSSLOPT_AUTO_CLIENT_CERT + ssl_options |= CURLSSLOPT_AUTO_CLIENT_CERT; +#endif + } + + if (ssl_options) + curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, ssl_options); } if (http_proactive_auth) From 3fd44297afb743b24f9e121e3846b4592275f691 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Thu, 5 Aug 2021 19:11:59 -0400 Subject: [PATCH 077/105] ci: run `contrib/subtree` tests in CI builds Because `git subtree` (unlike most other `contrib` modules) is included as part of the standard release of Git for Windows, its stability should be verified as consistently as it is for the rest of git. By including the `git subtree` tests in the CI workflow, these tests are as much of a gate to merging and indicator of stability as the standard test suite. Signed-off-by: Victoria Dye --- ci/run-build-and-tests.sh | 4 ++++ ci/run-test-slice.sh | 3 +++ 2 files changed, 7 insertions(+) diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh index 8ebff42596..1ea8909c6f 100755 --- a/ci/run-build-and-tests.sh +++ b/ci/run-build-and-tests.sh @@ -53,4 +53,8 @@ then fi check_unignored_build_artifacts +case " $MAKE_TARGETS " in +*" all "*) make -C contrib/subtree test;; +esac + save_good_tree diff --git a/ci/run-test-slice.sh b/ci/run-test-slice.sh index a3c67956a8..2f2dbea25b 100755 --- a/ci/run-test-slice.sh +++ b/ci/run-test-slice.sh @@ -15,4 +15,7 @@ group "Run tests" make --quiet -C t T="$(cd t && tr '\n' ' ')" || handle_failed_tests +# Run the git subtree tests only if main tests succeeded +test 0 != "$1" || make -C contrib/subtree test + check_unignored_build_artifacts From a1c57b55cfb6d2ae7c7569ef08188bebed2d60a8 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 8 Sep 2021 13:05:42 +0200 Subject: [PATCH 078/105] init: do parse _all_ core.* settings early In Git for Windows, `has_symlinks` is set to 0 by default. Therefore, we need to parse the config setting `core.symlinks` to know if it has been set to `true`. In `git init`, we must do that before copying the templates because they might contain symbolic links. Even if the support for symbolic links on Windows has not made it to upstream Git yet, we really should make sure that all the `core.*` settings are parsed before proceeding, as they might very well change the behavior of `git init` in a way the user intended. This fixes https://github.com/git-for-windows/git/issues/3414 Signed-off-by: Johannes Schindelin --- builtin/init-db.c | 2 +- config.c | 2 +- config.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/builtin/init-db.c b/builtin/init-db.c index 546f9c595e..f33d18e853 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -410,7 +410,7 @@ int init_db(const char *git_dir, const char *real_git_dir, startup_info->have_repository = 1; /* Ensure `core.hidedotfiles` is processed */ - git_config(platform_core_config, NULL); + git_config(git_default_core_config, NULL); safe_create_dir(git_dir, 0); diff --git a/config.c b/config.c index 9b0e9c9328..93bfad88e8 100644 --- a/config.c +++ b/config.c @@ -1463,7 +1463,7 @@ int git_config_color(char *dest, const char *var, const char *value) return 0; } -static int git_default_core_config(const char *var, const char *value, void *cb) +int git_default_core_config(const char *var, const char *value, void *cb) { /* This needs a better name */ if (!strcmp(var, "core.filemode")) { diff --git a/config.h b/config.h index 7654f61c63..51d442bc01 100644 --- a/config.h +++ b/config.h @@ -131,6 +131,7 @@ struct config_options { typedef int (*config_fn_t)(const char *, const char *, void *); int git_default_config(const char *, const char *, void *); +int git_default_core_config(const char *var, const char *value, void *cb); /** * Read a specific file in git-config format. From 09b61cf340489deaa8ec8b8ad64e6a4a2627625d Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Sun, 31 Oct 2021 23:15:13 +0000 Subject: [PATCH 079/105] hash-object: demonstrate a >4GB/LLP64 problem On LLP64 systems, such as Windows, the size of `long`, `int`, etc. is only 32 bits (for backward compatibility). Git's use of `unsigned long` for file memory sizes in many places, rather than size_t, limits the handling of large files on LLP64 systems (commonly given as `>4GB`). Provide a minimum test for handling a >4GB file. The `hash-object` command, with the `--literally` and without `-w` option avoids writing the object, either loose or packed. This avoids the code paths hitting the `bigFileThreshold` config test code, the zlib code, and the pack code. Subsequent patches will walk the test's call chain, converting types to `size_t` (which is larger in LLP64 data models) where appropriate. Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- t/t1007-hash-object.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index ac5ad8c740..428298fa29 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -50,6 +50,9 @@ test_expect_success 'setup' ' example sha1:ddd3f836d3e3fbb7ae289aa9ae83536f76956399 example sha256:b44fe1fe65589848253737db859bd490453510719d7424daab03daf0767b85ae + + large5GB sha1:0be2be10a4c8764f32c4bf372a98edc731a4b204 + large5GB sha256:dc18ca621300c8d3cfa505a275641ebab00de189859e022a975056882d313e64 EOF ' @@ -249,4 +252,12 @@ test_expect_success '--literally with extra-long type' ' echo example | git hash-object -t $t --literally --stdin ' +test_expect_failure EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ + 'files over 4GB hash literally' ' + test-tool genzeros $((5*1024*1024*1024)) >big && + test_oid large5GB >expect && + git hash-object --stdin --literally actual && + test_cmp expect actual +' + test_done From 68d7a5ebc927aac762b5e6d6c84f49a78c317d32 Mon Sep 17 00:00:00 2001 From: Victoria Dye Date: Mon, 4 Apr 2022 15:38:58 -0700 Subject: [PATCH 080/105] fsmonitor: reintroduce core.useBuiltinFSMonitor Reintroduce the 'core.useBuiltinFSMonitor' config setting (originally added in 0a756b2a25 (fsmonitor: config settings are repository-specific, 2021-03-05)) after its removal from the upstream version of FSMonitor. Upstream, the 'core.useBuiltinFSMonitor' setting was rendered obsolete by "overloading" the 'core.fsmonitor' setting to take a boolean value. However, several applications (e.g., 'scalar') utilize the original config setting, so it should be preserved for a deprecation period before complete removal: * if 'core.fsmonitor' is a boolean, the user is correctly using the new config syntax; do not use 'core.useBuiltinFSMonitor'. * if 'core.fsmonitor' is unspecified, use 'core.useBuiltinFSMonitor'. * if 'core.fsmonitor' is a path, override and use the builtin FSMonitor if 'core.useBuiltinFSMonitor' is 'true'; otherwise, use the FSMonitor hook indicated by the path. Additionally, for this deprecation period, advise users to switch to using 'core.fsmonitor' to specify their use of the builtin FSMonitor. Signed-off-by: Victoria Dye --- Documentation/config/advice.txt | 3 +++ advice.c | 1 + advice.h | 1 + fsmonitor-settings.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt index a00d0100a8..0d1e04f1ed 100644 --- a/Documentation/config/advice.txt +++ b/Documentation/config/advice.txt @@ -136,4 +136,7 @@ advice.*:: Advice shown when either linkgit:git-add[1] or linkgit:git-rm[1] is asked to update index entries outside the current sparse checkout. + useCoreFSMonitorConfig:: + Advice shown if the deprecated 'core.useBuiltinFSMonitor' config + setting is in use. -- diff --git a/advice.c b/advice.c index 6fda9edbc2..89cf9347ca 100644 --- a/advice.c +++ b/advice.c @@ -74,6 +74,7 @@ static struct { [ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE] = { "submoduleAlternateErrorStrategyDie", 1 }, [ADVICE_SUBMODULES_NOT_UPDATED] = { "submodulesNotUpdated", 1 }, [ADVICE_UPDATE_SPARSE_PATH] = { "updateSparsePath", 1 }, + [ADVICE_USE_CORE_FSMONITOR_CONFIG] = { "useCoreFSMonitorConfig", 1 }, [ADVICE_WAITING_FOR_EDITOR] = { "waitingForEditor", 1 }, }; diff --git a/advice.h b/advice.h index 7ddc6cbc1a..7d14e382d7 100644 --- a/advice.h +++ b/advice.h @@ -48,6 +48,7 @@ struct string_list; ADVICE_SUBMODULE_ALTERNATE_ERROR_STRATEGY_DIE, ADVICE_SUBMODULES_NOT_UPDATED, ADVICE_UPDATE_SPARSE_PATH, + ADVICE_USE_CORE_FSMONITOR_CONFIG, ADVICE_WAITING_FOR_EDITOR, ADVICE_SKIPPED_CHERRY_PICKS, }; diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c index 658cb79da0..c26d0beaac 100644 --- a/fsmonitor-settings.c +++ b/fsmonitor-settings.c @@ -47,6 +47,31 @@ static struct fsmonitor_settings *alloc_settings(void) return s; } +static int check_deprecated_builtin_config(struct repository *r) +{ + int core_use_builtin_fsmonitor = 0; + + /* + * If 'core.useBuiltinFSMonitor' is set, print a deprecation warning + * suggesting the use of 'core.fsmonitor' instead. If the config is + * set to true, set the appropriate mode and return 1 indicating that + * the check resulted the config being set by this (deprecated) setting. + */ + if(!repo_config_get_bool(r, "core.useBuiltinFSMonitor", &core_use_builtin_fsmonitor) && + core_use_builtin_fsmonitor) { + if (!git_env_bool("GIT_SUPPRESS_USEBUILTINFSMONITOR_ADVICE", 0)) { + advise_if_enabled(ADVICE_USE_CORE_FSMONITOR_CONFIG, + _("core.useBuiltinFSMonitor=true is deprecated;" + "please set core.fsmonitor=true instead")); + setenv("GIT_SUPPRESS_USEBUILTINFSMONITOR_ADVICE", "1", 1); + } + fsm_settings__set_ipc(r); + return 1; + } + + return 0; +} + static void lookup_fsmonitor_settings(struct repository *r) { const char *const_str; @@ -72,12 +97,16 @@ static void lookup_fsmonitor_settings(struct repository *r) return; case 1: /* config value was unset */ + if (check_deprecated_builtin_config(r)) + return; + const_str = getenv("GIT_TEST_FSMONITOR"); break; case -1: /* config value set to an arbitrary string */ - if (repo_config_get_pathname(r, "core.fsmonitor", &const_str)) - return; /* should not happen */ + if (check_deprecated_builtin_config(r) || + repo_config_get_pathname(r, "core.fsmonitor", &const_str)) + return; break; default: /* should not happen */ From ffe05e3ffe3697db5357457aa56277356849281d Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Fri, 12 Nov 2021 21:07:03 +0000 Subject: [PATCH 081/105] hash_object_file_literally(): use size_t The previous commit adds a test that demonstrates a problem in the `hash-object --literally` command, manifesting in an unnecessary file size limit on systems using the LLP64 data model (which includes Windows). Walking the affected code path is `cmd_hash_object()` >> `hash_fd()` >> `hash_literally()` >> `hash_object_file_literally()`. The function `hash_object_file_literally()` is the first with a file length parameter (via a mem buffer). This commit changes the type of that parameter to the LLP64 compatible `size_t` type. There are no other uses of the function. The `strbuf` type is already `size_t` compatible. Note: The hash-object test does not yet pass. Subsequent commits will continue to walk the call tree's lower level functions to identify further fixes. Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- object-file.c | 4 ++-- object-store.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/object-file.c b/object-file.c index 6c8e3b1660..4b56cad44e 100644 --- a/object-file.c +++ b/object-file.c @@ -1810,7 +1810,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo, } static void write_object_file_prepare_literally(const struct git_hash_algo *algo, - const void *buf, unsigned long len, + const void *buf, size_t len, const char *type, struct object_id *oid, char *hdr, int *hdrlen) { @@ -2067,7 +2067,7 @@ int write_object_file_flags(const void *buf, unsigned long len, return write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags); } -int write_object_file_literally(const void *buf, unsigned long len, +int write_object_file_literally(const void *buf, size_t len, const char *type, struct object_id *oid, unsigned flags) { diff --git a/object-store.h b/object-store.h index 539ea43904..58084be24d 100644 --- a/object-store.h +++ b/object-store.h @@ -266,7 +266,7 @@ static inline int write_object_file(const void *buf, unsigned long len, return write_object_file_flags(buf, len, type, oid, 0); } -int write_object_file_literally(const void *buf, unsigned long len, +int write_object_file_literally(const void *buf, size_t len, const char *type, struct object_id *oid, unsigned flags); From 11722b5d12ff011b30586dbe0afbc52d8393e0bd Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 5 Mar 2021 23:12:11 +0100 Subject: [PATCH 082/105] Enable the built-in FSMonitor as an experimental feature If `feature.experimental` and `feature.manyFiles` are set and the user has not explicitly turned off the builtin FSMonitor, we now start the built-in FSMonitor by default. Only forcing it when UNSET matches the behavior of UPDATE_DEFAULT_BOOL() used for other repo settings. Signed-off-by: Johannes Schindelin Signed-off-by: Jeff Hostetler --- repo-settings.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/repo-settings.c b/repo-settings.c index 2dfcb2b654..459041f65c 100644 --- a/repo-settings.c +++ b/repo-settings.c @@ -2,7 +2,8 @@ #include "config.h" #include "repository.h" #include "midx.h" -#include "compat/fsmonitor/fsm-listen.h" +#include "fsmonitor-ipc.h" +#include "fsmonitor-settings.h" static void repo_cfg_bool(struct repository *r, const char *key, int *dest, int def) @@ -36,6 +37,30 @@ void prepare_repo_settings(struct repository *r) /* Defaults modified by feature.* */ if (experimental) { r->settings.fetch_negotiation_algorithm = FETCH_NEGOTIATION_SKIPPING; + + /* + * Force enable the builtin FSMonitor (unless the repo + * is incompatible or they've already selected it or + * the hook version). But only if they haven't + * explicitly turned it off -- so only if our config + * value is UNSET. + * + * lookup_fsmonitor_settings() and check_for_ipc() do + * not distinguish between explicitly set FALSE and + * UNSET, so we re-test for an UNSET config key here. + * + * I'm not sure I want to fix fsmonitor-settings.c to + * have more than one _DISABLED state since our usage + * here is only to support this experimental period + * (and I don't want to overload the _reason field + * because it describes incompabilities). + */ + if (manyfiles && + fsmonitor_ipc__is_supported() && + fsm_settings__get_mode(r) == FSMONITOR_MODE_DISABLED && + repo_config_get_maybe_bool(r, "core.fsmonitor", &value) > 0 && + repo_config_get_bool(r, "core.useBuiltinFSMonitor", &value)) + fsm_settings__set_ipc(r); } if (manyfiles) { r->settings.index_version = 4; From 47849d10f82f585d76b9c7c03c80c3533c0e8a15 Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Fri, 12 Nov 2021 21:14:50 +0000 Subject: [PATCH 083/105] object-file.c: use size_t for header lengths Continue walking the code path for the >4GB `hash-object --literally` test. The `hash_object_file_literally()` function internally uses both `hash_object_file()` and `write_object_file_prepare()`. Both function signatures use `unsigned long` rather than `size_t` for the mem buffer sizes. Use `size_t` instead, for LLP64 compatibility. While at it, convert those function's object's header buffer length to `size_t` for consistency. The value is already upcast to `uintmax_t` for print format compatibility. Note: The hash-object test still does not pass. A subsequent commit continues to walk the call tree's lower level hash functions to identify further fixes. Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- object-file.c | 21 +++++++++++---------- object-store.h | 4 ++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/object-file.c b/object-file.c index 4b56cad44e..bd59413eb7 100644 --- a/object-file.c +++ b/object-file.c @@ -1787,7 +1787,7 @@ void *read_object_with_reference(struct repository *r, static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c, const void *buf, unsigned long len, struct object_id *oid, - char *hdr, int *hdrlen) + char *hdr, size_t *hdrlen) { algo->init_fn(c); algo->update_fn(c, hdr, *hdrlen); @@ -1796,9 +1796,9 @@ static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c, } static void write_object_file_prepare(const struct git_hash_algo *algo, - const void *buf, unsigned long len, + const void *buf, size_t len, enum object_type type, struct object_id *oid, - char *hdr, int *hdrlen) + char *hdr, size_t *hdrlen) { git_hash_ctx c; @@ -1812,7 +1812,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo, static void write_object_file_prepare_literally(const struct git_hash_algo *algo, const void *buf, size_t len, const char *type, struct object_id *oid, - char *hdr, int *hdrlen) + char *hdr, size_t *hdrlen) { git_hash_ctx c; @@ -1871,17 +1871,17 @@ static int write_buffer(int fd, const void *buf, size_t len) } static void hash_object_file_literally(const struct git_hash_algo *algo, - const void *buf, unsigned long len, + const void *buf, size_t len, const char *type, struct object_id *oid) { char hdr[MAX_HEADER_LEN]; - int hdrlen = sizeof(hdr); + size_t hdrlen = sizeof(hdr); write_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen); } void hash_object_file(const struct git_hash_algo *algo, const void *buf, - unsigned long len, enum object_type type, + size_t len, enum object_type type, struct object_id *oid) { hash_object_file_literally(algo, buf, len, type_name(type), oid); @@ -2050,12 +2050,12 @@ static int freshen_packed_object(const struct object_id *oid) return 1; } -int write_object_file_flags(const void *buf, unsigned long len, +int write_object_file_flags(const void *buf, size_t len, enum object_type type, struct object_id *oid, unsigned flags) { char hdr[MAX_HEADER_LEN]; - int hdrlen = sizeof(hdr); + size_t hdrlen = sizeof(hdr); /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. @@ -2072,7 +2072,8 @@ int write_object_file_literally(const void *buf, size_t len, unsigned flags) { char *header; - int hdrlen, status = 0; + size_t hdrlen; + int status = 0; /* type string, SP, %lu of the length plus NUL must fit this */ hdrlen = strlen(type) + MAX_HEADER_LEN; diff --git a/object-store.h b/object-store.h index 58084be24d..4c2050fe7f 100644 --- a/object-store.h +++ b/object-store.h @@ -254,10 +254,10 @@ static inline void *repo_read_object_file(struct repository *r, int oid_object_info(struct repository *r, const struct object_id *, unsigned long *); void hash_object_file(const struct git_hash_algo *algo, const void *buf, - unsigned long len, enum object_type type, + size_t len, enum object_type type, struct object_id *oid); -int write_object_file_flags(const void *buf, unsigned long len, +int write_object_file_flags(const void *buf, size_t len, enum object_type type, struct object_id *oid, unsigned flags); static inline int write_object_file(const void *buf, unsigned long len, From 2c65ff4197090c253fe5c0d7e119266f8b542ecf Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Fri, 12 Nov 2021 21:16:51 +0000 Subject: [PATCH 084/105] hash algorithms: use size_t for section lengths Continue walking the code path for the >4GB `hash-object --literally` test to the hash algorithm step for LLP64 systems. This patch lets the SHA1DC code use `size_t`, making it compatible with LLP64 data models (as used e.g. by Windows). The interested reader of this patch will note that we adjust the signature of the `git_SHA1DCUpdate()` function without updating _any_ call site. This certainly puzzled at least one reviewer already, so here is an explanation: This function is never called directly, but always via the macro `platform_SHA1_Update`, which is usually called via the macro `git_SHA1_Update`. However, we never call `git_SHA1_Update()` directly in `struct git_hash_algo`. Instead, we call `git_hash_sha1_update()`, which is defined thusly: static void git_hash_sha1_update(git_hash_ctx *ctx, const void *data, size_t len) { git_SHA1_Update(&ctx->sha1, data, len); } i.e. it contains an implicit downcast from `size_t` to `unsigned long` (before this here patch). With this patch, there is no downcast anymore. With this patch, finally, the t1007-hash-object.sh "files over 4GB hash literally" test case is fixed. Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- object-file.c | 4 ++-- sha1dc_git.c | 3 +-- sha1dc_git.h | 2 +- t/t1007-hash-object.sh | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/object-file.c b/object-file.c index bd59413eb7..f6257741b9 100644 --- a/object-file.c +++ b/object-file.c @@ -1785,7 +1785,7 @@ void *read_object_with_reference(struct repository *r, } static void hash_object_body(const struct git_hash_algo *algo, git_hash_ctx *c, - const void *buf, unsigned long len, + const void *buf, size_t len, struct object_id *oid, char *hdr, size_t *hdrlen) { @@ -1805,7 +1805,7 @@ static void write_object_file_prepare(const struct git_hash_algo *algo, /* Generate the header */ *hdrlen = format_object_header(hdr, *hdrlen, type, len); - /* Sha1.. */ + /* Hash (function pointers) computation */ hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); } diff --git a/sha1dc_git.c b/sha1dc_git.c index 5c300e812e..65a6f1f2cd 100644 --- a/sha1dc_git.c +++ b/sha1dc_git.c @@ -25,10 +25,9 @@ void git_SHA1DCFinal(unsigned char hash[20], SHA1_CTX *ctx) /* * Same as SHA1DCUpdate, but adjust types to match git's usual interface. */ -void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *vdata, unsigned long len) +void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *vdata, size_t len) { const char *data = vdata; - /* We expect an unsigned long, but sha1dc only takes an int */ while (len > INT_MAX) { SHA1DCUpdate(ctx, data, INT_MAX); data += INT_MAX; diff --git a/sha1dc_git.h b/sha1dc_git.h index 41e1c3fd3f..847b38fb4b 100644 --- a/sha1dc_git.h +++ b/sha1dc_git.h @@ -15,7 +15,7 @@ void git_SHA1DCInit(SHA1_CTX *); #endif void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *); -void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, unsigned long len); +void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, size_t len); #define platform_SHA_CTX SHA1_CTX #define platform_SHA1_Init git_SHA1DCInit diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index 428298fa29..b30fb1282a 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -252,7 +252,7 @@ test_expect_success '--literally with extra-long type' ' echo example | git hash-object -t $t --literally --stdin ' -test_expect_failure EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ +test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ 'files over 4GB hash literally' ' test-tool genzeros $((5*1024*1024*1024)) >big && test_oid large5GB >expect && From 4295666a8252cce769ed55d3f6f8687c19b3fd8b Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Mon, 6 Dec 2021 22:26:50 +0000 Subject: [PATCH 085/105] hash-object --stdin: verify that it works with >4GB/LLP64 Just like the `hash-object --literally` code path, the `--stdin` code path also needs to use `size_t` instead of `unsigned long` to represent memory sizes, otherwise it would cause problems on platforms using the LLP64 data model (such as Windows). To limit the scope of the test case, the object is explicitly not written to the object store, nor are any filters applied. The `big` file from the previous test case is reused to save setup time; To avoid relying on that side effect, it is generated if it does not exist (e.g. when running via `sh t1007-*.sh --long --run=1,41`). Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- t/t1007-hash-object.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index b30fb1282a..b6dbee4bb9 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -260,4 +260,12 @@ test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ test_cmp expect actual ' +test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ + 'files over 4GB hash correctly via --stdin' ' + { test -f big || test-tool genzeros $((5*1024*1024*1024)) >big; } && + test_oid large5GB >expect && + git hash-object --stdin actual && + test_cmp expect actual +' + test_done From bc48b4cf1aa53b416a39e963dc03eae5eb9db687 Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Mon, 6 Dec 2021 22:42:46 +0000 Subject: [PATCH 086/105] hash-object: add another >4GB/LLP64 test case To complement the `--stdin` and `--literally` test cases that verify that we can hash files larger than 4GB on 64-bit platforms using the LLP64 data model, here is a test case that exercises `hash-object` _without_ any options. Just as before, we use the `big` file from the previous test case if it exists to save on setup time, otherwise generate it. Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- t/t1007-hash-object.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index b6dbee4bb9..f7062ebca1 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -268,4 +268,12 @@ test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ test_cmp expect actual ' +test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ + 'files over 4GB hash correctly' ' + { test -f big || test-tool genzeros $((5*1024*1024*1024)) >big; } && + test_oid large5GB >expect && + git hash-object -- big >actual && + test_cmp expect actual +' + test_done From 8975e19d3e960b3f8c3f08ddb04fdf2f01b04151 Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Tue, 7 Dec 2021 09:53:41 +0000 Subject: [PATCH 087/105] hash-object: add a >4GB/LLP64 test case using filtered input To verify that the `clean` side of the `clean`/`smudge` filter code is correct with regards to LLP64 (read: to ensure that `size_t` is used instead of `unsigned long`), here is a test case using a trivial filter, specifically _not_ writing anything to the object store to limit the scope of the test case. As in previous commits, the `big` file from previous test cases is reused if available, to save setup time, otherwise re-generated. Signed-off-by: Philip Oakley Signed-off-by: Johannes Schindelin --- t/t1007-hash-object.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index f7062ebca1..df78646b07 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -276,4 +276,16 @@ test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ test_cmp expect actual ' +# This clean filter does nothing, other than excercising the interface. +# We ensure that cleaning doesn't mangle large files on 64-bit Windows. +test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \ + 'hash filtered files over 4GB correctly' ' + { test -f big || test-tool genzeros $((5*1024*1024*1024)) >big; } && + test_oid large5GB >expect && + test_config filter.null-filter.clean "cat" && + echo "big filter=null-filter" >.gitattributes && + git hash-object -- big >actual && + test_cmp expect actual +' + test_done From f8f2fc46d7c03c6c0287c45413dc898e2e60bff8 Mon Sep 17 00:00:00 2001 From: Philip Oakley Date: Mon, 21 Feb 2022 22:50:33 +0000 Subject: [PATCH 088/105] rebase: help user when dying with preserve-merges` Git will die if a "rebase --preserve-merges" is in progress. Users cannot --quit, --abort or --continue the rebase. This sceario can occur if the user updates their Git, or switches to another newer version, after starting a preserve-merges rebase, commonly via the pull setting. One trigger is an unexpectedly difficult to resolve conflict, as reported on the `git-users` group. (https://groups.google.com/g/git-for-windows/c/3jMWbBlXXHM) Tell the user the cause, i.e. the existence of the directory. The problem must be resolved manually, `git rebase --