diff --git a/.github/workflows/check-style.yml b/.github/workflows/check-style.yml index c052a5df2381e9..19a145d4ad0c5a 100644 --- a/.github/workflows/check-style.yml +++ b/.github/workflows/check-style.yml @@ -20,7 +20,7 @@ jobs: jobname: ClangFormat runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/.github/workflows/check-whitespace.yml b/.github/workflows/check-whitespace.yml index d0a78fc426f9e4..928fd4cfe2456d 100644 --- a/.github/workflows/check-whitespace.yml +++ b/.github/workflows/check-whitespace.yml @@ -19,7 +19,7 @@ jobs: check-whitespace: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 01a0437b2f2634..cfa17d394a7dbc 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -38,7 +38,7 @@ jobs: COVERITY_LANGUAGE: cxx COVERITY_PLATFORM: overridden-below steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: install minimal Git for Windows SDK if: contains(matrix.os, 'windows') uses: git-for-windows/setup-git-for-windows-sdk@v1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 393ea4d1ccf784..3622fec742ba13 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -63,7 +63,7 @@ jobs: echo "skip_concurrent=$skip_concurrent" >>$GITHUB_OUTPUT - name: skip if the commit or tree was already tested id: skip-if-redundant - uses: actions/github-script@v7 + uses: actions/github-script@v8 if: steps.check-ref.outputs.enabled == 'yes' with: github-token: ${{secrets.GITHUB_TOKEN}} @@ -112,7 +112,7 @@ jobs: group: windows-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: git-for-windows/setup-git-for-windows-sdk@v1 - name: build shell: bash @@ -140,7 +140,7 @@ jobs: cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - name: download tracked files and build artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: windows-artifacts path: ${{github.workspace}} @@ -173,10 +173,10 @@ jobs: group: vs-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: git-for-windows/setup-git-for-windows-sdk@v1 - name: initialize vcpkg - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: 'microsoft/vcpkg' path: 'compat/vcbuild/vcpkg' @@ -226,7 +226,7 @@ jobs: steps: - uses: git-for-windows/setup-git-for-windows-sdk@v1 - name: download tracked files and build artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: vs-artifacts path: ${{github.workspace}} @@ -258,8 +258,8 @@ jobs: group: windows-meson-build-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v5 + - uses: actions/setup-python@v6 - name: Set up dependencies shell: pwsh run: pip install meson ninja @@ -286,13 +286,13 @@ jobs: group: windows-meson-test-${{ matrix.nr }}-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v5 + - uses: actions/setup-python@v6 - name: Set up dependencies shell: pwsh run: pip install meson ninja - name: Download build artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: windows-meson-artifacts path: build @@ -331,7 +331,7 @@ jobs: TEST_OUTPUT_DIRECTORY: ${{github.workspace}}/t runs-on: ${{matrix.vector.pool}} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: ci/install-dependencies.sh - run: ci/run-build-and-tests.sh - name: print test failures @@ -352,7 +352,7 @@ jobs: CI_JOB_IMAGE: ubuntu-latest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: ci/install-dependencies.sh - run: ci/run-build-and-minimal-fuzzers.sh dockerized: @@ -429,7 +429,7 @@ jobs: else apt-get -q update && apt-get -q -y install git fi - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: ci/install-dependencies.sh - run: useradd builder --create-home - run: chown -R builder . @@ -454,7 +454,7 @@ jobs: group: static-analysis-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: ci/install-dependencies.sh - run: ci/run-static-analysis.sh - run: ci/check-directional-formatting.bash @@ -469,7 +469,7 @@ jobs: group: sparse-${{ github.ref }} cancel-in-progress: ${{ needs.ci-config.outputs.skip_concurrent == 'yes' }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install other dependencies run: ci/install-dependencies.sh - run: make sparse @@ -485,6 +485,6 @@ jobs: CI_JOB_IMAGE: ubuntu-latest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - run: ci/install-dependencies.sh - run: ci/test-documentation.sh diff --git a/Documentation/Makefile b/Documentation/Makefile index a3fbd29744bd39..627204928eebbb 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -34,6 +34,7 @@ MAN5_TXT += gitformat-bundle.adoc MAN5_TXT += gitformat-chunk.adoc MAN5_TXT += gitformat-commit-graph.adoc MAN5_TXT += gitformat-index.adoc +MAN5_TXT += gitformat-loose.adoc MAN5_TXT += gitformat-pack.adoc MAN5_TXT += gitformat-signature.adoc MAN5_TXT += githooks.adoc diff --git a/Documentation/RelNotes/2.52.0.adoc b/Documentation/RelNotes/2.52.0.adoc index 1e41b7380aebe0..cfce098d1453a0 100644 --- a/Documentation/RelNotes/2.52.0.adoc +++ b/Documentation/RelNotes/2.52.0.adoc @@ -131,6 +131,8 @@ Performance, Internal Implementation, Development Support etc. and one for xdiff), roll everything into a single libgit.a archive. This would help later effort to FFI into Rust. + * The beginning of SHA1-SHA256 interoperability work. + Fixes since v2.51 ----------------- @@ -380,3 +382,5 @@ including security updates, are included in this release. (merge 3860985105 js/unreachable-workaround-for-no-symlink-head later to maint). (merge b3ac6e737d kh/doc-continued-paragraph-fix later to maint). (merge 2cebca0582 tb/cat-file-objectmode-update later to maint). + (merge 96978d7545 js/ci-github-actions-update later to maint). + (merge 0c4f1346ca so/t2401-use-test-path-helpers later to maint). diff --git a/Documentation/fsck-msgids.adoc b/Documentation/fsck-msgids.adoc index 81f11ba125a22a..acac9683af83f4 100644 --- a/Documentation/fsck-msgids.adoc +++ b/Documentation/fsck-msgids.adoc @@ -10,6 +10,12 @@ `badFilemode`:: (INFO) A tree contains a bad filemode entry. +`badGpgsig`:: + (ERROR) A tag contains a bad (truncated) signature (e.g., `gpgsig`) header. + +`badHeaderContinuation`:: + (ERROR) A continuation header (such as for `gpgsig`) is unexpectedly truncated. + `badName`:: (ERROR) An author/committer name is empty. diff --git a/Documentation/git-pull.adoc b/Documentation/git-pull.adoc index 48e924a10a40c0..cd3bbc90e3008d 100644 --- a/Documentation/git-pull.adoc +++ b/Documentation/git-pull.adoc @@ -15,68 +15,54 @@ SYNOPSIS DESCRIPTION ----------- -Incorporates changes from a remote repository into the current branch. -If the current branch is behind the remote, then by default it will -fast-forward the current branch to match the remote. If the current -branch and the remote have diverged, the user needs to specify how to -reconcile the divergent branches with `--rebase` or `--no-rebase` (or -the corresponding configuration option in `pull.rebase`). - -More precisely, `git pull` runs `git fetch` with the given parameters -and then depending on configuration options or command line flags, -will call either `git rebase` or `git merge` to reconcile diverging -branches. - - should be the name of a remote repository as -passed to linkgit:git-fetch[1]. can name an -arbitrary remote ref (for example, the name of a tag) or even -a collection of refs with corresponding remote-tracking branches -(e.g., refs/heads/{asterisk}:refs/remotes/origin/{asterisk}), -but usually it is the name of a branch in the remote repository. - -Default values for and are read from the -"remote" and "merge" configuration for the current branch -as set by linkgit:git-branch[1] `--track`. - -Assume the following history exists and the current branch is -"`master`": +Integrate changes from a remote repository into the current branch. ------------- - A---B---C master on origin - / - D---E---F---G master - ^ - origin/master in your repository ------------- +First, `git pull` runs `git fetch` with the same arguments +(excluding merge options) to fetch remote branch(es). +Then it decides which remote branch to integrate: if you run `git pull` +with no arguments this defaults to the <> +for the current branch. +Then it integrates that branch into the current branch. -Then "`git pull`" will fetch and replay the changes from the remote -`master` branch since it diverged from the local `master` (i.e., `E`) -until its current commit (`C`) on top of `master` and record the -result in a new commit along with the names of the two parent commits -and a log message from the user describing the changes. - ------------- - A---B---C origin/master - / \ - D---E---F---G---H master ------------- +There are 4 main options for integrating the remote branch: -See linkgit:git-merge[1] for details, including how conflicts -are presented and handled. +1. `git pull --ff-only` will only do "fast-forward" updates: it + fails if your local branch has diverged from the remote branch. + This is the default. +2. `git pull --rebase` runs `git rebase` +3. `git pull --no-rebase` runs `git merge`. +4. `git pull --squash` runs `git merge --squash` -In Git 1.7.0 or later, to cancel a conflicting merge, use -`git reset --merge`. *Warning*: In older versions of Git, running 'git pull' -with uncommitted changes is discouraged: while possible, it leaves you -in a state that may be hard to back out of in the case of a conflict. +You can also set the configuration options `pull.rebase`, `pull.squash`, +or `pull.ff` with your preferred behaviour. -If any of the remote changes overlap with local uncommitted changes, -the merge will be automatically canceled and the work tree untouched. -It is generally best to get any local changes in working order before -pulling or stash them away with linkgit:git-stash[1]. +If there's a merge conflict during the merge or rebase that you don't +want to handle, you can safely abort it with `git merge --abort` or `git +--rebase abort`. OPTIONS ------- +:: + The "remote" repository to pull from. This can be either + a URL (see the section <> below) or the name + of a remote (see the section <> below). ++ +Defaults to the configured upstream for the current branch, or `origin`. +See <> below for more on how to +configure upstreams. + +:: + Which branch or other reference(s) to fetch and integrate into the + current branch, for example `main` in `git pull origin main`. + Defaults to the configured upstream for the current branch. ++ +This can be a branch, tag, or other collection of reference(s). +See <>> below under "Options related to fetching" +for the full syntax, and <> below +for how `git pull` uses this argument to determine which remote branch +to integrate. + -q:: --quiet:: This is passed to both underlying git-fetch to squelch reporting of @@ -145,6 +131,7 @@ include::urls-remotes.adoc[] include::merge-strategies.adoc[] +[[DEFAULT-BEHAVIOUR]] DEFAULT BEHAVIOUR ----------------- diff --git a/Documentation/git-rev-parse.adoc b/Documentation/git-rev-parse.adoc index 18383e52af72ad..5398691f3f15f7 100644 --- a/Documentation/git-rev-parse.adoc +++ b/Documentation/git-rev-parse.adoc @@ -324,11 +324,12 @@ The following options are unaffected by `--path-format`: path of the current directory relative to the top-level directory. ---show-object-format[=(storage|input|output)]:: - Show the object format (hash algorithm) used for the repository - for storage inside the `.git` directory, input, or output. For - input, multiple algorithms may be printed, space-separated. - If not specified, the default is "storage". +--show-object-format[=(storage|input|output|compat)]:: + Show the object format (hash algorithm) used for the repository for storage + inside the `.git` directory, input, output, or compatibility. For input, + multiple algorithms may be printed, space-separated. If `compat` is + requested and no compatibility algorithm is enabled, prints an empty line. If + not specified, the default is "storage". --show-ref-format:: Show the reference storage format used for the repository. diff --git a/Documentation/gitformat-loose.adoc b/Documentation/gitformat-loose.adoc new file mode 100644 index 00000000000000..947993663e167f --- /dev/null +++ b/Documentation/gitformat-loose.adoc @@ -0,0 +1,53 @@ +gitformat-loose(5) +================== + +NAME +---- +gitformat-loose - Git loose object format + + +SYNOPSIS +-------- +[verse] +$GIT_DIR/objects/[0-9a-f][0-9a-f]/* + +DESCRIPTION +----------- + +Loose objects are how Git stores individual objects, where every object is +written as a separate file. + +Over the lifetime of a repository, objects are usually written as loose objects +initially. Eventually, these loose objects will be compacted into packfiles +via repository maintenance to improve disk space usage and speed up the lookup +of these objects. + +== Loose objects + +Each loose object contains a prefix, followed immediately by the data of the +object. The prefix contains ` \0`. `` is one of `blob`, +`tree`, `commit`, or `tag` and `size` is the size of the data (without the +prefix) as a decimal integer expressed in ASCII. + +The entire contents, prefix and data concatenated, is then compressed with zlib +and the compressed data is stored in the file. The object ID of the object is +the SHA-1 or SHA-256 (as appropriate) hash of the uncompressed data. + +The file for the loose object is stored under the `objects` directory, with the +first two hex characters of the object ID being the directory and the remaining +characters being the file name. This is done to shard the data and avoid too +many files being in one directory, since some file systems perform poorly with +many items in a directory. + +As an example, the empty tree contains the data (when uncompressed) `tree 0\0` +and, in a SHA-256 repository, would have the object ID +`6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321` and would be +stored under +`$GIT_DIR/objects/6e/f19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321`. + +Similarly, a blob containing the contents `abc` would have the uncompressed +data of `blob 3\0abc`. + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Documentation/gitformat-pack.adoc b/Documentation/gitformat-pack.adoc index d6ae229be56859..1b4db4aa611e83 100644 --- a/Documentation/gitformat-pack.adoc +++ b/Documentation/gitformat-pack.adoc @@ -32,6 +32,10 @@ In a repository using the traditional SHA-1, pack checksums, index checksums, and object IDs (object names) mentioned below are all computed using SHA-1. Similarly, in SHA-256 repositories, these values are computed using SHA-256. +CRC32 checksums are always computed over the entire packed object, including +the header (n-byte type and length); the base object name or offset, if any; +and the entire compressed object. The CRC32 algorithm used is that of zlib. + == pack-*.pack files have the following format: - A header appears at the beginning and consists of the following: @@ -80,6 +84,16 @@ Valid object types are: Type 5 is reserved for future expansion. Type 0 is invalid. +=== Object encoding + +Unlike loose objects, packed objects do not have a prefix containing the type, +size, and a NUL byte. These are not necessary because they can be determined by +the n-byte type and length that prefixes the data and so they are omitted from +the compressed and deltified data. + +The computation of the object ID still uses this prefix by reconstructing it +from the type and length as needed. + === Size encoding This document uses the following "size encoding" of non-negative @@ -92,6 +106,11 @@ values are more significant. This size encoding should not be confused with the "offset encoding", which is also used in this document. +When encoding the size of an undeltified object in a pack, the size is that of +the uncompressed raw object. For deltified objects, it is the size of the +uncompressed delta. The base object name or offset is not included in the size +computation. + === Deltified representation Conceptually there are only four object types: commit, tree, tag and diff --git a/Documentation/meson.build b/Documentation/meson.build index 44f94cdb7ba672..9d24f2da544682 100644 --- a/Documentation/meson.build +++ b/Documentation/meson.build @@ -173,6 +173,7 @@ manpages = { 'gitformat-chunk.adoc' : 5, 'gitformat-commit-graph.adoc' : 5, 'gitformat-index.adoc' : 5, + 'gitformat-loose.adoc' : 5, 'gitformat-pack.adoc' : 5, 'gitformat-signature.adoc' : 5, 'githooks.adoc' : 5, diff --git a/Documentation/pull-fetch-param.adoc b/Documentation/pull-fetch-param.adoc index d79d2f6065bcd4..bb2cf6a4629e92 100644 --- a/Documentation/pull-fetch-param.adoc +++ b/Documentation/pull-fetch-param.adoc @@ -11,6 +11,7 @@ ifndef::git-pull[] (See linkgit:git-config[1]). endif::git-pull[] +[[fetch-refspec]] :: Specifies which refs to fetch and which local refs to update. When no s appear on the command line, the refs to fetch diff --git a/Documentation/technical/hash-function-transition.adoc b/Documentation/technical/hash-function-transition.adoc index f047fd80cadd1e..2359d7d106f842 100644 --- a/Documentation/technical/hash-function-transition.adoc +++ b/Documentation/technical/hash-function-transition.adoc @@ -227,9 +227,9 @@ network byte order): ** 4-byte length in bytes of shortened object names. This is the shortest possible length needed to make names in the shortened object name table unambiguous. - ** 4-byte integer, recording where tables relating to this format + ** 8-byte integer, recording where tables relating to this format are stored in this index file, as an offset from the beginning. - * 4-byte offset to the trailer from the beginning of this file. + * 8-byte offset to the trailer from the beginning of this file. * Zero or more additional key/value pairs (4-byte key, 4-byte value). Only one key is supported: 'PSRC'. See the "Loose objects and unreachable objects" section for supported values and how this @@ -260,12 +260,10 @@ network byte order): compressed data to be copied directly from pack to pack during repacking without undetected data corruption. - * A table of 4-byte offset values. For an object in the table of - sorted shortened object names, the value at the corresponding - index in this table indicates where that object can be found in - the pack file. These are usually 31-bit pack file offsets, but - large offsets are encoded as an index into the next table with the - most significant bit set. + * A table of 4-byte offset values. The index of this table in pack order + indicates where that object can be found in the pack file. These are + usually 31-bit pack file offsets, but large offsets are encoded as + an index into the next table with the most significant bit set. * A table of 8-byte offset entries (empty for pack files less than 2 GiB). Pack files are organized with heavily used objects toward @@ -276,10 +274,14 @@ network byte order): up to and not including the table of CRC32 values. - Zero or more NUL bytes. - The trailer consists of the following: - * A copy of the 20-byte SHA-256 checksum at the end of the + * A copy of the full main hash checksum at the end of the corresponding packfile. - * 20-byte SHA-256 checksum of all of the above. + * Full main hash checksum of all of the above. + +The "full main hash" is a full-length hash of the main (not compatibility) +algorithm in the repository. Thus, if the main algorithm is SHA-256, this is +a 32-byte SHA-256 hash and for SHA-1, it's a 20-byte SHA-1 hash. Loose object index ~~~~~~~~~~~~~~~~~~ @@ -427,17 +429,19 @@ ordinary unsigned commit. Signed Tags ~~~~~~~~~~~ -We add a new field "gpgsig-sha256" to the tag object format to allow -signing tags without relying on SHA-1. Its signed payload is the -SHA-256 content of the tag with its gpgsig-sha256 field and "-----BEGIN PGP -SIGNATURE-----" delimited in-body signature removed. - -This means tags can be signed - -1. using SHA-1 only, as in existing signed tag objects -2. using both SHA-1 and SHA-256, by using gpgsig-sha256 and an in-body - signature. -3. using only SHA-256, by only using the gpgsig-sha256 field. +We add new fields "gpgsig" and "gpgsig-sha256" to the tag object format to +allow signing tags in both formats. The in-body signature is used for the +signature in the current hash algorithm and the header is used for the +signature in the other algorithm. Thus, a dual-signature tag will contain both +an in-body signature and a gpgsig-sha256 header for the SHA-1 format of an +object or both an in-body signature and a gpgsig header for the SHA-256 format +of and object. + +The signed payload of the tag is the content of the tag in the current +algorithm with both its gpgsig and gpgsig-sha256 fields and +"-----BEGIN PGP SIGNATURE-----" delimited in-body signature removed. + +This means tags can be signed using one or both algorithms. Mergetag embedding ~~~~~~~~~~~~~~~~~~ diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 9da92b990d074b..7b3711cf34f534 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -1107,11 +1107,20 @@ int cmd_rev_parse(int argc, const char *val = arg ? arg : "storage"; if (strcmp(val, "storage") && + strcmp(val, "compat") && strcmp(val, "input") && strcmp(val, "output")) die(_("unknown mode for --show-object-format: %s"), arg); - puts(the_hash_algo->name); + + if (!strcmp(val, "compat")) { + if (the_repository->compat_hash_algo) + puts(the_repository->compat_hash_algo->name); + else + putchar('\n'); + } else { + puts(the_hash_algo->name); + } continue; } if (!strcmp(arg, "--show-ref-format")) { diff --git a/fsck.c b/fsck.c index 171b424dd57de1..341e100d24ece0 100644 --- a/fsck.c +++ b/fsck.c @@ -1067,6 +1067,24 @@ int fsck_tag_standalone(const struct object_id *oid, const char *buffer, else ret = fsck_ident(&buffer, oid, OBJ_TAG, options); + if (buffer < buffer_end && (skip_prefix(buffer, "gpgsig ", &buffer) || skip_prefix(buffer, "gpgsig-sha256 ", &buffer))) { + eol = memchr(buffer, '\n', buffer_end - buffer); + if (!eol) { + ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_GPGSIG, "invalid format - unexpected end after 'gpgsig' or 'gpgsig-sha256' line"); + goto done; + } + buffer = eol + 1; + + while (buffer < buffer_end && starts_with(buffer, " ")) { + eol = memchr(buffer, '\n', buffer_end - buffer); + if (!eol) { + ret = report(options, oid, OBJ_TAG, FSCK_MSG_BAD_HEADER_CONTINUATION, "invalid format - unexpected end in 'gpgsig' or 'gpgsig-sha256' continuation line"); + goto done; + } + buffer = eol + 1; + } + } + if (buffer < buffer_end && !starts_with(buffer, "\n")) { /* * The verify_headers() check will allow diff --git a/fsck.h b/fsck.h index 759df97655605d..cb6ef32f4f3aaa 100644 --- a/fsck.h +++ b/fsck.h @@ -25,9 +25,11 @@ enum fsck_msg_type { FUNC(NUL_IN_HEADER, FATAL) \ FUNC(UNTERMINATED_HEADER, FATAL) \ /* errors */ \ + FUNC(BAD_HEADER_CONTINUATION, ERROR) \ FUNC(BAD_DATE, ERROR) \ FUNC(BAD_DATE_OVERFLOW, ERROR) \ FUNC(BAD_EMAIL, ERROR) \ + FUNC(BAD_GPGSIG, ERROR) \ FUNC(BAD_NAME, ERROR) \ FUNC(BAD_OBJECT_SHA1, ERROR) \ FUNC(BAD_PACKED_REF_ENTRY, ERROR) \ diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh index e9973f74949661..312fe6717a622f 100755 --- a/t/t1010-mktree.sh +++ b/t/t1010-mktree.sh @@ -11,10 +11,13 @@ test_expect_success setup ' git add "$d" || return 1 done && echo zero >one && - git update-index --add --info-only one && - git write-tree --missing-ok >tree.missing && - git ls-tree $(cat tree.missing) >top.missing && - git ls-tree -r $(cat tree.missing) >all.missing && + if test_have_prereq BROKEN_OBJECTS + then + git update-index --add --info-only one && + git write-tree --missing-ok >tree.missing && + git ls-tree $(cat tree.missing) >top.missing && + git ls-tree -r $(cat tree.missing) >all.missing + fi && echo one >one && git add one && git write-tree >tree && @@ -53,7 +56,7 @@ test_expect_success 'ls-tree output in wrong order given to mktree (2)' ' test_cmp tree.withsub actual ' -test_expect_success 'allow missing object with --missing' ' +test_expect_success BROKEN_OBJECTS 'allow missing object with --missing' ' git mktree --missing actual && test_cmp tree.missing actual ' diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 5ae86c42be55ac..c4b651c2dc7938 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -454,6 +454,60 @@ test_expect_success 'tag with NUL in header' ' test_grep "error in tag $tag.*unterminated header: NUL at offset" out ' +test_expect_success 'tag accepts gpgsig header even if not validly signed' ' + test_oid_cache <<-\EOF && + header sha1:gpgsig-sha256 + header sha256:gpgsig + EOF + header=$(test_oid header) && + sha=$(git rev-parse HEAD) && + cat >good-tag <<-EOF && + object $sha + type commit + tag good + tagger T A Gger 1234567890 -0000 + $header -----BEGIN PGP SIGNATURE----- + Not a valid signature + -----END PGP SIGNATURE----- + + This is a good tag. + EOF + + tag=$(git hash-object --literally -t tag -w --stdin bad-tag <<-EOF && + object $sha + type commit + tag good + tagger T A Gger 1234567890 -0000 + $header -----BEGIN PGP SIGNATURE----- + Not a valid signature + -----END PGP SIGNATURE----- + junk + + This is a bad tag with junk at the end of the headers. + EOF + + tag=$(git hash-object --literally -t tag -w --stdin out && + test_grep "error in tag $tag.*invalid format - extra header" out +' + test_expect_success 'cleaned up' ' git fsck >actual 2>&1 && test_must_be_empty actual diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh index 58a4583088b859..7739ab611bc1c0 100755 --- a/t/t1500-rev-parse.sh +++ b/t/t1500-rev-parse.sh @@ -207,6 +207,40 @@ test_expect_success 'rev-parse --show-object-format in repo' ' grep "unknown mode for --show-object-format: squeamish-ossifrage" err ' + +test_expect_success 'rev-parse --show-object-format in repo with compat mode' ' + mkdir repo && + ( + sane_unset GIT_DEFAULT_HASH && + cd repo && + git init --object-format=sha256 && + git config extensions.compatobjectformat sha1 && + echo sha256 >expect && + git rev-parse --show-object-format >actual && + test_cmp expect actual && + git rev-parse --show-object-format=storage >actual && + test_cmp expect actual && + git rev-parse --show-object-format=input >actual && + test_cmp expect actual && + git rev-parse --show-object-format=output >actual && + test_cmp expect actual && + echo sha1 >expect && + git rev-parse --show-object-format=compat >actual && + test_cmp expect actual && + test_must_fail git rev-parse --show-object-format=squeamish-ossifrage 2>err && + grep "unknown mode for --show-object-format: squeamish-ossifrage" err + ) && + mkdir repo2 && + ( + sane_unset GIT_DEFAULT_HASH && + cd repo2 && + git init --object-format=sha256 && + echo >expect && + git rev-parse --show-object-format=compat >actual && + test_cmp expect actual + ) +' + test_expect_success 'rev-parse --show-ref-format' ' test_detect_ref_format >expect && git rev-parse --show-ref-format >actual && diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh index fe671d41974281..f8f28c76ee56c7 100755 --- a/t/t2401-worktree-prune.sh +++ b/t/t2401-worktree-prune.sh @@ -24,8 +24,8 @@ test_expect_success 'prune files inside $GIT_DIR/worktrees' ' Removing worktrees/abc: not a valid directory EOF test_cmp expect actual && - ! test -f .git/worktrees/abc && - ! test -d .git/worktrees + test_path_is_missing .git/worktrees/abc && + test_path_is_missing .git/worktrees ' test_expect_success 'prune directories without gitdir' ' @@ -36,8 +36,8 @@ Removing worktrees/def: gitdir file does not exist EOF git worktree prune --verbose 2>actual && test_cmp expect actual && - ! test -d .git/worktrees/def && - ! test -d .git/worktrees + test_path_is_missing .git/worktrees/def && + test_path_is_missing .git/worktrees ' test_expect_success SANITY 'prune directories with unreadable gitdir' ' @@ -47,8 +47,8 @@ test_expect_success SANITY 'prune directories with unreadable gitdir' ' chmod u-r .git/worktrees/def/gitdir && git worktree prune --verbose 2>actual && test_grep "Removing worktrees/def: unable to read gitdir file" actual && - ! test -d .git/worktrees/def && - ! test -d .git/worktrees + test_path_is_missing .git/worktrees/def && + test_path_is_missing .git/worktrees ' test_expect_success 'prune directories with invalid gitdir' ' @@ -57,8 +57,8 @@ test_expect_success 'prune directories with invalid gitdir' ' : >.git/worktrees/def/gitdir && git worktree prune --verbose 2>actual && test_grep "Removing worktrees/def: invalid gitdir file" actual && - ! test -d .git/worktrees/def && - ! test -d .git/worktrees + test_path_is_missing .git/worktrees/def && + test_path_is_missing .git/worktrees ' test_expect_success 'prune directories with gitdir pointing to nowhere' ' @@ -67,8 +67,8 @@ test_expect_success 'prune directories with gitdir pointing to nowhere' ' echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir && git worktree prune --verbose 2>actual && test_grep "Removing worktrees/def: gitdir file points to non-existent location" actual && - ! test -d .git/worktrees/def && - ! test -d .git/worktrees + test_path_is_missing .git/worktrees/def && + test_path_is_missing .git/worktrees ' test_expect_success 'not prune locked checkout' ' @@ -76,23 +76,23 @@ test_expect_success 'not prune locked checkout' ' mkdir -p .git/worktrees/ghi && : >.git/worktrees/ghi/locked && git worktree prune && - test -d .git/worktrees/ghi + test_path_is_dir .git/worktrees/ghi ' test_expect_success 'not prune recent checkouts' ' test_when_finished rm -r .git/worktrees && git worktree add jlm HEAD && - test -d .git/worktrees/jlm && + test_path_is_dir .git/worktrees/jlm && rm -rf jlm && git worktree prune --verbose --expire=2.days.ago && - test -d .git/worktrees/jlm + test_path_is_dir .git/worktrees/jlm ' test_expect_success 'not prune proper checkouts' ' test_when_finished rm -r .git/worktrees && git worktree add --detach "$PWD/nop" main && git worktree prune && - test -d .git/worktrees/nop + test_path_is_dir .git/worktrees/nop ' test_expect_success 'prune duplicate (linked/linked)' ' @@ -103,8 +103,8 @@ test_expect_success 'prune duplicate (linked/linked)' ' mv .git/worktrees/w2/gitdir.new .git/worktrees/w2/gitdir && git worktree prune --verbose 2>actual && test_grep "duplicate entry" actual && - test -d .git/worktrees/w1 && - ! test -d .git/worktrees/w2 + test_path_is_dir .git/worktrees/w1 && + test_path_is_missing .git/worktrees/w2 ' test_expect_success 'prune duplicate (main/linked)' ' @@ -116,7 +116,7 @@ test_expect_success 'prune duplicate (main/linked)' ' mv repo wt && git -C wt worktree prune --verbose 2>actual && test_grep "duplicate entry" actual && - ! test -d .git/worktrees/wt + test_path_is_missing .git/worktrees/wt ' test_expect_success 'not prune proper worktrees inside linked worktree with relative paths' ' diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index a28de7b19bc001..52d7759bf5762d 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -1708,11 +1708,16 @@ test_set_hash () { # Detect the hash algorithm in use. test_detect_hash () { case "${GIT_TEST_DEFAULT_HASH:-$GIT_TEST_BUILTIN_HASH}" in - "sha256") + *:*) + test_hash_algo="${GIT_TEST_DEFAULT_HASH%%:*}" + test_compat_hash_algo="${GIT_TEST_DEFAULT_HASH##*:}" + test_repo_compat_hash_algo="$test_compat_hash_algo" + ;; + sha256) test_hash_algo=sha256 test_compat_hash_algo=sha1 ;; - *) + sha1) test_hash_algo=sha1 test_compat_hash_algo=sha256 ;; diff --git a/t/test-lib.sh b/t/test-lib.sh index 562f950fb0aec2..ef0ab7ec2d1bb6 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1924,6 +1924,19 @@ test_lazy_prereq DEFAULT_HASH_ALGORITHM ' test_lazy_prereq DEFAULT_REPO_FORMAT ' test_have_prereq SHA1,REFFILES ' +# BROKEN_OBJECTS is a test whether we can write deliberately broken objects and +# expect them to work. When running using SHA-256 mode with SHA-1 +# compatibility, we cannot write such objects because there's no SHA-1 +# compatibility value for a nonexistent object. +test_lazy_prereq BROKEN_OBJECTS ' + ! test_have_prereq COMPAT_HASH +' + +# COMPAT_HASH is a test if we're operating in a repository with SHA-256 with +# SHA-1 compatibility. +test_lazy_prereq COMPAT_HASH ' + test -n "$test_repo_compat_hash_algo" +' # Ensure that no test accidentally triggers a Git command # that runs the actual maintenance scheduler, affecting a user's