diff options
Diffstat (limited to '')
38 files changed, 393 insertions, 175 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1ee0433acc..916a64b673 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -339,8 +339,8 @@ jobs: 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 @@ jobs: 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 37b991e080..c4c45dad2f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,6 +25,9 @@ test:linux: 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 8fb873358a..5edd3a0b9d 100644 --- a/Documentation/CodingGuidelines +++ b/Documentation/CodingGuidelines @@ -293,7 +293,9 @@ For C programs: 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 @@ For C programs: 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 3b4c44305f..e55c2c4a46 100644 --- a/Documentation/RelNotes/2.46.1.txt +++ b/Documentation/RelNotes/2.46.1.txt @@ -56,4 +56,20 @@ Fixes since Git 2.46 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 0000000000..51471e5400 --- /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 8efc53e836..36e771556c 100644 --- a/Documentation/config/remote.txt +++ b/Documentation/config/remote.txt @@ -42,14 +42,15 @@ remote.<name>.mirror:: 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 e22b217fba..80838fe37e 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 bd95a6c10a..d5890ae368 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -270,9 +270,9 @@ BATCH OUTPUT ------------ 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 65c645d461..7f81fbbea8 100644 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [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 @@ OPTIONS --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 @@ recommended to migrate to the new syntax. 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 143318c411..09286a85eb 100644 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@ -88,7 +88,7 @@ include::pretty-options.txt[] --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 51d0f7e94b..9d96819133 100644 --- a/Documentation/git-maintenance.txt +++ b/Documentation/git-maintenance.txt @@ -107,6 +107,9 @@ with the prefetch task, the objects necessary to complete a later real fetch 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 4759408788..f89ad30cf6 100644 --- a/Documentation/gittutorial.txt +++ b/Documentation/gittutorial.txt @@ -360,7 +360,7 @@ $ gitk HEAD...FETCH_HEAD 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 41f54050f8..da31332f11 100644 --- a/Documentation/howto/maintain-git.txt +++ b/Documentation/howto/maintain-git.txt @@ -181,6 +181,10 @@ by doing the following: $ 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 91a06caf63..efe61fd1f8 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=' ' @@ -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 @@ -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 d5d41a8f67..86d0ed7049 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 20a0b64090..97e4d5f57c 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 fd968d673d..763b01372a 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 1d969494cf..e6f22459f1 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 46b981c4dd..80ccfc7a08 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; @@ -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 b59fd7c1fd..e2c6ef0f66 100755 --- a/ci/install-dependencies.sh +++ b/ci/install-dependencies.sh @@ -33,37 +33,49 @@ fedora-*) 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" - - 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" - ;; -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 - ' + 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 --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 "$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 @@ -336,7 +336,14 @@ ubuntu-*) 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 6cd832efb9..0000000000 --- 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 af89d1624a..0000000000 --- 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 0afda730f2..d54efa1c5d 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 85d63821ec..bbf7744ddd 100644 --- a/config.mak.uname +++ b/config.mak.uname @@ -249,6 +249,7 @@ ifeq ($(uname_O),Cygwin) else NO_REGEX = UnfortunatelyYes endif + HAVE_DEV_TTY = YesPlease HAVE_ALLOCA_H = YesPlease NEEDS_LIBICONV = YesPlease NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes @@ -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 1c0192f522..5fecd7e0d7 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 88c524f655..48a1550371 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 setup.' ' 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 a7f71f8126..74666ff3e4 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -1397,6 +1397,21 @@ test_expect_success 'stash --keep-index with file deleted in index does not resu 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 f439f469bd..d644310e22 100755 --- a/t/t4017-diff-retval.sh +++ b/t/t4017-diff-retval.sh @@ -143,4 +143,41 @@ test_expect_success 'option errors are not confused by --exit-code' ' 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 4eb8444029..87ffd2b8e1 100755 --- a/t/t4129-apply-samemode.sh +++ b/t/t4129-apply-samemode.sh @@ -130,4 +130,66 @@ test_expect_success 'git apply respects core.fileMode' ' 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 4ad023c846..3b9dae331a 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -635,4 +635,43 @@ test_expect_success 'negative window clamps to 0' ' 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 1f859ade16..4ad36a31e1 100755 --- a/t/t5523-push-upstream.sh +++ b/t/t5523-push-upstream.sh @@ -124,14 +124,14 @@ test_expect_success TTY 'push --no-progress suppresses progress' ' 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 fe75a06572..34b5cd62c2 100755 --- a/t/t6020-bundle-misc.sh +++ b/t/t6020-bundle-misc.sh @@ -652,4 +652,36 @@ test_expect_success 'send a bundle to standard output' ' 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 3d3e13ccf8..0f7d8938d9 100755 --- a/t/t7513-interpret-trailers.sh +++ b/t/t7513-interpret-trailers.sh @@ -175,6 +175,46 @@ test_expect_success 'with only a title in the message' ' 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 |
