Merge branch 'ma/test-libcurl-prereq' into maint-2.46
Test portability fix.
* ma/test-libcurl-prereq:
t0211: add missing LIBCURL prereq
t1517: add missing LIBCURL prereq
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 1ee0433..916a64b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -339,8 +339,8 @@
image: alpine
distro: alpine-latest
- jobname: linux32
- image: daald/ubuntu32:xenial
- distro: ubuntu32-16.04
+ image: i386/ubuntu:focal
+ distro: ubuntu32-20.04
- jobname: pedantic
image: fedora
distro: fedora-latest
@@ -350,27 +350,21 @@
runs-on: ubuntu-latest
container: ${{matrix.vector.image}}
steps:
- - uses: actions/checkout@v4
- if: matrix.vector.jobname != 'linux32'
- - uses: actions/checkout@v1 # cannot be upgraded because Node.js Actions aren't supported in this container
+ - name: prepare libc6 for actions
if: matrix.vector.jobname == 'linux32'
+ run: apt -q update && apt -q -y install libc6-amd64 lib64stdc++6
+ - uses: actions/checkout@v4
- run: ci/install-dependencies.sh
- run: ci/run-build-and-tests.sh
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
run: ci/print-test-failures.sh
- name: Upload failed tests' directories
- if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname != 'linux32'
+ if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v4
with:
name: failed-tests-${{matrix.vector.jobname}}
path: ${{env.FAILED_TEST_ARTIFACTS}}
- - name: Upload failed tests' directories
- if: failure() && env.FAILED_TEST_ARTIFACTS != '' && matrix.vector.jobname == 'linux32'
- uses: actions/upload-artifact@v1 # cannot be upgraded because Node.js Actions aren't supported in this container
- with:
- name: failed-tests-${{matrix.vector.jobname}}
- path: ${{env.FAILED_TEST_ARTIFACTS}}
static-analysis:
needs: ci-config
if: needs.ci-config.outputs.enabled == 'yes'
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 37b991e..c4c45da 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -25,6 +25,9 @@
fi
parallel:
matrix:
+ - jobname: linux-old
+ image: ubuntu:16.04
+ CC: gcc
- jobname: linux-sha256
image: ubuntu:latest
CC: clang
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 8fb8733..5edd3a0 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -293,7 +293,9 @@
v12.01, 2022-03-28).
- Variables have to be declared at the beginning of the block, before
- the first statement (i.e. -Wdeclaration-after-statement).
+ the first statement (i.e. -Wdeclaration-after-statement). It is
+ encouraged to have a blank line between the end of the declarations
+ and the first statement in the block.
- NULL pointers shall be written as NULL, not as 0.
@@ -313,6 +315,13 @@
while( condition )
func (bar+1);
+ - A binary operator (other than ",") and ternary conditional "?:"
+ have a space on each side of the operator to separate it from its
+ operands. E.g. "A + 1", not "A+1".
+
+ - A unary operator (other than "." and "->") have no space between it
+ and its operand. E.g. "(char *)ptr", not "(char *) ptr".
+
- Do not explicitly compare an integral value with constant 0 or '\0',
or a pointer value with constant NULL. For instance, to validate that
counted array <ptr, cnt> is initialized but has no elements, write:
diff --git a/Documentation/RelNotes/2.46.1.txt b/Documentation/RelNotes/2.46.1.txt
index 3b4c443..e55c2c4 100644
--- a/Documentation/RelNotes/2.46.1.txt
+++ b/Documentation/RelNotes/2.46.1.txt
@@ -56,4 +56,20 @@
behave more or less like "git log -p --remerge-diff" but instead it
crashed, forgetting to prepare a temporary object store needed.
+ * The patch parser in "git patch-id" has been tightened to avoid
+ getting confused by lines that look like a patch header in the log
+ message.
+
+ * "git bundle unbundle" outside a repository triggered a BUG()
+ unnecessarily, which has been corrected.
+
+ * The code forgot to discard unnecessary in-core commit buffer data
+ for commits that "git log --skip=<number>" traversed but omitted
+ from the output, which has been corrected.
+
+ * "git verify-pack" and "git index-pack" started dying outside a
+ repository, which has been corrected.
+
+ * A corner case bug in "git stash" was fixed.
+
Also contains minor documentation updates and code clean-ups.
diff --git a/Documentation/RelNotes/2.46.2.txt b/Documentation/RelNotes/2.46.2.txt
new file mode 100644
index 0000000..51471e5
--- /dev/null
+++ b/Documentation/RelNotes/2.46.2.txt
@@ -0,0 +1,11 @@
+Git 2.46.2 Release Notes
+========================
+
+This release is primarily to merge changes to unbreak the 32-bit
+GitHub actions jobs we use for CI testing, so that we can release
+real fixes for the 2.46.x track after they pass CI.
+
+It also reverts the "git patch-id" change that went into 2.46.1,
+as it seems to have got a regression reported (I haven't verified,
+but it is better to keep a known breakage than adding an unintended
+regression).
diff --git a/Documentation/config/remote.txt b/Documentation/config/remote.txt
index 8efc53e..36e7715 100644
--- a/Documentation/config/remote.txt
+++ b/Documentation/config/remote.txt
@@ -42,14 +42,15 @@
as if the `--mirror` option was given on the command line.
remote.<name>.skipDefaultUpdate::
- If true, this remote will be skipped by default when updating
- using linkgit:git-fetch[1] or the `update` subcommand of
- linkgit:git-remote[1].
+ A deprecated synonym to `remote.<name>.skipFetchAll` (if
+ both are set in the configuration files with different
+ values, the value of the last occurrence will be used).
remote.<name>.skipFetchAll::
- If true, this remote will be skipped by default when updating
- using linkgit:git-fetch[1] or the `update` subcommand of
- linkgit:git-remote[1].
+ If true, this remote will be skipped when updating
+ using linkgit:git-fetch[1], the `update` subcommand of
+ linkgit:git-remote[1], and ignored by the prefetch task
+ of `git maitenance`.
remote.<name>.receivepack::
The default program to execute on the remote side when pushing. See
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index e22b217..80838fe 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -1,6 +1,7 @@
--[no-]all::
- Fetch all remotes. This overrides the configuration variable
- `fetch.all`.
+ Fetch all remotes, except for the ones that has the
+ `remote.<name>.skipFetchAll` configuration variable set.
+ This overrides the configuration variable fetch.all`.
-a::
--append::
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index bd95a6c..d5890ae 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -270,9 +270,9 @@
------------
If `--batch` or `--batch-check` is given, `cat-file` will read objects
-from stdin, one per line, and print information about them. By default,
-the whole line is considered as an object, as if it were fed to
-linkgit:git-rev-parse[1].
+from stdin, one per line, and print information about them in the same
+order as they have been read. By default, the whole line is
+considered as an object, as if it were fed to linkgit:git-rev-parse[1].
When `--batch-command` is given, `cat-file` will read commands from stdin,
one per line, and print information based on the command given. With
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 65c645d..7f81fbb 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -10,7 +10,7 @@
--------
[verse]
'git config list' [<file-option>] [<display-option>] [--includes]
-'git config get' [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>
+'git config get' [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>
'git config set' [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>
'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>
'git config rename-section' [<file-option>] <old-name> <new-name>
@@ -130,7 +130,7 @@
--all::
With `get`, return all values for a multi-valued key.
----regexp::
+--regexp::
With `get`, interpret the name as a regular expression. Regular
expression matching is currently case-sensitive and done against a
canonicalized version of the key in which section and variable names
@@ -309,7 +309,7 @@
Replaced by `git config get [--value=<pattern>] <name>`.
--get-all <name> [<value-pattern>]::
- Replaced by `git config get [--value=<pattern>] --all --show-names <name>`.
+ Replaced by `git config get [--value=<pattern>] --all <name>`.
--get-regexp <name-regexp>::
Replaced by `git config get --all --show-names --regexp <name-regexp>`.
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
index 143318c..09286a8 100644
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -88,7 +88,7 @@
--no-commit-id::
'git diff-tree' outputs a line with the commit ID when
- applicable. This flag suppressed the commit ID output.
+ applicable. This flag suppresses the commit ID output.
-c::
This flag changes the way a merge commit is displayed
diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt
index 51d0f7e..9d96819 100644
--- a/Documentation/git-maintenance.txt
+++ b/Documentation/git-maintenance.txt
@@ -107,6 +107,9 @@
would already be obtained, making the real fetch faster. In the ideal case,
it will just become an update to a bunch of remote-tracking branches without
any object transfer.
++
+The `remote.<name>.skipFetchAll` configuration can be used to
+exclude a particular remote from getting prefetched.
gc::
Clean up unnecessary files and optimize the local repository. "GC"
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index 4759408..f89ad30 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -360,7 +360,7 @@
This means "show everything that is reachable from either one, but
exclude anything that is reachable from both of them".
-Please note that these range notation can be used with both `gitk`
+Please note that these range notations can be used with both `gitk`
and `git log`.
After inspecting what Bob did, if there is nothing urgent, Alice may
diff --git a/Documentation/howto/maintain-git.txt b/Documentation/howto/maintain-git.txt
index 41f5405..da31332 100644
--- a/Documentation/howto/maintain-git.txt
+++ b/Documentation/howto/maintain-git.txt
@@ -181,6 +181,10 @@
$ git diff ORIG_HEAD.. ;# final review
$ make test ;# final review
+ If the tip of 'master' is updated, also generate the preformatted
+ documentation and push the out result to git-htmldocs and
+ git-manpages repositories.
+
- Handle the remaining patches:
- Anything unobvious that is applicable to 'master' (in other
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 91a06ca..efe61fd 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.46.1-pre
+DEF_VER=v2.46.2-pre
LF='
'
diff --git a/RelNotes b/RelNotes
index 89b65f2..0dfe046 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.46.1.txt
\ No newline at end of file
+Documentation/RelNotes/2.46.2.txt
\ No newline at end of file
diff --git a/apply.c b/apply.c
index 0f2f5da..6e1060a 100644
--- a/apply.c
+++ b/apply.c
@@ -995,6 +995,7 @@ static int parse_mode_line(const char *line, int linenr, unsigned int *mode)
*mode = strtoul(line, &end, 8);
if (end == line || !isspace(*end))
return error(_("invalid mode on line %d: %s"), linenr, line);
+ *mode = canon_mode(*mode);
return 0;
}
diff --git a/builtin/bundle.c b/builtin/bundle.c
index d5d41a8..86d0ed7 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -207,12 +207,13 @@ static int cmd_bundle_unbundle(int argc, const char **argv, const char *prefix)
builtin_bundle_unbundle_usage, options, &bundle_file);
/* bundle internals use argv[1] as further parameters */
+ if (!startup_info->have_repository)
+ die(_("Need a repository to unbundle."));
+
if ((bundle_fd = open_bundle(bundle_file, &header, NULL)) < 0) {
ret = 1;
goto cleanup;
}
- if (!startup_info->have_repository)
- die(_("Need a repository to unbundle."));
if (progress)
strvec_pushl(&extra_index_pack_args, "-v", "--progress-title",
_("Unbundling objects"), NULL);
diff --git a/builtin/config.c b/builtin/config.c
index 20a0b64..97e4d5f 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -17,7 +17,7 @@
static const char *const builtin_config_usage[] = {
N_("git config list [<file-option>] [<display-option>] [--includes]"),
- N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
+ N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
N_("git config rename-section [<file-option>] <old-name> <new-name>"),
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index fd968d6..763b013 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1868,6 +1868,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
if (!index_name && pack_name)
index_name = derive_filename(pack_name, "pack", "idx", &index_name_buf);
+ /*
+ * Packfiles and indices do not carry enough information to be able to
+ * identify their object hash. So when we are neither in a repository
+ * nor has the user told us which object hash to use we have no other
+ * choice but to guess the object hash.
+ */
+ if (!the_repository->hash_algo)
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
+
opts.flags &= ~(WRITE_REV | WRITE_REV_VERIFY);
if (rev_index) {
opts.flags |= verify ? WRITE_REV_VERIFY : WRITE_REV;
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 1d96949..e6f2245 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -132,6 +132,7 @@ static void read_input_file(struct strbuf *sb, const char *file)
if (strbuf_read(sb, fileno(stdin), 0) < 0)
die_errno(_("could not read from stdin"));
}
+ strbuf_complete_line(sb);
}
static void interpret_trailers(const struct process_trailer_options *opts,
diff --git a/builtin/stash.c b/builtin/stash.c
index 46b981c..80ccfc7 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1671,7 +1671,28 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
}
}
- if (keep_index == 1 && !is_null_oid(&info.i_tree)) {
+ /*
+ * When keeping staged entries, we need to reset the working
+ * directory to match the state of our index. This can be
+ * skipped when the index is the empty tree, because there is
+ * nothing to reset in that case:
+ *
+ * - When the index has any file, regardless of whether
+ * staged or not, the tree cannot be empty by definition
+ * and thus we enter the condition.
+ *
+ * - When the index has no files, the only thing we need to
+ * care about is untracked files when `--include-untracked`
+ * is given. But as we already execute git-clean(1) further
+ * up to delete such untracked files we don't have to do
+ * anything here, either.
+ *
+ * We thus skip calling git-checkout(1) in this case, also
+ * because running it on an empty tree will cause it to fail
+ * due to the pathspec not matching anything.
+ */
+ if (keep_index == 1 && !is_null_oid(&info.i_tree) &&
+ !is_empty_tree_oid(&info.i_tree, the_repository->hash_algo)) {
struct child_process cp = CHILD_PROCESS_INIT;
cp.git_cmd = 1;
diff --git a/bundle.c b/bundle.c
index ce164c3..b0a8a92 100644
--- a/bundle.c
+++ b/bundle.c
@@ -89,7 +89,12 @@ int read_bundle_header_fd(int fd, struct bundle_header *header,
goto abort;
}
- header->hash_algo = the_hash_algo;
+ /*
+ * The default hash format for bundles is SHA1, unless told otherwise
+ * by an "object-format=" capability, which is being handled in
+ * `parse_capability()`.
+ */
+ header->hash_algo = &hash_algos[GIT_HASH_SHA1];
/* The bundle header ends with an empty line */
while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index b59fd7c..e2c6ef0 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -33,37 +33,49 @@
dnf -yq update >/dev/null &&
dnf -yq install make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null
;;
-ubuntu-*)
+ubuntu-*|ubuntu32-*)
# Required so that apt doesn't wait for user input on certain packages.
export DEBIAN_FRONTEND=noninteractive
+ case "$distro" in
+ ubuntu-*)
+ SVN='libsvn-perl subversion'
+ ;;
+ *)
+ SVN=
+ ;;
+ esac
+
sudo apt-get -q update
sudo apt-get -q -y install \
- language-pack-is libsvn-perl apache2 cvs cvsps git gnupg subversion \
+ language-pack-is apache2 cvs cvsps git gnupg $SVN \
make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \
tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \
libemail-valid-perl libio-pty-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \
${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE
- mkdir --parents "$CUSTOM_PATH"
- wget --quiet --directory-prefix="$CUSTOM_PATH" \
- "$P4WHENCE/bin.linux26x86_64/p4d" "$P4WHENCE/bin.linux26x86_64/p4"
- chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4"
+ case "$distro" in
+ ubuntu-16.04)
+ # Does not support JGit, but we also don't really care about
+ # the others. We rather care whether Git still compiles and
+ # runs fine overall.
+ ;;
+ ubuntu-*)
+ mkdir --parents "$CUSTOM_PATH"
- wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
- tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \
- -C "$CUSTOM_PATH" --strip-components=1 "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs"
- rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
+ wget --quiet --directory-prefix="$CUSTOM_PATH" \
+ "$P4WHENCE/bin.linux26x86_64/p4d" "$P4WHENCE/bin.linux26x86_64/p4"
+ chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4"
- wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit"
- chmod a+x "$CUSTOM_PATH/jgit"
- ;;
-ubuntu32-*)
- sudo linux32 --32bit i386 sh -c '
- apt update >/dev/null &&
- apt install -y build-essential libcurl4-openssl-dev \
- libssl-dev libexpat-dev gettext python >/dev/null
- '
+ wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
+ tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \
+ -C "$CUSTOM_PATH" --strip-components=1 "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs"
+ rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
+
+ wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit"
+ chmod a+x "$CUSTOM_PATH/jgit"
+ ;;
+ esac
;;
macos-*)
export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1
diff --git a/ci/lib.sh b/ci/lib.sh
index 51f8f59..74b430b 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -336,7 +336,14 @@
fi
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE"
- export GIT_TEST_HTTPD=true
+ case "$distro" in
+ ubuntu-16.04)
+ # Apache is too old for HTTP/2.
+ ;;
+ *)
+ export GIT_TEST_HTTPD=true
+ ;;
+ esac
# The Linux build installs the defined dependency versions below.
# The OS X build installs much more recent versions, whichever
diff --git a/ci/run-docker-build.sh b/ci/run-docker-build.sh
deleted file mode 100755
index 6cd832e..0000000
--- a/ci/run-docker-build.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#
-# Build and test Git inside container
-#
-# Usage:
-# run-docker-build.sh <host-user-id>
-#
-
-set -ex
-
-if test $# -ne 1 || test -z "$1"
-then
- echo >&2 "usage: run-docker-build.sh <host-user-id>"
- exit 1
-fi
-
-case "$jobname" in
-linux32)
- switch_cmd="linux32 --32bit i386"
- ;;
-linux-musl)
- switch_cmd=
- useradd () { adduser -D "$@"; }
- ;;
-*)
- exit 1
- ;;
-esac
-
-"${0%/*}/install-docker-dependencies.sh"
-
-# If this script runs inside a docker container, then all commands are
-# usually executed as root. Consequently, the host user might not be
-# able to access the test output files.
-# If a non 0 host user id is given, then create a user "ci" with that
-# user id to make everything accessible to the host user.
-HOST_UID=$1
-if test $HOST_UID -eq 0
-then
- # Just in case someone does want to run the test suite as root.
- CI_USER=root
-else
- CI_USER=ci
- if test "$(id -u $CI_USER 2>/dev/null)" = $HOST_UID
- then
- echo "user '$CI_USER' already exists with the requested ID $HOST_UID"
- else
- useradd -u $HOST_UID $CI_USER
- fi
-fi
-
-# Build and test
-command $switch_cmd su -m -l $CI_USER -c "
- set -ex
- export DEVELOPER='$DEVELOPER'
- export DEFAULT_TEST_TARGET='$DEFAULT_TEST_TARGET'
- export GIT_PROVE_OPTS='$GIT_PROVE_OPTS'
- export GIT_TEST_OPTS='$GIT_TEST_OPTS'
- export GIT_TEST_CLONE_2GB='$GIT_TEST_CLONE_2GB'
- export MAKEFLAGS='$MAKEFLAGS'
- export cache_dir='$cache_dir'
- cd /usr/src/git
- test -n '$cache_dir' && ln -s '$cache_dir/.prove' t/.prove
- make
- make test
-"
diff --git a/ci/run-docker.sh b/ci/run-docker.sh
deleted file mode 100755
index af89d16..0000000
--- a/ci/run-docker.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-#
-# Download and run Docker image to build and test Git
-#
-
-. ${0%/*}/lib.sh
-
-case "$jobname" in
-linux32)
- CI_CONTAINER="daald/ubuntu32:xenial"
- ;;
-linux-musl)
- CI_CONTAINER=alpine
- ;;
-*)
- exit 1
- ;;
-esac
-
-docker pull "$CI_CONTAINER"
-
-# Use the following command to debug the docker build locally:
-# <host-user-id> must be 0 if podman is used as drop-in replacement for docker
-# $ docker run -itv "${PWD}:/usr/src/git" --entrypoint /bin/sh "$CI_CONTAINER"
-# root@container:/# export jobname=<jobname>
-# root@container:/# /usr/src/git/ci/run-docker-build.sh <host-user-id>
-
-container_cache_dir=/tmp/container-cache
-
-docker run \
- --interactive \
- --env DEVELOPER \
- --env DEFAULT_TEST_TARGET \
- --env GIT_PROVE_OPTS \
- --env GIT_TEST_OPTS \
- --env GIT_TEST_CLONE_2GB \
- --env MAKEFLAGS \
- --env jobname \
- --env cache_dir="$container_cache_dir" \
- --volume "${PWD}:/usr/src/git" \
- --volume "$cache_dir:$container_cache_dir" \
- "$CI_CONTAINER" \
- /usr/src/git/ci/run-docker-build.sh $(id -u $USER)
-
-check_unignored_build_artifacts
-
-save_good_tree
diff --git a/compat/terminal.c b/compat/terminal.c
index 0afda73..d54efa1 100644
--- a/compat/terminal.c
+++ b/compat/terminal.c
@@ -594,7 +594,7 @@ void restore_term(void)
{
}
-char *git_terminal_prompt(const char *prompt, int echo)
+char *git_terminal_prompt(const char *prompt, int echo UNUSED)
{
return getpass(prompt);
}
diff --git a/config.mak.uname b/config.mak.uname
index 85d6382..bbf7744 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -249,6 +249,7 @@
else
NO_REGEX = UnfortunatelyYes
endif
+ HAVE_DEV_TTY = YesPlease
HAVE_ALLOCA_H = YesPlease
NEEDS_LIBICONV = YesPlease
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
diff --git a/diff.c b/diff.c
index ebb7538..a834099 100644
--- a/diff.c
+++ b/diff.c
@@ -3565,6 +3565,7 @@ static void builtin_diff(const char *name_a,
show_submodule_diff_summary(o, one->path ? one->path : two->path,
&one->oid, &two->oid,
two->dirty_submodule);
+ o->found_changes = 1;
return;
} else if (o->submodule_format == DIFF_SUBMODULE_INLINE_DIFF &&
(!one->mode || S_ISGITLINK(one->mode)) &&
@@ -3573,6 +3574,7 @@ static void builtin_diff(const char *name_a,
show_submodule_inline_diff(o, one->path ? one->path : two->path,
&one->oid, &two->oid,
two->dirty_submodule);
+ o->found_changes = 1;
return;
}
@@ -4587,6 +4589,9 @@ static void run_diff_cmd(const struct external_diff *pgm,
builtin_diff(name, other ? other : name,
one, two, xfrm_msg, must_show_header,
o, complete_rewrite);
+ if (p->status == DIFF_STATUS_COPIED ||
+ p->status == DIFF_STATUS_RENAMED)
+ o->found_changes = 1;
} else {
fprintf(o->file, "* Unmerged path %s\n", name);
o->found_changes = 1;
diff --git a/revision.c b/revision.c
index 1c0192f..5fecd7e 100644
--- a/revision.c
+++ b/revision.c
@@ -4407,6 +4407,7 @@ static struct commit *get_revision_internal(struct rev_info *revs)
c = get_revision_1(revs);
if (!c)
break;
+ free_commit_buffer(revs->repo->parsed_objects, c);
}
}
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 88c524f..48a1550 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -397,7 +397,7 @@
test_expect_success 'a/b vs a, plus c/d case test.' '
read_tree_u_must_succeed -u -m "$treeH" "$treeM" &&
- git ls-files --stage | tee >treeMcheck.out &&
+ git ls-files --stage >treeMcheck.out &&
test_cmp treeM.out treeMcheck.out
'
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index a7f71f8..74666ff 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -1397,6 +1397,21 @@
test_path_is_missing to-remove
'
+test_expect_success 'stash --keep-index --include-untracked with empty tree' '
+ test_when_finished "rm -rf empty" &&
+ git init empty &&
+ (
+ cd empty &&
+ git commit --allow-empty --message "empty" &&
+ echo content >file &&
+ git stash push --keep-index --include-untracked &&
+ test_path_is_missing file &&
+ git stash pop &&
+ echo content >expect &&
+ test_cmp expect file
+ )
+'
+
test_expect_success 'stash apply should succeed with unmodified file' '
echo base >file &&
git add file &&
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index f439f46..d644310 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -143,4 +143,41 @@
grep '^usage:' err
'
+for option in --exit-code --quiet
+do
+ test_expect_success "git diff $option returns 1 for copied file" "
+ git reset --hard &&
+ cp a copy &&
+ git add copy &&
+ test_expect_code 1 git diff $option --cached --find-copies-harder
+ "
+
+ test_expect_success "git diff $option returns 1 for renamed file" "
+ git reset --hard &&
+ git mv a renamed &&
+ test_expect_code 1 git diff $option --cached
+ "
+done
+
+test_expect_success 'setup dirty subrepo' '
+ git reset --hard &&
+ test_create_repo subrepo &&
+ test_commit -C subrepo subrepo-file &&
+ test_tick &&
+ git add subrepo &&
+ git commit -m subrepo &&
+ test_commit -C subrepo another-subrepo-file
+'
+
+for option in --exit-code --quiet
+do
+ for submodule_format in diff log short
+ do
+ opts="$option --submodule=$submodule_format" &&
+ test_expect_success "git diff $opts returns 1 for dirty subrepo" "
+ test_expect_code 1 git diff $opts
+ "
+ done
+done
+
test_done
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index 4eb8444..87ffd2b 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -130,4 +130,66 @@
test_grep ! "has type 100644, expected 100755" err
'
+test_expect_success POSIXPERM 'patch mode for new file is canonicalized' '
+ cat >patch <<-\EOF &&
+ diff --git a/non-canon b/non-canon
+ new file mode 100660
+ --- /dev/null
+ +++ b/non-canon
+ +content
+ EOF
+ test_when_finished "git reset --hard" &&
+ (
+ umask 0 &&
+ git apply --index patch 2>err
+ ) &&
+ test_must_be_empty err &&
+ git ls-files -s -- non-canon >staged &&
+ test_grep "^100644" staged &&
+ ls -l non-canon >worktree &&
+ test_grep "^-rw-rw-rw" worktree
+'
+
+test_expect_success POSIXPERM 'patch mode for deleted file is canonicalized' '
+ test_when_finished "git reset --hard" &&
+ echo content >non-canon &&
+ chmod 666 non-canon &&
+ git add non-canon &&
+
+ cat >patch <<-\EOF &&
+ diff --git a/non-canon b/non-canon
+ deleted file mode 100660
+ --- a/non-canon
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -content
+ EOF
+ git apply --index patch 2>err &&
+ test_must_be_empty err &&
+ git ls-files -- non-canon >staged &&
+ test_must_be_empty staged &&
+ test_path_is_missing non-canon
+'
+
+test_expect_success POSIXPERM 'patch mode for mode change is canonicalized' '
+ test_when_finished "git reset --hard" &&
+ echo content >non-canon &&
+ git add non-canon &&
+
+ cat >patch <<-\EOF &&
+ diff --git a/non-canon b/non-canon
+ old mode 100660
+ new mode 100770
+ EOF
+ (
+ umask 0 &&
+ git apply --index patch 2>err
+ ) &&
+ test_must_be_empty err &&
+ git ls-files -s -- non-canon >staged &&
+ test_grep "^100755" staged &&
+ ls -l non-canon >worktree &&
+ test_grep "^-rwxrwxrwx" worktree
+'
+
test_done
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 4ad023c..3b9dae3 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -635,4 +635,43 @@
check_deltas stderr = 0
'
+for hash in sha1 sha256
+do
+ test_expect_success "verify-pack with $hash packfile" '
+ test_when_finished "rm -rf repo" &&
+ git init --object-format=$hash repo &&
+ test_commit -C repo initial &&
+ git -C repo repack -ad &&
+ git -C repo verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx &&
+ if test $hash = sha1
+ then
+ nongit git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx
+ else
+ # We have no way to identify the hash used by packfiles
+ # or indices, so we always fall back to SHA1.
+ nongit test_must_fail git verify-pack "$(pwd)"/repo/.git/objects/pack/*.idx &&
+ # But with an explicit object format we should succeed.
+ nongit git verify-pack --object-format=$hash "$(pwd)"/repo/.git/objects/pack/*.idx
+ fi
+ '
+
+ test_expect_success "index-pack outside of a $hash repository" '
+ test_when_finished "rm -rf repo" &&
+ git init --object-format=$hash repo &&
+ test_commit -C repo initial &&
+ git -C repo repack -ad &&
+ git -C repo index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack &&
+ if test $hash = sha1
+ then
+ nongit git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack
+ else
+ # We have no way to identify the hash used by packfiles
+ # or indices, so we always fall back to SHA1.
+ nongit test_must_fail git index-pack --verify "$(pwd)"/repo/.git/objects/pack/*.pack 2>err &&
+ # But with an explicit object format we should succeed.
+ nongit git index-pack --object-format=$hash --verify "$(pwd)"/repo/.git/objects/pack/*.pack
+ fi
+ '
+done
+
test_done
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index 1f859ad..4ad36a3 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -124,14 +124,14 @@
test_expect_success TTY 'quiet push' '
ensure_fresh_upstream &&
- test_terminal git push --quiet --no-progress upstream main 2>&1 | tee output &&
+ test_terminal git push --quiet --no-progress upstream main >output 2>&1 &&
test_must_be_empty output
'
test_expect_success TTY 'quiet push -u' '
ensure_fresh_upstream &&
- test_terminal git push --quiet -u --no-progress upstream main 2>&1 | tee output &&
+ test_terminal git push --quiet -u --no-progress upstream main >output 2>&1 &&
test_must_be_empty output
'
diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh
index fe75a06..34b5cd6 100755
--- a/t/t6020-bundle-misc.sh
+++ b/t/t6020-bundle-misc.sh
@@ -652,4 +652,36 @@
test_cmp expect actual
'
+test_expect_success 'unbundle outside of a repository' '
+ git bundle create some.bundle HEAD &&
+ echo "fatal: Need a repository to unbundle." >expect &&
+ nongit test_must_fail git bundle unbundle "$(pwd)/some.bundle" 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'list-heads outside of a repository' '
+ git bundle create some.bundle HEAD &&
+ cat >expect <<-EOF &&
+ $(git rev-parse HEAD) HEAD
+ EOF
+ nongit git bundle list-heads "$(pwd)/some.bundle" >actual &&
+ test_cmp expect actual
+'
+
+for hash in sha1 sha256
+do
+ test_expect_success "list-heads with bundle using $hash" '
+ test_when_finished "rm -rf hash" &&
+ git init --object-format=$hash hash &&
+ test_commit -C hash initial &&
+ git -C hash bundle create hash.bundle HEAD &&
+
+ cat >expect <<-EOF &&
+ $(git -C hash rev-parse HEAD) HEAD
+ EOF
+ git bundle list-heads hash/hash.bundle >actual &&
+ test_cmp expect actual
+ '
+done
+
test_done
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 3d3e13c..0f7d893 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -175,6 +175,46 @@
test_cmp expected actual
'
+test_expect_success 'with a bodiless message that lacks a trailing newline after the subject' '
+ cat >expected <<-\EOF &&
+ area: change
+
+ Reviewed-by: Peff
+ Acked-by: Johan
+ EOF
+ printf "area: change" |
+ git interpret-trailers --trailer "Reviewed-by: Peff" \
+ --trailer "Acked-by: Johan" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with a bodied message that lacks a trailing newline after the body' '
+ cat >expected <<-\EOF &&
+ area: change
+
+ details about the change.
+
+ Reviewed-by: Peff
+ Acked-by: Johan
+ EOF
+ printf "area: change\n\ndetails about the change." |
+ git interpret-trailers --trailer "Reviewed-by: Peff" \
+ --trailer "Acked-by: Johan" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with a message that lacks a trailing newline after the trailers' '
+ cat >expected <<-\EOF &&
+ area: change
+
+ Reviewed-by: Peff
+ Acked-by: Johan
+ EOF
+ printf "area: change\n\nReviewed-by: Peff" |
+ git interpret-trailers --trailer "Acked-by: Johan" >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'with multiline title in the message' '
cat >expected <<-\EOF &&
place of