Merge branch 'jk/oideq-hasheq-cleanup'
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Oct 2018 07:16:07 +0000 (16:16 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Oct 2018 07:16:08 +0000 (16:16 +0900)
Code clean-up.

* jk/oideq-hasheq-cleanup:
more oideq/hasheq conversions

133 files changed:
.mailmap
Documentation/CodingGuidelines
Documentation/RelNotes/2.14.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.15.3.txt [new file with mode: 0644]
Documentation/RelNotes/2.16.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.17.2.txt [new file with mode: 0644]
Documentation/RelNotes/2.18.1.txt [new file with mode: 0644]
Documentation/RelNotes/2.19.1.txt [new file with mode: 0644]
Documentation/RelNotes/2.20.0.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/fetch-config.txt [new file with mode: 0644]
Documentation/format-config.txt [new file with mode: 0644]
Documentation/git-archimport.txt
Documentation/git-column.txt
Documentation/git-commit-graph.txt
Documentation/git-config.txt
Documentation/git-describe.txt
Documentation/git-multi-pack-index.txt
Documentation/git.txt
Documentation/gitcredentials.txt
Documentation/gitcvs-config.txt [new file with mode: 0644]
Documentation/gui-config.txt [new file with mode: 0644]
Documentation/pull-config.txt [new file with mode: 0644]
Documentation/push-config.txt [new file with mode: 0644]
Documentation/receive-config.txt [new file with mode: 0644]
Documentation/sendemail-config.txt [new file with mode: 0644]
Documentation/submodule-config.txt [new file with mode: 0644]
Documentation/technical/commit-graph.txt
Makefile
RelNotes [changed from file to symlink]
builtin/commit-graph.c
builtin/commit.c
builtin/fsck.c
builtin/gc.c
builtin/multi-pack-index.c
builtin/pack-objects.c
builtin/receive-pack.c
builtin/replace.c
builtin/submodule--helper.c
commit-graph.c
commit-graph.h
commit-reach.c
commit.c
commit.h
delta-islands.h
ewah/ewok_rlw.h
fsck.c
fsck.h
git-rebase.sh
git.c
json-writer.h
merge-recursive.c
midx.c
midx.h
refs.c
refs.h
refs/iterator.c
refs/packed-backend.h
refs/ref-cache.h
refs/refs-internal.h
replace-object.c
replace-object.h
submodule-config.c
t/README
t/helper/test-dump-fsmonitor.c
t/helper/test-dump-untracked-cache.c
t/helper/test-parse-options.c
t/helper/test-pkt-line.c
t/helper/test-repository.c
t/helper/test-tool.c
t/helper/test-tool.h
t/lib-gpg.sh
t/oid-info/README [new file with mode: 0644]
t/oid-info/hash-info [new file with mode: 0644]
t/oid-info/oid [new file with mode: 0644]
t/perf/p1450-fsck.sh [new file with mode: 0755]
t/perf/p1451-fsck-skip-list.sh [new file with mode: 0755]
t/t0000-basic.sh
t/t0002-gitfile.sh
t/t0014-alias.sh [new file with mode: 0755]
t/t0021-conversion.sh
t/t0040-parse-options.sh
t/t0064-sha1-array.sh
t/t1006-cat-file.sh
t/t1300-config.sh
t/t1303-wacky-config.sh
t/t1400-update-ref.sh
t/t1405-main-ref-store.sh
t/t1406-submodule-ref-store.sh
t/t1407-worktree-ref-store.sh
t/t2101-update-index-reupdate.sh
t/t3200-branch.sh
t/t3320-notes-merge-worktrees.sh
t/t3400-rebase.sh
t/t3417-rebase-whitespace-fix.sh
t/t3702-add-edit.sh
t/t3903-stash.sh
t/t3905-stash-include-untracked.sh
t/t4025-hunk-header.sh
t/t4117-apply-reject.sh
t/t4124-apply-ws-rule.sh
t/t4138-apply-ws-expansion.sh
t/t5317-pack-objects-filter-objects.sh
t/t5318-commit-graph.sh
t/t5319-multi-pack-index.sh
t/t5500-fetch-pack.sh
t/t5504-fetch-receive-strict.sh
t/t5551-http-fetch-smart.sh
t/t5616-partial-clone.sh
t/t5701-git-serve.sh
t/t5702-protocol-v2.sh
t/t5703-upload-pack-ref-in-want.sh
t/t6023-merge-file.sh
t/t6027-merge-binary.sh
t/t6031-merge-filemode.sh
t/t6112-rev-list-filters-objects.sh
t/t6500-gc.sh
t/t7063-status-untracked-cache.sh
t/t7201-co.sh
t/t7406-submodule-update.sh
t/t7416-submodule-dash-url.sh [new file with mode: 0755]
t/t7417-submodule-path-url.sh [new file with mode: 0755]
t/t7500-commit.sh
t/t7519-status-fsmonitor.sh
t/t7800-difftool.sh
t/t9100-git-svn-basic.sh
t/t9101-git-svn-props.sh
t/t9133-git-svn-nested-git-repo.sh
t/t9600-cvsimport.sh
t/t9603-cvsimport-patchsets.sh
t/t9604-cvsimport-timestamps.sh
t/test-lib-functions.sh
upload-pack.c
index f165222a7821e982174adc8e1c3678275ae80753..bef3352b0d3c6e84a33304b2fe44f6a68f6044a3 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -25,7 +25,7 @@ Ben Walton <bdwalton@gmail.com> <bwalton@artsci.utoronto.ca>
 Benoit Sigoure <tsunanet@gmail.com> <tsuna@lrde.epita.fr>
 Bernt Hansen <bernt@norang.ca> <bernt@alumni.uwaterloo.ca>
 Brandon Casey <drafnel@gmail.com> <casey@nrlssc.navy.mil>
-brian m. carlson <sandals@crustytoothpaste.net> Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
+brian m. carlson <sandals@crustytoothpaste.net>
 brian m. carlson <sandals@crustytoothpaste.net> <sandals@crustytoothpaste.ath.cx>
 Bryan Larsen <bryan@larsen.st> <bryan.larsen@gmail.com>
 Bryan Larsen <bryan@larsen.st> <bryanlarsen@yahoo.com>
index 48aa4edfbdd180e1c6d874b6bb61ea5fc8e32ef5..72967deb785814546830cf23a54eeeb93d147681 100644 (file)
@@ -118,6 +118,24 @@ For shell scripts specifically (not exhaustive):
                do this
        fi
 
+ - If a command sequence joined with && or || or | spans multiple
+   lines, put each command on a separate line and put && and || and |
+   operators at the end of each line, rather than the start. This
+   means you don't need to use \ to join lines, since the above
+   operators imply the sequence isn't finished.
+
+       (incorrect)
+       grep blob verify_pack_result \
+       | awk -f print_1.awk \
+       | sort >actual &&
+       ...
+
+       (correct)
+       grep blob verify_pack_result |
+       awk -f print_1.awk |
+       sort >actual &&
+       ...
+
  - We prefer "test" over "[ ... ]".
 
  - We do not write the noiseword "function" in front of shell
diff --git a/Documentation/RelNotes/2.14.5.txt b/Documentation/RelNotes/2.14.5.txt
new file mode 100644 (file)
index 0000000..130645f
--- /dev/null
@@ -0,0 +1,16 @@
+Git v2.14.5 Release Notes
+=========================
+
+This release is to address the recently reported CVE-2018-17456.
+
+Fixes since v2.14.4
+-------------------
+
+ * Submodules' "URL"s come from the untrusted .gitmodules file, but
+   we blindly gave it to "git clone" to clone submodules when "git
+   clone --recurse-submodules" was used to clone a project that has
+   such a submodule.  The code has been hardened to reject such
+   malformed URLs (e.g. one that begins with a dash).
+
+Credit for finding and fixing this vulnerability goes to joernchen
+and Jeff King, respectively.
diff --git a/Documentation/RelNotes/2.15.3.txt b/Documentation/RelNotes/2.15.3.txt
new file mode 100644 (file)
index 0000000..fd2e6f8
--- /dev/null
@@ -0,0 +1,6 @@
+Git v2.15.3 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.14.5 to address
+the recently reported CVE-2018-17456; see the release notes for that
+version for details.
diff --git a/Documentation/RelNotes/2.16.5.txt b/Documentation/RelNotes/2.16.5.txt
new file mode 100644 (file)
index 0000000..cb8ee02
--- /dev/null
@@ -0,0 +1,6 @@
+Git v2.16.5 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.14.5 to address
+the recently reported CVE-2018-17456; see the release notes for that
+version for details.
diff --git a/Documentation/RelNotes/2.17.2.txt b/Documentation/RelNotes/2.17.2.txt
new file mode 100644 (file)
index 0000000..ef021be
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.17.2 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.14.5 to address
+the recently reported CVE-2018-17456; see the release notes for that
+version for details.
+
+In addition, this release also teaches "fsck" and the server side
+logic to reject pushes to repositories that attempt to create such a
+problematic ".gitmodules" file as tracked contents, to help hosting
+sites protect their customers by preventing malicious contents from
+spreading.
diff --git a/Documentation/RelNotes/2.18.1.txt b/Documentation/RelNotes/2.18.1.txt
new file mode 100644 (file)
index 0000000..2098cdd
--- /dev/null
@@ -0,0 +1,6 @@
+Git v2.18.1 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.14.5 and in
+v2.17.2 to address the recently reported CVE-2018-17456; see the
+release notes for those versions for details.
diff --git a/Documentation/RelNotes/2.19.1.txt b/Documentation/RelNotes/2.19.1.txt
new file mode 100644 (file)
index 0000000..da76726
--- /dev/null
@@ -0,0 +1,6 @@
+Git v2.19.1 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.14.5 and in
+v2.17.2 to address the recently reported CVE-2018-17456; see the
+release notes for those versions for details.
diff --git a/Documentation/RelNotes/2.20.0.txt b/Documentation/RelNotes/2.20.0.txt
new file mode 100644 (file)
index 0000000..2cc5fd7
--- /dev/null
@@ -0,0 +1,183 @@
+Git Release Notes
+=================
+
+Backward Compatibility Notes
+----------------------------
+
+ * "git branch -l <foo>" used to be a way to ask a reflog to be
+   created while creating a new branch, but that is no longer the
+   case.  It is a short-hand for "git branch --list <foo>" now.
+
+ * "git push" into refs/tags/* hierarchy is rejected without getting
+   forced, but "git fetch" (misguidedly) used the "fast forwarding"
+   rule used for the refs/heads/* hierarchy; this has been corrected,
+   which means some fetches of tags that did not fail with older
+   version of Git will fail without "--force" with this version.
+
+
+Updates since v2.19
+-------------------
+
+UI, Workflows & Features
+
+ * Running "git clone" against a project that contain two files with
+   pathnames that differ only in cases on a case insensitive
+   filesystem would result in one of the files lost because the
+   underlying filesystem is incapable of holding both at the same
+   time.  An attempt is made to detect such a case and warn.
+
+ * "git checkout -b newbranch [HEAD]" should not have to do as much as
+   checking out a commit different from HEAD.  An attempt is made to
+   optimize this special case.
+
+ * "git rev-list --stdin </dev/null" used to be an error; it now shows
+   no output without an error.  "git rev-list --stdin --default HEAD"
+   still falls back to the given default when nothing is given on the
+   standard input.
+
+ * Lift code from GitHub to restrict delta computation so that an
+   object that exists in one fork is not made into a delta against
+   another object that does not appear in the same forked repository.
+
+ * "git format-patch" learned new "--interdiff" and "--range-diff"
+   options to explain the difference between this version and the
+   previous attempt in the cover letter (or after the tree-dashes as
+   a comment).
+
+ * "git mailinfo" used in "git am" learned to make a best-effort
+   recovery of a patch corrupted by MUA that sends text/plain with
+   format=flawed option.
+   (merge 3aa4d81f88 rs/mailinfo-format-flowed later to maint).
+
+ * The rules used by "git push" and "git fetch" to determine if a ref
+   can or cannot be updated were inconsistent; specifically, fetching
+   to update existing tags were allowed even though tags are supposed
+   to be unmoving anchoring points.  "git fetch" was taught to forbid
+   updates to existing tags without the "--force" option.
+
+ * "git multi-pack-index" learned to detect corruption in the .midx
+   file it uses, and this feature has been integrated into "git fsck".
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * When there are too many packfiles in a repository (which is not
+   recommended), looking up an object in these would require
+   consulting many pack .idx files; a new mechanism to have a single
+   file that consolidates all of these .idx files is introduced.
+
+ * "git submodule update" is getting rewritten piece-by-piece into C.
+
+ * The code for computing history reachability has been shuffled,
+   obtained a bunch of new tests to cover them, and then being
+   improved.
+
+ * The unpack_trees() API used in checking out a branch and merging
+   walks one or more trees along with the index.  When the cache-tree
+   in the index tells us that we are walking a tree whose flattened
+   contents is known (i.e. matches a span in the index), as linearly
+   scanning a span in the index is much more efficient than having to
+   open tree objects recursively and listing their entries, the walk
+   can be optimized, which has been done.
+
+ * When creating a thin pack, which allows objects to be made into a
+   delta against another object that is not in the resulting pack but
+   is known to be present on the receiving end, the code learned to
+   take advantage of the reachability bitmap; this allows the server
+   to send a delta against a base beyond the "boundary" commit.
+
+ * spatch transformation to replace boolean uses of !hashcmp() to
+   newly introduced oideq() is added, and applied, to regain
+   performance lost due to support of multiple hash algorithms.
+
+ * Fix a bug in which the same path could be registered under multiple
+   worktree entries if the path was missing (for instance, was removed
+   manually).  Also, as a convenience, expand the number of cases in
+   which --force is applicable.
+
+ * Split Documentation/config.txt for easier maintenance.
+   (merge 6014363f0b nd/config-split later to maint).
+
+ * Test helper binaries clean-up.
+   (merge c9a1f4161f nd/test-tool later to maint).
+
+ * Various tests have been updated to make it easier to swap the
+   hash function used for object identification.
+   (merge ae0c89d41b bc/hash-independent-tests later to maint).
+
+ * Update fsck.skipList implementation and documentation.
+   (merge 371a655074 ab/fsck-skiplist later to maint).
+
+
+Fixes since v2.19
+-----------------
+
+ * "git interpret-trailers" and its underlying machinery had a buggy
+   code that attempted to ignore patch text after commit log message,
+   which triggered in various codepaths that will always get the log
+   message alone and never get such an input.
+   (merge 66e83d9b41 jk/trailer-fixes later to maint).
+
+ * Malformed or crafted data in packstream can make our code attempt
+   to read or write past the allocated buffer and abort, instead of
+   reporting an error, which has been fixed.
+
+ * "git rebase -i" did not clear the state files correctly when a run
+   of "squash/fixup" is aborted and then the user manually amended the
+   commit instead, which has been corrected.
+   (merge 10d2f35436 js/rebase-i-autosquash-fix later to maint).
+
+ * When fsmonitor is in use, after operation on submodules updates
+   .gitmodules, we lost track of the fact that we did so and relied on
+   stale fsmonitor data.
+   (merge 43f1180814 bp/mv-submodules-with-fsmonitor later to maint).
+
+ * Fix for a long-standing bug that leaves the index file corrupt when
+   it shrinks during a partial commit.
+   (merge 6c003d6ffb jk/reopen-tempfile-truncate later to maint).
+
+ * Further fix for O_APPEND emulation on Windows
+   (merge eeaf7ddac7 js/mingw-o-append later to maint).
+
+ * A corner case bugfix in "git rerere" code.
+   (merge ad2bf0d9b4 en/rerere-multi-stage-1-fix later to maint).
+
+ * "git add ':(attr:foo)'" is not supported and is supposed to be
+   rejected while the command line arguments are parsed, but we fail
+   to reject such a command line upfront.
+   (merge 84d938b732 nd/attr-pathspec-fix later to maint).
+
+ * Recent update broke the reachability algorithm when refs (e.g.
+   tags) that point at objects that are not commit were involved,
+   which has been fixed.
+
+ * "git rebase" etc. in Git 2.19 fails to abort when given an empty
+   commit log message as result of editing, which has been corrected.
+   (merge a3ec9eaf38 en/sequencer-empty-edit-result-aborts later to maint).
+
+ * The code to backfill objects in lazily cloned repository did not
+   work correctly, which has been corrected.
+   (merge e68302011c jt/lazy-object-fetch-fix later to maint).
+
+ * Update error messages given by "git remote" and make them consistent.
+   (merge 5025425dff ms/remote-error-message-update later to maint).
+
+ * "git update-ref" learned to make both "--no-deref" and "--stdin"
+   work at the same time.
+   (merge d345e9fbe7 en/update-ref-no-deref-stdin later to maint).
+
+ * Recently added "range-diff" had a corner-case bug to cause it
+   segfault, which has been corrected.
+   (merge e467a90c7a tg/range-diff-corner-case-fix later to maint).
+
+ * Code cleanup, docfix, build fix, etc.
+   (merge 96a7501aad ts/doc-build-manpage-xsl-quietly later to maint).
+   (merge b9b07efdb2 tg/conflict-marker-size later to maint).
+   (merge fa0aeea770 sg/doc-trace-appends later to maint).
+   (merge d64324cb60 tb/void-check-attr later to maint).
+   (merge c3b9bc94b9 en/double-semicolon-fix later to maint).
+   (merge 79336116f5 sg/t3701-tighten-trace later to maint).
+   (merge 801fa63a90 jk/dev-build-format-security later to maint).
+   (merge 0597dd62ba sb/string-list-remove-unused later to maint).
+   (merge db2d36fad8 bw/protocol-v2 later to maint).
+   (merge 456d7cd3a9 sg/split-index-test later to maint).
index ad0f4510c39c977bc95b41776eda4088d7a89885..f6f4c21a54579934ef8a413c4f77787911ed14c9 100644 (file)
@@ -225,7 +225,7 @@ boolean::
        false;; Boolean false literals are `no`, `off`, `false`,
                `0` and the empty string.
 +
-When converting value to the canonical form using `--bool` type
+When converting a value to its canonical form using the `--type=bool` type
 specifier, 'git config' will ensure that the output is "true" or
 "false" (spelled in lowercase).
 
@@ -832,12 +832,6 @@ core.packedRefsTimeout::
        all; -1 means to try indefinitely. Default is 1000 (i.e.,
        retry for 1 second).
 
-sequence.editor::
-       Text editor used by `git rebase -i` for editing the rebase instruction file.
-       The value is meant to be interpreted by the shell when it is used.
-       It can be overridden by the `GIT_SEQUENCE_EDITOR` environment variable.
-       When not configured the default commit message editor is used instead.
-
 core.pager::
        Text viewer for use by Git commands (e.g., 'less').  The value
        is meant to be interpreted by the shell.  The order of preference
@@ -1520,159 +1514,9 @@ fastimport.unpackLimit::
        operation complete faster, especially on slow filesystems.  If
        not set, the value of `transfer.unpackLimit` is used instead.
 
-fetch.recurseSubmodules::
-       This option can be either set to a boolean value or to 'on-demand'.
-       Setting it to a boolean changes the behavior of fetch and pull to
-       unconditionally recurse into submodules when set to true or to not
-       recurse at all when set to false. When set to 'on-demand' (the default
-       value), fetch and pull will only recurse into a populated submodule
-       when its superproject retrieves a commit that updates the submodule's
-       reference.
-
-fetch.fsckObjects::
-       If it is set to true, git-fetch-pack will check all fetched
-       objects. See `transfer.fsckObjects` for what's
-       checked. Defaults to false. If not set, the value of
-       `transfer.fsckObjects` is used instead.
-
-fetch.fsck.<msg-id>::
-       Acts like `fsck.<msg-id>`, but is used by
-       linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
-       the `fsck.<msg-id>` documentation for details.
-
-fetch.fsck.skipList::
-       Acts like `fsck.skipList`, but is used by
-       linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
-       the `fsck.skipList` documentation for details.
-
-fetch.unpackLimit::
-       If the number of objects fetched over the Git native
-       transfer is below this
-       limit, then the objects will be unpacked into loose object
-       files. However if the number of received objects equals or
-       exceeds this limit then the received pack will be stored as
-       a pack, after adding any missing delta bases.  Storing the
-       pack from a push can make the push operation complete faster,
-       especially on slow filesystems.  If not set, the value of
-       `transfer.unpackLimit` is used instead.
-
-fetch.prune::
-       If true, fetch will automatically behave as if the `--prune`
-       option was given on the command line.  See also `remote.<name>.prune`
-       and the PRUNING section of linkgit:git-fetch[1].
-
-fetch.pruneTags::
-       If true, fetch will automatically behave as if the
-       `refs/tags/*:refs/tags/*` refspec was provided when pruning,
-       if not set already. This allows for setting both this option
-       and `fetch.prune` to maintain a 1=1 mapping to upstream
-       refs. See also `remote.<name>.pruneTags` and the PRUNING
-       section of linkgit:git-fetch[1].
-
-fetch.output::
-       Control how ref update status is printed. Valid values are
-       `full` and `compact`. Default value is `full`. See section
-       OUTPUT in linkgit:git-fetch[1] for detail.
-
-fetch.negotiationAlgorithm::
-       Control how information about the commits in the local repository is
-       sent when negotiating the contents of the packfile to be sent by the
-       server. Set to "skipping" to use an algorithm that skips commits in an
-       effort to converge faster, but may result in a larger-than-necessary
-       packfile; The default is "default" which instructs Git to use the default algorithm
-       that never skips commits (unless the server has acknowledged it or one
-       of its descendants).
-       Unknown values will cause 'git fetch' to error out.
-+
-See also the `--negotiation-tip` option for linkgit:git-fetch[1].
-
-format.attach::
-       Enable multipart/mixed attachments as the default for
-       'format-patch'.  The value can also be a double quoted string
-       which will enable attachments as the default and set the
-       value as the boundary.  See the --attach option in
-       linkgit:git-format-patch[1].
-
-format.from::
-       Provides the default value for the `--from` option to format-patch.
-       Accepts a boolean value, or a name and email address.  If false,
-       format-patch defaults to `--no-from`, using commit authors directly in
-       the "From:" field of patch mails.  If true, format-patch defaults to
-       `--from`, using your committer identity in the "From:" field of patch
-       mails and including a "From:" field in the body of the patch mail if
-       different.  If set to a non-boolean value, format-patch uses that
-       value instead of your committer identity.  Defaults to false.
-
-format.numbered::
-       A boolean which can enable or disable sequence numbers in patch
-       subjects.  It defaults to "auto" which enables it only if there
-       is more than one patch.  It can be enabled or disabled for all
-       messages by setting it to "true" or "false".  See --numbered
-       option in linkgit:git-format-patch[1].
-
-format.headers::
-       Additional email headers to include in a patch to be submitted
-       by mail.  See linkgit:git-format-patch[1].
-
-format.to::
-format.cc::
-       Additional recipients to include in a patch to be submitted
-       by mail.  See the --to and --cc options in
-       linkgit:git-format-patch[1].
-
-format.subjectPrefix::
-       The default for format-patch is to output files with the '[PATCH]'
-       subject prefix. Use this variable to change that prefix.
-
-format.signature::
-       The default for format-patch is to output a signature containing
-       the Git version number. Use this variable to change that default.
-       Set this variable to the empty string ("") to suppress
-       signature generation.
-
-format.signatureFile::
-       Works just like format.signature except the contents of the
-       file specified by this variable will be used as the signature.
-
-format.suffix::
-       The default for format-patch is to output files with the suffix
-       `.patch`. Use this variable to change that suffix (make sure to
-       include the dot if you want it).
-
-format.pretty::
-       The default pretty format for log/show/whatchanged command,
-       See linkgit:git-log[1], linkgit:git-show[1],
-       linkgit:git-whatchanged[1].
-
-format.thread::
-       The default threading style for 'git format-patch'.  Can be
-       a boolean value, or `shallow` or `deep`.  `shallow` threading
-       makes every mail a reply to the head of the series,
-       where the head is chosen from the cover letter, the
-       `--in-reply-to`, and the first patch mail, in this order.
-       `deep` threading makes every mail a reply to the previous one.
-       A true boolean value is the same as `shallow`, and a false
-       value disables threading.
-
-format.signOff::
-       A boolean value which lets you enable the `-s/--signoff` option of
-       format-patch by default. *Note:* Adding the Signed-off-by: line to a
-       patch should be a conscious act and means that you certify you have
-       the rights to submit this work under the same open source license.
-       Please see the 'SubmittingPatches' document for further discussion.
-
-format.coverLetter::
-       A boolean that controls whether to generate a cover-letter when
-       format-patch is invoked, but in addition can be set to "auto", to
-       generate a cover-letter only when there's more than one patch.
-
-format.outputDirectory::
-       Set a custom directory to store the resulting files instead of the
-       current working directory.
-
-format.useAutoBase::
-       A boolean value which lets you enable the `--base=auto` option of
-       format-patch by default.
+include::fetch-config.txt[]
+
+include::format-config.txt[]
 
 filter.<driver>.clean::
        The command which is used to convert the content of a worktree
@@ -1723,12 +1567,16 @@ doing the same for `receive.fsck.<msg-id>` and `fetch.fsck.<msg-id>`
 will only cause git to warn.
 
 fsck.skipList::
-       The path to a sorted list of object names (i.e. one SHA-1 per
+       The path to a list of object names (i.e. one unabbreviated SHA-1 per
        line) that are known to be broken in a non-fatal way and should
-       be ignored. This feature is useful when an established project
-       should be accepted despite early commits containing errors that
-       can be safely ignored such as invalid committer email addresses.
-       Note: corrupt objects cannot be skipped with this setting.
+       be ignored. On versions of Git 2.20 and later comments ('#'), empty
+       lines, and any leading and trailing whitespace is ignored. Everything
+       but a SHA-1 per line will error out on older versions.
++
+This feature is useful when an established project should be accepted
+despite early commits containing errors that can be safely ignored
+such as invalid committer email addresses.  Note: corrupt objects
+cannot be skipped with this setting.
 +
 Like `fsck.<msg-id>` this variable has corresponding
 `receive.fsck.skipList` and `fetch.fsck.skipList` variants.
@@ -1738,6 +1586,15 @@ Unlike variables like `color.ui` and `core.editor` the
 fall back on the `fsck.skipList` configuration if they aren't set. To
 uniformly configure the same fsck settings in different circumstances
 all three of them they must all set to the same values.
++
+Older versions of Git (before 2.20) documented that the object names
+list should be sorted. This was never a requirement, the object names
+could appear in any order, but when reading the list we tracked whether
+the list was sorted for the purposes of an internal binary search
+implementation, which could save itself some work with an already sorted
+list. Unless you had a humongous list there was no reason to go out of
+your way to pre-sort the list. After Git version 2.20 a hash implementation
+is used instead, so there's now no reason to pre-sort the list.
 
 gc.aggressiveDepth::
        The depth parameter used in the delta compression
@@ -1786,7 +1643,8 @@ gc.writeCommitGraph::
        for details.
 
 gc.logExpiry::
-       If the file gc.log exists, then `git gc --auto` won't run
+       If the file gc.log exists, then `git gc --auto` will print
+       its content and exit with status zero instead of running
        unless that file is more than 'gc.logExpiry' old.  Default is
        "1.day".  See `gc.pruneExpire` for more ways to specify its
        value.
@@ -1847,73 +1705,7 @@ gc.rerereUnresolved::
        You can also use more human-readable "1.month.ago", etc.
        The default is 15 days.  See linkgit:git-rerere[1].
 
-gitcvs.commitMsgAnnotation::
-       Append this string to each commit message. Set to empty string
-       to disable this feature. Defaults to "via git-CVS emulator".
-
-gitcvs.enabled::
-       Whether the CVS server interface is enabled for this repository.
-       See linkgit:git-cvsserver[1].
-
-gitcvs.logFile::
-       Path to a log file where the CVS server interface well... logs
-       various stuff. See linkgit:git-cvsserver[1].
-
-gitcvs.usecrlfattr::
-       If true, the server will look up the end-of-line conversion
-       attributes for files to determine the `-k` modes to use. If
-       the attributes force Git to treat a file as text,
-       the `-k` mode will be left blank so CVS clients will
-       treat it as text. If they suppress text conversion, the file
-       will be set with '-kb' mode, which suppresses any newline munging
-       the client might otherwise do. If the attributes do not allow
-       the file type to be determined, then `gitcvs.allBinary` is
-       used. See linkgit:gitattributes[5].
-
-gitcvs.allBinary::
-       This is used if `gitcvs.usecrlfattr` does not resolve
-       the correct '-kb' mode to use. If true, all
-       unresolved files are sent to the client in
-       mode '-kb'. This causes the client to treat them
-       as binary files, which suppresses any newline munging it
-       otherwise might do. Alternatively, if it is set to "guess",
-       then the contents of the file are examined to decide if
-       it is binary, similar to `core.autocrlf`.
-
-gitcvs.dbName::
-       Database used by git-cvsserver to cache revision information
-       derived from the Git repository. The exact meaning depends on the
-       used database driver, for SQLite (which is the default driver) this
-       is a filename. Supports variable substitution (see
-       linkgit:git-cvsserver[1] for details). May not contain semicolons (`;`).
-       Default: '%Ggitcvs.%m.sqlite'
-
-gitcvs.dbDriver::
-       Used Perl DBI driver. You can specify any available driver
-       for this here, but it might not work. git-cvsserver is tested
-       with 'DBD::SQLite', reported to work with 'DBD::Pg', and
-       reported *not* to work with 'DBD::mysql'. Experimental feature.
-       May not contain double colons (`:`). Default: 'SQLite'.
-       See linkgit:git-cvsserver[1].
-
-gitcvs.dbUser, gitcvs.dbPass::
-       Database user and password. Only useful if setting `gitcvs.dbDriver`,
-       since SQLite has no concept of database users and/or passwords.
-       'gitcvs.dbUser' supports variable substitution (see
-       linkgit:git-cvsserver[1] for details).
-
-gitcvs.dbTableNamePrefix::
-       Database table name prefix.  Prepended to the names of any
-       database tables used, allowing a single database to be used
-       for several repositories.  Supports variable substitution (see
-       linkgit:git-cvsserver[1] for details).  Any non-alphabetic
-       characters will be replaced with underscores.
-
-All gitcvs variables except for `gitcvs.usecrlfattr` and
-`gitcvs.allBinary` can also be specified as
-'gitcvs.<access_method>.<varname>' (where 'access_method'
-is one of "ext" and "pserver") to make them apply only for the given
-access method.
+include::gitcvs-config.txt[]
 
 gitweb.category::
 gitweb.description::
@@ -1978,63 +1770,7 @@ gpg.<format>.program::
        be used as a legacy synonym for `gpg.openpgp.program`. The default
        value for `gpg.x509.program` is "gpgsm".
 
-gui.commitMsgWidth::
-       Defines how wide the commit message window is in the
-       linkgit:git-gui[1]. "75" is the default.
-
-gui.diffContext::
-       Specifies how many context lines should be used in calls to diff
-       made by the linkgit:git-gui[1]. The default is "5".
-
-gui.displayUntracked::
-       Determines if linkgit:git-gui[1] shows untracked files
-       in the file list. The default is "true".
-
-gui.encoding::
-       Specifies the default encoding to use for displaying of
-       file contents in linkgit:git-gui[1] and linkgit:gitk[1].
-       It can be overridden by setting the 'encoding' attribute
-       for relevant files (see linkgit:gitattributes[5]).
-       If this option is not set, the tools default to the
-       locale encoding.
-
-gui.matchTrackingBranch::
-       Determines if new branches created with linkgit:git-gui[1] should
-       default to tracking remote branches with matching names or
-       not. Default: "false".
-
-gui.newBranchTemplate::
-       Is used as suggested name when creating new branches using the
-       linkgit:git-gui[1].
-
-gui.pruneDuringFetch::
-       "true" if linkgit:git-gui[1] should prune remote-tracking branches when
-       performing a fetch. The default value is "false".
-
-gui.trustmtime::
-       Determines if linkgit:git-gui[1] should trust the file modification
-       timestamp or not. By default the timestamps are not trusted.
-
-gui.spellingDictionary::
-       Specifies the dictionary used for spell checking commit messages in
-       the linkgit:git-gui[1]. When set to "none" spell checking is turned
-       off.
-
-gui.fastCopyBlame::
-       If true, 'git gui blame' uses `-C` instead of `-C -C` for original
-       location detection. It makes blame significantly faster on huge
-       repositories at the expense of less thorough copy detection.
-
-gui.copyBlameThreshold::
-       Specifies the threshold to use in 'git gui blame' original location
-       detection, measured in alphanumeric characters. See the
-       linkgit:git-blame[1] manual for more information on copy detection.
-
-gui.blamehistoryctx::
-       Specifies the radius of history context in days to show in
-       linkgit:gitk[1] for the selected commit, when the `Show History
-       Context` menu item is invoked from 'git gui blame'. If this
-       variable is set to zero, the whole history is shown.
+include::gui-config.txt[]
 
 guitool.<name>.cmd::
        Specifies the shell command line to execute when the corresponding item
@@ -2860,282 +2596,13 @@ protocol.version::
 
 --
 
-pull.ff::
-       By default, Git does not create an extra merge commit when merging
-       a commit that is a descendant of the current commit. Instead, the
-       tip of the current branch is fast-forwarded. When set to `false`,
-       this variable tells Git to create an extra merge commit in such
-       a case (equivalent to giving the `--no-ff` option from the command
-       line). When set to `only`, only such fast-forward merges are
-       allowed (equivalent to giving the `--ff-only` option from the
-       command line). This setting overrides `merge.ff` when pulling.
-
-pull.rebase::
-       When true, rebase branches on top of the fetched branch, instead
-       of merging the default branch from the default remote when "git
-       pull" is run. See "branch.<name>.rebase" for setting this on a
-       per-branch basis.
-+
-When `merges`, pass the `--rebase-merges` option to 'git rebase'
-so that the local merge commits are included in the rebase (see
-linkgit:git-rebase[1] for details).
-+
-When preserve, also pass `--preserve-merges` along to 'git rebase'
-so that locally committed merge commits will not be flattened
-by running 'git pull'.
-+
-When the value is `interactive`, the rebase is run in interactive mode.
-+
-*NOTE*: this is a possibly dangerous operation; do *not* use
-it unless you understand the implications (see linkgit:git-rebase[1]
-for details).
-
-pull.octopus::
-       The default merge strategy to use when pulling multiple branches
-       at once.
-
-pull.twohead::
-       The default merge strategy to use when pulling a single branch.
-
-push.default::
-       Defines the action `git push` should take if no refspec is
-       explicitly given.  Different values are well-suited for
-       specific workflows; for instance, in a purely central workflow
-       (i.e. the fetch source is equal to the push destination),
-       `upstream` is probably what you want.  Possible values are:
-+
---
-
-* `nothing` - do not push anything (error out) unless a refspec is
-  explicitly given. This is primarily meant for people who want to
-  avoid mistakes by always being explicit.
-
-* `current` - push the current branch to update a branch with the same
-  name on the receiving end.  Works in both central and non-central
-  workflows.
+include::pull-config.txt[]
 
-* `upstream` - push the current branch back to the branch whose
-  changes are usually integrated into the current branch (which is
-  called `@{upstream}`).  This mode only makes sense if you are
-  pushing to the same repository you would normally pull from
-  (i.e. central workflow).
-
-* `tracking` - This is a deprecated synonym for `upstream`.
-
-* `simple` - in centralized workflow, work like `upstream` with an
-  added safety to refuse to push if the upstream branch's name is
-  different from the local one.
-+
-When pushing to a remote that is different from the remote you normally
-pull from, work as `current`.  This is the safest option and is suited
-for beginners.
-+
-This mode has become the default in Git 2.0.
-
-* `matching` - push all branches having the same name on both ends.
-  This makes the repository you are pushing to remember the set of
-  branches that will be pushed out (e.g. if you always push 'maint'
-  and 'master' there and no other branches, the repository you push
-  to will have these two branches, and your local 'maint' and
-  'master' will be pushed there).
-+
-To use this mode effectively, you have to make sure _all_ the
-branches you would push out are ready to be pushed out before
-running 'git push', as the whole point of this mode is to allow you
-to push all of the branches in one go.  If you usually finish work
-on only one branch and push out the result, while other branches are
-unfinished, this mode is not for you.  Also this mode is not
-suitable for pushing into a shared central repository, as other
-people may add new branches there, or update the tip of existing
-branches outside your control.
-+
-This used to be the default, but not since Git 2.0 (`simple` is the
-new default).
-
---
-
-push.followTags::
-       If set to true enable `--follow-tags` option by default.  You
-       may override this configuration at time of push by specifying
-       `--no-follow-tags`.
-
-push.gpgSign::
-       May be set to a boolean value, or the string 'if-asked'. A true
-       value causes all pushes to be GPG signed, as if `--signed` is
-       passed to linkgit:git-push[1]. The string 'if-asked' causes
-       pushes to be signed if the server supports it, as if
-       `--signed=if-asked` is passed to 'git push'. A false value may
-       override a value from a lower-priority config file. An explicit
-       command-line flag always overrides this config option.
-
-push.pushOption::
-       When no `--push-option=<option>` argument is given from the
-       command line, `git push` behaves as if each <value> of
-       this variable is given as `--push-option=<value>`.
-+
-This is a multi-valued variable, and an empty value can be used in a
-higher priority configuration file (e.g. `.git/config` in a
-repository) to clear the values inherited from a lower priority
-configuration files (e.g. `$HOME/.gitconfig`).
-+
---
-
-Example:
-
-/etc/gitconfig
-  push.pushoption = a
-  push.pushoption = b
-
-~/.gitconfig
-  push.pushoption = c
-
-repo/.git/config
-  push.pushoption =
-  push.pushoption = b
-
-This will result in only b (a and c are cleared).
-
---
-
-push.recurseSubmodules::
-       Make sure all submodule commits used by the revisions to be pushed
-       are available on a remote-tracking branch. If the value is 'check'
-       then Git will verify that all submodule commits that changed in the
-       revisions to be pushed are available on at least one remote of the
-       submodule. If any commits are missing, the push will be aborted and
-       exit with non-zero status. If the value is 'on-demand' then all
-       submodules that changed in the revisions to be pushed will be
-       pushed. If on-demand was not able to push all necessary revisions
-       it will also be aborted and exit with non-zero status. If the value
-       is 'no' then default behavior of ignoring submodules when pushing
-       is retained. You may override this configuration at time of push by
-       specifying '--recurse-submodules=check|on-demand|no'.
+include::push-config.txt[]
 
 include::rebase-config.txt[]
 
-receive.advertiseAtomic::
-       By default, git-receive-pack will advertise the atomic push
-       capability to its clients. If you don't want to advertise this
-       capability, set this variable to false.
-
-receive.advertisePushOptions::
-       When set to true, git-receive-pack will advertise the push options
-       capability to its clients. False by default.
-
-receive.autogc::
-       By default, git-receive-pack will run "git-gc --auto" after
-       receiving data from git-push and updating refs.  You can stop
-       it by setting this variable to false.
-
-receive.certNonceSeed::
-       By setting this variable to a string, `git receive-pack`
-       will accept a `git push --signed` and verifies it by using
-       a "nonce" protected by HMAC using this string as a secret
-       key.
-
-receive.certNonceSlop::
-       When a `git push --signed` sent a push certificate with a
-       "nonce" that was issued by a receive-pack serving the same
-       repository within this many seconds, export the "nonce"
-       found in the certificate to `GIT_PUSH_CERT_NONCE` to the
-       hooks (instead of what the receive-pack asked the sending
-       side to include).  This may allow writing checks in
-       `pre-receive` and `post-receive` a bit easier.  Instead of
-       checking `GIT_PUSH_CERT_NONCE_SLOP` environment variable
-       that records by how many seconds the nonce is stale to
-       decide if they want to accept the certificate, they only
-       can check `GIT_PUSH_CERT_NONCE_STATUS` is `OK`.
-
-receive.fsckObjects::
-       If it is set to true, git-receive-pack will check all received
-       objects. See `transfer.fsckObjects` for what's checked.
-       Defaults to false. If not set, the value of
-       `transfer.fsckObjects` is used instead.
-
-receive.fsck.<msg-id>::
-       Acts like `fsck.<msg-id>`, but is used by
-       linkgit:git-receive-pack[1] instead of
-       linkgit:git-fsck[1]. See the `fsck.<msg-id>` documentation for
-       details.
-
-receive.fsck.skipList::
-       Acts like `fsck.skipList`, but is used by
-       linkgit:git-receive-pack[1] instead of
-       linkgit:git-fsck[1]. See the `fsck.skipList` documentation for
-       details.
-
-receive.keepAlive::
-       After receiving the pack from the client, `receive-pack` may
-       produce no output (if `--quiet` was specified) while processing
-       the pack, causing some networks to drop the TCP connection.
-       With this option set, if `receive-pack` does not transmit
-       any data in this phase for `receive.keepAlive` seconds, it will
-       send a short keepalive packet.  The default is 5 seconds; set
-       to 0 to disable keepalives entirely.
-
-receive.unpackLimit::
-       If the number of objects received in a push is below this
-       limit then the objects will be unpacked into loose object
-       files. However if the number of received objects equals or
-       exceeds this limit then the received pack will be stored as
-       a pack, after adding any missing delta bases.  Storing the
-       pack from a push can make the push operation complete faster,
-       especially on slow filesystems.  If not set, the value of
-       `transfer.unpackLimit` is used instead.
-
-receive.maxInputSize::
-       If the size of the incoming pack stream is larger than this
-       limit, then git-receive-pack will error out, instead of
-       accepting the pack file. If not set or set to 0, then the size
-       is unlimited.
-
-receive.denyDeletes::
-       If set to true, git-receive-pack will deny a ref update that deletes
-       the ref. Use this to prevent such a ref deletion via a push.
-
-receive.denyDeleteCurrent::
-       If set to true, git-receive-pack will deny a ref update that
-       deletes the currently checked out branch of a non-bare repository.
-
-receive.denyCurrentBranch::
-       If set to true or "refuse", git-receive-pack will deny a ref update
-       to the currently checked out branch of a non-bare repository.
-       Such a push is potentially dangerous because it brings the HEAD
-       out of sync with the index and working tree. If set to "warn",
-       print a warning of such a push to stderr, but allow the push to
-       proceed. If set to false or "ignore", allow such pushes with no
-       message. Defaults to "refuse".
-+
-Another option is "updateInstead" which will update the working
-tree if pushing into the current branch.  This option is
-intended for synchronizing working directories when one side is not easily
-accessible via interactive ssh (e.g. a live web site, hence the requirement
-that the working directory be clean). This mode also comes in handy when
-developing inside a VM to test and fix code on different Operating Systems.
-+
-By default, "updateInstead" will refuse the push if the working tree or
-the index have any difference from the HEAD, but the `push-to-checkout`
-hook can be used to customize this.  See linkgit:githooks[5].
-
-receive.denyNonFastForwards::
-       If set to true, git-receive-pack will deny a ref update which is
-       not a fast-forward. Use this to prevent such an update via a push,
-       even if that push is forced. This configuration variable is
-       set when initializing a shared repository.
-
-receive.hideRefs::
-       This variable is the same as `transfer.hideRefs`, but applies
-       only to `receive-pack` (and so affects pushes, but not fetches).
-       An attempt to update or delete a hidden ref by `git push` is
-       rejected.
-
-receive.updateServerInfo::
-       If set to true, git-receive-pack will run git-update-server-info
-       after receiving data from git-push and updating refs.
-
-receive.shallowUpdate::
-       If set to true, .git/shallow can be updated when new refs
-       require new shallow roots. Otherwise those refs are rejected.
+include::receive-config.txt[]
 
 remote.pushDefault::
        The remote to push to by default.  Overrides
@@ -3261,71 +2728,15 @@ rerere.enabled::
        `$GIT_DIR`, e.g. if "rerere" was previously used in the
        repository.
 
-sendemail.identity::
-       A configuration identity. When given, causes values in the
-       'sendemail.<identity>' subsection to take precedence over
-       values in the 'sendemail' section. The default identity is
-       the value of `sendemail.identity`.
-
-sendemail.smtpEncryption::
-       See linkgit:git-send-email[1] for description.  Note that this
-       setting is not subject to the 'identity' mechanism.
-
-sendemail.smtpssl (deprecated)::
-       Deprecated alias for 'sendemail.smtpEncryption = ssl'.
-
-sendemail.smtpsslcertpath::
-       Path to ca-certificates (either a directory or a single file).
-       Set it to an empty string to disable certificate verification.
-
-sendemail.<identity>.*::
-       Identity-specific versions of the 'sendemail.*' parameters
-       found below, taking precedence over those when this
-       identity is selected, through either the command-line or
-       `sendemail.identity`.
-
-sendemail.aliasesFile::
-sendemail.aliasFileType::
-sendemail.annotate::
-sendemail.bcc::
-sendemail.cc::
-sendemail.ccCmd::
-sendemail.chainReplyTo::
-sendemail.confirm::
-sendemail.envelopeSender::
-sendemail.from::
-sendemail.multiEdit::
-sendemail.signedoffbycc::
-sendemail.smtpPass::
-sendemail.suppresscc::
-sendemail.suppressFrom::
-sendemail.to::
-sendemail.tocmd::
-sendemail.smtpDomain::
-sendemail.smtpServer::
-sendemail.smtpServerPort::
-sendemail.smtpServerOption::
-sendemail.smtpUser::
-sendemail.thread::
-sendemail.transferEncoding::
-sendemail.validate::
-sendemail.xmailer::
-       See linkgit:git-send-email[1] for description.
-
-sendemail.signedoffcc (deprecated)::
-       Deprecated alias for `sendemail.signedoffbycc`.
-
-sendemail.smtpBatchSize::
-       Number of messages to be sent per connection, after that a relogin
-       will happen.  If the value is 0 or undefined, send all messages in
-       one connection.
-       See also the `--batch-size` option of linkgit:git-send-email[1].
-
-sendemail.smtpReloginDelay::
-       Seconds wait before reconnecting to smtp server.
-       See also the `--relogin-delay` option of linkgit:git-send-email[1].
-
-showbranch.default::
+include::sendemail-config.txt[]
+
+sequence.editor::
+       Text editor used by `git rebase -i` for editing the rebase instruction file.
+       The value is meant to be interpreted by the shell when it is used.
+       It can be overridden by the `GIT_SEQUENCE_EDITOR` environment variable.
+       When not configured the default commit message editor is used instead.
+
+showBranch.default::
        The default set of branches for linkgit:git-show-branch[1].
        See linkgit:git-show-branch[1].
 
@@ -3437,88 +2848,7 @@ stash.showStat::
        option will show diffstat of the stash entry.  Defaults to true.
        See description of 'show' command in linkgit:git-stash[1].
 
-submodule.<name>.url::
-       The URL for a submodule. This variable is copied from the .gitmodules
-       file to the git config via 'git submodule init'. The user can change
-       the configured URL before obtaining the submodule via 'git submodule
-       update'. If neither submodule.<name>.active or submodule.active are
-       set, the presence of this variable is used as a fallback to indicate
-       whether the submodule is of interest to git commands.
-       See linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
-
-submodule.<name>.update::
-       The method by which a submodule is updated by 'git submodule update',
-       which is the only affected command, others such as
-       'git checkout --recurse-submodules' are unaffected. It exists for
-       historical reasons, when 'git submodule' was the only command to
-       interact with submodules; settings like `submodule.active`
-       and `pull.rebase` are more specific. It is populated by
-       `git submodule init` from the linkgit:gitmodules[5] file.
-       See description of 'update' command in linkgit:git-submodule[1].
-
-submodule.<name>.branch::
-       The remote branch name for a submodule, used by `git submodule
-       update --remote`.  Set this option to override the value found in
-       the `.gitmodules` file.  See linkgit:git-submodule[1] and
-       linkgit:gitmodules[5] for details.
-
-submodule.<name>.fetchRecurseSubmodules::
-       This option can be used to control recursive fetching of this
-       submodule. It can be overridden by using the --[no-]recurse-submodules
-       command-line option to "git fetch" and "git pull".
-       This setting will override that from in the linkgit:gitmodules[5]
-       file.
-
-submodule.<name>.ignore::
-       Defines under what circumstances "git status" and the diff family show
-       a submodule as modified. When set to "all", it will never be considered
-       modified (but it will nonetheless show up in the output of status and
-       commit when it has been staged), "dirty" will ignore all changes
-       to the submodules work tree and
-       takes only differences between the HEAD of the submodule and the commit
-       recorded in the superproject into account. "untracked" will additionally
-       let submodules with modified tracked files in their work tree show up.
-       Using "none" (the default when this option is not set) also shows
-       submodules that have untracked files in their work tree as changed.
-       This setting overrides any setting made in .gitmodules for this submodule,
-       both settings can be overridden on the command line by using the
-       "--ignore-submodules" option. The 'git submodule' commands are not
-       affected by this setting.
-
-submodule.<name>.active::
-       Boolean value indicating if the submodule is of interest to git
-       commands.  This config option takes precedence over the
-       submodule.active config option. See linkgit:gitsubmodules[7] for
-       details.
-
-submodule.active::
-       A repeated field which contains a pathspec used to match against a
-       submodule's path to determine if the submodule is of interest to git
-       commands. See linkgit:gitsubmodules[7] for details.
-
-submodule.recurse::
-       Specifies if commands recurse into submodules by default. This
-       applies to all commands that have a `--recurse-submodules` option,
-       except `clone`.
-       Defaults to false.
-
-submodule.fetchJobs::
-       Specifies how many submodules are fetched/cloned at the same time.
-       A positive integer allows up to that number of submodules fetched
-       in parallel. A value of 0 will give some reasonable default.
-       If unset, it defaults to 1.
-
-submodule.alternateLocation::
-       Specifies how the submodules obtain alternates when submodules are
-       cloned. Possible values are `no`, `superproject`.
-       By default `no` is assumed, which doesn't add references. When the
-       value is set to `superproject` the submodule to be cloned computes
-       its alternates location relative to the superprojects alternate.
-
-submodule.alternateErrorStrategy::
-       Specifies how to treat errors with the alternates for a submodule
-       as computed via `submodule.alternateLocation`. Possible values are
-       `ignore`, `info`, `die`. Default is `die`.
+include::submodule-config.txt[]
 
 tag.forceSignAnnotated::
        A boolean to specify whether annotated tags created should be GPG signed.
@@ -3666,15 +2996,15 @@ uploadpack.packObjectsHook::
        was run. I.e., `upload-pack` will feed input intended for
        `pack-objects` to the hook, and expects a completed packfile on
        stdout.
-
-uploadpack.allowFilter::
-       If this option is set, `upload-pack` will support partial
-       clone and partial fetch object filtering.
 +
 Note that this configuration variable is ignored if it is seen in the
 repository-level config (this is a safety measure against fetching from
 untrusted repositories).
 
+uploadpack.allowFilter::
+       If this option is set, `upload-pack` will support partial
+       clone and partial fetch object filtering.
+
 uploadpack.allowRefInWant::
        If this option is set, `upload-pack` will support the `ref-in-want`
        feature of the protocol version 2 `fetch` command.  This feature
diff --git a/Documentation/fetch-config.txt b/Documentation/fetch-config.txt
new file mode 100644 (file)
index 0000000..cbfad6c
--- /dev/null
@@ -0,0 +1,65 @@
+fetch.recurseSubmodules::
+       This option can be either set to a boolean value or to 'on-demand'.
+       Setting it to a boolean changes the behavior of fetch and pull to
+       unconditionally recurse into submodules when set to true or to not
+       recurse at all when set to false. When set to 'on-demand' (the default
+       value), fetch and pull will only recurse into a populated submodule
+       when its superproject retrieves a commit that updates the submodule's
+       reference.
+
+fetch.fsckObjects::
+       If it is set to true, git-fetch-pack will check all fetched
+       objects. See `transfer.fsckObjects` for what's
+       checked. Defaults to false. If not set, the value of
+       `transfer.fsckObjects` is used instead.
+
+fetch.fsck.<msg-id>::
+       Acts like `fsck.<msg-id>`, but is used by
+       linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
+       the `fsck.<msg-id>` documentation for details.
+
+fetch.fsck.skipList::
+       Acts like `fsck.skipList`, but is used by
+       linkgit:git-fetch-pack[1] instead of linkgit:git-fsck[1]. See
+       the `fsck.skipList` documentation for details.
+
+fetch.unpackLimit::
+       If the number of objects fetched over the Git native
+       transfer is below this
+       limit, then the objects will be unpacked into loose object
+       files. However if the number of received objects equals or
+       exceeds this limit then the received pack will be stored as
+       a pack, after adding any missing delta bases.  Storing the
+       pack from a push can make the push operation complete faster,
+       especially on slow filesystems.  If not set, the value of
+       `transfer.unpackLimit` is used instead.
+
+fetch.prune::
+       If true, fetch will automatically behave as if the `--prune`
+       option was given on the command line.  See also `remote.<name>.prune`
+       and the PRUNING section of linkgit:git-fetch[1].
+
+fetch.pruneTags::
+       If true, fetch will automatically behave as if the
+       `refs/tags/*:refs/tags/*` refspec was provided when pruning,
+       if not set already. This allows for setting both this option
+       and `fetch.prune` to maintain a 1=1 mapping to upstream
+       refs. See also `remote.<name>.pruneTags` and the PRUNING
+       section of linkgit:git-fetch[1].
+
+fetch.output::
+       Control how ref update status is printed. Valid values are
+       `full` and `compact`. Default value is `full`. See section
+       OUTPUT in linkgit:git-fetch[1] for detail.
+
+fetch.negotiationAlgorithm::
+       Control how information about the commits in the local repository is
+       sent when negotiating the contents of the packfile to be sent by the
+       server. Set to "skipping" to use an algorithm that skips commits in an
+       effort to converge faster, but may result in a larger-than-necessary
+       packfile; The default is "default" which instructs Git to use the default algorithm
+       that never skips commits (unless the server has acknowledged it or one
+       of its descendants).
+       Unknown values will cause 'git fetch' to error out.
++
+See also the `--negotiation-tip` option for linkgit:git-fetch[1].
diff --git a/Documentation/format-config.txt b/Documentation/format-config.txt
new file mode 100644 (file)
index 0000000..dc77941
--- /dev/null
@@ -0,0 +1,87 @@
+format.attach::
+       Enable multipart/mixed attachments as the default for
+       'format-patch'.  The value can also be a double quoted string
+       which will enable attachments as the default and set the
+       value as the boundary.  See the --attach option in
+       linkgit:git-format-patch[1].
+
+format.from::
+       Provides the default value for the `--from` option to format-patch.
+       Accepts a boolean value, or a name and email address.  If false,
+       format-patch defaults to `--no-from`, using commit authors directly in
+       the "From:" field of patch mails.  If true, format-patch defaults to
+       `--from`, using your committer identity in the "From:" field of patch
+       mails and including a "From:" field in the body of the patch mail if
+       different.  If set to a non-boolean value, format-patch uses that
+       value instead of your committer identity.  Defaults to false.
+
+format.numbered::
+       A boolean which can enable or disable sequence numbers in patch
+       subjects.  It defaults to "auto" which enables it only if there
+       is more than one patch.  It can be enabled or disabled for all
+       messages by setting it to "true" or "false".  See --numbered
+       option in linkgit:git-format-patch[1].
+
+format.headers::
+       Additional email headers to include in a patch to be submitted
+       by mail.  See linkgit:git-format-patch[1].
+
+format.to::
+format.cc::
+       Additional recipients to include in a patch to be submitted
+       by mail.  See the --to and --cc options in
+       linkgit:git-format-patch[1].
+
+format.subjectPrefix::
+       The default for format-patch is to output files with the '[PATCH]'
+       subject prefix. Use this variable to change that prefix.
+
+format.signature::
+       The default for format-patch is to output a signature containing
+       the Git version number. Use this variable to change that default.
+       Set this variable to the empty string ("") to suppress
+       signature generation.
+
+format.signatureFile::
+       Works just like format.signature except the contents of the
+       file specified by this variable will be used as the signature.
+
+format.suffix::
+       The default for format-patch is to output files with the suffix
+       `.patch`. Use this variable to change that suffix (make sure to
+       include the dot if you want it).
+
+format.pretty::
+       The default pretty format for log/show/whatchanged command,
+       See linkgit:git-log[1], linkgit:git-show[1],
+       linkgit:git-whatchanged[1].
+
+format.thread::
+       The default threading style for 'git format-patch'.  Can be
+       a boolean value, or `shallow` or `deep`.  `shallow` threading
+       makes every mail a reply to the head of the series,
+       where the head is chosen from the cover letter, the
+       `--in-reply-to`, and the first patch mail, in this order.
+       `deep` threading makes every mail a reply to the previous one.
+       A true boolean value is the same as `shallow`, and a false
+       value disables threading.
+
+format.signOff::
+       A boolean value which lets you enable the `-s/--signoff` option of
+       format-patch by default. *Note:* Adding the Signed-off-by: line to a
+       patch should be a conscious act and means that you certify you have
+       the rights to submit this work under the same open source license.
+       Please see the 'SubmittingPatches' document for further discussion.
+
+format.coverLetter::
+       A boolean that controls whether to generate a cover-letter when
+       format-patch is invoked, but in addition can be set to "auto", to
+       generate a cover-letter only when there's more than one patch.
+
+format.outputDirectory::
+       Set a custom directory to store the resulting files instead of the
+       current working directory.
+
+format.useAutoBase::
+       A boolean value which lets you enable the `--base=auto` option of
+       format-patch by default.
index ea7065336920756d03329475472016391cec83dc..a595a0ffeee56d8426907c9297078fac6977e5a3 100644 (file)
@@ -3,7 +3,7 @@ git-archimport(1)
 
 NAME
 ----
-git-archimport - Import an Arch repository into Git
+git-archimport - Import a GNU Arch repository into Git
 
 
 SYNOPSIS
@@ -14,7 +14,8 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Imports a project from one or more Arch repositories. It will follow branches
+Imports a project from one or more GNU Arch repositories.
+It will follow branches
 and repositories within the namespaces defined by the <archive/branch>
 parameters supplied. If it cannot find the remote branch a merge comes from
 it will just import it as a regular commit. If it can find it, it will mark it
index 03d18465d4f2cc8327362917d1c808e523333d11..763afabb6dc7487009ab49f5bb258f9181f0da78 100644 (file)
@@ -13,7 +13,10 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This command formats its input into multiple columns.
+This command formats the lines of its standard input into a table with
+multiple columns. Each input line occupies one cell of the table. It
+is used internally by other git commands to format output into
+columns.
 
 OPTIONS
 -------
@@ -23,7 +26,7 @@ OPTIONS
 
 --mode=<mode>::
        Specify layout mode. See configuration variable column.ui for option
-       syntax.
+       syntax in linkgit:git-config[1].
 
 --raw-mode=<n>::
        Same as --mode but take mode encoded as a number. This is mainly used
@@ -43,6 +46,34 @@ OPTIONS
 --padding=<N>::
        The number of spaces between columns. One space by default.
 
+EXAMPLES
+------
+
+Format data by columns:
+------------
+$ seq 1 24 | git column --mode=column --padding=5
+1      4      7      10     13     16     19     22
+2      5      8      11     14     17     20     23
+3      6      9      12     15     18     21     24
+------------
+
+Format data by rows:
+------------
+$ seq 1 21 | git column --mode=row --padding=5
+1      2      3      4      5      6      7
+8      9      10     11     12     13     14
+15     16     17     18     19     20     21
+------------
+
+List some tags in a table with unequal column widths:
+------------
+$ git tag --list 'v2.4.*' --column=row,dense
+v2.4.0  v2.4.0-rc0  v2.4.0-rc1  v2.4.0-rc2  v2.4.0-rc3
+v2.4.1  v2.4.10     v2.4.11     v2.4.12     v2.4.2
+v2.4.3  v2.4.4      v2.4.5      v2.4.6      v2.4.7
+v2.4.8  v2.4.9
+------------
+
 GIT
 ---
 Part of the linkgit:git[1] suite
index dececb79d772447e5ca0d3ea8253f20ea288ddf6..624470e198202a47e91e89274bb32b2bc3d441d6 100644 (file)
@@ -3,7 +3,7 @@ git-commit-graph(1)
 
 NAME
 ----
-git-commit-graph - Write and verify Git commit graph files
+git-commit-graph - Write and verify Git commit-graph files
 
 
 SYNOPSIS
@@ -17,24 +17,24 @@ SYNOPSIS
 DESCRIPTION
 -----------
 
-Manage the serialized commit graph file.
+Manage the serialized commit-graph file.
 
 
 OPTIONS
 -------
 --object-dir::
-       Use given directory for the location of packfiles and commit graph
+       Use given directory for the location of packfiles and commit-graph
        file. This parameter exists to specify the location of an alternate
-       that only has the objects directory, not a full .git directory. The
-       commit graph file is expected to be at <dir>/info/commit-graph and
-       the packfiles are expected to be in <dir>/pack.
+       that only has the objects directory, not a full `.git` directory. The
+       commit-graph file is expected to be at `<dir>/info/commit-graph` and
+       the packfiles are expected to be in `<dir>/pack`.
 
 
 COMMANDS
 --------
 'write'::
 
-Write a commit graph file based on the commits found in packfiles.
+Write a commit-graph file based on the commits found in packfiles.
 +
 With the `--stdin-packs` option, generate the new commit graph by
 walking objects only in the specified pack-indexes. (Cannot be combined
@@ -54,8 +54,8 @@ existing commit-graph file.
 
 'read'::
 
-Read a graph file given by the commit-graph file and output basic
-details about the graph file. Used for debugging purposes.
+Read the commit-graph file and output basic details about it.
+Used for debugging purposes.
 
 'verify'::
 
@@ -66,27 +66,28 @@ database. Used to check for corrupted data.
 EXAMPLES
 --------
 
-* Write a commit graph file for the packed commits in your local .git folder.
+* Write a commit-graph file for the packed commits in your local `.git`
+  directory.
 +
 ------------------------------------------------
 $ git commit-graph write
 ------------------------------------------------
 
-* Write a graph file, extending the current graph file using commits
-* in <pack-index>.
+* Write a commit-graph file, extending the current commit-graph file
+  using commits in `<pack-index>`.
 +
 ------------------------------------------------
 $ echo <pack-index> | git commit-graph write --stdin-packs
 ------------------------------------------------
 
-* Write a graph file containing all reachable commits.
+* Write a commit-graph file containing all reachable commits.
 +
 ------------------------------------------------
 $ git show-ref -s | git commit-graph write --stdin-commits
 ------------------------------------------------
 
-* Write a graph file containing all commits in the current
-* commit-graph file along with those reachable from HEAD.
+* Write a commit-graph file containing all commits in the current
+  commit-graph file along with those reachable from `HEAD`.
 +
 ------------------------------------------------
 $ git rev-parse HEAD | git commit-graph write --stdin-commits --append
index 8e240435bee8fb9599fc979a5dab48742d7e1e1d..5e87d82933e77aec1e9f8a715b264d72521e8bc9 100644 (file)
@@ -188,8 +188,8 @@ Valid `<type>`'s include:
 --bool-or-int::
 --path::
 --expiry-date::
-  Historical options for selecting a type specifier. Prefer instead `--type`,
-  (see: above).
+  Historical options for selecting a type specifier. Prefer instead `--type`
+  (see above).
 
 --no-type::
   Un-sets the previously set type specifier (if one was previously set). This
@@ -442,9 +442,9 @@ For URLs in `https://weak.example.com`, `http.sslVerify` is set to
 false, while it is set to `true` for all others:
 
 ------------
-% git config --bool --get-urlmatch http.sslverify https://good.example.com
+% git config --type=bool --get-urlmatch http.sslverify https://good.example.com
 true
-% git config --bool --get-urlmatch http.sslverify https://weak.example.com
+% git config --type=bool --get-urlmatch http.sslverify https://weak.example.com
 false
 % git config --get-urlmatch http https://weak.example.com
 http.cookieFile /tmp/cookie.txt
index e027fb8c4b8269bb2266ca98f87c9c18ca45fad3..ccdc5f83d6dcd297f1e4922b27b904f00d6f4721 100644 (file)
@@ -18,7 +18,9 @@ The command finds the most recent tag that is reachable from a
 commit.  If the tag points to the commit, then only the tag is
 shown.  Otherwise, it suffixes the tag name with the number of
 additional commits on top of the tagged object and the
-abbreviated object name of the most recent commit.
+abbreviated object name of the most recent commit. The result
+is a "human-readable" object name which can also be used to
+identify the commit to other git commands.
 
 By default (without --all or --tags) `git describe` only shows
 annotated tags.  For more information about creating annotated tags
index 1f97e79912f45df81956285337c1be89bccfb390..f7778a2c85c1aaa1295dbf3b9e4f74f3683def23 100644 (file)
@@ -27,6 +27,10 @@ write::
        When given as the verb, write a new MIDX file to
        `<dir>/packs/multi-pack-index`.
 
+verify::
+       When given as the verb, verify the contents of the MIDX file
+       at `<dir>/packs/multi-pack-index`.
+
 
 EXAMPLES
 --------
@@ -43,6 +47,12 @@ $ git multi-pack-index write
 $ git multi-pack-index --object-dir <alt> write
 -----------------------------------------------
 
+* Verify the MIDX file for the packfiles in the current .git folder.
++
+-----------------------------------------------
+$ git multi-pack-index verify
+-----------------------------------------------
+
 
 SEE ALSO
 --------
index 74a9d7edb45815a55fcc1e5c13cd78141b1d4190..2ac9b1c7fe00fea0772d5269121ffdf424435b96 100644 (file)
@@ -76,7 +76,7 @@ Note that omitting the `=` in `git -c foo.bar ...` is allowed and sets
 `foo.bar` to the boolean true value (just like `[foo]bar` would in a
 config file). Including the equals but with an empty value (like `git -c
 foo.bar= ...`) sets `foo.bar` to the empty string which `git config
---bool` will convert to `false`.
+--type=bool` will convert to `false`.
 
 --exec-path[=<path>]::
        Path to wherever your core Git programs are installed.
@@ -858,7 +858,9 @@ Reporting Bugs
 
 Report bugs to the Git mailing list <git@vger.kernel.org> where the
 development and maintenance is primarily done.  You do not have to be
-subscribed to the list to send a message there.
+subscribed to the list to send a message there.  See the list archive
+at https://public-inbox.org/git for previous bug reports and other
+discussions.
 
 Issues which are security relevant should be disclosed privately to
 the Git Security mailing list <git-security@googlegroups.com>.
index f970196bc1c52f489538ab515e1640ac435fead3..adc759612de99a2b86c89e353ff724e5eb25472e 100644 (file)
@@ -133,6 +133,12 @@ compares hostnames exactly, without considering whether two hosts are part of
 the same domain. Likewise, a config entry for `http://example.com` would not
 match: Git compares the protocols exactly.
 
+If the "pattern" URL does include a path component, then this too must match
+exactly: the context `https://example.com/bar/baz.git` will match a config
+entry for `https://example.com/bar/baz.git` (in addition to matching the config
+entry for `https://example.com`) but will not match a config entry for
+`https://example.com/bar`.
+
 
 CONFIGURATION OPTIONS
 ---------------------
diff --git a/Documentation/gitcvs-config.txt b/Documentation/gitcvs-config.txt
new file mode 100644 (file)
index 0000000..02da427
--- /dev/null
@@ -0,0 +1,67 @@
+gitcvs.commitMsgAnnotation::
+       Append this string to each commit message. Set to empty string
+       to disable this feature. Defaults to "via git-CVS emulator".
+
+gitcvs.enabled::
+       Whether the CVS server interface is enabled for this repository.
+       See linkgit:git-cvsserver[1].
+
+gitcvs.logFile::
+       Path to a log file where the CVS server interface well... logs
+       various stuff. See linkgit:git-cvsserver[1].
+
+gitcvs.usecrlfattr::
+       If true, the server will look up the end-of-line conversion
+       attributes for files to determine the `-k` modes to use. If
+       the attributes force Git to treat a file as text,
+       the `-k` mode will be left blank so CVS clients will
+       treat it as text. If they suppress text conversion, the file
+       will be set with '-kb' mode, which suppresses any newline munging
+       the client might otherwise do. If the attributes do not allow
+       the file type to be determined, then `gitcvs.allBinary` is
+       used. See linkgit:gitattributes[5].
+
+gitcvs.allBinary::
+       This is used if `gitcvs.usecrlfattr` does not resolve
+       the correct '-kb' mode to use. If true, all
+       unresolved files are sent to the client in
+       mode '-kb'. This causes the client to treat them
+       as binary files, which suppresses any newline munging it
+       otherwise might do. Alternatively, if it is set to "guess",
+       then the contents of the file are examined to decide if
+       it is binary, similar to `core.autocrlf`.
+
+gitcvs.dbName::
+       Database used by git-cvsserver to cache revision information
+       derived from the Git repository. The exact meaning depends on the
+       used database driver, for SQLite (which is the default driver) this
+       is a filename. Supports variable substitution (see
+       linkgit:git-cvsserver[1] for details). May not contain semicolons (`;`).
+       Default: '%Ggitcvs.%m.sqlite'
+
+gitcvs.dbDriver::
+       Used Perl DBI driver. You can specify any available driver
+       for this here, but it might not work. git-cvsserver is tested
+       with 'DBD::SQLite', reported to work with 'DBD::Pg', and
+       reported *not* to work with 'DBD::mysql'. Experimental feature.
+       May not contain double colons (`:`). Default: 'SQLite'.
+       See linkgit:git-cvsserver[1].
+
+gitcvs.dbUser, gitcvs.dbPass::
+       Database user and password. Only useful if setting `gitcvs.dbDriver`,
+       since SQLite has no concept of database users and/or passwords.
+       'gitcvs.dbUser' supports variable substitution (see
+       linkgit:git-cvsserver[1] for details).
+
+gitcvs.dbTableNamePrefix::
+       Database table name prefix.  Prepended to the names of any
+       database tables used, allowing a single database to be used
+       for several repositories.  Supports variable substitution (see
+       linkgit:git-cvsserver[1] for details).  Any non-alphabetic
+       characters will be replaced with underscores.
+
+All gitcvs variables except for `gitcvs.usecrlfattr` and
+`gitcvs.allBinary` can also be specified as
+'gitcvs.<access_method>.<varname>' (where 'access_method'
+is one of "ext" and "pserver") to make them apply only for the given
+access method.
diff --git a/Documentation/gui-config.txt b/Documentation/gui-config.txt
new file mode 100644 (file)
index 0000000..d30831a
--- /dev/null
@@ -0,0 +1,57 @@
+gui.commitMsgWidth::
+       Defines how wide the commit message window is in the
+       linkgit:git-gui[1]. "75" is the default.
+
+gui.diffContext::
+       Specifies how many context lines should be used in calls to diff
+       made by the linkgit:git-gui[1]. The default is "5".
+
+gui.displayUntracked::
+       Determines if linkgit:git-gui[1] shows untracked files
+       in the file list. The default is "true".
+
+gui.encoding::
+       Specifies the default encoding to use for displaying of
+       file contents in linkgit:git-gui[1] and linkgit:gitk[1].
+       It can be overridden by setting the 'encoding' attribute
+       for relevant files (see linkgit:gitattributes[5]).
+       If this option is not set, the tools default to the
+       locale encoding.
+
+gui.matchTrackingBranch::
+       Determines if new branches created with linkgit:git-gui[1] should
+       default to tracking remote branches with matching names or
+       not. Default: "false".
+
+gui.newBranchTemplate::
+       Is used as suggested name when creating new branches using the
+       linkgit:git-gui[1].
+
+gui.pruneDuringFetch::
+       "true" if linkgit:git-gui[1] should prune remote-tracking branches when
+       performing a fetch. The default value is "false".
+
+gui.trustmtime::
+       Determines if linkgit:git-gui[1] should trust the file modification
+       timestamp or not. By default the timestamps are not trusted.
+
+gui.spellingDictionary::
+       Specifies the dictionary used for spell checking commit messages in
+       the linkgit:git-gui[1]. When set to "none" spell checking is turned
+       off.
+
+gui.fastCopyBlame::
+       If true, 'git gui blame' uses `-C` instead of `-C -C` for original
+       location detection. It makes blame significantly faster on huge
+       repositories at the expense of less thorough copy detection.
+
+gui.copyBlameThreshold::
+       Specifies the threshold to use in 'git gui blame' original location
+       detection, measured in alphanumeric characters. See the
+       linkgit:git-blame[1] manual for more information on copy detection.
+
+gui.blamehistoryctx::
+       Specifies the radius of history context in days to show in
+       linkgit:gitk[1] for the selected commit, when the `Show History
+       Context` menu item is invoked from 'git gui blame'. If this
+       variable is set to zero, the whole history is shown.
diff --git a/Documentation/pull-config.txt b/Documentation/pull-config.txt
new file mode 100644 (file)
index 0000000..bb23a99
--- /dev/null
@@ -0,0 +1,36 @@
+pull.ff::
+       By default, Git does not create an extra merge commit when merging
+       a commit that is a descendant of the current commit. Instead, the
+       tip of the current branch is fast-forwarded. When set to `false`,
+       this variable tells Git to create an extra merge commit in such
+       a case (equivalent to giving the `--no-ff` option from the command
+       line). When set to `only`, only such fast-forward merges are
+       allowed (equivalent to giving the `--ff-only` option from the
+       command line). This setting overrides `merge.ff` when pulling.
+
+pull.rebase::
+       When true, rebase branches on top of the fetched branch, instead
+       of merging the default branch from the default remote when "git
+       pull" is run. See "branch.<name>.rebase" for setting this on a
+       per-branch basis.
++
+When `merges`, pass the `--rebase-merges` option to 'git rebase'
+so that the local merge commits are included in the rebase (see
+linkgit:git-rebase[1] for details).
++
+When preserve, also pass `--preserve-merges` along to 'git rebase'
+so that locally committed merge commits will not be flattened
+by running 'git pull'.
++
+When the value is `interactive`, the rebase is run in interactive mode.
++
+*NOTE*: this is a possibly dangerous operation; do *not* use
+it unless you understand the implications (see linkgit:git-rebase[1]
+for details).
+
+pull.octopus::
+       The default merge strategy to use when pulling multiple branches
+       at once.
+
+pull.twohead::
+       The default merge strategy to use when pulling a single branch.
diff --git a/Documentation/push-config.txt b/Documentation/push-config.txt
new file mode 100644 (file)
index 0000000..0a0e000
--- /dev/null
@@ -0,0 +1,113 @@
+push.default::
+       Defines the action `git push` should take if no refspec is
+       explicitly given.  Different values are well-suited for
+       specific workflows; for instance, in a purely central workflow
+       (i.e. the fetch source is equal to the push destination),
+       `upstream` is probably what you want.  Possible values are:
++
+--
+
+* `nothing` - do not push anything (error out) unless a refspec is
+  explicitly given. This is primarily meant for people who want to
+  avoid mistakes by always being explicit.
+
+* `current` - push the current branch to update a branch with the same
+  name on the receiving end.  Works in both central and non-central
+  workflows.
+
+* `upstream` - push the current branch back to the branch whose
+  changes are usually integrated into the current branch (which is
+  called `@{upstream}`).  This mode only makes sense if you are
+  pushing to the same repository you would normally pull from
+  (i.e. central workflow).
+
+* `tracking` - This is a deprecated synonym for `upstream`.
+
+* `simple` - in centralized workflow, work like `upstream` with an
+  added safety to refuse to push if the upstream branch's name is
+  different from the local one.
++
+When pushing to a remote that is different from the remote you normally
+pull from, work as `current`.  This is the safest option and is suited
+for beginners.
++
+This mode has become the default in Git 2.0.
+
+* `matching` - push all branches having the same name on both ends.
+  This makes the repository you are pushing to remember the set of
+  branches that will be pushed out (e.g. if you always push 'maint'
+  and 'master' there and no other branches, the repository you push
+  to will have these two branches, and your local 'maint' and
+  'master' will be pushed there).
++
+To use this mode effectively, you have to make sure _all_ the
+branches you would push out are ready to be pushed out before
+running 'git push', as the whole point of this mode is to allow you
+to push all of the branches in one go.  If you usually finish work
+on only one branch and push out the result, while other branches are
+unfinished, this mode is not for you.  Also this mode is not
+suitable for pushing into a shared central repository, as other
+people may add new branches there, or update the tip of existing
+branches outside your control.
++
+This used to be the default, but not since Git 2.0 (`simple` is the
+new default).
+
+--
+
+push.followTags::
+       If set to true enable `--follow-tags` option by default.  You
+       may override this configuration at time of push by specifying
+       `--no-follow-tags`.
+
+push.gpgSign::
+       May be set to a boolean value, or the string 'if-asked'. A true
+       value causes all pushes to be GPG signed, as if `--signed` is
+       passed to linkgit:git-push[1]. The string 'if-asked' causes
+       pushes to be signed if the server supports it, as if
+       `--signed=if-asked` is passed to 'git push'. A false value may
+       override a value from a lower-priority config file. An explicit
+       command-line flag always overrides this config option.
+
+push.pushOption::
+       When no `--push-option=<option>` argument is given from the
+       command line, `git push` behaves as if each <value> of
+       this variable is given as `--push-option=<value>`.
++
+This is a multi-valued variable, and an empty value can be used in a
+higher priority configuration file (e.g. `.git/config` in a
+repository) to clear the values inherited from a lower priority
+configuration files (e.g. `$HOME/.gitconfig`).
++
+--
+
+Example:
+
+/etc/gitconfig
+  push.pushoption = a
+  push.pushoption = b
+
+~/.gitconfig
+  push.pushoption = c
+
+repo/.git/config
+  push.pushoption =
+  push.pushoption = b
+
+This will result in only b (a and c are cleared).
+
+--
+
+push.recurseSubmodules::
+       Make sure all submodule commits used by the revisions to be pushed
+       are available on a remote-tracking branch. If the value is 'check'
+       then Git will verify that all submodule commits that changed in the
+       revisions to be pushed are available on at least one remote of the
+       submodule. If any commits are missing, the push will be aborted and
+       exit with non-zero status. If the value is 'on-demand' then all
+       submodules that changed in the revisions to be pushed will be
+       pushed. If on-demand was not able to push all necessary revisions
+       it will also be aborted and exit with non-zero status. If the value
+       is 'no' then default behavior of ignoring submodules when pushing
+       is retained. You may override this configuration at time of push by
+       specifying '--recurse-submodules=check|on-demand|no'.
diff --git a/Documentation/receive-config.txt b/Documentation/receive-config.txt
new file mode 100644 (file)
index 0000000..65f78aa
--- /dev/null
@@ -0,0 +1,123 @@
+receive.advertiseAtomic::
+       By default, git-receive-pack will advertise the atomic push
+       capability to its clients. If you don't want to advertise this
+       capability, set this variable to false.
+
+receive.advertisePushOptions::
+       When set to true, git-receive-pack will advertise the push options
+       capability to its clients. False by default.
+
+receive.autogc::
+       By default, git-receive-pack will run "git-gc --auto" after
+       receiving data from git-push and updating refs.  You can stop
+       it by setting this variable to false.
+
+receive.certNonceSeed::
+       By setting this variable to a string, `git receive-pack`
+       will accept a `git push --signed` and verifies it by using
+       a "nonce" protected by HMAC using this string as a secret
+       key.
+
+receive.certNonceSlop::
+       When a `git push --signed` sent a push certificate with a
+       "nonce" that was issued by a receive-pack serving the same
+       repository within this many seconds, export the "nonce"
+       found in the certificate to `GIT_PUSH_CERT_NONCE` to the
+       hooks (instead of what the receive-pack asked the sending
+       side to include).  This may allow writing checks in
+       `pre-receive` and `post-receive` a bit easier.  Instead of
+       checking `GIT_PUSH_CERT_NONCE_SLOP` environment variable
+       that records by how many seconds the nonce is stale to
+       decide if they want to accept the certificate, they only
+       can check `GIT_PUSH_CERT_NONCE_STATUS` is `OK`.
+
+receive.fsckObjects::
+       If it is set to true, git-receive-pack will check all received
+       objects. See `transfer.fsckObjects` for what's checked.
+       Defaults to false. If not set, the value of
+       `transfer.fsckObjects` is used instead.
+
+receive.fsck.<msg-id>::
+       Acts like `fsck.<msg-id>`, but is used by
+       linkgit:git-receive-pack[1] instead of
+       linkgit:git-fsck[1]. See the `fsck.<msg-id>` documentation for
+       details.
+
+receive.fsck.skipList::
+       Acts like `fsck.skipList`, but is used by
+       linkgit:git-receive-pack[1] instead of
+       linkgit:git-fsck[1]. See the `fsck.skipList` documentation for
+       details.
+
+receive.keepAlive::
+       After receiving the pack from the client, `receive-pack` may
+       produce no output (if `--quiet` was specified) while processing
+       the pack, causing some networks to drop the TCP connection.
+       With this option set, if `receive-pack` does not transmit
+       any data in this phase for `receive.keepAlive` seconds, it will
+       send a short keepalive packet.  The default is 5 seconds; set
+       to 0 to disable keepalives entirely.
+
+receive.unpackLimit::
+       If the number of objects received in a push is below this
+       limit then the objects will be unpacked into loose object
+       files. However if the number of received objects equals or
+       exceeds this limit then the received pack will be stored as
+       a pack, after adding any missing delta bases.  Storing the
+       pack from a push can make the push operation complete faster,
+       especially on slow filesystems.  If not set, the value of
+       `transfer.unpackLimit` is used instead.
+
+receive.maxInputSize::
+       If the size of the incoming pack stream is larger than this
+       limit, then git-receive-pack will error out, instead of
+       accepting the pack file. If not set or set to 0, then the size
+       is unlimited.
+
+receive.denyDeletes::
+       If set to true, git-receive-pack will deny a ref update that deletes
+       the ref. Use this to prevent such a ref deletion via a push.
+
+receive.denyDeleteCurrent::
+       If set to true, git-receive-pack will deny a ref update that
+       deletes the currently checked out branch of a non-bare repository.
+
+receive.denyCurrentBranch::
+       If set to true or "refuse", git-receive-pack will deny a ref update
+       to the currently checked out branch of a non-bare repository.
+       Such a push is potentially dangerous because it brings the HEAD
+       out of sync with the index and working tree. If set to "warn",
+       print a warning of such a push to stderr, but allow the push to
+       proceed. If set to false or "ignore", allow such pushes with no
+       message. Defaults to "refuse".
++
+Another option is "updateInstead" which will update the working
+tree if pushing into the current branch.  This option is
+intended for synchronizing working directories when one side is not easily
+accessible via interactive ssh (e.g. a live web site, hence the requirement
+that the working directory be clean). This mode also comes in handy when
+developing inside a VM to test and fix code on different Operating Systems.
++
+By default, "updateInstead" will refuse the push if the working tree or
+the index have any difference from the HEAD, but the `push-to-checkout`
+hook can be used to customize this.  See linkgit:githooks[5].
+
+receive.denyNonFastForwards::
+       If set to true, git-receive-pack will deny a ref update which is
+       not a fast-forward. Use this to prevent such an update via a push,
+       even if that push is forced. This configuration variable is
+       set when initializing a shared repository.
+
+receive.hideRefs::
+       This variable is the same as `transfer.hideRefs`, but applies
+       only to `receive-pack` (and so affects pushes, but not fetches).
+       An attempt to update or delete a hidden ref by `git push` is
+       rejected.
+
+receive.updateServerInfo::
+       If set to true, git-receive-pack will run git-update-server-info
+       after receiving data from git-push and updating refs.
+
+receive.shallowUpdate::
+       If set to true, .git/shallow can be updated when new refs
+       require new shallow roots. Otherwise those refs are rejected.
diff --git a/Documentation/sendemail-config.txt b/Documentation/sendemail-config.txt
new file mode 100644 (file)
index 0000000..0006faf
--- /dev/null
@@ -0,0 +1,63 @@
+sendemail.identity::
+       A configuration identity. When given, causes values in the
+       'sendemail.<identity>' subsection to take precedence over
+       values in the 'sendemail' section. The default identity is
+       the value of `sendemail.identity`.
+
+sendemail.smtpEncryption::
+       See linkgit:git-send-email[1] for description.  Note that this
+       setting is not subject to the 'identity' mechanism.
+
+sendemail.smtpssl (deprecated)::
+       Deprecated alias for 'sendemail.smtpEncryption = ssl'.
+
+sendemail.smtpsslcertpath::
+       Path to ca-certificates (either a directory or a single file).
+       Set it to an empty string to disable certificate verification.
+
+sendemail.<identity>.*::
+       Identity-specific versions of the 'sendemail.*' parameters
+       found below, taking precedence over those when this
+       identity is selected, through either the command-line or
+       `sendemail.identity`.
+
+sendemail.aliasesFile::
+sendemail.aliasFileType::
+sendemail.annotate::
+sendemail.bcc::
+sendemail.cc::
+sendemail.ccCmd::
+sendemail.chainReplyTo::
+sendemail.confirm::
+sendemail.envelopeSender::
+sendemail.from::
+sendemail.multiEdit::
+sendemail.signedoffbycc::
+sendemail.smtpPass::
+sendemail.suppresscc::
+sendemail.suppressFrom::
+sendemail.to::
+sendemail.tocmd::
+sendemail.smtpDomain::
+sendemail.smtpServer::
+sendemail.smtpServerPort::
+sendemail.smtpServerOption::
+sendemail.smtpUser::
+sendemail.thread::
+sendemail.transferEncoding::
+sendemail.validate::
+sendemail.xmailer::
+       See linkgit:git-send-email[1] for description.
+
+sendemail.signedoffcc (deprecated)::
+       Deprecated alias for `sendemail.signedoffbycc`.
+
+sendemail.smtpBatchSize::
+       Number of messages to be sent per connection, after that a relogin
+       will happen.  If the value is 0 or undefined, send all messages in
+       one connection.
+       See also the `--batch-size` option of linkgit:git-send-email[1].
+
+sendemail.smtpReloginDelay::
+       Seconds wait before reconnecting to smtp server.
+       See also the `--relogin-delay` option of linkgit:git-send-email[1].
diff --git a/Documentation/submodule-config.txt b/Documentation/submodule-config.txt
new file mode 100644 (file)
index 0000000..0a1293b
--- /dev/null
@@ -0,0 +1,82 @@
+submodule.<name>.url::
+       The URL for a submodule. This variable is copied from the .gitmodules
+       file to the git config via 'git submodule init'. The user can change
+       the configured URL before obtaining the submodule via 'git submodule
+       update'. If neither submodule.<name>.active or submodule.active are
+       set, the presence of this variable is used as a fallback to indicate
+       whether the submodule is of interest to git commands.
+       See linkgit:git-submodule[1] and linkgit:gitmodules[5] for details.
+
+submodule.<name>.update::
+       The method by which a submodule is updated by 'git submodule update',
+       which is the only affected command, others such as
+       'git checkout --recurse-submodules' are unaffected. It exists for
+       historical reasons, when 'git submodule' was the only command to
+       interact with submodules; settings like `submodule.active`
+       and `pull.rebase` are more specific. It is populated by
+       `git submodule init` from the linkgit:gitmodules[5] file.
+       See description of 'update' command in linkgit:git-submodule[1].
+
+submodule.<name>.branch::
+       The remote branch name for a submodule, used by `git submodule
+       update --remote`.  Set this option to override the value found in
+       the `.gitmodules` file.  See linkgit:git-submodule[1] and
+       linkgit:gitmodules[5] for details.
+
+submodule.<name>.fetchRecurseSubmodules::
+       This option can be used to control recursive fetching of this
+       submodule. It can be overridden by using the --[no-]recurse-submodules
+       command-line option to "git fetch" and "git pull".
+       This setting will override that from in the linkgit:gitmodules[5]
+       file.
+
+submodule.<name>.ignore::
+       Defines under what circumstances "git status" and the diff family show
+       a submodule as modified. When set to "all", it will never be considered
+       modified (but it will nonetheless show up in the output of status and
+       commit when it has been staged), "dirty" will ignore all changes
+       to the submodules work tree and
+       takes only differences between the HEAD of the submodule and the commit
+       recorded in the superproject into account. "untracked" will additionally
+       let submodules with modified tracked files in their work tree show up.
+       Using "none" (the default when this option is not set) also shows
+       submodules that have untracked files in their work tree as changed.
+       This setting overrides any setting made in .gitmodules for this submodule,
+       both settings can be overridden on the command line by using the
+       "--ignore-submodules" option. The 'git submodule' commands are not
+       affected by this setting.
+
+submodule.<name>.active::
+       Boolean value indicating if the submodule is of interest to git
+       commands.  This config option takes precedence over the
+       submodule.active config option. See linkgit:gitsubmodules[7] for
+       details.
+
+submodule.active::
+       A repeated field which contains a pathspec used to match against a
+       submodule's path to determine if the submodule is of interest to git
+       commands. See linkgit:gitsubmodules[7] for details.
+
+submodule.recurse::
+       Specifies if commands recurse into submodules by default. This
+       applies to all commands that have a `--recurse-submodules` option,
+       except `clone`.
+       Defaults to false.
+
+submodule.fetchJobs::
+       Specifies how many submodules are fetched/cloned at the same time.
+       A positive integer allows up to that number of submodules fetched
+       in parallel. A value of 0 will give some reasonable default.
+       If unset, it defaults to 1.
+
+submodule.alternateLocation::
+       Specifies how the submodules obtain alternates when submodules are
+       cloned. Possible values are `no`, `superproject`.
+       By default `no` is assumed, which doesn't add references. When the
+       value is set to `superproject` the submodule to be cloned computes
+       its alternates location relative to the superprojects alternate.
+
+submodule.alternateErrorStrategy::
+       Specifies how to treat errors with the alternates for a submodule
+       as computed via `submodule.alternateLocation`. Possible values are
+       `ignore`, `info`, `die`. Default is `die`.
index c664acbd765d06f000b2feeef1d7e98f1616ff62..7805b0968c828fda1601fe00c2b5b9d9359b38e2 100644 (file)
@@ -15,13 +15,13 @@ There are two main costs here:
 1. Decompressing and parsing commits.
 2. Walking the entire graph to satisfy topological order constraints.
 
-The commit graph file is a supplemental data structure that accelerates
+The commit-graph file is a supplemental data structure that accelerates
 commit graph walks. If a user downgrades or disables the 'core.commitGraph'
 config setting, then the existing ODB is sufficient. The file is stored
 as "commit-graph" either in the .git/objects/info directory or in the info
 directory of an alternate.
 
-The commit graph file stores the commit graph structure along with some
+The commit-graph file stores the commit graph structure along with some
 extra metadata to speed up graph walks. By listing commit OIDs in lexi-
 cographic order, we can identify an integer position for each commit and
 refer to the parents of a commit using those integer positions. We use
@@ -103,7 +103,7 @@ that of a parent.
 Design Details
 --------------
 
-- The commit graph file is stored in a file named 'commit-graph' in the
+- The commit-graph file is stored in a file named 'commit-graph' in the
   .git/objects/info directory. This could be stored in the info directory
   of an alternate.
 
@@ -112,12 +112,24 @@ Design Details
 - The file format includes parameters for the object ID hash function,
   so a future change of hash algorithm does not require a change in format.
 
+- Commit grafts and replace objects can change the shape of the commit
+  history. The latter can also be enabled/disabled on the fly using
+  `--no-replace-objects`. This leads to difficultly storing both possible
+  interpretations of a commit id, especially when computing generation
+  numbers. The commit-graph will not be read or written when
+  replace-objects or grafts are present.
+
+- Shallow clones create grafts of commits by dropping their parents. This
+  leads the commit-graph to think those commits have generation number 1.
+  If and when those commits are made unshallow, those generation numbers
+  become invalid. Since shallow clones are intended to restrict the commit
+  history to a very small set of commits, the commit-graph feature is less
+  helpful for these clones, anyway. The commit-graph will not be read or
+  written when shallow commits are present.
+
 Future Work
 -----------
 
-- The commit graph feature currently does not honor commit grafts. This can
-  be remedied by duplicating or refactoring the current graft logic.
-
 - After computing and storing generation numbers, we must make graph
   walks aware of generation numbers to gain the performance benefits they
   enable. This will mostly be accomplished by swapping a commit-date-ordered
@@ -127,7 +139,7 @@ Future Work
     - 'log --topo-order'
     - 'tag --merged'
 
-- A server could provide a commit graph file as part of the network protocol
+- A server could provide a commit-graph file as part of the network protocol
   to avoid extra calculations by clients. This feature is only of benefit if
   the user is willing to trust the file, because verifying the file is correct
   is as hard as computing it from scratch.
index 13e1c5247824d8db94126cb91d35df57440c9384..5bf1af369ec46421c68b9194bbb9938e2ba2933f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -709,7 +709,9 @@ TEST_BUILTINS_OBJS += test-date.o
 TEST_BUILTINS_OBJS += test-delta.o
 TEST_BUILTINS_OBJS += test-drop-caches.o
 TEST_BUILTINS_OBJS += test-dump-cache-tree.o
+TEST_BUILTINS_OBJS += test-dump-fsmonitor.o
 TEST_BUILTINS_OBJS += test-dump-split-index.o
+TEST_BUILTINS_OBJS += test-dump-untracked-cache.o
 TEST_BUILTINS_OBJS += test-example-decorate.o
 TEST_BUILTINS_OBJS += test-genrandom.o
 TEST_BUILTINS_OBJS += test-hashmap.o
@@ -720,7 +722,9 @@ TEST_BUILTINS_OBJS += test-match-trees.o
 TEST_BUILTINS_OBJS += test-mergesort.o
 TEST_BUILTINS_OBJS += test-mktemp.o
 TEST_BUILTINS_OBJS += test-online-cpus.o
+TEST_BUILTINS_OBJS += test-parse-options.o
 TEST_BUILTINS_OBJS += test-path-utils.o
+TEST_BUILTINS_OBJS += test-pkt-line.o
 TEST_BUILTINS_OBJS += test-prio-queue.o
 TEST_BUILTINS_OBJS += test-reach.o
 TEST_BUILTINS_OBJS += test-read-cache.o
@@ -731,8 +735,8 @@ TEST_BUILTINS_OBJS += test-repository.o
 TEST_BUILTINS_OBJS += test-revision-walking.o
 TEST_BUILTINS_OBJS += test-run-command.o
 TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
-TEST_BUILTINS_OBJS += test-sha1-array.o
 TEST_BUILTINS_OBJS += test-sha1.o
+TEST_BUILTINS_OBJS += test-sha1-array.o
 TEST_BUILTINS_OBJS += test-sigchain.o
 TEST_BUILTINS_OBJS += test-strcmp-offset.o
 TEST_BUILTINS_OBJS += test-string-list.o
@@ -743,12 +747,10 @@ TEST_BUILTINS_OBJS += test-wildmatch.o
 TEST_BUILTINS_OBJS += test-windows-named-pipe.o
 TEST_BUILTINS_OBJS += test-write-cache.o
 
-TEST_PROGRAMS_NEED_X += test-dump-fsmonitor
-TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
+# Do not add more tests here unless they have extra dependencies. Add
+# them in TEST_BUILTINS_OBJS above.
 TEST_PROGRAMS_NEED_X += test-fake-ssh
 TEST_PROGRAMS_NEED_X += test-line-buffer
-TEST_PROGRAMS_NEED_X += test-parse-options
-TEST_PROGRAMS_NEED_X += test-pkt-line
 TEST_PROGRAMS_NEED_X += test-svn-fe
 TEST_PROGRAMS_NEED_X += test-tool
 
@@ -1794,6 +1796,7 @@ ifndef V
        QUIET_MSGFMT   = @echo '   ' MSGFMT $@;
        QUIET_GCOV     = @echo '   ' GCOV $@;
        QUIET_SP       = @echo '   ' SP $<;
+       QUIET_HDR      = @echo '   ' HDR $<;
        QUIET_RC       = @echo '   ' RC $@;
        QUIET_SUBDIR0  = +@subdir=
        QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
@@ -2676,6 +2679,17 @@ $(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE
 .PHONY: sparse $(SP_OBJ)
 sparse: $(SP_OBJ)
 
+GEN_HDRS := command-list.h unicode-width.h
+EXCEPT_HDRS := $(GEN_HDRS) compat% xdiff%
+CHK_HDRS = $(filter-out $(EXCEPT_HDRS),$(patsubst ./%,%,$(LIB_H)))
+HCO = $(patsubst %.h,%.hco,$(CHK_HDRS))
+
+$(HCO): %.hco: %.h FORCE
+       $(QUIET_HDR)$(CC) -include git-compat-util.h -I. -o /dev/null -c -xc $<
+
+.PHONY: hdr-check $(HCO)
+hdr-check: $(HCO)
+
 .PHONY: style
 style:
        git clang-format --style file --diff --extensions c,h
deleted file mode 100644 (file)
index 007bc065dd88d6fbbde553c550c58b363fc29c40..0000000000000000000000000000000000000000
--- a/RelNotes
+++ /dev/null
@@ -1,167 +0,0 @@
-Git Release Notes
-=================
-
-Backward Compatibility Notes
-----------------------------
-
- * "git branch -l <foo>" used to be a way to ask a reflog to be
-   created while creating a new branch, but that is no longer the
-   case.  It is a short-hand for "git branch --list <foo>" now.
-
- * "git push" into refs/tags/* hierarchy is rejected without getting
-   forced, but "git fetch" (misguidedly) used the "fast forwarding"
-   rule used for the refs/heads/* hierarchy; this has been corrected,
-   which means some fetches of tags that did not fail with older
-   version of Git will fail without "--force" with this version.
-
-
-Updates since v2.19
--------------------
-
-UI, Workflows & Features
-
- * Running "git clone" against a project that contain two files with
-   pathnames that differ only in cases on a case insensitive
-   filesystem would result in one of the files lost because the
-   underlying filesystem is incapable of holding both at the same
-   time.  An attempt is made to detect such a case and warn.
-
- * "git checkout -b newbranch [HEAD]" should not have to do as much as
-   checking out a commit different from HEAD.  An attempt is made to
-   optimize this special case.
-
- * "git rev-list --stdin </dev/null" used to be an error; it now shows
-   no output without an error.  "git rev-list --stdin --default HEAD"
-   still falls back to the given default when nothing is given on the
-   standard input.
-
- * Lift code from GitHub to restrict delta computation so that an
-   object that exists in one fork is not made into a delta against
-   another object that does not appear in the same forked repository.
-
- * "git format-patch" learned new "--interdiff" and "--range-diff"
-   options to explain the difference between this version and the
-   previous attempt in the cover letter (or after the tree-dashes as
-   a comment).
-
- * "git mailinfo" used in "git am" learned to make a best-effort
-   recovery of a patch corrupted by MUA that sends text/plain with
-   format=flawed option.
-   (merge 3aa4d81f88 rs/mailinfo-format-flowed later to maint).
-
- * The rules used by "git push" and "git fetch" to determine if a ref
-   can or cannot be updated were inconsistent; specifically, fetching
-   to update existing tags were allowed even though tags are supposed
-   to be unmoving anchoring points.  "git fetch" was taught to forbid
-   updates to existing tags without the "--force" option.
-
-
-Performance, Internal Implementation, Development Support etc.
-
- * When there are too many packfiles in a repository (which is not
-   recommended), looking up an object in these would require
-   consulting many pack .idx files; a new mechanism to have a single
-   file that consolidates all of these .idx files is introduced.
-
- * "git submodule update" is getting rewritten piece-by-piece into C.
-
- * The code for computing history reachability has been shuffled,
-   obtained a bunch of new tests to cover them, and then being
-   improved.
-
- * The unpack_trees() API used in checking out a branch and merging
-   walks one or more trees along with the index.  When the cache-tree
-   in the index tells us that we are walking a tree whose flattened
-   contents is known (i.e. matches a span in the index), as linearly
-   scanning a span in the index is much more efficient than having to
-   open tree objects recursively and listing their entries, the walk
-   can be optimized, which has been done.
-
- * When creating a thin pack, which allows objects to be made into a
-   delta against another object that is not in the resulting pack but
-   is known to be present on the receiving end, the code learned to
-   take advantage of the reachability bitmap; this allows the server
-   to send a delta against a base beyond the "boundary" commit.
-
- * spatch transformation to replace boolean uses of !hashcmp() to
-   newly introduced oideq() is added, and applied, to regain
-   performance lost due to support of multiple hash algorithms.
-
- * Fix a bug in which the same path could be registered under multiple
-   worktree entries if the path was missing (for instance, was removed
-   manually).  Also, as a convenience, expand the number of cases in
-   which --force is applicable.
-
-
-Fixes since v2.19
------------------
-
- * "git interpret-trailers" and its underlying machinery had a buggy
-   code that attempted to ignore patch text after commit log message,
-   which triggered in various codepaths that will always get the log
-   message alone and never get such an input.
-   (merge 66e83d9b41 jk/trailer-fixes later to maint).
-
- * Malformed or crafted data in packstream can make our code attempt
-   to read or write past the allocated buffer and abort, instead of
-   reporting an error, which has been fixed.
-
- * "git rebase -i" did not clear the state files correctly when a run
-   of "squash/fixup" is aborted and then the user manually amended the
-   commit instead, which has been corrected.
-   (merge 10d2f35436 js/rebase-i-autosquash-fix later to maint).
-
- * When fsmonitor is in use, after operation on submodules updates
-   .gitmodules, we lost track of the fact that we did so and relied on
-   stale fsmonitor data.
-   (merge 43f1180814 bp/mv-submodules-with-fsmonitor later to maint).
-
- * Fix for a long-standing bug that leaves the index file corrupt when
-   it shrinks during a partial commit.
-   (merge 6c003d6ffb jk/reopen-tempfile-truncate later to maint).
-
- * Further fix for O_APPEND emulation on Windows
-   (merge eeaf7ddac7 js/mingw-o-append later to maint).
-
- * A corner case bugfix in "git rerere" code.
-   (merge ad2bf0d9b4 en/rerere-multi-stage-1-fix later to maint).
-
- * "git add ':(attr:foo)'" is not supported and is supposed to be
-   rejected while the command line arguments are parsed, but we fail
-   to reject such a command line upfront.
-   (merge 84d938b732 nd/attr-pathspec-fix later to maint).
-
- * Recent update broke the reachability algorithm when refs (e.g.
-   tags) that point at objects that are not commit were involved,
-   which has been fixed.
-
- * "git rebase" etc. in Git 2.19 fails to abort when given an empty
-   commit log message as result of editing, which has been corrected.
-   (merge a3ec9eaf38 en/sequencer-empty-edit-result-aborts later to maint).
-
- * The code to backfill objects in lazily cloned repository did not
-   work correctly, which has been corrected.
-   (merge e68302011c jt/lazy-object-fetch-fix later to maint).
-
- * Update error messages given by "git remote" and make them consistent.
-   (merge 5025425dff ms/remote-error-message-update later to maint).
-
- * "git update-ref" learned to make both "--no-deref" and "--stdin"
-   work at the same time.
-   (merge d345e9fbe7 en/update-ref-no-deref-stdin later to maint).
-
- * Recently added "range-diff" had a corner-case bug to cause it
-   segfault, which has been corrected.
-   (merge e467a90c7a tg/range-diff-corner-case-fix later to maint).
-
- * Code cleanup, docfix, build fix, etc.
-   (merge 96a7501aad ts/doc-build-manpage-xsl-quietly later to maint).
-   (merge b9b07efdb2 tg/conflict-marker-size later to maint).
-   (merge fa0aeea770 sg/doc-trace-appends later to maint).
-   (merge d64324cb60 tb/void-check-attr later to maint).
-   (merge c3b9bc94b9 en/double-semicolon-fix later to maint).
-   (merge 79336116f5 sg/t3701-tighten-trace later to maint).
-   (merge 801fa63a90 jk/dev-build-format-security later to maint).
-   (merge 0597dd62ba sb/string-list-remove-unused later to maint).
-   (merge db2d36fad8 bw/protocol-v2 later to maint).
-   (merge 456d7cd3a9 sg/split-index-test later to maint).
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..8d0b1654d25536f72abe885634c36412ae8b3246
--- /dev/null
+++ b/RelNotes
@@ -0,0 +1 @@
+Documentation/RelNotes/2.20.0.txt
\ No newline at end of file
index 0bf0c486575a8557b729658ce05be02d28a1a8b8..22b974f4b434913cf3ebe9e4073d2cb847f8a468 100644 (file)
@@ -120,6 +120,8 @@ static int graph_read(int argc, const char **argv)
        return 0;
 }
 
+extern int read_replace_refs;
+
 static int graph_write(int argc, const char **argv)
 {
        struct string_list *pack_indexes = NULL;
@@ -150,8 +152,10 @@ static int graph_write(int argc, const char **argv)
        if (!opts.obj_dir)
                opts.obj_dir = get_object_directory();
 
+       read_replace_refs = 0;
+
        if (opts.reachable) {
-               write_commit_graph_reachable(opts.obj_dir, opts.append);
+               write_commit_graph_reachable(opts.obj_dir, opts.append, 1);
                return 0;
        }
 
@@ -171,7 +175,8 @@ static int graph_write(int argc, const char **argv)
        write_commit_graph(opts.obj_dir,
                           pack_indexes,
                           commit_hex,
-                          opts.append);
+                          opts.append,
+                          1);
 
        string_list_clear(&lines, 0);
        return 0;
index b57d8e4b82052bdb85287b5fcb675261a68c639b..1d5292e4d827312d3a08ceb44f6a120cbd0c4576 100644 (file)
@@ -874,6 +874,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                s->use_color = 0;
                commitable = run_status(s->fp, index_file, prefix, 1, s);
                s->use_color = saved_color_setting;
+               string_list_clear(&s->change, 1);
        } else {
                struct object_id oid;
                const char *parent = "HEAD";
@@ -1654,7 +1655,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                      "not exceeded, and then \"git reset HEAD\" to recover."));
 
        if (git_env_bool(GIT_TEST_COMMIT_GRAPH, 0))
-               write_commit_graph_reachable(get_object_directory(), 0);
+               write_commit_graph_reachable(get_object_directory(), 0, 0);
 
        rerere(0);
        run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
index 63c8578cc16cd2f77f28d7c1b0515ce317f4e264..06eb42172099a39e6f181d0dd7eab581595d9756 100644 (file)
@@ -848,5 +848,23 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
                }
        }
 
+       if (!git_config_get_bool("core.multipackindex", &i) && i) {
+               struct child_process midx_verify = CHILD_PROCESS_INIT;
+               const char *midx_argv[] = { "multi-pack-index", "verify", NULL, NULL, NULL };
+
+               midx_verify.argv = midx_argv;
+               midx_verify.git_cmd = 1;
+               if (run_command(&midx_verify))
+                       errors_found |= ERROR_COMMIT_GRAPH;
+
+               prepare_alt_odb(the_repository);
+               for (alt =  the_repository->objects->alt_odb_list; alt; alt = alt->next) {
+                       midx_argv[2] = "--object-dir";
+                       midx_argv[3] = alt->path;
+                       if (run_command(&midx_verify))
+                               errors_found |= ERROR_COMMIT_GRAPH;
+               }
+       }
+
        return errors_found;
 }
index 2b592260e9ad0de18e8eaae4df20cc6f886a4681..871a56f1c5a5804db9363b117ae3891ea832bc5f 100644 (file)
@@ -441,10 +441,16 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
        return NULL;
 }
 
+/*
+ * Returns 0 if there was no previous error and gc can proceed, 1 if
+ * gc should not proceed due to an error in the last run. Prints a
+ * message and returns -1 if an error occured while reading gc.log
+ */
 static int report_last_gc_error(void)
 {
        struct strbuf sb = STRBUF_INIT;
        int ret = 0;
+       ssize_t len;
        struct stat st;
        char *gc_log_path = git_pathdup("gc.log");
 
@@ -452,39 +458,47 @@ static int report_last_gc_error(void)
                if (errno == ENOENT)
                        goto done;
 
-               ret = error_errno(_("Can't stat %s"), gc_log_path);
+               ret = error_errno(_("cannot stat '%s'"), gc_log_path);
                goto done;
        }
 
        if (st.st_mtime < gc_log_expire_time)
                goto done;
 
-       ret = strbuf_read_file(&sb, gc_log_path, 0);
-       if (ret > 0)
-               ret = error(_("The last gc run reported the following. "
+       len = strbuf_read_file(&sb, gc_log_path, 0);
+       if (len < 0)
+               ret = error_errno(_("cannot read '%s'"), gc_log_path);
+       else if (len > 0) {
+               /*
+                * A previous gc failed.  Report the error, and don't
+                * bother with an automatic gc run since it is likely
+                * to fail in the same way.
+                */
+               warning(_("The last gc run reported the following. "
                               "Please correct the root cause\n"
                               "and remove %s.\n"
                               "Automatic cleanup will not be performed "
                               "until the file is removed.\n\n"
                               "%s"),
                            gc_log_path, sb.buf);
+               ret = 1;
+       }
        strbuf_release(&sb);
 done:
        free(gc_log_path);
        return ret;
 }
 
-static int gc_before_repack(void)
+static void gc_before_repack(void)
 {
        if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
-               return error(FAILED_RUN, pack_refs_cmd.argv[0]);
+               die(FAILED_RUN, pack_refs_cmd.argv[0]);
 
        if (prune_reflogs && run_command_v_opt(reflog.argv, RUN_GIT_CMD))
-               return error(FAILED_RUN, reflog.argv[0]);
+               die(FAILED_RUN, reflog.argv[0]);
 
        pack_refs = 0;
        prune_reflogs = 0;
-       return 0;
 }
 
 int cmd_gc(int argc, const char **argv, const char *prefix)
@@ -565,13 +579,17 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                        fprintf(stderr, _("See \"git help gc\" for manual housekeeping.\n"));
                }
                if (detach_auto) {
-                       if (report_last_gc_error())
-                               return -1;
+                       int ret = report_last_gc_error();
+                       if (ret < 0)
+                               /* an I/O error occured, already reported */
+                               exit(128);
+                       if (ret == 1)
+                               /* Last gc --auto failed. Skip this one. */
+                               return 0;
 
                        if (lock_repo_for_gc(force, &pid))
                                return 0;
-                       if (gc_before_repack())
-                               return -1;
+                       gc_before_repack(); /* dies on failure */
                        delete_tempfile(&pidfile);
 
                        /*
@@ -611,13 +629,12 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                atexit(process_log_file_at_exit);
        }
 
-       if (gc_before_repack())
-               return -1;
+       gc_before_repack();
 
        if (!repository_format_precious_objects) {
                close_all_packs(the_repository->objects);
                if (run_command_v_opt(repack.argv, RUN_GIT_CMD))
-                       return error(FAILED_RUN, repack.argv[0]);
+                       die(FAILED_RUN, repack.argv[0]);
 
                if (prune_expire) {
                        argv_array_push(&prune, prune_expire);
@@ -627,18 +644,18 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                                argv_array_push(&prune,
                                                "--exclude-promisor-objects");
                        if (run_command_v_opt(prune.argv, RUN_GIT_CMD))
-                               return error(FAILED_RUN, prune.argv[0]);
+                               die(FAILED_RUN, prune.argv[0]);
                }
        }
 
        if (prune_worktrees_expire) {
                argv_array_push(&prune_worktrees, prune_worktrees_expire);
                if (run_command_v_opt(prune_worktrees.argv, RUN_GIT_CMD))
-                       return error(FAILED_RUN, prune_worktrees.argv[0]);
+                       die(FAILED_RUN, prune_worktrees.argv[0]);
        }
 
        if (run_command_v_opt(rerere.argv, RUN_GIT_CMD))
-               return error(FAILED_RUN, rerere.argv[0]);
+               die(FAILED_RUN, rerere.argv[0]);
 
        report_garbage = report_pack_garbage;
        reprepare_packed_git(the_repository);
@@ -646,7 +663,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
                clean_pack_garbage();
 
        if (gc_write_commit_graph)
-               write_commit_graph_reachable(get_object_directory(), 0);
+               write_commit_graph_reachable(get_object_directory(), 0,
+                                            !quiet && !daemonized);
 
        if (auto_gc && too_many_loose_objects())
                warning(_("There are too many unreachable loose objects; "
index 2633efd95d01cd2d3440b203985eab997941a5f6..fca70f8e4fcca8432619c41fd68234732a92f07a 100644 (file)
@@ -5,7 +5,7 @@
 #include "midx.h"
 
 static char const * const builtin_multi_pack_index_usage[] = {
-       N_("git multi-pack-index [--object-dir=<dir>] write"),
+       N_("git multi-pack-index [--object-dir=<dir>] (write|verify)"),
        NULL
 };
 
@@ -42,6 +42,8 @@ int cmd_multi_pack_index(int argc, const char **argv,
 
        if (!strcmp(argv[0], "write"))
                return write_midx_file(opts.object_dir);
+       if (!strcmp(argv[0], "verify"))
+               return verify_midx_file(opts.object_dir);
 
        die(_("unrecognized verb: %s"), argv[0]);
 }
index e6316d294dca1a84149af0bb439027454c54e720..c6370f2716a7d5a9f78ea6e6627a87b40ab32cc9 100644 (file)
@@ -1469,6 +1469,57 @@ static void cleanup_preferred_base(void)
        done_pbase_paths_num = done_pbase_paths_alloc = 0;
 }
 
+/*
+ * Return 1 iff the object specified by "delta" can be sent
+ * literally as a delta against the base in "base_sha1". If
+ * so, then *base_out will point to the entry in our packing
+ * list, or NULL if we must use the external-base list.
+ *
+ * Depth value does not matter - find_deltas() will
+ * never consider reused delta as the base object to
+ * deltify other objects against, in order to avoid
+ * circular deltas.
+ */
+static int can_reuse_delta(const unsigned char *base_sha1,
+                          struct object_entry *delta,
+                          struct object_entry **base_out)
+{
+       struct object_entry *base;
+
+       if (!base_sha1)
+               return 0;
+
+       /*
+        * First see if we're already sending the base (or it's explicitly in
+        * our "excluded" list).
+        */
+       base = packlist_find(&to_pack, base_sha1, NULL);
+       if (base) {
+               if (!in_same_island(&delta->idx.oid, &base->idx.oid))
+                       return 0;
+               *base_out = base;
+               return 1;
+       }
+
+       /*
+        * Otherwise, reachability bitmaps may tell us if the receiver has it,
+        * even if it was buried too deep in history to make it into the
+        * packing list.
+        */
+       if (thin && bitmap_has_sha1_in_uninteresting(bitmap_git, base_sha1)) {
+               if (use_delta_islands) {
+                       struct object_id base_oid;
+                       hashcpy(base_oid.hash, base_sha1);
+                       if (!in_same_island(&delta->idx.oid, &base_oid))
+                               return 0;
+               }
+               *base_out = NULL;
+               return 1;
+       }
+
+       return 0;
+}
+
 static void check_object(struct object_entry *entry)
 {
        unsigned long canonical_size;
@@ -1555,22 +1606,7 @@ static void check_object(struct object_entry *entry)
                        break;
                }
 
-               if (base_ref && (
-                   (base_entry = packlist_find(&to_pack, base_ref, NULL)) ||
-                   (thin &&
-                    bitmap_has_sha1_in_uninteresting(bitmap_git, base_ref))) &&
-                   in_same_island(&entry->idx.oid, &base_entry->idx.oid)) {
-                       /*
-                        * If base_ref was set above that means we wish to
-                        * reuse delta data, and either we found that object in
-                        * the list of objects we want to pack, or it's one we
-                        * know the receiver has.
-                        *
-                        * Depth value does not matter - find_deltas() will
-                        * never consider reused delta as the base object to
-                        * deltify other objects against, in order to avoid
-                        * circular deltas.
-                        */
+               if (can_reuse_delta(base_ref, entry, &base_entry)) {
                        oe_set_type(entry, entry->in_pack_type);
                        SET_SIZE(entry, in_pack_size); /* delta size */
                        SET_DELTA_SIZE(entry, in_pack_size);
index 4d30001950ae176201d47f745acfe0a2ea73d7cc..95740f4f0e71de95484edf53a2b86dc71952c5a7 100644 (file)
@@ -1834,7 +1834,7 @@ static void prepare_shallow_update(struct command *commands,
        /*
         * keep hooks happy by forcing a temporary shallow file via
         * env variable because we can't add --shallow-file to every
-        * command. check_everything_connected() will be done with
+        * command. check_connected() will be done with
         * true .git/shallow though.
         */
        setenv(GIT_SHALLOW_FILE_ENVIRONMENT, alt_shallow_file, 1);
index 8e67e09819e1e9445dde80b23f7d9e104799deec..30a661ea0c71f058cdb8bc7626334cb03747fa7c 100644 (file)
@@ -39,7 +39,8 @@ struct show_data {
        enum replace_format format;
 };
 
-static int show_reference(const char *refname, const struct object_id *oid,
+static int show_reference(struct repository *r, const char *refname,
+                         const struct object_id *oid,
                          int flag, void *cb_data)
 {
        struct show_data *data = cb_data;
@@ -56,9 +57,8 @@ static int show_reference(const char *refname, const struct object_id *oid,
                        if (get_oid(refname, &object))
                                return error(_("failed to resolve '%s' as a valid ref"), refname);
 
-                       obj_type = oid_object_info(the_repository, &object,
-                                                  NULL);
-                       repl_type = oid_object_info(the_repository, oid, NULL);
+                       obj_type = oid_object_info(r, &object, NULL);
+                       repl_type = oid_object_info(r, oid, NULL);
 
                        printf("%s (%s) -> %s (%s)\n", refname, type_name(obj_type),
                               oid_to_hex(oid), type_name(repl_type));
index 40844870cfb158b014ee5ea10517c27349e09133..247881189fde2a910bbd993342bb74fe10e06b0e 100644 (file)
@@ -1233,6 +1233,7 @@ static int clone_submodule(const char *path, const char *gitdir, const char *url
        if (gitdir && *gitdir)
                argv_array_pushl(&cp.args, "--separate-git-dir", gitdir, NULL);
 
+       argv_array_push(&cp.args, "--");
        argv_array_push(&cp.args, url);
        argv_array_push(&cp.args, path);
 
index 7f4519ec3b1a6659551fc4ba792cbef151367a4e..a6867586039b507e7802a469a1a3bed82e44bddb 100644 (file)
@@ -13,6 +13,9 @@
 #include "commit-graph.h"
 #include "object-store.h"
 #include "alloc.h"
+#include "hashmap.h"
+#include "replace-object.h"
+#include "progress.h"
 
 #define GRAPH_SIGNATURE 0x43475048 /* "CGPH" */
 #define GRAPH_CHUNKID_OIDFANOUT 0x4f494446 /* "OIDF" */
@@ -56,6 +59,28 @@ static struct commit_graph *alloc_commit_graph(void)
        return g;
 }
 
+extern int read_replace_refs;
+
+static int commit_graph_compatible(struct repository *r)
+{
+       if (!r->gitdir)
+               return 0;
+
+       if (read_replace_refs) {
+               prepare_replace_object(r);
+               if (hashmap_get_size(&r->objects->replace_map->map))
+                       return 0;
+       }
+
+       prepare_commit_graft(r);
+       if (r->parsed_objects && r->parsed_objects->grafts_nr)
+               return 0;
+       if (is_repository_shallow(r))
+               return 0;
+
+       return 1;
+}
+
 struct commit_graph *load_commit_graph_one(const char *graph_file)
 {
        void *graph_map;
@@ -224,6 +249,9 @@ static int prepare_commit_graph(struct repository *r)
                 */
                return 0;
 
+       if (!commit_graph_compatible(r))
+               return 0;
+
        obj_dir = r->objects->objectdir;
        prepare_commit_graph_one(r, obj_dir);
        prepare_alt_odb(r);
@@ -252,10 +280,10 @@ int generation_numbers_enabled(struct repository *r)
        return !!first_generation;
 }
 
-static void close_commit_graph(void)
+void close_commit_graph(struct repository *r)
 {
-       free_commit_graph(the_repository->objects->commit_graph);
-       the_repository->objects->commit_graph = NULL;
+       free_commit_graph(r->objects->commit_graph);
+       r->objects->commit_graph = NULL;
 }
 
 static int bsearch_graph(struct commit_graph *g, struct object_id *oid, uint32_t *pos)
@@ -567,6 +595,8 @@ struct packed_oid_list {
        struct object_id *list;
        int nr;
        int alloc;
+       struct progress *progress;
+       int progress_done;
 };
 
 static int add_packed_commits(const struct object_id *oid,
@@ -579,6 +609,9 @@ static int add_packed_commits(const struct object_id *oid,
        off_t offset = nth_packed_object_offset(pack, pos);
        struct object_info oi = OBJECT_INFO_INIT;
 
+       if (list->progress)
+               display_progress(list->progress, ++list->progress_done);
+
        oi.typep = &type;
        if (packed_object_info(the_repository, pack, offset, &oi) < 0)
                die(_("unable to get type of object %s"), oid_to_hex(oid));
@@ -606,12 +639,18 @@ static void add_missing_parents(struct packed_oid_list *oids, struct commit *com
        }
 }
 
-static void close_reachable(struct packed_oid_list *oids)
+static void close_reachable(struct packed_oid_list *oids, int report_progress)
 {
        int i;
        struct commit *commit;
+       struct progress *progress = NULL;
+       int j = 0;
 
+       if (report_progress)
+               progress = start_delayed_progress(
+                       _("Annotating commits in commit graph"), 0);
        for (i = 0; i < oids->nr; i++) {
+               display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
                if (commit)
                        commit->object.flags |= UNINTERESTING;
@@ -623,6 +662,7 @@ static void close_reachable(struct packed_oid_list *oids)
         * closure.
         */
        for (i = 0; i < oids->nr; i++) {
+               display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
 
                if (commit && !parse_commit(commit))
@@ -630,19 +670,28 @@ static void close_reachable(struct packed_oid_list *oids)
        }
 
        for (i = 0; i < oids->nr; i++) {
+               display_progress(progress, ++j);
                commit = lookup_commit(the_repository, &oids->list[i]);
 
                if (commit)
                        commit->object.flags &= ~UNINTERESTING;
        }
+       stop_progress(&progress);
 }
 
-static void compute_generation_numbers(struct packed_commit_list* commits)
+static void compute_generation_numbers(struct packed_commit_list* commits,
+                                      int report_progress)
 {
        int i;
        struct commit_list *list = NULL;
+       struct progress *progress = NULL;
 
+       if (report_progress)
+               progress = start_progress(
+                       _("Computing commit graph generation numbers"),
+                       commits->nr);
        for (i = 0; i < commits->nr; i++) {
+               display_progress(progress, i + 1);
                if (commits->list[i]->generation != GENERATION_NUMBER_INFINITY &&
                    commits->list[i]->generation != GENERATION_NUMBER_ZERO)
                        continue;
@@ -674,6 +723,7 @@ static void compute_generation_numbers(struct packed_commit_list* commits)
                        }
                }
        }
+       stop_progress(&progress);
 }
 
 static int add_ref_to_list(const char *refname,
@@ -686,19 +736,20 @@ static int add_ref_to_list(const char *refname,
        return 0;
 }
 
-void write_commit_graph_reachable(const char *obj_dir, int append)
+void write_commit_graph_reachable(const char *obj_dir, int append,
+                                 int report_progress)
 {
        struct string_list list;
 
        string_list_init(&list, 1);
        for_each_ref(add_ref_to_list, &list);
-       write_commit_graph(obj_dir, NULL, &list, append);
+       write_commit_graph(obj_dir, NULL, &list, append, report_progress);
 }
 
 void write_commit_graph(const char *obj_dir,
                        struct string_list *pack_indexes,
                        struct string_list *commit_hex,
-                       int append)
+                       int append, int report_progress)
 {
        struct packed_oid_list oids;
        struct packed_commit_list commits;
@@ -711,9 +762,15 @@ void write_commit_graph(const char *obj_dir,
        int num_chunks;
        int num_extra_edges;
        struct commit_list *parent;
+       struct progress *progress = NULL;
+
+       if (!commit_graph_compatible(the_repository))
+               return;
 
        oids.nr = 0;
        oids.alloc = approximate_object_count() / 4;
+       oids.progress = NULL;
+       oids.progress_done = 0;
 
        if (append) {
                prepare_commit_graph_one(the_repository, obj_dir);
@@ -740,6 +797,11 @@ void write_commit_graph(const char *obj_dir,
                int dirlen;
                strbuf_addf(&packname, "%s/pack/", obj_dir);
                dirlen = packname.len;
+               if (report_progress) {
+                       oids.progress = start_delayed_progress(
+                               _("Finding commits for commit graph"), 0);
+                       oids.progress_done = 0;
+               }
                for (i = 0; i < pack_indexes->nr; i++) {
                        struct packed_git *p;
                        strbuf_setlen(&packname, dirlen);
@@ -752,15 +814,21 @@ void write_commit_graph(const char *obj_dir,
                        for_each_object_in_pack(p, add_packed_commits, &oids, 0);
                        close_pack(p);
                }
+               stop_progress(&oids.progress);
                strbuf_release(&packname);
        }
 
        if (commit_hex) {
+               if (report_progress)
+                       progress = start_delayed_progress(
+                               _("Finding commits for commit graph"),
+                               commit_hex->nr);
                for (i = 0; i < commit_hex->nr; i++) {
                        const char *end;
                        struct object_id oid;
                        struct commit *result;
 
+                       display_progress(progress, i + 1);
                        if (commit_hex->items[i].string &&
                            parse_oid_hex(commit_hex->items[i].string, &oid, &end))
                                continue;
@@ -773,12 +841,18 @@ void write_commit_graph(const char *obj_dir,
                                oids.nr++;
                        }
                }
+               stop_progress(&progress);
        }
 
-       if (!pack_indexes && !commit_hex)
+       if (!pack_indexes && !commit_hex) {
+               if (report_progress)
+                       oids.progress = start_delayed_progress(
+                               _("Finding commits for commit graph"), 0);
                for_each_packed_object(add_packed_commits, &oids, 0);
+               stop_progress(&oids.progress);
+       }
 
-       close_reachable(&oids);
+       close_reachable(&oids, report_progress);
 
        QSORT(oids.list, oids.nr, commit_compare);
 
@@ -818,7 +892,7 @@ void write_commit_graph(const char *obj_dir,
        if (commits.nr >= GRAPH_PARENT_MISSING)
                die(_("too many commits to write graph"));
 
-       compute_generation_numbers(&commits);
+       compute_generation_numbers(&commits, report_progress);
 
        graph_name = get_commit_graph_filename(obj_dir);
        if (safe_create_leading_directories(graph_name))
@@ -864,7 +938,7 @@ void write_commit_graph(const char *obj_dir,
        write_graph_chunk_data(f, GRAPH_OID_LEN, commits.list, commits.nr);
        write_graph_chunk_large_edges(f, commits.list, commits.nr);
 
-       close_commit_graph();
+       close_commit_graph(the_repository);
        finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_FSYNC);
        commit_lock_file(&lk);
 
@@ -897,6 +971,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g)
        int generation_zero = 0;
        struct hashfile *f;
        int devnull;
+       struct progress *progress = NULL;
 
        if (!g) {
                graph_report("no commit-graph file loaded");
@@ -964,11 +1039,14 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g)
        if (verify_commit_graph_error & ~VERIFY_COMMIT_GRAPH_ERROR_HASH)
                return verify_commit_graph_error;
 
+       progress = start_progress(_("Verifying commits in commit graph"),
+                                 g->num_commits);
        for (i = 0; i < g->num_commits; i++) {
                struct commit *graph_commit, *odb_commit;
                struct commit_list *graph_parents, *odb_parents;
                uint32_t max_generation = 0;
 
+               display_progress(progress, i + 1);
                hashcpy(cur_oid.hash, g->chunk_oid_lookup + g->hash_len * i);
 
                graph_commit = lookup_commit(r, &cur_oid);
@@ -1045,6 +1123,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g)
                                     graph_commit->date,
                                     odb_commit->date);
        }
+       stop_progress(&progress);
 
        return verify_commit_graph_error;
 }
index b05047676514e4d031ac90de50510eb33a4b6db6..9db40b4d3aadb75b4dcea5027d07d373bdf169e1 100644 (file)
@@ -60,14 +60,16 @@ struct commit_graph *load_commit_graph_one(const char *graph_file);
  */
 int generation_numbers_enabled(struct repository *r);
 
-void write_commit_graph_reachable(const char *obj_dir, int append);
+void write_commit_graph_reachable(const char *obj_dir, int append,
+                                 int report_progress);
 void write_commit_graph(const char *obj_dir,
                        struct string_list *pack_indexes,
                        struct string_list *commit_hex,
-                       int append);
+                       int append, int report_progress);
 
 int verify_commit_graph(struct repository *r, struct commit_graph *g);
 
+void close_commit_graph(struct repository *);
 void free_commit_graph(struct commit_graph *);
 
 #endif
index a7808430e1a0a9187f4771eef0546924e00a3472..9f79ce0a22946174376d247127027e4a0ad3c1e9 100644 (file)
@@ -561,7 +561,8 @@ int can_all_from_reach_with_flag(struct object_array *from,
                from_one = deref_tag(the_repository, from_one,
                                     "a from object", 0);
                if (!from_one || from_one->type != OBJ_COMMIT) {
-                       /* no way to tell if this is reachable by
+                       /*
+                        * no way to tell if this is reachable by
                         * looking at the ancestry chain alone, so
                         * leave a note to ourselves not to worry about
                         * this object anymore.
@@ -625,10 +626,7 @@ int can_all_from_reach_with_flag(struct object_array *from,
        }
 
 cleanup:
-       for (i = 0; i < nr_commits; i++) {
-               clear_commit_marks(list[i], RESULT);
-               clear_commit_marks(list[i], assign_flag);
-       }
+       clear_commit_marks_many(nr_commits, list, RESULT | assign_flag);
        free(list);
 
        for (i = 0; i < from->nr; i++)
index d0f199e12286983c3f9f23b6567dc78a2ceeaf79..dc8a39d52a1c31f979068a34bbdeeca14f3a7547 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -209,7 +209,7 @@ static int read_graft_file(struct repository *r, const char *graft_file)
        return 0;
 }
 
-static void prepare_commit_graft(struct repository *r)
+void prepare_commit_graft(struct repository *r)
 {
        char *graft_file;
 
index 2b1a73438873f20e2c9e570121a2e024d7762fbe..1d260d62f57a24864986252892faa89c17572210 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -202,6 +202,7 @@ typedef int (*each_commit_graft_fn)(const struct commit_graft *, void *);
 
 struct commit_graft *read_graft_line(struct strbuf *line);
 int register_commit_graft(struct repository *r, struct commit_graft *, int);
+void prepare_commit_graft(struct repository *r);
 struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid);
 
 /* largest positive number a signed 32-bit integer can contain */
index f9725730f4a3fb9303427c5c0e11eff9faf2ca72..b635cd07d8d80ea14b86e72da5dcaee1fb4ab11a 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef DELTA_ISLANDS_H
 #define DELTA_ISLANDS_H
 
+struct object_id;
+struct packing_data;
+struct commit;
+
 int island_delta_cmp(const struct object_id *a, const struct object_id *b);
 int in_same_island(const struct object_id *, const struct object_id *);
 void resolve_tree_islands(int progress, struct packing_data *to_pack);
index 7cdfdd0c020e37abbc30624b2ea1bcf4ef0ddfee..d487966935e2d81aeece7f57f382c941d14325d7 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef __EWOK_RLW_H__
 #define __EWOK_RLW_H__
 
+#include "ewok.h"
+
 #define RLW_RUNNING_BITS (sizeof(eword_t) * 4)
 #define RLW_LITERAL_BITS (sizeof(eword_t) * 8 - 1 - RLW_RUNNING_BITS)
 
diff --git a/fsck.c b/fsck.c
index a0cee0be590020e4ff4b42da86c322ba4d0010ae..38624d251126ed5a75cd6b8e8b7adfddbb29b283 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -10,7 +10,6 @@
 #include "fsck.h"
 #include "refs.h"
 #include "utf8.h"
-#include "sha1-array.h"
 #include "decorate.h"
 #include "oidset.h"
 #include "packfile.h"
@@ -67,6 +66,8 @@ static struct oidset gitmodules_done = OIDSET_INIT;
        FUNC(GITMODULES_LARGE, ERROR) \
        FUNC(GITMODULES_NAME, ERROR) \
        FUNC(GITMODULES_SYMLINK, ERROR) \
+       FUNC(GITMODULES_URL, ERROR) \
+       FUNC(GITMODULES_PATH, ERROR) \
        /* warnings */ \
        FUNC(BAD_FILEMODE, WARN) \
        FUNC(EMPTY_NAME, WARN) \
@@ -182,40 +183,37 @@ static int fsck_msg_type(enum fsck_msg_id msg_id,
 
 static void init_skiplist(struct fsck_options *options, const char *path)
 {
-       static struct oid_array skiplist = OID_ARRAY_INIT;
-       int sorted, fd;
-       char buffer[GIT_MAX_HEXSZ + 1];
+       FILE *fp;
+       struct strbuf sb = STRBUF_INIT;
        struct object_id oid;
 
-       if (options->skiplist)
-               sorted = options->skiplist->sorted;
-       else {
-               sorted = 1;
-               options->skiplist = &skiplist;
-       }
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0)
+       fp = fopen(path, "r");
+       if (!fp)
                die("Could not open skip list: %s", path);
-       for (;;) {
+       while (!strbuf_getline(&sb, fp)) {
                const char *p;
-               int result = read_in_full(fd, buffer, sizeof(buffer));
-               if (result < 0)
-                       die_errno("Could not read '%s'", path);
-               if (!result)
-                       break;
-               if (parse_oid_hex(buffer, &oid, &p) || *p != '\n')
-                       die("Invalid SHA-1: %s", buffer);
-               oid_array_append(&skiplist, &oid);
-               if (sorted && skiplist.nr > 1 &&
-                               oidcmp(&skiplist.oid[skiplist.nr - 2],
-                                      &oid) > 0)
-                       sorted = 0;
-       }
-       close(fd);
+               const char *hash;
 
-       if (sorted)
-               skiplist.sorted = 1;
+               /*
+                * Allow trailing comments, leading whitespace
+                * (including before commits), and empty or whitespace
+                * only lines.
+                */
+               hash = strchr(sb.buf, '#');
+               if (hash)
+                       strbuf_setlen(&sb, hash - sb.buf);
+               strbuf_trim(&sb);
+               if (!sb.len)
+                       continue;
+
+               if (parse_oid_hex(sb.buf, &oid, &p) || *p != '\0')
+                       die("Invalid SHA-1: %s", sb.buf);
+               oidset_insert(&options->skiplist, &oid);
+       }
+       if (ferror(fp))
+               die_errno("Could not read '%s'", path);
+       fclose(fp);
+       strbuf_release(&sb);
 }
 
 static int parse_msg_type(const char *str)
@@ -320,9 +318,7 @@ static void append_msg_id(struct strbuf *sb, const char *msg_id)
 
 static int object_on_skiplist(struct fsck_options *opts, struct object *obj)
 {
-       if (opts && opts->skiplist && obj)
-               return oid_array_lookup(opts->skiplist, &obj->oid) >= 0;
-       return 0;
+       return opts && obj && oidset_contains(&opts->skiplist, &obj->oid);
 }
 
 __attribute__((format (printf, 4, 5)))
@@ -992,6 +988,18 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
                                    FSCK_MSG_GITMODULES_NAME,
                                    "disallowed submodule name: %s",
                                    name);
+       if (!strcmp(key, "url") && value &&
+           looks_like_command_line_option(value))
+               data->ret |= report(data->options, data->obj,
+                                   FSCK_MSG_GITMODULES_URL,
+                                   "disallowed submodule url: %s",
+                                   value);
+       if (!strcmp(key, "path") && value &&
+           looks_like_command_line_option(value))
+               data->ret |= report(data->options, data->obj,
+                                   FSCK_MSG_GITMODULES_PATH,
+                                   "disallowed submodule path: %s",
+                                   value);
        free(name);
 
        return 0;
diff --git a/fsck.h b/fsck.h
index 0c7e8c9428bbc808abf27ff5dfe77d8d7309b470..b95595ae5fee6c065c4f54ad66ddc0edb8824d37 100644 (file)
--- a/fsck.h
+++ b/fsck.h
@@ -1,6 +1,8 @@
 #ifndef GIT_FSCK_H
 #define GIT_FSCK_H
 
+#include "oidset.h"
+
 #define FSCK_ERROR 1
 #define FSCK_WARN 2
 #define FSCK_IGNORE 3
@@ -35,12 +37,12 @@ struct fsck_options {
        fsck_error error_func;
        unsigned strict:1;
        int *msg_type;
-       struct oid_array *skiplist;
+       struct oidset skiplist;
        struct decoration *object_names;
 };
 
-#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL }
-#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1, NULL }
+#define FSCK_OPTIONS_DEFAULT { NULL, fsck_error_function, 0, NULL, OIDSET_INIT }
+#define FSCK_OPTIONS_STRICT { NULL, fsck_error_function, 1, NULL, OIDSET_INIT }
 
 /* descend in all linked child objects
  * the return value is:
index 797344764510e0a2b09bf91af08c528411a9025b..45b6ee9c0ec14e924a5864fa31d93f0ca65b32d0 100755 (executable)
@@ -553,15 +553,15 @@ then
        # Note: incompatibility with --interactive is just a strong warning;
        #       git-rebase.txt caveats with "unless you know what you are doing"
        test -n "$rebase_merges" &&
-               die "$(gettext "error: cannot combine '--preserve_merges' with '--rebase-merges'")"
+               die "$(gettext "error: cannot combine '--preserve-merges' with '--rebase-merges'")"
 fi
 
 if test -n "$rebase_merges"
 then
        test -n "$strategy_opts" &&
-               die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy-option'")"
+               die "$(gettext "error: cannot combine '--rebase-merges' with '--strategy-option'")"
        test -n "$strategy" &&
-               die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy'")"
+               die "$(gettext "error: cannot combine '--rebase-merges' with '--strategy'")"
 fi
 
 if test -z "$rebase_root"
diff --git a/git.c b/git.c
index a6f4b44af520627bd1d7caaaf38ba6356ef807b3..5920f8019bb3b26db0c7c50f9ea02f8ff96230e8 100644 (file)
--- a/git.c
+++ b/git.c
@@ -675,6 +675,8 @@ static void execv_dashed_external(const char **argv)
 static int run_argv(int *argcp, const char ***argv)
 {
        int done_alias = 0;
+       struct string_list cmd_list = STRING_LIST_INIT_NODUP;
+       struct string_list_item *seen;
 
        while (1) {
                /*
@@ -692,17 +694,37 @@ static int run_argv(int *argcp, const char ***argv)
                /* .. then try the external ones */
                execv_dashed_external(*argv);
 
-               /* It could be an alias -- this works around the insanity
+               seen = unsorted_string_list_lookup(&cmd_list, *argv[0]);
+               if (seen) {
+                       int i;
+                       struct strbuf sb = STRBUF_INIT;
+                       for (i = 0; i < cmd_list.nr; i++) {
+                               struct string_list_item *item = &cmd_list.items[i];
+
+                               strbuf_addf(&sb, "\n  %s", item->string);
+                               if (item == seen)
+                                       strbuf_addstr(&sb, " <==");
+                               else if (i == cmd_list.nr - 1)
+                                       strbuf_addstr(&sb, " ==>");
+                       }
+                       die(_("alias loop detected: expansion of '%s' does"
+                             " not terminate:%s"), cmd_list.items[0].string, sb.buf);
+               }
+
+               string_list_append(&cmd_list, *argv[0]);
+
+               /*
+                * It could be an alias -- this works around the insanity
                 * of overriding "git log" with "git show" by having
                 * alias.log = show
                 */
-               if (done_alias)
-                       break;
                if (!handle_alias(argcp, argv))
                        break;
                done_alias = 1;
        }
 
+       string_list_clear(&cmd_list, 0);
+
        return done_alias;
 }
 
index fc18acc7d913d170797b65b4f80071bce5310ba7..83906b09c173894111383b3fc3a0ec7e398373c7 100644 (file)
@@ -42,6 +42,8 @@
  * of the given strings.
  */
 
+#include "strbuf.h"
+
 struct json_writer
 {
        /*
index fa87341e678ba5908963e7b2795970c6bac5dcf7..0684dab77965b6abd0f8429bc53cd936a826482b 100644 (file)
@@ -1274,14 +1274,14 @@ static int merge_submodule(struct merge_options *o,
        return 0;
 }
 
-static int merge_file_1(struct merge_options *o,
-                       const struct diff_filespec *one,
-                       const struct diff_filespec *a,
-                       const struct diff_filespec *b,
-                       const char *filename,
-                       const char *branch1,
-                       const char *branch2,
-                       struct merge_file_info *result)
+static int merge_mode_and_contents(struct merge_options *o,
+                                  const struct diff_filespec *one,
+                                  const struct diff_filespec *a,
+                                  const struct diff_filespec *b,
+                                  const char *filename,
+                                  const char *branch1,
+                                  const char *branch2,
+                                  struct merge_file_info *result)
 {
        result->merge = 0;
        result->clean = 1;
@@ -1366,56 +1366,6 @@ static int merge_file_1(struct merge_options *o,
        return 0;
 }
 
-static int merge_file_special_markers(struct merge_options *o,
-                                     const struct diff_filespec *one,
-                                     const struct diff_filespec *a,
-                                     const struct diff_filespec *b,
-                                     const char *target_filename,
-                                     const char *branch1,
-                                     const char *filename1,
-                                     const char *branch2,
-                                     const char *filename2,
-                                     struct merge_file_info *mfi)
-{
-       char *side1 = NULL;
-       char *side2 = NULL;
-       int ret;
-
-       if (filename1)
-               side1 = xstrfmt("%s:%s", branch1, filename1);
-       if (filename2)
-               side2 = xstrfmt("%s:%s", branch2, filename2);
-
-       ret = merge_file_1(o, one, a, b, target_filename,
-                          side1 ? side1 : branch1,
-                          side2 ? side2 : branch2, mfi);
-
-       free(side1);
-       free(side2);
-       return ret;
-}
-
-static int merge_file_one(struct merge_options *o,
-                         const char *path,
-                         const struct object_id *o_oid, int o_mode,
-                         const struct object_id *a_oid, int a_mode,
-                         const struct object_id *b_oid, int b_mode,
-                         const char *branch1,
-                         const char *branch2,
-                         struct merge_file_info *mfi)
-{
-       struct diff_filespec one, a, b;
-
-       one.path = a.path = b.path = (char *)path;
-       oidcpy(&one.oid, o_oid);
-       one.mode = o_mode;
-       oidcpy(&a.oid, a_oid);
-       a.mode = a_mode;
-       oidcpy(&b.oid, b_oid);
-       b.mode = b_mode;
-       return merge_file_1(o, &one, &a, &b, path, branch1, branch2, mfi);
-}
-
 static int handle_rename_via_dir(struct merge_options *o,
                                 struct diff_filepair *pair,
                                 const char *rename_branch,
@@ -1659,11 +1609,8 @@ static int handle_rename_rename_1to2(struct merge_options *o,
                struct merge_file_info mfi;
                struct diff_filespec other;
                struct diff_filespec *add;
-               if (merge_file_one(o, one->path,
-                                &one->oid, one->mode,
-                                &a->oid, a->mode,
-                                &b->oid, b->mode,
-                                ci->branch1, ci->branch2, &mfi))
+               if (merge_mode_and_contents(o, one, a, b, one->path,
+                                           ci->branch1, ci->branch2, &mfi))
                        return -1;
 
                /*
@@ -1729,14 +1676,10 @@ static int handle_rename_rename_2to1(struct merge_options *o,
 
        path_side_1_desc = xstrfmt("%s (was %s)", path, a->path);
        path_side_2_desc = xstrfmt("%s (was %s)", path, b->path);
-       if (merge_file_special_markers(o, a, c1, &ci->ren1_other,
-                                      path_side_1_desc,
-                                      o->branch1, c1->path,
-                                      o->branch2, ci->ren1_other.path, &mfi_c1) ||
-           merge_file_special_markers(o, b, &ci->ren2_other, c2,
-                                      path_side_2_desc,
-                                      o->branch1, ci->ren2_other.path,
-                                      o->branch2, c2->path, &mfi_c2))
+       if (merge_mode_and_contents(o, a, c1, &ci->ren1_other, path_side_1_desc,
+                                   o->branch1, o->branch2, &mfi_c1) ||
+           merge_mode_and_contents(o, b, &ci->ren2_other, c2, path_side_2_desc,
+                                   o->branch1, o->branch2, &mfi_c2))
                return -1;
        free(path_side_1_desc);
        free(path_side_2_desc);
@@ -2766,12 +2709,23 @@ static int process_renames(struct merge_options *o,
                                       ren1_dst, branch2);
                                if (o->call_depth) {
                                        struct merge_file_info mfi;
-                                       if (merge_file_one(o, ren1_dst, &null_oid, 0,
-                                                          &ren1->pair->two->oid,
-                                                          ren1->pair->two->mode,
-                                                          &dst_other.oid,
-                                                          dst_other.mode,
-                                                          branch1, branch2, &mfi)) {
+                                       struct diff_filespec one, a, b;
+
+                                       oidcpy(&one.oid, &null_oid);
+                                       one.mode = 0;
+                                       one.path = ren1->pair->two->path;
+
+                                       oidcpy(&a.oid, &ren1->pair->two->oid);
+                                       a.mode = ren1->pair->two->mode;
+                                       a.path = one.path;
+
+                                       oidcpy(&b.oid, &dst_other.oid);
+                                       b.mode = dst_other.mode;
+                                       b.path = one.path;
+
+                                       if (merge_mode_and_contents(o, &one, &a, &b, ren1_dst,
+                                                                   branch1, branch2,
+                                                                   &mfi)) {
                                                clean_merge = -1;
                                                goto cleanup_and_return;
                                        }
@@ -3021,13 +2975,13 @@ static int handle_modify_delete(struct merge_options *o,
                                    _("modify"), _("modified"));
 }
 
-static int merge_content(struct merge_options *o,
-                        const char *path,
-                        int is_dirty,
-                        struct object_id *o_oid, int o_mode,
-                        struct object_id *a_oid, int a_mode,
-                        struct object_id *b_oid, int b_mode,
-                        struct rename_conflict_info *rename_conflict_info)
+static int handle_content_merge(struct merge_options *o,
+                               const char *path,
+                               int is_dirty,
+                               struct object_id *o_oid, int o_mode,
+                               struct object_id *a_oid, int a_mode,
+                               struct object_id *b_oid, int b_mode,
+                               struct rename_conflict_info *rename_conflict_info)
 {
        const char *reason = _("content");
        const char *path1 = NULL, *path2 = NULL;
@@ -3059,14 +3013,16 @@ static int merge_content(struct merge_options *o,
                path2 = (rename_conflict_info->pair2 ||
                         o->branch2 == rename_conflict_info->branch1) ?
                        pair1->two->path : pair1->one->path;
+               one.path = pair1->one->path;
+               a.path = (char *)path1;
+               b.path = (char *)path2;
 
                if (dir_in_way(path, !o->call_depth,
                               S_ISGITLINK(pair1->two->mode)))
                        df_conflict_remains = 1;
        }
-       if (merge_file_special_markers(o, &one, &a, &b, path,
-                                      o->branch1, path1,
-                                      o->branch2, path2, &mfi))
+       if (merge_mode_and_contents(o, &one, &a, &b, path,
+                                   o->branch1, o->branch2, &mfi))
                return -1;
 
        /*
@@ -3157,9 +3113,9 @@ static int handle_rename_normal(struct merge_options *o,
                                struct rename_conflict_info *ci)
 {
        /* Merge the content and write it out */
-       return merge_content(o, path, was_dirty(o, path),
-                            o_oid, o_mode, a_oid, a_mode, b_oid, b_mode,
-                            ci);
+       return handle_content_merge(o, path, was_dirty(o, path),
+                                   o_oid, o_mode, a_oid, a_mode, b_oid, b_mode,
+                                   ci);
 }
 
 /* Per entry merge function */
@@ -3283,9 +3239,11 @@ static int process_entry(struct merge_options *o,
                /* Case C: Added in both (check for same permissions) and */
                /* case D: Modified in both, but differently. */
                int is_dirty = 0; /* unpack_trees would have bailed if dirty */
-               clean_merge = merge_content(o, path, is_dirty,
-                                           o_oid, o_mode, a_oid, a_mode, b_oid, b_mode,
-                                           NULL);
+               clean_merge = handle_content_merge(o, path, is_dirty,
+                                                  o_oid, o_mode,
+                                                  a_oid, a_mode,
+                                                  b_oid, b_mode,
+                                                  NULL);
        } else if (!o_oid && !a_oid && !b_oid) {
                /*
                 * this entry was deleted altogether. a_mode == 0 means
diff --git a/midx.c b/midx.c
index 06aef564000d68441ac3966fd79ce535a3923b15..ea2f3ffe2e21700038eabf00aa975e5cc111a47f 100644 (file)
--- a/midx.c
+++ b/midx.c
@@ -7,6 +7,7 @@
 #include "object-store.h"
 #include "sha1-lookup.h"
 #include "midx.h"
+#include "progress.h"
 
 #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
 #define MIDX_VERSION 1
@@ -76,24 +77,18 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
        m->local = local;
 
        m->signature = get_be32(m->data);
-       if (m->signature != MIDX_SIGNATURE) {
-               error(_("multi-pack-index signature 0x%08x does not match signature 0x%08x"),
+       if (m->signature != MIDX_SIGNATURE)
+               die(_("multi-pack-index signature 0x%08x does not match signature 0x%08x"),
                      m->signature, MIDX_SIGNATURE);
-               goto cleanup_fail;
-       }
 
        m->version = m->data[MIDX_BYTE_FILE_VERSION];
-       if (m->version != MIDX_VERSION) {
-               error(_("multi-pack-index version %d not recognized"),
+       if (m->version != MIDX_VERSION)
+               die(_("multi-pack-index version %d not recognized"),
                      m->version);
-               goto cleanup_fail;
-       }
 
        hash_version = m->data[MIDX_BYTE_HASH_VERSION];
-       if (hash_version != MIDX_HASH_VERSION) {
-               error(_("hash version %u does not match"), hash_version);
-               goto cleanup_fail;
-       }
+       if (hash_version != MIDX_HASH_VERSION)
+               die(_("hash version %u does not match"), hash_version);
        m->hash_len = MIDX_HASH_LEN;
 
        m->num_chunks = m->data[MIDX_BYTE_NUM_CHUNKS];
@@ -106,6 +101,9 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
                uint64_t chunk_offset = get_be64(m->data + MIDX_HEADER_SIZE + 4 +
                                                 MIDX_CHUNKLOOKUP_WIDTH * i);
 
+               if (chunk_offset >= m->data_len)
+                       die(_("invalid chunk offset (too large)"));
+
                switch (chunk_id) {
                        case MIDX_CHUNKID_PACKNAMES:
                                m->chunk_pack_names = m->data + chunk_offset;
@@ -160,12 +158,10 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir, int local
 
                cur_pack_name += strlen(cur_pack_name) + 1;
 
-               if (i && strcmp(m->pack_names[i], m->pack_names[i - 1]) <= 0) {
-                       error(_("multi-pack-index pack names out of order: '%s' before '%s'"),
+               if (i && strcmp(m->pack_names[i], m->pack_names[i - 1]) <= 0)
+                       die(_("multi-pack-index pack names out of order: '%s' before '%s'"),
                              m->pack_names[i - 1],
                              m->pack_names[i]);
-                       goto cleanup_fail;
-               }
        }
 
        return m;
@@ -202,7 +198,8 @@ int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id)
        struct strbuf pack_name = STRBUF_INIT;
 
        if (pack_int_id >= m->num_packs)
-               BUG("bad pack-int-id");
+               die(_("bad pack-int-id: %u (%u total packs"),
+                   pack_int_id, m->num_packs);
 
        if (m->packs[pack_int_id])
                return 0;
@@ -241,7 +238,7 @@ static off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos)
        offset32 = get_be32(offset_data + sizeof(uint32_t));
 
        if (m->chunk_large_offsets && offset32 & MIDX_LARGE_OFFSET_NEEDED) {
-               if (sizeof(offset32) < sizeof(uint64_t))
+               if (sizeof(off_t) < sizeof(uint64_t))
                        die(_("multi-pack-index stores a 64-bit offset, but off_t is too small"));
 
                offset32 ^= MIDX_LARGE_OFFSET_NEEDED;
@@ -928,3 +925,83 @@ void clear_midx_file(const char *object_dir)
 
        free(midx);
 }
+
+static int verify_midx_error;
+
+static void midx_report(const char *fmt, ...)
+{
+       va_list ap;
+       verify_midx_error = 1;
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       fprintf(stderr, "\n");
+       va_end(ap);
+}
+
+int verify_midx_file(const char *object_dir)
+{
+       uint32_t i;
+       struct progress *progress = NULL;
+       struct multi_pack_index *m = load_multi_pack_index(object_dir, 1);
+       verify_midx_error = 0;
+
+       if (!m)
+               return 0;
+
+       for (i = 0; i < m->num_packs; i++) {
+               if (prepare_midx_pack(m, i))
+                       midx_report("failed to load pack in position %d", i);
+       }
+
+       for (i = 0; i < 255; i++) {
+               uint32_t oid_fanout1 = ntohl(m->chunk_oid_fanout[i]);
+               uint32_t oid_fanout2 = ntohl(m->chunk_oid_fanout[i + 1]);
+
+               if (oid_fanout1 > oid_fanout2)
+                       midx_report(_("oid fanout out of order: fanout[%d] = %"PRIx32" > %"PRIx32" = fanout[%d]"),
+                                   i, oid_fanout1, oid_fanout2, i + 1);
+       }
+
+       for (i = 0; i < m->num_objects - 1; i++) {
+               struct object_id oid1, oid2;
+
+               nth_midxed_object_oid(&oid1, m, i);
+               nth_midxed_object_oid(&oid2, m, i + 1);
+
+               if (oidcmp(&oid1, &oid2) >= 0)
+                       midx_report(_("oid lookup out of order: oid[%d] = %s >= %s = oid[%d]"),
+                                   i, oid_to_hex(&oid1), oid_to_hex(&oid2), i + 1);
+       }
+
+       progress = start_progress(_("Verifying object offsets"), m->num_objects);
+       for (i = 0; i < m->num_objects; i++) {
+               struct object_id oid;
+               struct pack_entry e;
+               off_t m_offset, p_offset;
+
+               nth_midxed_object_oid(&oid, m, i);
+               if (!fill_midx_entry(&oid, &e, m)) {
+                       midx_report(_("failed to load pack entry for oid[%d] = %s"),
+                                   i, oid_to_hex(&oid));
+                       continue;
+               }
+
+               if (open_pack_index(e.p)) {
+                       midx_report(_("failed to load pack-index for packfile %s"),
+                                   e.p->pack_name);
+                       break;
+               }
+
+               m_offset = e.offset;
+               p_offset = find_pack_entry_one(oid.hash, e.p);
+
+               if (m_offset != p_offset)
+                       midx_report(_("incorrect object offset for oid[%d] = %s: %"PRIx64" != %"PRIx64),
+                                   i, oid_to_hex(&oid), m_offset, p_offset);
+
+               display_progress(progress, i + 1);
+       }
+       stop_progress(&progress);
+
+       return verify_midx_error;
+}
diff --git a/midx.h b/midx.h
index a210f1af2af6bd7c7dc2210ac4b5ca398c8c60d1..2d7c9c6cd1d829f3eb6aa924d316e54c6d4e9e00 100644 (file)
--- a/midx.h
+++ b/midx.h
@@ -3,6 +3,9 @@
 
 #include "repository.h"
 
+struct object_id;
+struct pack_entry;
+
 struct multi_pack_index {
        struct multi_pack_index *next;
 
@@ -43,5 +46,6 @@ int prepare_multi_pack_index_one(struct repository *r, const char *object_dir, i
 
 int write_midx_file(const char *object_dir);
 void clear_midx_file(const char *object_dir);
+int verify_midx_file(const char *object_dir);
 
 #endif
diff --git a/refs.c b/refs.c
index a7a75b4cc0b9b93ec3a56340a711900c76b506ce..bbcac921b6d78fd598380608e7195675aae1d4f6 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1394,17 +1394,50 @@ struct ref_iterator *refs_ref_iterator_begin(
  * non-zero value, stop the iteration and return that value;
  * otherwise, return 0.
  */
+static int do_for_each_repo_ref(struct repository *r, const char *prefix,
+                               each_repo_ref_fn fn, int trim, int flags,
+                               void *cb_data)
+{
+       struct ref_iterator *iter;
+       struct ref_store *refs = get_main_ref_store(r);
+
+       if (!refs)
+               return 0;
+
+       iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
+
+       return do_for_each_repo_ref_iterator(r, iter, fn, cb_data);
+}
+
+struct do_for_each_ref_help {
+       each_ref_fn *fn;
+       void *cb_data;
+};
+
+static int do_for_each_ref_helper(struct repository *r,
+                                 const char *refname,
+                                 const struct object_id *oid,
+                                 int flags,
+                                 void *cb_data)
+{
+       struct do_for_each_ref_help *hp = cb_data;
+
+       return hp->fn(refname, oid, flags, hp->cb_data);
+}
+
 static int do_for_each_ref(struct ref_store *refs, const char *prefix,
                           each_ref_fn fn, int trim, int flags, void *cb_data)
 {
        struct ref_iterator *iter;
+       struct do_for_each_ref_help hp = { fn, cb_data };
 
        if (!refs)
                return 0;
 
        iter = refs_ref_iterator_begin(refs, prefix, trim, flags);
 
-       return do_for_each_ref_iterator(iter, fn, cb_data);
+       return do_for_each_repo_ref_iterator(the_repository, iter,
+                                       do_for_each_ref_helper, &hp);
 }
 
 int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
@@ -1449,12 +1482,11 @@ int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
        return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
 }
 
-int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data)
+int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
 {
-       return do_for_each_ref(get_main_ref_store(r),
-                              git_replace_ref_base, fn,
-                              strlen(git_replace_ref_base),
-                              DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
+       return do_for_each_repo_ref(r, git_replace_ref_base, fn,
+                                   strlen(git_replace_ref_base),
+                                   DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
 int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
@@ -2033,10 +2065,12 @@ int refs_verify_refname_available(struct ref_store *refs,
 int refs_for_each_reflog(struct ref_store *refs, each_ref_fn fn, void *cb_data)
 {
        struct ref_iterator *iter;
+       struct do_for_each_ref_help hp = { fn, cb_data };
 
        iter = refs->be->reflog_iterator_begin(refs);
 
-       return do_for_each_ref_iterator(iter, fn, cb_data);
+       return do_for_each_repo_ref_iterator(the_repository, iter,
+                                            do_for_each_ref_helper, &hp);
 }
 
 int for_each_reflog(each_ref_fn fn, void *cb_data)
diff --git a/refs.h b/refs.h
index bd52c1bbae3a68fe8ca8f9e6cae7cc54bdbf9852..6cc0397679fd55bfdfc72b7a7f4cbf3ee5d028a0 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -276,6 +276,16 @@ struct ref_transaction;
 typedef int each_ref_fn(const char *refname,
                        const struct object_id *oid, int flags, void *cb_data);
 
+/*
+ * The same as each_ref_fn, but also with a repository argument that
+ * contains the repository associated with the callback.
+ */
+typedef int each_repo_ref_fn(struct repository *r,
+                            const char *refname,
+                            const struct object_id *oid,
+                            int flags,
+                            void *cb_data);
+
 /*
  * The following functions invoke the specified callback function for
  * each reference indicated.  If the function ever returns a nonzero
@@ -309,7 +319,7 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
 int for_each_tag_ref(each_ref_fn fn, void *cb_data);
 int for_each_branch_ref(each_ref_fn fn, void *cb_data);
 int for_each_remote_ref(each_ref_fn fn, void *cb_data);
-int for_each_replace_ref(struct repository *r, each_ref_fn fn, void *cb_data);
+int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data);
 int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data);
 int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
                         const char *prefix, void *cb_data);
index 2ac91ac3401c87108b9cdb4983acb7c165df82d9..629e00a122a7a867ae3350ce35469c2ceb1259a1 100644 (file)
@@ -407,15 +407,15 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
 
 struct ref_iterator *current_ref_iter = NULL;
 
-int do_for_each_ref_iterator(struct ref_iterator *iter,
-                            each_ref_fn fn, void *cb_data)
+int do_for_each_repo_ref_iterator(struct repository *r, struct ref_iterator *iter,
+                                 each_repo_ref_fn fn, void *cb_data)
 {
        int retval = 0, ok;
        struct ref_iterator *old_ref_iter = current_ref_iter;
 
        current_ref_iter = iter;
        while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
-               retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
+               retval = fn(r, iter->refname, iter->oid, iter->flags, cb_data);
                if (retval) {
                        /*
                         * If ref_iterator_abort() returns ITER_ERROR,
index 640245d3b9f23a8ae7866dd477a5ed9bbfc71cde..a01a0aff9c77280d7b3e605230af822fdab24ca9 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef REFS_PACKED_BACKEND_H
 #define REFS_PACKED_BACKEND_H
 
+struct ref_transaction;
+
 /*
  * Support for storing references in a `packed-refs` file.
  *
index eda65e73edd2d978e7c07065b888219f42348d87..3bfb89d2b343e958ed094a7fd922f2fd6e0c4178 100644 (file)
@@ -1,7 +1,10 @@
 #ifndef REFS_REF_CACHE_H
 #define REFS_REF_CACHE_H
 
+#include "cache.h"
+
 struct ref_dir;
+struct ref_store;
 
 /*
  * If this ref_cache is filled lazily, this function is used to load
index 04425d6d1e45e2401454e7b89b0ed4b3959926de..f2d8c0123a7724bca18eb76de71748d3760391ee 100644 (file)
@@ -1,8 +1,12 @@
 #ifndef REFS_REFS_INTERNAL_H
 #define REFS_REFS_INTERNAL_H
 
+#include "cache.h"
+#include "refs.h"
 #include "iterator.h"
 
+struct ref_transaction;
+
 /*
  * Data structures and functions for the internal use of the refs
  * module. Code outside of the refs module should use only the public
@@ -282,7 +286,7 @@ int refs_rename_ref_available(struct ref_store *refs,
  *
  *             // Access information about the current reference:
  *             if (!(iter->flags & REF_ISSYMREF))
- *                     printf("%s is %s\n", iter->refname, oid_to_hex(&iter->oid));
+ *                     printf("%s is %s\n", iter->refname, oid_to_hex(iter->oid));
  *
  *             // If you need to peel the reference:
  *             ref_iterator_peel(iter, &oid);
@@ -474,8 +478,9 @@ extern struct ref_iterator *current_ref_iter;
  * adapter between the callback style of reference iteration and the
  * iterator style.
  */
-int do_for_each_ref_iterator(struct ref_iterator *iter,
-                            each_ref_fn fn, void *cb_data);
+int do_for_each_repo_ref_iterator(struct repository *r,
+                                 struct ref_iterator *iter,
+                                 each_repo_ref_fn fn, void *cb_data);
 
 /*
  * Only include per-worktree refs in a do_for_each_ref*() iteration.
index 4ec77ce41848311a912256046bd2bf8dc9ee63c0..e295e87943102c2a1ad903aea1a634d34bf603a0 100644 (file)
@@ -6,7 +6,8 @@
 #include "repository.h"
 #include "commit.h"
 
-static int register_replace_ref(const char *refname,
+static int register_replace_ref(struct repository *r,
+                               const char *refname,
                                const struct object_id *oid,
                                int flag, void *cb_data)
 {
@@ -25,13 +26,13 @@ static int register_replace_ref(const char *refname,
        oidcpy(&repl_obj->replacement, oid);
 
        /* Register new object */
-       if (oidmap_put(the_repository->objects->replace_map, repl_obj))
+       if (oidmap_put(r->objects->replace_map, repl_obj))
                die(_("duplicate replace ref: %s"), refname);
 
        return 0;
 }
 
-static void prepare_replace_object(struct repository *r)
+void prepare_replace_object(struct repository *r)
 {
        if (r->objects->replace_map)
                return;
index 9345e105ddcaa38cf9e856df70d960245a3b696c..16528df942f79e3d7ce65d99e0103395d0c69f51 100644 (file)
@@ -10,6 +10,8 @@ struct replace_object {
        struct object_id replacement;
 };
 
+void prepare_replace_object(struct repository *r);
+
 /*
  * This internal function is only declared here for the benefit of
  * lookup_replace_object().  Please do not call it directly.
index e04ba756d954e03f4c94785f260c2ac9af6a6f9b..b132f7a80ba6fc692069f765caf0b92027b920d8 100644 (file)
@@ -384,6 +384,12 @@ static void warn_multiple_config(const struct object_id *treeish_name,
                        commit_string, name, option);
 }
 
+static void warn_command_line_option(const char *var, const char *value)
+{
+       warning(_("ignoring '%s' which may be interpreted as"
+                 " a command-line option: %s"), var, value);
+}
+
 struct parse_config_parameter {
        struct submodule_cache *cache;
        const struct object_id *treeish_name;
@@ -409,6 +415,8 @@ static int parse_config(const char *var, const char *value, void *data)
        if (!strcmp(item.buf, "path")) {
                if (!value)
                        ret = config_error_nonbool(var);
+               else if (looks_like_command_line_option(value))
+                       warn_command_line_option(var, value);
                else if (!me->overwrite && submodule->path)
                        warn_multiple_config(me->treeish_name, submodule->name,
                                        "path");
@@ -449,6 +457,8 @@ static int parse_config(const char *var, const char *value, void *data)
        } else if (!strcmp(item.buf, "url")) {
                if (!value) {
                        ret = config_error_nonbool(var);
+               } else if (looks_like_command_line_option(value)) {
+                       warn_command_line_option(var, value);
                } else if (!me->overwrite && submodule->url) {
                        warn_multiple_config(me->treeish_name, submodule->name,
                                        "url");
index 3ea6c854606056e1a7d9431dd59518d817768527..4d8dbc7c5f5800bb838a09a8ca87fab8a3de72ab 100644 (file)
--- a/t/README
+++ b/t/README
@@ -401,13 +401,13 @@ This test harness library does the following things:
    consistently when command line arguments --verbose (or -v),
    --debug (or -d), and --immediate (or -i) is given.
 
-Do's, don'ts & things to keep in mind
--------------------------------------
+Do's & don'ts
+-------------
 
 Here are a few examples of things you probably should and shouldn't do
 when writing tests.
 
-Do:
+Here are the "do's:"
 
  - Put all code inside test_expect_success and other assertions.
 
@@ -452,16 +452,21 @@ Do:
    Windows, where the shell (MSYS bash) mangles absolute path names.
    For details, see the commit message of 4114156ae9.
 
-Don't:
+ - Remember that inside the <script> part, the standard output and
+   standard error streams are discarded, and the test harness only
+   reports "ok" or "not ok" to the end user running the tests. Under
+   --verbose, they are shown to help debug the tests.
+
+And here are the "don'ts:"
 
- - exit() within a <script> part.
+ - Don't exit() within a <script> part.
 
    The harness will catch this as a programming error of the test.
    Use test_done instead if you need to stop the tests early (see
    "Skipping tests" below).
 
- - use '! git cmd' when you want to make sure the git command exits
-   with failure in a controlled way by calling "die()".  Instead,
+ - Don't use '! git cmd' when you want to make sure the git command
+   exits with failure in a controlled way by calling "die()".  Instead,
    use 'test_must_fail git cmd'.  This will signal a failure if git
    dies in an unexpected way (e.g. segfault).
 
@@ -469,8 +474,35 @@ Don't:
    platform commands; just use '! cmd'.  We are not in the business
    of verifying that the world given to us sanely works.
 
- - use perl without spelling it as "$PERL_PATH". This is to help our
-   friends on Windows where the platform Perl often adds CR before
+ - Don't feed the output of a git command to a pipe, as in:
+
+     git -C repo ls-files |
+     xargs -n 1 basename |
+     grep foo
+
+   which will discard git's exit code and may mask a crash. In the
+   above example, all exit codes are ignored except grep's.
+
+   Instead, write the output of that command to a temporary
+   file with ">" or assign it to a variable with "x=$(git ...)" rather
+   than pipe it.
+
+ - Don't use command substitution in a way that discards git's exit
+   code. When assigning to a variable, the exit code is not discarded,
+   e.g.:
+
+     x=$(git cat-file -p $sha) &&
+     ...
+
+   is OK because a crash in "git cat-file" will cause the "&&" chain
+   to fail, but:
+
+     test "refs/heads/foo" = "$(git symbolic-ref HEAD)"
+
+   is not OK and a crash in git could go undetected.
+
+ - Don't use perl without spelling it as "$PERL_PATH". This is to help
+   our friends on Windows where the platform Perl often adds CR before
    the end of line, and they bundle Git with a version of Perl that
    does not do so, whose path is specified with $PERL_PATH. Note that we
    provide a "perl" function which uses $PERL_PATH under the hood, so
@@ -478,17 +510,17 @@ Don't:
    (but you do, for example, on a shebang line or in a sub script
    created via "write_script").
 
- - use sh without spelling it as "$SHELL_PATH", when the script can
-   be misinterpreted by broken platform shell (e.g. Solaris).
+ - Don't use sh without spelling it as "$SHELL_PATH", when the script
+   can be misinterpreted by broken platform shell (e.g. Solaris).
 
- - chdir around in tests.  It is not sufficient to chdir to
+ - Don't chdir around in tests.  It is not sufficient to chdir to
    somewhere and then chdir back to the original location later in
    the test, as any intermediate step can fail and abort the test,
    causing the next test to start in an unexpected directory.  Do so
    inside a subshell if necessary.
 
- - save and verify the standard error of compound commands, i.e. group
-   commands, subshells, and shell functions (except test helper
+ - Don't save and verify the standard error of compound commands, i.e.
+   group commands, subshells, and shell functions (except test helper
    functions like 'test_must_fail') like this:
 
      ( cd dir && git cmd ) 2>error &&
@@ -503,7 +535,7 @@ Don't:
      ( cd dir && git cmd 2>../error ) &&
      test_cmp expect error
 
- - Break the TAP output
+ - Don't break the TAP output
 
    The raw output from your test may be interpreted by a TAP harness. TAP
    harnesses will ignore everything they don't know about, but don't step
@@ -523,13 +555,6 @@ Don't:
    but the best indication is to just run the tests with prove(1),
    it'll complain if anything is amiss.
 
-Keep in mind:
-
- - Inside the <script> part, the standard output and standard error
-   streams are discarded, and the test harness only reports "ok" or
-   "not ok" to the end user running the tests. Under --verbose, they
-   are shown to help debugging the tests.
-
 
 Skipping tests
 --------------
@@ -814,6 +839,28 @@ library for your script to use.
    the symbolic link in the file system and a part that does; then only
    the latter part need be protected by a SYMLINKS prerequisite (see below).
 
+ - test_oid_init
+
+   This function loads facts and useful object IDs related to the hash
+   algorithm(s) in use from the files in t/oid-info.
+
+ - test_oid_cache
+
+   This function reads per-hash algorithm information from standard
+   input (usually a heredoc) in the format described in
+   t/oid-info/README.  This is useful for test-specific values, such as
+   object IDs, which must vary based on the hash algorithm.
+
+   Certain fixed values, such as hash sizes and common placeholder
+   object IDs, can be loaded with test_oid_init (described above).
+
+ - test_oid <key>
+
+   This function looks up a value for the hash algorithm in use, based
+   on the key given.  The value must have been loaded using
+   test_oid_init or test_oid_cache.  Providing an unknown key is an
+   error.
+
 Prerequisites
 -------------
 
index ad452707e88b609d4d39e6f12bff9f73df2271c7..08e3684aff223670fb0786d80426d18bb8800a44 100644 (file)
@@ -1,6 +1,7 @@
+#include "test-tool.h"
 #include "cache.h"
 
-int cmd_main(int ac, const char **av)
+int cmd__dump_fsmonitor(int ac, const char **av)
 {
        struct index_state *istate = &the_index;
        int i;
index bd92fb305a239cb4b96d38b4a07fe885e71bbeb3..52870ebbb3ea7b2d69aecb1bb429dbbaf6388b51 100644 (file)
@@ -1,3 +1,4 @@
+#include "test-tool.h"
 #include "cache.h"
 #include "dir.h"
 
@@ -38,7 +39,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)
        strbuf_setlen(base, len);
 }
 
-int cmd_main(int ac, const char **av)
+int cmd__dump_untracked_cache(int ac, const char **av)
 {
        struct untracked_cache *uc;
        struct strbuf base = STRBUF_INIT;
index 630c76d1275485d2d460896407e645116c997916..9cb8a0ea0f8ae7b3da8525b2a354bfa542db93c3 100644 (file)
@@ -1,3 +1,4 @@
+#include "test-tool.h"
 #include "cache.h"
 #include "parse-options.h"
 #include "string-list.h"
@@ -94,11 +95,11 @@ static void show(struct string_list *expect, int *status, const char *fmt, ...)
        strbuf_release(&buf);
 }
 
-int cmd_main(int argc, const char **argv)
+int cmd__parse_options(int argc, const char **argv)
 {
        const char *prefix = "prefix/";
        const char *usage[] = {
-               "test-parse-options <options>",
+               "test-tool parse-options <options>",
                "",
                "A helper function for the parse-options API.",
                NULL
index 30775f986f8067323808f6ccd064067f6c27489b..282d53638446bb2f0c91b81b313852cbadfb3c1f 100644 (file)
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "test-tool.h"
 #include "pkt-line.h"
 
 static void pack_line(const char *line)
@@ -79,7 +80,7 @@ static void unpack_sideband(void)
        }
 }
 
-int cmd_main(int argc, const char **argv)
+int cmd__pkt_line(int argc, const char **argv)
 {
        if (argc < 2)
                die("too few arguments");
index 2762ca656262baa9494d96a2647248f4042a2e01..6a84a53efbf6919c83d3f1fd73786acd92ee7abf 100644 (file)
@@ -15,7 +15,10 @@ static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
        struct commit *c;
        struct commit_list *parent;
 
-       repo_init(&r, gitdir, worktree);
+       setup_git_env(gitdir);
+
+       if (repo_init(&r, gitdir, worktree))
+               die("Couldn't init repo");
 
        c = lookup_commit(&r, commit_oid);
 
@@ -38,7 +41,10 @@ static void test_get_commit_tree_in_graph(const char *gitdir,
        struct commit *c;
        struct tree *tree;
 
-       repo_init(&r, gitdir, worktree);
+       setup_git_env(gitdir);
+
+       if (repo_init(&r, gitdir, worktree))
+               die("Couldn't init repo");
 
        c = lookup_commit(&r, commit_oid);
 
index b87a8c1f229ce51eaa29d37614370c058389ca4b..6b5836dc1b93b85333f2acb9cf1717a4462e209c 100644 (file)
@@ -14,7 +14,9 @@ static struct test_cmd cmds[] = {
        { "delta", cmd__delta },
        { "drop-caches", cmd__drop_caches },
        { "dump-cache-tree", cmd__dump_cache_tree },
+       { "dump-fsmonitor", cmd__dump_fsmonitor },
        { "dump-split-index", cmd__dump_split_index },
+       { "dump-untracked-cache", cmd__dump_untracked_cache },
        { "example-decorate", cmd__example_decorate },
        { "genrandom", cmd__genrandom },
        { "hashmap", cmd__hashmap },
@@ -25,7 +27,9 @@ static struct test_cmd cmds[] = {
        { "mergesort", cmd__mergesort },
        { "mktemp", cmd__mktemp },
        { "online-cpus", cmd__online_cpus },
+       { "parse-options", cmd__parse_options },
        { "path-utils", cmd__path_utils },
+       { "pkt-line", cmd__pkt_line },
        { "prio-queue", cmd__prio_queue },
        { "reach", cmd__reach },
        { "read-cache", cmd__read_cache },
@@ -36,8 +40,8 @@ static struct test_cmd cmds[] = {
        { "revision-walking", cmd__revision_walking },
        { "run-command", cmd__run_command },
        { "scrap-cache-tree", cmd__scrap_cache_tree },
-       { "sha1-array", cmd__sha1_array },
        { "sha1", cmd__sha1 },
+       { "sha1-array", cmd__sha1_array },
        { "sigchain", cmd__sigchain },
        { "strcmp-offset", cmd__strcmp_offset },
        { "string-list", cmd__string_list },
index e074957279f16cce0cf2c6ea1fc5401fb1aac42b..e4890566da552eb10ae718c4c921ad103c3f1a71 100644 (file)
@@ -10,7 +10,9 @@ int cmd__date(int argc, const char **argv);
 int cmd__delta(int argc, const char **argv);
 int cmd__drop_caches(int argc, const char **argv);
 int cmd__dump_cache_tree(int argc, const char **argv);
+int cmd__dump_fsmonitor(int argc, const char **argv);
 int cmd__dump_split_index(int argc, const char **argv);
+int cmd__dump_untracked_cache(int argc, const char **argv);
 int cmd__example_decorate(int argc, const char **argv);
 int cmd__genrandom(int argc, const char **argv);
 int cmd__hashmap(int argc, const char **argv);
@@ -21,7 +23,9 @@ int cmd__match_trees(int argc, const char **argv);
 int cmd__mergesort(int argc, const char **argv);
 int cmd__mktemp(int argc, const char **argv);
 int cmd__online_cpus(int argc, const char **argv);
+int cmd__parse_options(int argc, const char **argv);
 int cmd__path_utils(int argc, const char **argv);
+int cmd__pkt_line(int argc, const char **argv);
 int cmd__prio_queue(int argc, const char **argv);
 int cmd__reach(int argc, const char **argv);
 int cmd__read_cache(int argc, const char **argv);
@@ -32,8 +36,8 @@ int cmd__repository(int argc, const char **argv);
 int cmd__revision_walking(int argc, const char **argv);
 int cmd__run_command(int argc, const char **argv);
 int cmd__scrap_cache_tree(int argc, const char **argv);
-int cmd__sha1_array(int argc, const char **argv);
 int cmd__sha1(int argc, const char **argv);
+int cmd__sha1_array(int argc, const char **argv);
 int cmd__sigchain(int argc, const char **argv);
 int cmd__strcmp_offset(int argc, const char **argv);
 int cmd__string_list(int argc, const char **argv);
index 3fe02876c1fc7e4f7488c1534a4745f5760f1ca0..f1277bef4fa65e72607ea1f2dac326048559e6aa 100755 (executable)
@@ -57,9 +57,12 @@ then
                echo | gpgsm --homedir "${GNUPGHOME}" 2>/dev/null \
                        --passphrase-fd 0 --pinentry-mode loopback \
                        --import "$TEST_DIRECTORY"/lib-gpg/gpgsm_cert.p12 &&
-               gpgsm --homedir "${GNUPGHOME}" 2>/dev/null -K \
-                       | grep fingerprint: | cut -d" " -f4 | tr -d '\n' > \
-                       ${GNUPGHOME}/trustlist.txt &&
+
+               gpgsm --homedir "${GNUPGHOME}" 2>/dev/null -K |
+               grep fingerprint: |
+               cut -d" " -f4 |
+               tr -d '\n' >"${GNUPGHOME}/trustlist.txt" &&
+
                echo " S relax" >> ${GNUPGHOME}/trustlist.txt &&
                (gpgconf --kill gpg-agent >/dev/null 2>&1 || : ) &&
                echo hello | gpgsm --homedir "${GNUPGHOME}" >/dev/null \
diff --git a/t/oid-info/README b/t/oid-info/README
new file mode 100644 (file)
index 0000000..27f843f
--- /dev/null
@@ -0,0 +1,19 @@
+This directory contains various per-hash values that are used in the testsuite.
+
+Each file contains lines containing a key-value pair; blank lines and lines
+starting with `#` are ignored.  The key and value are separated by whitespace
+(specifically, those whitespace in the default `$IFS`).  The key consists only
+of shell identifier characters, and the value consists of a hash algorithm,
+colon, and value.  The hash algorithm also consists only of shell identifier
+characters; it should match the value in sha1-file.c.
+
+For example, the following lines map the key "rawsz" to "20" if SHA-1 is in use
+and to "32" if SHA-256 is in use:
+
+----
+rawsz sha1:20
+rawsz sha256:32
+----
+
+The keys and values used here are loaded by `test_oid_init` (see the README file
+in the "t" directory) and are used by calling `test_oid`.
diff --git a/t/oid-info/hash-info b/t/oid-info/hash-info
new file mode 100644 (file)
index 0000000..ccdbfdf
--- /dev/null
@@ -0,0 +1,8 @@
+rawsz sha1:20
+rawsz sha256:32
+
+hexsz sha1:40
+hexsz sha256:64
+
+zero sha1:0000000000000000000000000000000000000000
+zero sha256:0000000000000000000000000000000000000000000000000000000000000000
diff --git a/t/oid-info/oid b/t/oid-info/oid
new file mode 100644 (file)
index 0000000..a754970
--- /dev/null
@@ -0,0 +1,29 @@
+# These are some common invalid and partial object IDs used in tests.
+001    sha1:0000000000000000000000000000000000000001
+001    sha256:0000000000000000000000000000000000000000000000000000000000000001
+002    sha1:0000000000000000000000000000000000000002
+002    sha256:0000000000000000000000000000000000000000000000000000000000000002
+003    sha1:0000000000000000000000000000000000000003
+003    sha256:0000000000000000000000000000000000000000000000000000000000000003
+004    sha1:0000000000000000000000000000000000000004
+004    sha256:0000000000000000000000000000000000000000000000000000000000000004
+005    sha1:0000000000000000000000000000000000000005
+005    sha256:0000000000000000000000000000000000000000000000000000000000000005
+006    sha1:0000000000000000000000000000000000000006
+006    sha256:0000000000000000000000000000000000000000000000000000000000000006
+007    sha1:0000000000000000000000000000000000000007
+007    sha256:0000000000000000000000000000000000000000000000000000000000000007
+# All zeros or Fs missing one or two hex segments.
+zero_1         sha1:000000000000000000000000000000000000000
+zero_1         sha256:000000000000000000000000000000000000000000000000000000000000000
+zero_2         sha1:00000000000000000000000000000000000000
+zero_2         sha256:00000000000000000000000000000000000000000000000000000000000000
+ff_1           sha1:fffffffffffffffffffffffffffffffffffffff
+ff_1           sha256:fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+ff_2           sha1:ffffffffffffffffffffffffffffffffffffff
+ff_2           sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+# More various invalid OIDs.
+numeric                sha1:0123456789012345678901234567890123456789
+numeric                sha256:0123456789012345678901234567890123456789012345678901234567890123
+deadbeef       sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
+deadbeef       sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
diff --git a/t/perf/p1450-fsck.sh b/t/perf/p1450-fsck.sh
new file mode 100755 (executable)
index 0000000..ae1b841
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+test_description='Test fsck performance'
+
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+test_perf 'fsck' '
+       git fsck
+'
+
+test_done
diff --git a/t/perf/p1451-fsck-skip-list.sh b/t/perf/p1451-fsck-skip-list.sh
new file mode 100755 (executable)
index 0000000..c2b97d2
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='Test fsck skipList performance'
+
+. ./perf-lib.sh
+
+test_perf_fresh_repo
+
+n=1000000
+
+test_expect_success "setup $n bad commits" '
+       for i in $(test_seq 1 $n)
+       do
+               echo "commit refs/heads/master" &&
+               echo "committer C <c@example.com> 1234567890 +0000" &&
+               echo "data <<EOF" &&
+               echo "$i.Q." &&
+               echo "EOF"
+       done | q_to_nul | git fast-import
+'
+
+skip=0
+while test $skip -le $n
+do
+       test_expect_success "create skipList for $skip bad commits" '
+               git log --format=%H --max-count=$skip |
+               sort >skiplist
+       '
+
+       test_perf "fsck with $skip skipped bad commits" '
+               git -c fsck.skipList=skiplist fsck
+       '
+
+       case $skip in
+       0) skip=1 ;;
+       *) skip=${skip}0 ;;
+       esac
+done
+
+test_done
index 850f651e4e434084bbc8995fcfb3bb001d83875c..26601e698bd3abebd2e1f10ba6012f80c65ffa85 100755 (executable)
@@ -821,9 +821,87 @@ test_expect_success 'tests clean up even on failures' "
        EOF
 "
 
+test_expect_success 'test_oid setup' '
+       test_oid_init
+'
+
+test_expect_success 'test_oid provides sane info by default' '
+       test_oid zero >actual &&
+       grep "^00*\$" actual &&
+       rawsz="$(test_oid rawsz)" &&
+       hexsz="$(test_oid hexsz)" &&
+       test "$hexsz" -eq $(wc -c <actual) &&
+       test $(( $rawsz * 2)) -eq "$hexsz"
+'
+
+test_expect_success 'test_oid can look up data for SHA-1' '
+       test_when_finished "test_detect_hash" &&
+       test_set_hash sha1 &&
+       test_oid zero >actual &&
+       grep "^00*\$" actual &&
+       rawsz="$(test_oid rawsz)" &&
+       hexsz="$(test_oid hexsz)" &&
+       test $(wc -c <actual) -eq 40 &&
+       test "$rawsz" -eq 20 &&
+       test "$hexsz" -eq 40
+'
+
+test_expect_success 'test_oid can look up data for SHA-256' '
+       test_when_finished "test_detect_hash" &&
+       test_set_hash sha256 &&
+       test_oid zero >actual &&
+       grep "^00*\$" actual &&
+       rawsz="$(test_oid rawsz)" &&
+       hexsz="$(test_oid hexsz)" &&
+       test $(wc -c <actual) -eq 64 &&
+       test "$rawsz" -eq 32 &&
+       test "$hexsz" -eq 64
+'
+
 ################################################################
 # Basics of the basics
 
+test_oid_cache <<\EOF
+path0f sha1:f87290f8eb2cbbea7857214459a0739927eab154
+path0f sha256:638106af7c38be056f3212cbd7ac65bc1bac74f420ca5a436ff006a9d025d17d
+
+path0s sha1:15a98433ae33114b085f3eb3bb03b832b3180a01
+path0s sha256:3a24cc53cf68edddac490bbf94a418a52932130541361f685df685e41dd6c363
+
+path2f sha1:3feff949ed00a62d9f7af97c15cd8a30595e7ac7
+path2f sha256:2a7f36571c6fdbaf0e3f62751a0b25a3f4c54d2d1137b3f4af9cb794bb498e5f
+
+path2s sha1:d8ce161addc5173867a3c3c730924388daedbc38
+path2s sha256:18fd611b787c2e938ddcc248fabe4d66a150f9364763e9ec133dd01d5bb7c65a
+
+path2d sha1:58a09c23e2ca152193f2786e06986b7b6712bdbe
+path2d sha256:00e4b32b96e7e3d65d79112dcbea53238a22715f896933a62b811377e2650c17
+
+path3f sha1:0aa34cae68d0878578ad119c86ca2b5ed5b28376
+path3f sha256:09f58616b951bd571b8cb9dc76d372fbb09ab99db2393f5ab3189d26c45099ad
+
+path3s sha1:8599103969b43aff7e430efea79ca4636466794f
+path3s sha256:fce1aed087c053306f3f74c32c1a838c662bbc4551a7ac2420f5d6eb061374d0
+
+path3d sha1:21ae8269cacbe57ae09138dcc3a2887f904d02b3
+path3d sha256:9b60497be959cb830bf3f0dc82bcc9ad9e925a24e480837ade46b2295e47efe1
+
+subp3f sha1:00fb5908cb97c2564a9783c0c64087333b3b464f
+subp3f sha256:a1a9e16998c988453f18313d10375ee1d0ddefe757e710dcae0d66aa1e0c58b3
+
+subp3s sha1:6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c
+subp3s sha256:81759d9f5e93c6546ecfcadb560c1ff057314b09f93fe8ec06e2d8610d34ef10
+
+subp3d sha1:3c5e5399f3a333eddecce7a9b9465b63f65f51e2
+subp3d sha256:76b4ef482d4fa1c754390344cf3851c7f883b27cf9bc999c6547928c46aeafb7
+
+root sha1:087704a96baf1c2d1c869a8b084481e121c88b5b
+root sha256:9481b52abab1b2ffeedbf9de63ce422b929f179c1b98ff7bee5f8f1bc0710751
+
+simpletree sha1:7bb943559a305bdd6bdee2cef6e5df2413c3d30a
+simpletree sha256:1710c07a6c86f9a3c7376364df04c47ee39e5a5e221fcdd84b743bc9bb7e2bc5
+EOF
+
 # updating a new file without --add should fail.
 test_expect_success 'git update-index without --add should fail adding' '
        test_must_fail git update-index should-be-empty
@@ -839,8 +917,8 @@ test_expect_success 'writing tree out with git write-tree' '
 '
 
 # we know the shape and contents of the tree and know the object ID for it.
-test_expect_success SHA1 'validate object ID of a known tree' '
-       test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a
+test_expect_success 'validate object ID of a known tree' '
+       test "$tree" = "$(test_oid simpletree)"
     '
 
 # Removing paths.
@@ -882,16 +960,16 @@ test_expect_success 'showing stage with git ls-files --stage' '
        git ls-files --stage >current
 '
 
-test_expect_success SHA1 'validate git ls-files output for a known tree' '
-       cat >expected <<-\EOF &&
-       100644 f87290f8eb2cbbea7857214459a0739927eab154 0       path0
-       120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0       path0sym
-       100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0       path2/file2
-       120000 d8ce161addc5173867a3c3c730924388daedbc38 0       path2/file2sym
-       100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0       path3/file3
-       120000 8599103969b43aff7e430efea79ca4636466794f 0       path3/file3sym
-       100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0       path3/subp3/file3
-       120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0       path3/subp3/file3sym
+test_expect_success 'validate git ls-files output for a known tree' '
+       cat >expected <<-EOF &&
+       100644 $(test_oid path0f) 0     path0
+       120000 $(test_oid path0s) 0     path0sym
+       100644 $(test_oid path2f) 0     path2/file2
+       120000 $(test_oid path2s) 0     path2/file2sym
+       100644 $(test_oid path3f) 0     path3/file3
+       120000 $(test_oid path3s) 0     path3/file3sym
+       100644 $(test_oid subp3f) 0     path3/subp3/file3
+       120000 $(test_oid subp3s) 0     path3/subp3/file3sym
        EOF
        test_cmp expected current
 '
@@ -900,20 +978,20 @@ test_expect_success 'writing tree out with git write-tree' '
        tree=$(git write-tree)
 '
 
-test_expect_success SHA1 'validate object ID for a known tree' '
-       test "$tree" = 087704a96baf1c2d1c869a8b084481e121c88b5b
+test_expect_success 'validate object ID for a known tree' '
+       test "$tree" = "$(test_oid root)"
 '
 
 test_expect_success 'showing tree with git ls-tree' '
     git ls-tree $tree >current
 '
 
-test_expect_success SHA1 'git ls-tree output for a known tree' '
-       cat >expected <<-\EOF &&
-       100644 blob f87290f8eb2cbbea7857214459a0739927eab154    path0
-       120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01    path0sym
-       040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe    path2
-       040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3    path3
+test_expect_success 'git ls-tree output for a known tree' '
+       cat >expected <<-EOF &&
+       100644 blob $(test_oid path0f)  path0
+       120000 blob $(test_oid path0s)  path0sym
+       040000 tree $(test_oid path2d)  path2
+       040000 tree $(test_oid path3d)  path3
        EOF
        test_cmp expected current
 '
@@ -924,16 +1002,16 @@ test_expect_success 'showing tree with git ls-tree -r' '
        git ls-tree -r $tree >current
 '
 
-test_expect_success SHA1 'git ls-tree -r output for a known tree' '
-       cat >expected <<-\EOF &&
-       100644 blob f87290f8eb2cbbea7857214459a0739927eab154    path0
-       120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01    path0sym
-       100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7    path2/file2
-       120000 blob d8ce161addc5173867a3c3c730924388daedbc38    path2/file2sym
-       100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376    path3/file3
-       120000 blob 8599103969b43aff7e430efea79ca4636466794f    path3/file3sym
-       100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f    path3/subp3/file3
-       120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c    path3/subp3/file3sym
+test_expect_success 'git ls-tree -r output for a known tree' '
+       cat >expected <<-EOF &&
+       100644 blob $(test_oid path0f)  path0
+       120000 blob $(test_oid path0s)  path0sym
+       100644 blob $(test_oid path2f)  path2/file2
+       120000 blob $(test_oid path2s)  path2/file2sym
+       100644 blob $(test_oid path3f)  path3/file3
+       120000 blob $(test_oid path3s)  path3/file3sym
+       100644 blob $(test_oid subp3f)  path3/subp3/file3
+       120000 blob $(test_oid subp3s)  path3/subp3/file3sym
        EOF
        test_cmp expected current
 '
@@ -943,19 +1021,19 @@ test_expect_success 'showing tree with git ls-tree -r -t' '
        git ls-tree -r -t $tree >current
 '
 
-test_expect_success SHA1 'git ls-tree -r output for a known tree' '
-       cat >expected <<-\EOF &&
-       100644 blob f87290f8eb2cbbea7857214459a0739927eab154    path0
-       120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01    path0sym
-       040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe    path2
-       100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7    path2/file2
-       120000 blob d8ce161addc5173867a3c3c730924388daedbc38    path2/file2sym
-       040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3    path3
-       100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376    path3/file3
-       120000 blob 8599103969b43aff7e430efea79ca4636466794f    path3/file3sym
-       040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2    path3/subp3
-       100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f    path3/subp3/file3
-       120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c    path3/subp3/file3sym
+test_expect_success 'git ls-tree -r output for a known tree' '
+       cat >expected <<-EOF &&
+       100644 blob $(test_oid path0f)  path0
+       120000 blob $(test_oid path0s)  path0sym
+       040000 tree $(test_oid path2d)  path2
+       100644 blob $(test_oid path2f)  path2/file2
+       120000 blob $(test_oid path2s)  path2/file2sym
+       040000 tree $(test_oid path3d)  path3
+       100644 blob $(test_oid path3f)  path3/file3
+       120000 blob $(test_oid path3s)  path3/file3sym
+       040000 tree $(test_oid subp3d)  path3/subp3
+       100644 blob $(test_oid subp3f)  path3/subp3/file3
+       120000 blob $(test_oid subp3s)  path3/subp3/file3sym
        EOF
        test_cmp expected current
 '
@@ -964,26 +1042,27 @@ test_expect_success 'writing partial tree out with git write-tree --prefix' '
        ptree=$(git write-tree --prefix=path3)
 '
 
-test_expect_success SHA1 'validate object ID for a known tree' '
-       test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3
+test_expect_success 'validate object ID for a known tree' '
+       test "$ptree" = $(test_oid path3d)
 '
 
 test_expect_success 'writing partial tree out with git write-tree --prefix' '
        ptree=$(git write-tree --prefix=path3/subp3)
 '
 
-test_expect_success SHA1 'validate object ID for a known tree' '
-       test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2
+test_expect_success 'validate object ID for a known tree' '
+       test "$ptree" = $(test_oid subp3d)
 '
 
 test_expect_success 'put invalid objects into the index' '
        rm -f .git/index &&
-       cat >badobjects <<-\EOF &&
-       100644 blob 1000000000000000000000000000000000000000    dir/file1
-       100644 blob 2000000000000000000000000000000000000000    dir/file2
-       100644 blob 3000000000000000000000000000000000000000    dir/file3
-       100644 blob 4000000000000000000000000000000000000000    dir/file4
-       100644 blob 5000000000000000000000000000000000000000    dir/file5
+       suffix=$(echo $ZERO_OID | sed -e "s/^.//") &&
+       cat >badobjects <<-EOF &&
+       100644 blob $(test_oid 001)     dir/file1
+       100644 blob $(test_oid 002)     dir/file2
+       100644 blob $(test_oid 003)     dir/file3
+       100644 blob $(test_oid 004)     dir/file4
+       100644 blob $(test_oid 005)     dir/file5
        EOF
        git update-index --index-info <badobjects
 '
@@ -1006,19 +1085,19 @@ test_expect_success 'git read-tree followed by write-tree should be idempotent'
        test "$newtree" = "$tree"
 '
 
-test_expect_success SHA1 'validate git diff-files output for a know cache/work tree state' '
-       cat >expected <<\EOF &&
-:100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M     path0
-:120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M     path0sym
-:100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M     path2/file2
-:120000 120000 d8ce161addc5173867a3c3c730924388daedbc38 0000000000000000000000000000000000000000 M     path2/file2sym
-:100644 100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0000000000000000000000000000000000000000 M     path3/file3
-:120000 120000 8599103969b43aff7e430efea79ca4636466794f 0000000000000000000000000000000000000000 M     path3/file3sym
-:100644 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0000000000000000000000000000000000000000 M     path3/subp3/file3
-:120000 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0000000000000000000000000000000000000000 M     path3/subp3/file3sym
+test_expect_success 'validate git diff-files output for a know cache/work tree state' '
+       cat >expected <<EOF &&
+:100644 100644 $(test_oid path0f) $ZERO_OID M  path0
+:120000 120000 $(test_oid path0s) $ZERO_OID M  path0sym
+:100644 100644 $(test_oid path2f) $ZERO_OID M  path2/file2
+:120000 120000 $(test_oid path2s) $ZERO_OID M  path2/file2sym
+:100644 100644 $(test_oid path3f) $ZERO_OID M  path3/file3
+:120000 120000 $(test_oid path3s) $ZERO_OID M  path3/file3sym
+:100644 100644 $(test_oid subp3f) $ZERO_OID M  path3/subp3/file3
+:120000 120000 $(test_oid subp3s) $ZERO_OID M  path3/subp3/file3sym
 EOF
        git diff-files >current &&
-       test_cmp current expected
+       test_cmp expected current
 '
 
 test_expect_success 'git update-index --refresh should succeed' '
@@ -1031,23 +1110,23 @@ test_expect_success 'no diff after checkout and git update-index --refresh' '
 '
 
 ################################################################
-P=087704a96baf1c2d1c869a8b084481e121c88b5b
+P=$(test_oid root)
 
-test_expect_success SHA1 'git commit-tree records the correct tree in a commit' '
+test_expect_success 'git commit-tree records the correct tree in a commit' '
        commit0=$(echo NO | git commit-tree $P) &&
        tree=$(git show --pretty=raw $commit0 |
                 sed -n -e "s/^tree //p" -e "/^author /q") &&
        test "z$tree" = "z$P"
 '
 
-test_expect_success SHA1 'git commit-tree records the correct parent in a commit' '
+test_expect_success 'git commit-tree records the correct parent in a commit' '
        commit1=$(echo NO | git commit-tree $P -p $commit0) &&
        parent=$(git show --pretty=raw $commit1 |
                sed -n -e "s/^parent //p" -e "/^author /q") &&
        test "z$commit0" = "z$parent"
 '
 
-test_expect_success SHA1 'git commit-tree omits duplicated parent in a commit' '
+test_expect_success 'git commit-tree omits duplicated parent in a commit' '
        commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) &&
             parent=$(git show --pretty=raw $commit2 |
                sed -n -e "s/^parent //p" -e "/^author /q" |
index 3691023d510a0d97bf1390b781afe1ac9fa270f4..0aa9908ea12d7592841e10ac09afe8b36f37ce7f 100755 (executable)
@@ -92,11 +92,12 @@ test_expect_success 'enter_repo non-strict mode' '
                mv .git .realgit &&
                echo "gitdir: .realgit" >.git
        ) &&
+       head=$(git -C enter_repo rev-parse HEAD) &&
        git ls-remote enter_repo >actual &&
-       cat >expected <<-\EOF &&
-       946e985ab20de757ca5b872b16d64e92ff3803a9        HEAD
-       946e985ab20de757ca5b872b16d64e92ff3803a9        refs/heads/master
-       946e985ab20de757ca5b872b16d64e92ff3803a9        refs/tags/foo
+       cat >expected <<-EOF &&
+       $head   HEAD
+       $head   refs/heads/master
+       $head   refs/tags/foo
        EOF
        test_cmp expected actual
 '
@@ -106,21 +107,23 @@ test_expect_success 'enter_repo linked checkout' '
                cd enter_repo &&
                git worktree add  ../foo refs/tags/foo
        ) &&
+       head=$(git -C enter_repo rev-parse HEAD) &&
        git ls-remote foo >actual &&
-       cat >expected <<-\EOF &&
-       946e985ab20de757ca5b872b16d64e92ff3803a9        HEAD
-       946e985ab20de757ca5b872b16d64e92ff3803a9        refs/heads/master
-       946e985ab20de757ca5b872b16d64e92ff3803a9        refs/tags/foo
+       cat >expected <<-EOF &&
+       $head   HEAD
+       $head   refs/heads/master
+       $head   refs/tags/foo
        EOF
        test_cmp expected actual
 '
 
 test_expect_success 'enter_repo strict mode' '
+       head=$(git -C enter_repo rev-parse HEAD) &&
        git ls-remote --upload-pack="git upload-pack --strict" foo/.git >actual &&
-       cat >expected <<-\EOF &&
-       946e985ab20de757ca5b872b16d64e92ff3803a9        HEAD
-       946e985ab20de757ca5b872b16d64e92ff3803a9        refs/heads/master
-       946e985ab20de757ca5b872b16d64e92ff3803a9        refs/tags/foo
+       cat >expected <<-EOF &&
+       $head   HEAD
+       $head   refs/heads/master
+       $head   refs/tags/foo
        EOF
        test_cmp expected actual
 '
diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh
new file mode 100755 (executable)
index 0000000..a070e64
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='git command aliasing'
+
+. ./test-lib.sh
+
+test_expect_success 'nested aliases - internal execution' '
+       git config alias.nested-internal-1 nested-internal-2 &&
+       git config alias.nested-internal-2 status &&
+       git nested-internal-1 >output &&
+       test_i18ngrep "^On branch " output
+'
+
+test_expect_success 'nested aliases - mixed execution' '
+       git config alias.nested-external-1 nested-external-2 &&
+       git config alias.nested-external-2 "!git nested-external-3" &&
+       git config alias.nested-external-3 status &&
+       git nested-external-1 >output &&
+       test_i18ngrep "^On branch " output
+'
+
+test_expect_success 'looping aliases - internal execution' '
+       git config alias.loop-internal-1 loop-internal-2 &&
+       git config alias.loop-internal-2 loop-internal-3 &&
+       git config alias.loop-internal-3 loop-internal-2 &&
+       test_must_fail git loop-internal-1 2>output &&
+       test_i18ngrep "^fatal: alias loop detected: expansion of" output
+'
+
+# This test is disabled until external loops are fixed, because would block
+# the test suite for a full minute.
+#
+#test_expect_failure 'looping aliases - mixed execution' '
+#      git config alias.loop-mixed-1 loop-mixed-2 &&
+#      git config alias.loop-mixed-2 "!git loop-mixed-1" &&
+#      test_must_fail git loop-mixed-1 2>output &&
+#      test_i18ngrep "^fatal: alias loop detected: expansion of" output
+#'
+
+test_done
index 308cd28f3bd7304a63628e8a64014e8d20faa82f..fd5f1ac649dc411bf3c70dcb54f7965e4006aca8 100755 (executable)
@@ -166,10 +166,10 @@ test_expect_success expanded_in_repo '
        rm -f expanded-keywords expanded-keywords-crlf &&
 
        git checkout -- expanded-keywords &&
-       test_cmp expanded-keywords expected-output &&
+       test_cmp expected-output expanded-keywords &&
 
        git checkout -- expanded-keywords-crlf &&
-       test_cmp expanded-keywords-crlf expected-output-crlf
+       test_cmp expected-output-crlf expanded-keywords-crlf
 '
 
 # The use of %f in a filter definition is expanded to the path to
index 5b0560fa20e3459a3fa62753ebfafaa2afa276e1..17d0c18feb84e2c47167b9b54f71f192d78b0e9b 100755 (executable)
@@ -8,7 +8,7 @@ test_description='our own option parser'
 . ./test-lib.sh
 
 cat >expect <<\EOF
-usage: test-parse-options <options>
+usage: test-tool parse-options <options>
 
     A helper function for the parse-options API.
 
@@ -52,7 +52,7 @@ Standard options
 EOF
 
 test_expect_success 'test help' '
-       test_must_fail test-parse-options -h >output 2>output.err &&
+       test_must_fail test-tool parse-options -h >output 2>output.err &&
        test_must_be_empty output.err &&
        test_i18ncmp expect output
 '
@@ -64,7 +64,7 @@ check () {
        shift &&
        expect="$1" &&
        shift &&
-       test-parse-options --expect="$what $expect" "$@"
+       test-tool parse-options --expect="$what $expect" "$@"
 }
 
 check_unknown_i18n() {
@@ -75,7 +75,7 @@ check_unknown_i18n() {
                echo error: unknown switch \`${1#-}\' >expect ;;
        esac &&
        cat expect.err >>expect &&
-       test_must_fail test-parse-options $* >output 2>output.err &&
+       test_must_fail test-tool parse-options $* >output 2>output.err &&
        test_must_be_empty output &&
        test_i18ncmp expect output.err
 }
@@ -133,7 +133,7 @@ file: prefix/my.file
 EOF
 
 test_expect_success 'short options' '
-       test-parse-options -s123 -b -i 1729 -m 16k -b -vv -n -F my.file \
+       test-tool parse-options -s123 -b -i 1729 -m 16k -b -vv -n -F my.file \
        >output 2>output.err &&
        test_cmp expect output &&
        test_must_be_empty output.err
@@ -153,7 +153,7 @@ file: prefix/fi.le
 EOF
 
 test_expect_success 'long options' '
-       test-parse-options --boolean --integer 1729 --magnitude 16k \
+       test-tool parse-options --boolean --integer 1729 --magnitude 16k \
                --boolean --string2=321 --verbose --verbose --no-dry-run \
                --abbrev=10 --file fi.le --obsolete \
                >output 2>output.err &&
@@ -162,9 +162,9 @@ test_expect_success 'long options' '
 '
 
 test_expect_success 'missing required value' '
-       test_expect_code 129 test-parse-options -s &&
-       test_expect_code 129 test-parse-options --string &&
-       test_expect_code 129 test-parse-options --file
+       test_expect_code 129 test-tool parse-options -s &&
+       test_expect_code 129 test-tool parse-options --string &&
+       test_expect_code 129 test-tool parse-options --file
 '
 
 cat >expect <<\EOF
@@ -184,7 +184,7 @@ arg 02: --boolean
 EOF
 
 test_expect_success 'intermingled arguments' '
-       test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
+       test-tool parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
                >output 2>output.err &&
        test_must_be_empty output.err &&
        test_cmp expect output
@@ -204,21 +204,21 @@ file: (not set)
 EOF
 
 test_expect_success 'unambiguously abbreviated option' '
-       test-parse-options --int 2 --boolean --no-bo >output 2>output.err &&
+       test-tool parse-options --int 2 --boolean --no-bo >output 2>output.err &&
        test_must_be_empty output.err &&
        test_cmp expect output
 '
 
 test_expect_success 'unambiguously abbreviated option with "="' '
-       test-parse-options --expect="integer: 2" --int=2
+       test-tool parse-options --expect="integer: 2" --int=2
 '
 
 test_expect_success 'ambiguously abbreviated option' '
-       test_expect_code 129 test-parse-options --strin 123
+       test_expect_code 129 test-tool parse-options --strin 123
 '
 
 test_expect_success 'non ambiguous option (after two options it abbreviates)' '
-       test-parse-options --expect="string: 123" --st 123
+       test-tool parse-options --expect="string: 123" --st 123
 '
 
 cat >typo.err <<\EOF
@@ -226,7 +226,7 @@ error: did you mean `--boolean` (with two dashes ?)
 EOF
 
 test_expect_success 'detect possible typos' '
-       test_must_fail test-parse-options -boolean >output 2>output.err &&
+       test_must_fail test-tool parse-options -boolean >output 2>output.err &&
        test_must_be_empty output &&
        test_cmp typo.err output.err
 '
@@ -236,13 +236,13 @@ error: did you mean `--ambiguous` (with two dashes ?)
 EOF
 
 test_expect_success 'detect possible typos' '
-       test_must_fail test-parse-options -ambiguous >output 2>output.err &&
+       test_must_fail test-tool parse-options -ambiguous >output 2>output.err &&
        test_must_be_empty output &&
        test_cmp typo.err output.err
 '
 
 test_expect_success 'keep some options as arguments' '
-       test-parse-options --expect="arg 00: --quux" --quux
+       test-tool parse-options --expect="arg 00: --quux" --quux
 '
 
 cat >expect <<\EOF
@@ -260,7 +260,7 @@ arg 00: foo
 EOF
 
 test_expect_success 'OPT_DATE() works' '
-       test-parse-options -t "1970-01-01 00:00:01 +0000" \
+       test-tool parse-options -t "1970-01-01 00:00:01 +0000" \
                foo -q >output 2>output.err &&
        test_must_be_empty output.err &&
        test_cmp expect output
@@ -281,13 +281,13 @@ file: (not set)
 EOF
 
 test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
-       test-parse-options --length=four -b -4 >output 2>output.err &&
+       test-tool parse-options --length=four -b -4 >output 2>output.err &&
        test_must_be_empty output.err &&
        test_cmp expect output
 '
 
 test_expect_success 'OPT_CALLBACK() and callback errors work' '
-       test_must_fail test-parse-options --no-length >output 2>output.err &&
+       test_must_fail test-tool parse-options --no-length >output 2>output.err &&
        test_must_be_empty output &&
        test_must_be_empty output.err
 '
@@ -306,31 +306,31 @@ file: (not set)
 EOF
 
 test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
-       test-parse-options --set23 -bbbbb --no-or4 >output 2>output.err &&
+       test-tool parse-options --set23 -bbbbb --no-or4 >output 2>output.err &&
        test_must_be_empty output.err &&
        test_cmp expect output
 '
 
 test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
-       test-parse-options --set23 -bbbbb --neg-or4 >output 2>output.err &&
+       test-tool parse-options --set23 -bbbbb --neg-or4 >output 2>output.err &&
        test_must_be_empty output.err &&
        test_cmp expect output
 '
 
 test_expect_success 'OPT_BIT() works' '
-       test-parse-options --expect="boolean: 6" -bb --or4
+       test-tool parse-options --expect="boolean: 6" -bb --or4
 '
 
 test_expect_success 'OPT_NEGBIT() works' '
-       test-parse-options --expect="boolean: 6" -bb --no-neg-or4
+       test-tool parse-options --expect="boolean: 6" -bb --no-neg-or4
 '
 
 test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
-       test-parse-options --expect="boolean: 6" + + + + + +
+       test-tool parse-options --expect="boolean: 6" + + + + + +
 '
 
 test_expect_success 'OPT_NUMBER_CALLBACK() works' '
-       test-parse-options --expect="integer: 12345" -12345
+       test-tool parse-options --expect="integer: 12345" -12345
 '
 
 cat >expect <<\EOF
@@ -347,7 +347,7 @@ file: (not set)
 EOF
 
 test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
-       test-parse-options --no-ambig >output 2>output.err &&
+       test-tool parse-options --no-ambig >output 2>output.err &&
        test_must_be_empty output.err &&
        test_cmp expect output
 '
@@ -358,38 +358,38 @@ list: bar
 list: baz
 EOF
 test_expect_success '--list keeps list of strings' '
-       test-parse-options --list foo --list=bar --list=baz >output &&
+       test-tool parse-options --list foo --list=bar --list=baz >output &&
        test_cmp expect output
 '
 
 test_expect_success '--no-list resets list' '
-       test-parse-options --list=other --list=irrelevant --list=options \
+       test-tool parse-options --list=other --list=irrelevant --list=options \
                --no-list --list=foo --list=bar --list=baz >output &&
        test_cmp expect output
 '
 
 test_expect_success 'multiple quiet levels' '
-       test-parse-options --expect="quiet: 3" -q -q -q
+       test-tool parse-options --expect="quiet: 3" -q -q -q
 '
 
 test_expect_success 'multiple verbose levels' '
-       test-parse-options --expect="verbose: 3" -v -v -v
+       test-tool parse-options --expect="verbose: 3" -v -v -v
 '
 
 test_expect_success '--no-quiet sets --quiet to 0' '
-       test-parse-options --expect="quiet: 0" --no-quiet
+       test-tool parse-options --expect="quiet: 0" --no-quiet
 '
 
 test_expect_success '--no-quiet resets multiple -q to 0' '
-       test-parse-options --expect="quiet: 0" -q -q -q --no-quiet
+       test-tool parse-options --expect="quiet: 0" -q -q -q --no-quiet
 '
 
 test_expect_success '--no-verbose sets verbose to 0' '
-       test-parse-options --expect="verbose: 0" --no-verbose
+       test-tool parse-options --expect="verbose: 0" --no-verbose
 '
 
 test_expect_success '--no-verbose resets multiple verbose to 0' '
-       test-parse-options --expect="verbose: 0" -v -v -v --no-verbose
+       test-tool parse-options --expect="verbose: 0" -v -v -v --no-verbose
 '
 
 test_done
index 67484502a007e3fed09fe381898bee52d21d07bb..5dda570b9a1ef3139165a4b901e16f64a3263209 100755 (executable)
@@ -3,30 +3,30 @@
 test_description='basic tests for the SHA1 array implementation'
 . ./test-lib.sh
 
-echo20 () {
+echoid () {
        prefix="${1:+$1 }"
        shift
        while test $# -gt 0
        do
-               echo "$prefix$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1"
+               echo "$prefix$ZERO_OID" | sed -e "s/00/$1/g"
                shift
        done
 }
 
 test_expect_success 'ordered enumeration' '
-       echo20 "" 44 55 88 aa >expect &&
+       echoid "" 44 55 88 aa >expect &&
        {
-               echo20 append 88 44 aa 55 &&
+               echoid append 88 44 aa 55 &&
                echo for_each_unique
        } | test-tool sha1-array >actual &&
        test_cmp expect actual
 '
 
 test_expect_success 'ordered enumeration with duplicate suppression' '
-       echo20 "" 44 55 88 aa >expect &&
+       echoid "" 44 55 88 aa >expect &&
        {
-               echo20 append 88 44 aa 55 &&
-               echo20 append 88 44 aa 55 &&
+               echoid append 88 44 aa 55 &&
+               echoid append 88 44 aa 55 &&
                echo for_each_unique
        } | test-tool sha1-array >actual &&
        test_cmp expect actual
@@ -34,8 +34,8 @@ test_expect_success 'ordered enumeration with duplicate suppression' '
 
 test_expect_success 'lookup' '
        {
-               echo20 append 88 44 aa 55 &&
-               echo20 lookup 55
+               echoid append 88 44 aa 55 &&
+               echoid lookup 55
        } | test-tool sha1-array >actual &&
        n=$(cat actual) &&
        test "$n" -eq 1
@@ -43,8 +43,8 @@ test_expect_success 'lookup' '
 
 test_expect_success 'lookup non-existing entry' '
        {
-               echo20 append 88 44 aa 55 &&
-               echo20 lookup 33
+               echoid append 88 44 aa 55 &&
+               echoid lookup 33
        } | test-tool sha1-array >actual &&
        n=$(cat actual) &&
        test "$n" -lt 0
@@ -52,9 +52,9 @@ test_expect_success 'lookup non-existing entry' '
 
 test_expect_success 'lookup with duplicates' '
        {
-               echo20 append 88 44 aa 55 &&
-               echo20 append 88 44 aa 55 &&
-               echo20 lookup 55
+               echoid append 88 44 aa 55 &&
+               echoid append 88 44 aa 55 &&
+               echoid lookup 55
        } | test-tool sha1-array >actual &&
        n=$(cat actual) &&
        test "$n" -ge 2 &&
@@ -63,19 +63,24 @@ test_expect_success 'lookup with duplicates' '
 
 test_expect_success 'lookup non-existing entry with duplicates' '
        {
-               echo20 append 88 44 aa 55 &&
-               echo20 append 88 44 aa 55 &&
-               echo20 lookup 66
+               echoid append 88 44 aa 55 &&
+               echoid append 88 44 aa 55 &&
+               echoid lookup 66
        } | test-tool sha1-array >actual &&
        n=$(cat actual) &&
        test "$n" -lt 0
 '
 
 test_expect_success 'lookup with almost duplicate values' '
+       # n-1 5s
+       root=$(echoid "" 55) &&
+       root=${root%5} &&
        {
-               echo "append 5555555555555555555555555555555555555555" &&
-               echo "append 555555555555555555555555555555555555555f" &&
-               echo20 lookup 55
+               id1="${root}5" &&
+               id2="${root}f" &&
+               echo "append $id1" &&
+               echo "append $id2" &&
+               echoid lookup 55
        } | test-tool sha1-array >actual &&
        n=$(cat actual) &&
        test "$n" -eq 0
@@ -83,8 +88,8 @@ test_expect_success 'lookup with almost duplicate values' '
 
 test_expect_success 'lookup with single duplicate value' '
        {
-               echo20 append 55 55 &&
-               echo20 lookup 55
+               echoid append 55 55 &&
+               echoid lookup 55
        } | test-tool sha1-array >actual &&
        n=$(cat actual) &&
        test "$n" -ge 0 &&
index 7f19d591f250bd61f7d25a5e5e0fae2ca1d8f118..43c4be1e5ef559d10ca276ef777a8fe7ba8a3971 100755 (executable)
@@ -140,15 +140,17 @@ test_expect_success '--batch-check without %(rest) considers whole line' '
        test_cmp expect actual
 '
 
+test_oid_init
+
 tree_sha1=$(git write-tree)
-tree_size=33
+tree_size=$(($(test_oid rawsz) + 13))
 tree_pretty_content="100644 blob $hello_sha1   hello"
 
 run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content"
 
 commit_message="Initial commit"
 commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1)
-commit_size=177
+commit_size=$(($(test_oid hexsz) + 137))
 commit_content="tree $tree_sha1
 author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000
 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000
@@ -218,8 +220,8 @@ test_expect_success "--batch-check for a non-existent hash" '
     test "0000000000000000000000000000000000000042 missing
 0000000000000000000000000000000000000084 missing" = \
     "$( ( echo 0000000000000000000000000000000000000042;
-         echo_without_newline 0000000000000000000000000000000000000084; ) \
-       git cat-file --batch-check)"
+        echo_without_newline 0000000000000000000000000000000000000084; ) |
+       git cat-file --batch-check)"
 '
 
 test_expect_success "--batch for an existent and a non-existent hash" '
@@ -227,8 +229,8 @@ test_expect_success "--batch for an existent and a non-existent hash" '
 $tag_content
 0000000000000000000000000000000000000000 missing" = \
     "$( ( echo $tag_sha1;
-         echo_without_newline 0000000000000000000000000000000000000000; ) \
-       git cat-file --batch)"
+        echo_without_newline 0000000000000000000000000000000000000000; ) |
+       git cat-file --batch)"
 '
 
 test_expect_success "--batch-check for an empty line" '
index cdf1fed5d1c33e659b5d2c9bfb64423b13f05e94..e2cd50ecfcbcd849661cb46f23c2ddb54e9ad19e 100755 (executable)
@@ -1001,7 +1001,7 @@ EOF
 
 test_expect_success 'value continued on next line' '
        git config --list > result &&
-       test_cmp result expect
+       test_cmp expect result
 '
 
 cat > .git/config <<\EOF
@@ -1770,8 +1770,9 @@ test_expect_success '--show-origin stdin with file include' '
        cat >expect <<-EOF &&
                file:$INCLUDE_DIR/stdin.include include
        EOF
-       echo "[include]path=\"$INCLUDE_DIR\"/stdin.include" \
-               | git config --show-origin --includes --file - user.stdin >output &&
+       echo "[include]path=\"$INCLUDE_DIR\"/stdin.include" |
+       git config --show-origin --includes --file - user.stdin >output &&
+
        test_cmp expect output
 '
 
@@ -1881,7 +1882,7 @@ test_expect_success '--replace-all does not invent newlines' '
        Qkey = b
        EOF
        git config --replace-all abc.key b &&
-       test_cmp .git/config expect
+       test_cmp expect .git/config
 '
 
 test_done
index 3b92083e19d09bad951519201f9605a17b168c1a..0000e664e7b6d8c62cc12032f71224b832829e9d 100755 (executable)
@@ -14,7 +14,7 @@ setup() {
 check() {
        echo "$2" >expected
        git config --get "$1" >actual 2>&1
-       test_cmp actual expected
+       test_cmp expected actual
 }
 
 # 'check section.key regex value' verifies that the entry for
@@ -22,7 +22,7 @@ check() {
 check_regex() {
        echo "$3" >expected
        git config --get "$1" "$2" >actual 2>&1
-       test_cmp actual expected
+       test_cmp expected actual
 }
 
 test_expect_success 'modify same key' '
index 02493f14ba2071bb79d520c1d9c262ccf63c5207..1fbd94040818ce818c4c7119ee3419620f9c16ff 100755 (executable)
@@ -346,7 +346,7 @@ test_expect_success "verifying $m's log (logged by config)" '
 
 git update-ref $m $D
 cat >.git/logs/$m <<EOF
-0000000000000000000000000000000000000000 $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+$Z $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
 $C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500
 $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
 $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
@@ -366,7 +366,7 @@ test_expect_success 'Query master@{2005-05-25} (before history)' '
        test_when_finished "rm -f o e" &&
        git rev-parse --verify master@{2005-05-25} >o 2>e &&
        test $C = $(cat o) &&
-       echo test "warning: Log for '\''master'\'' only goes back to $ed." = "$(cat e)"
+       test "warning: Log for '\''master'\'' only goes back to $ed." = "$(cat e)"
 '
 test_expect_success 'Query "master@{May 26 2005 23:31:59}" (1 second before history)' '
        test_when_finished "rm -f o e" &&
index a74c38b5fb22a6d274c26ed008c6bec355801e34..331899ddc4bd33805c83ebad8983233da7d67ec8 100755 (executable)
@@ -54,7 +54,7 @@ test_expect_success 'for_each_ref(refs/heads/)' '
 '
 
 test_expect_success 'for_each_ref() is sorted' '
-       $RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
+       $RUN for-each-ref refs/heads/ | cut -d" " -f 2- >actual &&
        sort actual > expected &&
        test_cmp expected actual
 '
@@ -71,7 +71,7 @@ test_expect_success 'verify_ref(new-master)' '
 '
 
 test_expect_success 'for_each_reflog()' '
-       $RUN for-each-reflog | sort -k2 | cut -c 42- >actual &&
+       $RUN for-each-reflog | sort -k2 | cut -d" " -f 2- >actual &&
        cat >expected <<-\EOF &&
        HEAD 0x1
        refs/heads/master 0x0
index e093782cc37c495a122eb8676797b1988b828c29..d199d872fb1996922a0a77058955c105aef4377c 100755 (executable)
@@ -39,7 +39,7 @@ test_expect_success 'rename_refs() not allowed' '
 '
 
 test_expect_success 'for_each_ref(refs/heads/)' '
-       $RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
+       $RUN for-each-ref refs/heads/ | cut -d" " -f 2- >actual &&
        cat >expected <<-\EOF &&
        master 0x0
        new-master 0x0
@@ -48,7 +48,7 @@ test_expect_success 'for_each_ref(refs/heads/)' '
 '
 
 test_expect_success 'for_each_ref() is sorted' '
-       $RUN for-each-ref refs/heads/ | cut -c 42- >actual &&
+       $RUN for-each-ref refs/heads/ | cut -d" " -f 2- >actual &&
        sort actual > expected &&
        test_cmp expected actual
 '
@@ -65,7 +65,7 @@ test_expect_success 'verify_ref(new-master)' '
 '
 
 test_expect_success 'for_each_reflog()' '
-       $RUN for-each-reflog | sort | cut -c 42- >actual &&
+       $RUN for-each-reflog | sort | cut -d" " -f 2- >actual &&
        cat >expected <<-\EOF &&
        HEAD 0x1
        refs/heads/master 0x0
index 4623ae15c4fd45df64b4acb94308e5ac4ca8f1f5..9a848581180ff73b41b345e448e427457b487ff7 100755 (executable)
@@ -58,7 +58,7 @@ test_expect_success 'for_each_reflog()' '
        mkdir -p     .git/worktrees/wt/logs/refs/bisect &&
        echo $ZERO_OID > .git/worktrees/wt/logs/refs/bisect/wt-random &&
 
-       $RWT for-each-reflog | cut -c 42- | sort >actual &&
+       $RWT for-each-reflog | cut -d" " -f 2- | sort >actual &&
        cat >expected <<-\EOF &&
        HEAD 0x1
        PSEUDO-WT 0x0
@@ -68,7 +68,7 @@ test_expect_success 'for_each_reflog()' '
        EOF
        test_cmp expected actual &&
 
-       $RMAIN for-each-reflog | cut -c 42- | sort >actual &&
+       $RMAIN for-each-reflog | cut -d" " -f 2- | sort >actual &&
        cat >expected <<-\EOF &&
        HEAD 0x1
        PSEUDO-MAIN 0x0
index 685ec45639a5e9a2bf929e10aa30976e9a4c456b..6c32d42c8c688845682d578141dbef760a663215 100755 (executable)
@@ -73,7 +73,7 @@ test_expect_success 'update-index --update from subdir' '
        100644 $(git hash-object dir1/file3) 0  dir1/file3
        100644 $file2 0 file2
        EOF
-       test_cmp current expected
+       test_cmp expected current
 '
 
 test_expect_success 'update-index --update with pathspec' '
index 93f21ab078080d00100cd63f6b5ee5cdfd636d29..478b82cf9b513a8f45f250de59d519847227f794 100755 (executable)
@@ -1221,7 +1221,7 @@ test_expect_success 'use --edit-description' '
        EOF
        EDITOR=./editor git branch --edit-description &&
        echo "New contents" >expect &&
-       test_cmp EDITOR_OUTPUT expect
+       test_cmp expect EDITOR_OUTPUT
 '
 
 test_expect_success 'detect typo in branch name when using --edit-description' '
index 10bfc8b94710caf8d33a3a1fa66ad3a4ba394c0f..823fdbda1f32355e6db952976c1210b35fd452ec 100755 (executable)
@@ -44,7 +44,7 @@ test_expect_success 'merge z into y fails and sets NOTES_MERGE_REF' '
        git config core.notesRef refs/notes/y &&
        test_must_fail git notes merge z &&
        echo "ref: refs/notes/y" >expect &&
-       test_cmp .git/NOTES_MERGE_REF expect
+       test_cmp expect .git/NOTES_MERGE_REF
 '
 
 test_expect_success 'merge z into y while mid-merge in another workdir fails' '
@@ -66,7 +66,7 @@ test_expect_success 'merge z into x while mid-merge on y succeeds' '
                grep -v "A notes merge into refs/notes/x is already in-progress in" out
        ) &&
        echo "ref: refs/notes/x" >expect &&
-       test_cmp .git/worktrees/worktree2/NOTES_MERGE_REF expect
+       test_cmp expect .git/worktrees/worktree2/NOTES_MERGE_REF
 '
 
 test_done
index 3996ee013563ce1f91b2a693318b1e07aba96568..3e73f7584ce7d3a23e7e75d0f71bd595f5f822a3 100755 (executable)
@@ -183,13 +183,13 @@ test_expect_success 'cherry-picked commits and fork-point work together' '
        test_commit final_B B "Final B" &&
        git rebase &&
        echo Amended >expect &&
-       test_cmp A expect &&
+       test_cmp expect A &&
        echo "Final B" >expect &&
-       test_cmp B expect &&
+       test_cmp expect B &&
        echo C >expect &&
-       test_cmp C expect &&
+       test_cmp expect C &&
        echo D >expect &&
-       test_cmp D expect
+       test_cmp expect D
 '
 
 test_expect_success 'rebase -q is quiet' '
index 1fb3e499b4a044d935c090bfa567a7ace271c054..e85cdc7037bcb6184d1ce6f9aa7ff2cfc4af2096 100755 (executable)
@@ -55,7 +55,7 @@ test_expect_success 'blank line at end of file; extend at end of file' '
        git add file && git commit -m second &&
        git rebase --whitespace=fix HEAD^^ &&
        git diff --exit-code HEAD^:file expect-first &&
-       test_cmp file expect-second
+       test_cmp expect-second file
 '
 
 # prepare third revision of "file"
@@ -82,7 +82,7 @@ test_expect_success 'two blanks line at end of file; extend at end of file' '
        cp third file && git add file && git commit -m third &&
        git rebase --whitespace=fix HEAD^^ &&
        git diff --exit-code HEAD^:file expect-second &&
-       test_cmp file expect-third
+       test_cmp expect-third file
 '
 
 test_expect_success 'same, but do not remove trailing spaces' '
@@ -120,7 +120,7 @@ test_expect_success 'at beginning of file' '
        done >> file &&
        git commit -m more file &&
        git rebase --whitespace=fix HEAD^^ &&
-       test_cmp file expect-beginning
+       test_cmp expect-beginning file
 '
 
 test_done
index c6af7f82b58f606b3f6c7e2612931a1fc2af15c7..6c676645d837477077e9e349bf01398f3aa52b5f 100755 (executable)
@@ -110,10 +110,10 @@ test_expect_success 'add -e' '
        cp second-part file &&
        git add -e &&
        test_cmp second-part file &&
-       test_cmp orig-patch expected-patch &&
+       test_cmp expected-patch orig-patch &&
        git diff --cached >actual &&
        grep -v index actual >out &&
-       test_cmp out expected
+       test_cmp expected out
 
 '
 
index 6450bc669860f0f3e7d809514fc073013ffbf0b8..cd216655b97b852eec963916e796d11d32eb976a 100755 (executable)
@@ -36,7 +36,7 @@ EOF
 test_expect_success 'parents of stash' '
        test $(git rev-parse stash^) = $(git rev-parse HEAD) &&
        git diff stash^2..stash > output &&
-       test_cmp output expect
+       test_cmp expect output
 '
 
 test_expect_success 'applying bogus stash does nothing' '
@@ -210,9 +210,9 @@ test_expect_success 'stash branch' '
        test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
        test $(git rev-parse HEAD) = $(git rev-parse master^) &&
        git diff --cached > output &&
-       test_cmp output expect &&
+       test_cmp expect output &&
        git diff > output &&
-       test_cmp output expect1 &&
+       test_cmp expect1 output &&
        git add file &&
        git commit -m alternate\ second &&
        git diff master..stashbranch > output &&
@@ -710,7 +710,7 @@ test_expect_success 'stash where working directory contains "HEAD" file' '
        git diff-index --cached --quiet HEAD &&
        test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" &&
        git diff stash^..stash > output &&
-       test_cmp output expect
+       test_cmp expect output
 '
 
 test_expect_success 'store called with invalid commit' '
index 597b0637d160be0cab4d3114aace598616e371fd..cc1c8a7bb2da508e570621ddf9e08694007425d4 100755 (executable)
@@ -142,7 +142,7 @@ test_expect_success 'stash save --include-untracked removed files' '
        rm -f file &&
        git stash save --include-untracked &&
        echo 1 > expect &&
-       test_cmp file expect
+       test_cmp expect file
 '
 
 rm -f expect
index fa44e788695c6f3226ad17cb6e8f2b8e256814ed..35578f2bb91dab8a00f40b5fbb26bd0a31ca7d58 100755 (executable)
@@ -37,7 +37,7 @@ test_expect_success 'hunk header truncation with an overly long line' '
                echo " A $N$N$N$N$N$N$N$N$N2" &&
                echo " L  $N$N$N$N$N$N$N$N$N1"
        ) >expected &&
-       test_cmp actual expected
+       test_cmp expected actual
 
 '
 
index d80187de9446c3129e1c69d3b67278f2fd40c9a0..f7de6f077a6e055b79dfc2ae572f1552c40d2eb3 100755 (executable)
@@ -72,7 +72,7 @@ test_expect_success 'apply with --reject should fail but update the file' '
        rm -f file1.rej file2.rej &&
 
        test_must_fail git apply --reject patch.1 &&
-       test_cmp file1 expected &&
+       test_cmp expected file1 &&
 
        cat file1.rej &&
        test_path_is_missing file2.rej
@@ -85,7 +85,7 @@ test_expect_success 'apply with --reject should fail but update the file' '
 
        test_must_fail git apply --reject patch.2 >rejects &&
        test_path_is_missing file1 &&
-       test_cmp file2 expected &&
+       test_cmp expected file2 &&
 
        cat file2.rej &&
        test_path_is_missing file1.rej
@@ -99,7 +99,7 @@ test_expect_success 'the same test with --verbose' '
 
        test_must_fail git apply --reject --verbose patch.2 >rejects &&
        test_path_is_missing file1 &&
-       test_cmp file2 expected &&
+       test_cmp expected file2 &&
 
        cat file2.rej &&
        test_path_is_missing file1.rej
index 7e32237a2ae9a21e370d501caa8adfe561c6bc6b..ff51e9e78914e4b9c7a801b4f88f3691b5f2844d 100755 (executable)
@@ -313,9 +313,9 @@ test_expect_success 'applying beyond EOF requires one non-blank context line' '
        { echo a; echo; } >one &&
        cp one expect &&
        test_must_fail git apply --whitespace=fix patch &&
-       test_cmp one expect &&
+       test_cmp expect one &&
        test_must_fail git apply --ignore-space-change --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'tons of blanks at EOF should not apply' '
@@ -342,10 +342,10 @@ test_expect_success 'missing blank line at end with --whitespace=fix' '
        cp one saved-one &&
        test_must_fail git apply patch &&
        git apply --whitespace=fix patch &&
-       test_cmp one expect &&
+       test_cmp expect one &&
        mv saved-one one &&
        git apply --ignore-space-change --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'two missing blank lines at end with --whitespace=fix' '
@@ -360,11 +360,11 @@ test_expect_success 'two missing blank lines at end with --whitespace=fix' '
        cp no-blank-lines one &&
        test_must_fail git apply patch &&
        git apply --whitespace=fix patch &&
-       test_cmp one expect &&
+       test_cmp expect one &&
        mv no-blank-lines one &&
        test_must_fail git apply patch &&
        git apply --ignore-space-change --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'missing blank line at end, insert before end, --whitespace=fix' '
@@ -376,7 +376,7 @@ test_expect_success 'missing blank line at end, insert before end, --whitespace=
        echo a >one &&
        test_must_fail git apply patch &&
        git apply --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'shrink file with tons of missing blanks at end of file' '
@@ -392,10 +392,10 @@ test_expect_success 'shrink file with tons of missing blanks at end of file' '
        cp no-blank-lines one &&
        test_must_fail git apply patch &&
        git apply --whitespace=fix patch &&
-       test_cmp one expect &&
+       test_cmp expect one &&
        mv no-blank-lines one &&
        git apply --ignore-space-change --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'missing blanks at EOF must only match blank lines' '
@@ -427,7 +427,7 @@ test_expect_success 'missing blank line should match context line with spaces' '
        git add one &&
 
        git apply --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 sed -e's/Z//' >one <<EOF
@@ -447,7 +447,7 @@ test_expect_success 'same, but with the --ignore-space-option' '
 
        git checkout-index -f one &&
        git apply --ignore-space-change --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
@@ -464,7 +464,7 @@ test_expect_success 'same, but with CR-LF line endings && cr-at-eol set' '
        mv save-one one &&
 
        git apply --ignore-space-change --whitespace=fix patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'CR-LF line endings && add line && text=auto' '
@@ -478,7 +478,7 @@ test_expect_success 'CR-LF line endings && add line && text=auto' '
        mv save-one one &&
        echo "one text=auto" >.gitattributes &&
        git apply patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'CR-LF line endings && change line && text=auto' '
@@ -491,7 +491,7 @@ test_expect_success 'CR-LF line endings && change line && text=auto' '
        mv save-one one &&
        echo "one text=auto" >.gitattributes &&
        git apply patch &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'LF in repo, CRLF in worktree && change line && text=auto' '
@@ -503,7 +503,7 @@ test_expect_success 'LF in repo, CRLF in worktree && change line && text=auto' '
        echo "one text=auto" >.gitattributes &&
        git -c core.eol=CRLF apply patch &&
        printf "b\r\n" >expect &&
-       test_cmp one expect
+       test_cmp expect one
 '
 
 test_expect_success 'whitespace=fix to expand' '
index 0ffe33fbefdc72c664d3914da234f7d4052ed462..3b636a63a3ef048c4568442d4354c7ad4d6a73f0 100755 (executable)
@@ -114,7 +114,7 @@ for t in 1 2 3 4
 do
        test_expect_success 'apply with ws expansion (t=$t)' '
                git apply patch$t.patch &&
-               test_cmp test-$t expect-$t
+               test_cmp expect-$t test-$t
        '
 done
 
index 6710c8bc8c4699035bec418258fcaec8a634855c..2e718f0bdede397d399399536707743f9f7cff34 100755 (executable)
@@ -21,17 +21,21 @@ test_expect_success 'setup r1' '
 
 test_expect_success 'verify blob count in normal packfile' '
        git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+               >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r1 pack-objects --rev --stdout >all.pack <<-EOF &&
        HEAD
        EOF
        git -C r1 index-pack ../all.pack &&
-       git -C r1 verify-pack -v ../all.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r1 verify-pack -v ../all.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:none packfile has no blobs' '
@@ -39,24 +43,28 @@ test_expect_success 'verify blob:none packfile has no blobs' '
        HEAD
        EOF
        git -C r1 index-pack ../filter.pack &&
-       git -C r1 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
+
+       git -C r1 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
        nr=$(wc -l <observed) &&
        test 0 -eq $nr
 '
 
 test_expect_success 'verify normal and blob:none packfiles have same commits/trees' '
-       git -C r1 verify-pack -v ../all.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >expected &&
-       git -C r1 verify-pack -v ../filter.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r1 verify-pack -v ../all.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >expected &&
+
+       git -C r1 verify-pack -v ../filter.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 # Test blob:limit=<n>[kmg] filter.
@@ -75,18 +83,21 @@ test_expect_success 'setup r2' '
 '
 
 test_expect_success 'verify blob count in normal packfile' '
-       git -C r2 ls-files -s large.1000 large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r2 pack-objects --rev --stdout >all.pack <<-EOF &&
        HEAD
        EOF
        git -C r2 index-pack ../all.pack &&
-       git -C r2 verify-pack -v ../all.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r2 verify-pack -v ../all.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=500 omits all blobs' '
@@ -94,10 +105,12 @@ test_expect_success 'verify blob:limit=500 omits all blobs' '
        HEAD
        EOF
        git -C r2 index-pack ../filter.pack &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
        nr=$(wc -l <observed) &&
        test 0 -eq $nr
 '
@@ -107,100 +120,119 @@ test_expect_success 'verify blob:limit=1000' '
        HEAD
        EOF
        git -C r2 index-pack ../filter.pack &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
        nr=$(wc -l <observed) &&
        test 0 -eq $nr
 '
 
 test_expect_success 'verify blob:limit=1001' '
-       git -C r2 ls-files -s large.1000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r2 ls-files -s large.1000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r2 pack-objects --rev --stdout --filter=blob:limit=1001 >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r2 index-pack ../filter.pack &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=10001' '
-       git -C r2 ls-files -s large.1000 large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r2 pack-objects --rev --stdout --filter=blob:limit=10001 >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r2 index-pack ../filter.pack &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=1k' '
-       git -C r2 ls-files -s large.1000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r2 ls-files -s large.1000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r2 pack-objects --rev --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r2 index-pack ../filter.pack &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify explicitly specifying oversized blob in input' '
-       git -C r2 ls-files -s large.1000 large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r2 pack-objects --rev --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&
        HEAD
        $(git -C r2 rev-parse HEAD:large.10000)
        EOF
        git -C r2 index-pack ../filter.pack &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=1m' '
-       git -C r2 ls-files -s large.1000 large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r2 pack-objects --rev --stdout --filter=blob:limit=1m >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r2 index-pack ../filter.pack &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify normal and blob:limit packfiles have same commits/trees' '
-       git -C r2 verify-pack -v ../all.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >expected &&
-       git -C r2 verify-pack -v ../filter.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r2 verify-pack -v ../all.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >expected &&
+
+       git -C r2 verify-pack -v ../filter.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 # Test sparse:path=<path> filter.
@@ -225,71 +257,85 @@ test_expect_success 'setup r3' '
 
 test_expect_success 'verify blob count in normal packfile' '
        git -C r3 ls-files -s sparse1 sparse2 dir1/sparse1 dir1/sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+               >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r3 pack-objects --rev --stdout >all.pack <<-EOF &&
        HEAD
        EOF
        git -C r3 index-pack ../all.pack &&
-       git -C r3 verify-pack -v ../all.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r3 verify-pack -v ../all.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify sparse:path=pattern1' '
-       git -C r3 ls-files -s dir1/sparse1 dir1/sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r3 ls-files -s dir1/sparse1 dir1/sparse2 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r3 pack-objects --rev --stdout --filter=sparse:path=../pattern1 >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r3 index-pack ../filter.pack &&
-       git -C r3 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r3 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify normal and sparse:path=pattern1 packfiles have same commits/trees' '
-       git -C r3 verify-pack -v ../all.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >expected &&
-       git -C r3 verify-pack -v ../filter.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r3 verify-pack -v ../all.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >expected &&
+
+       git -C r3 verify-pack -v ../filter.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify sparse:path=pattern2' '
-       git -C r3 ls-files -s sparse1 dir1/sparse1 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r3 ls-files -s sparse1 dir1/sparse1 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r3 pack-objects --rev --stdout --filter=sparse:path=../pattern2 >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r3 index-pack ../filter.pack &&
-       git -C r3 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r3 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify normal and sparse:path=pattern2 packfiles have same commits/trees' '
-       git -C r3 verify-pack -v ../all.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >expected &&
-       git -C r3 verify-pack -v ../filter.pack \
-               | grep -E "commit|tree" \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r3 verify-pack -v ../all.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >expected &&
+
+       git -C r3 verify-pack -v ../filter.pack >verify_result &&
+       grep -E "commit|tree" verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 # Test sparse:oid=<oid-ish> filter.
@@ -313,48 +359,58 @@ test_expect_success 'setup r4' '
 
 test_expect_success 'verify blob count in normal packfile' '
        git -C r4 ls-files -s pattern sparse1 sparse2 dir1/sparse1 dir1/sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+               >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r4 pack-objects --rev --stdout >all.pack <<-EOF &&
        HEAD
        EOF
        git -C r4 index-pack ../all.pack &&
-       git -C r4 verify-pack -v ../all.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r4 verify-pack -v ../all.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify sparse:oid=OID' '
-       git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        oid=$(git -C r4 ls-files -s pattern | awk -f print_2.awk) &&
        git -C r4 pack-objects --rev --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r4 index-pack ../filter.pack &&
-       git -C r4 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r4 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify sparse:oid=oid-ish' '
-       git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r4 ls-files -s dir1/sparse1 dir1/sparse2 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        git -C r4 pack-objects --rev --stdout --filter=sparse:oid=master:pattern >filter.pack <<-EOF &&
        HEAD
        EOF
        git -C r4 index-pack ../filter.pack &&
-       git -C r4 verify-pack -v ../filter.pack \
-               | grep blob \
-               | awk -f print_1.awk \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r4 verify-pack -v ../filter.pack >verify_result &&
+       grep blob verify_result |
+       awk -f print_1.awk |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 # Delete some loose objects and use pack-objects, but WITHOUT any filtering.
@@ -362,8 +418,10 @@ test_expect_success 'verify sparse:oid=oid-ish' '
 
 test_expect_success 'setup r1 - delete loose blobs' '
        git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+               >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        for id in `cat expected | sed "s|..|&/|"`
        do
                rm r1/.git/objects/$id
index 0c500f7ca2641a2752f5d4819bb11efcf5f588bf..5fe21db99f43aa79dc36ab36bf6d40ca2f47264d 100755 (executable)
@@ -8,7 +8,8 @@ test_expect_success 'setup full repo' '
        cd "$TRASH_DIRECTORY/full" &&
        git init &&
        git config core.commitGraph true &&
-       objdir=".git/objects"
+       objdir=".git/objects" &&
+       test_oid_init
 '
 
 test_expect_success 'verify graph with no graph file' '
@@ -35,7 +36,7 @@ test_expect_success 'create commits and repack' '
 graph_git_two_modes() {
        git -c core.commitGraph=true $1 >output
        git -c core.commitGraph=false $1 >expect
-       test_cmp output expect
+       test_cmp expect output
 }
 
 graph_git_behavior() {
@@ -259,6 +260,66 @@ test_expect_success 'check that gc computes commit-graph' '
        test_cmp_bin commit-graph-after-gc $objdir/info/commit-graph
 '
 
+test_expect_success 'replace-objects invalidates commit-graph' '
+       cd "$TRASH_DIRECTORY" &&
+       test_when_finished rm -rf replace &&
+       git clone full replace &&
+       (
+               cd replace &&
+               git commit-graph write --reachable &&
+               test_path_is_file .git/objects/info/commit-graph &&
+               git replace HEAD~1 HEAD~2 &&
+               git -c core.commitGraph=false log >expect &&
+               git -c core.commitGraph=true log >actual &&
+               test_cmp expect actual &&
+               git commit-graph write --reachable &&
+               git -c core.commitGraph=false --no-replace-objects log >expect &&
+               git -c core.commitGraph=true --no-replace-objects log >actual &&
+               test_cmp expect actual &&
+               rm -rf .git/objects/info/commit-graph &&
+               git commit-graph write --reachable &&
+               test_path_is_file .git/objects/info/commit-graph
+       )
+'
+
+test_expect_success 'commit grafts invalidate commit-graph' '
+       cd "$TRASH_DIRECTORY" &&
+       test_when_finished rm -rf graft &&
+       git clone full graft &&
+       (
+               cd graft &&
+               git commit-graph write --reachable &&
+               test_path_is_file .git/objects/info/commit-graph &&
+               H1=$(git rev-parse --verify HEAD~1) &&
+               H3=$(git rev-parse --verify HEAD~3) &&
+               echo "$H1 $H3" >.git/info/grafts &&
+               git -c core.commitGraph=false log >expect &&
+               git -c core.commitGraph=true log >actual &&
+               test_cmp expect actual &&
+               git commit-graph write --reachable &&
+               git -c core.commitGraph=false --no-replace-objects log >expect &&
+               git -c core.commitGraph=true --no-replace-objects log >actual &&
+               test_cmp expect actual &&
+               rm -rf .git/objects/info/commit-graph &&
+               git commit-graph write --reachable &&
+               test_path_is_missing .git/objects/info/commit-graph
+       )
+'
+
+test_expect_success 'replace-objects invalidates commit-graph' '
+       cd "$TRASH_DIRECTORY" &&
+       test_when_finished rm -rf shallow &&
+       git clone --depth 2 "file://$TRASH_DIRECTORY/full" shallow &&
+       (
+               cd shallow &&
+               git commit-graph write --reachable &&
+               test_path_is_missing .git/objects/info/commit-graph &&
+               git fetch origin --unshallow &&
+               git commit-graph write --reachable &&
+               test_path_is_file .git/objects/info/commit-graph
+       )
+'
+
 # the verify tests below expect the commit-graph to contain
 # exactly the commits reachable from the commits/8 branch.
 # If the file changes the set of commits in the list, then the
@@ -273,7 +334,7 @@ test_expect_success 'git commit-graph verify' '
 
 NUM_COMMITS=9
 NUM_OCTOPUS_EDGES=2
-HASH_LEN=20
+HASH_LEN="$(test_oid rawsz)"
 GRAPH_BYTE_VERSION=4
 GRAPH_BYTE_HASH=5
 GRAPH_BYTE_CHUNK_COUNT=6
index 6f56b38674fd62085e757cbc685436107a6bb9fe..bd8e841b816bcb45c8c9ad32079e6172b277bb36 100755 (executable)
@@ -150,6 +150,125 @@ test_expect_success 'write midx with twelve packs' '
 
 compare_results_with_midx "twelve packs"
 
+test_expect_success 'verify multi-pack-index success' '
+       git multi-pack-index verify --object-dir=$objdir
+'
+
+# usage: corrupt_midx_and_verify <pos> <data> <objdir> <string>
+corrupt_midx_and_verify() {
+       POS=$1 &&
+       DATA="${2:-\0}" &&
+       OBJDIR=$3 &&
+       GREPSTR="$4" &&
+       COMMAND="$5" &&
+       if test -z "$COMMAND"
+       then
+               COMMAND="git multi-pack-index verify --object-dir=$OBJDIR"
+       fi &&
+       FILE=$OBJDIR/pack/multi-pack-index &&
+       chmod a+w $FILE &&
+       test_when_finished mv midx-backup $FILE &&
+       cp $FILE midx-backup &&
+       printf "$DATA" | dd of="$FILE" bs=1 seek="$POS" conv=notrunc &&
+       test_must_fail $COMMAND 2>test_err &&
+       grep -v "^+" test_err >err &&
+       test_i18ngrep "$GREPSTR" err
+}
+
+test_expect_success 'verify bad signature' '
+       corrupt_midx_and_verify 0 "\00" $objdir \
+               "multi-pack-index signature"
+'
+
+HASH_LEN=20
+NUM_OBJECTS=74
+MIDX_BYTE_VERSION=4
+MIDX_BYTE_OID_VERSION=5
+MIDX_BYTE_CHUNK_COUNT=6
+MIDX_HEADER_SIZE=12
+MIDX_BYTE_CHUNK_ID=$MIDX_HEADER_SIZE
+MIDX_BYTE_CHUNK_OFFSET=$(($MIDX_HEADER_SIZE + 4))
+MIDX_NUM_CHUNKS=5
+MIDX_CHUNK_LOOKUP_WIDTH=12
+MIDX_OFFSET_PACKNAMES=$(($MIDX_HEADER_SIZE + \
+                        $MIDX_NUM_CHUNKS * $MIDX_CHUNK_LOOKUP_WIDTH))
+MIDX_BYTE_PACKNAME_ORDER=$(($MIDX_OFFSET_PACKNAMES + 2))
+MIDX_OFFSET_OID_FANOUT=$(($MIDX_OFFSET_PACKNAMES + 652))
+MIDX_OID_FANOUT_WIDTH=4
+MIDX_BYTE_OID_FANOUT_ORDER=$((MIDX_OFFSET_OID_FANOUT + 250 * $MIDX_OID_FANOUT_WIDTH + 1))
+MIDX_OFFSET_OID_LOOKUP=$(($MIDX_OFFSET_OID_FANOUT + 256 * $MIDX_OID_FANOUT_WIDTH))
+MIDX_BYTE_OID_LOOKUP=$(($MIDX_OFFSET_OID_LOOKUP + 16 * $HASH_LEN))
+MIDX_OFFSET_OBJECT_OFFSETS=$(($MIDX_OFFSET_OID_LOOKUP + $NUM_OBJECTS * $HASH_LEN))
+MIDX_OFFSET_WIDTH=8
+MIDX_BYTE_PACK_INT_ID=$(($MIDX_OFFSET_OBJECT_OFFSETS + 16 * $MIDX_OFFSET_WIDTH + 2))
+MIDX_BYTE_OFFSET=$(($MIDX_OFFSET_OBJECT_OFFSETS + 16 * $MIDX_OFFSET_WIDTH + 6))
+
+test_expect_success 'verify bad version' '
+       corrupt_midx_and_verify $MIDX_BYTE_VERSION "\00" $objdir \
+               "multi-pack-index version"
+'
+
+test_expect_success 'verify bad OID version' '
+       corrupt_midx_and_verify $MIDX_BYTE_OID_VERSION "\02" $objdir \
+               "hash version"
+'
+
+test_expect_success 'verify truncated chunk count' '
+       corrupt_midx_and_verify $MIDX_BYTE_CHUNK_COUNT "\01" $objdir \
+               "missing required"
+'
+
+test_expect_success 'verify extended chunk count' '
+       corrupt_midx_and_verify $MIDX_BYTE_CHUNK_COUNT "\07" $objdir \
+               "terminating multi-pack-index chunk id appears earlier than expected"
+'
+
+test_expect_success 'verify missing required chunk' '
+       corrupt_midx_and_verify $MIDX_BYTE_CHUNK_ID "\01" $objdir \
+               "missing required"
+'
+
+test_expect_success 'verify invalid chunk offset' '
+       corrupt_midx_and_verify $MIDX_BYTE_CHUNK_OFFSET "\01" $objdir \
+               "invalid chunk offset (too large)"
+'
+
+test_expect_success 'verify packnames out of order' '
+       corrupt_midx_and_verify $MIDX_BYTE_PACKNAME_ORDER "z" $objdir \
+               "pack names out of order"
+'
+
+test_expect_success 'verify packnames out of order' '
+       corrupt_midx_and_verify $MIDX_BYTE_PACKNAME_ORDER "a" $objdir \
+               "failed to load pack"
+'
+
+test_expect_success 'verify oid fanout out of order' '
+       corrupt_midx_and_verify $MIDX_BYTE_OID_FANOUT_ORDER "\01" $objdir \
+               "oid fanout out of order"
+'
+
+test_expect_success 'verify oid lookup out of order' '
+       corrupt_midx_and_verify $MIDX_BYTE_OID_LOOKUP "\00" $objdir \
+               "oid lookup out of order"
+'
+
+test_expect_success 'verify incorrect pack-int-id' '
+       corrupt_midx_and_verify $MIDX_BYTE_PACK_INT_ID "\07" $objdir \
+               "bad pack-int-id"
+'
+
+test_expect_success 'verify incorrect offset' '
+       corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\07" $objdir \
+               "incorrect object offset"
+'
+
+test_expect_success 'git-fsck incorrect offset' '
+       corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\07" $objdir \
+               "incorrect object offset" \
+               "git -c core.multipackindex=true fsck"
+'
+
 test_expect_success 'repack removes multi-pack-index' '
        test_path_is_file $objdir/pack/multi-pack-index &&
        git repack -adf &&
@@ -187,7 +306,6 @@ test_expect_success 'multi-pack-index in an alternate' '
 
 compare_results_with_midx "with alternate (remote midx)"
 
-
 # usage: corrupt_data <file> <pos> [<data>]
 corrupt_data () {
        file=$1
@@ -214,4 +332,20 @@ test_expect_success 'force some 64-bit offsets with pack-objects' '
        midx_read_expect 1 63 5 objects64 " large-offsets"
 '
 
+test_expect_success 'verify multi-pack-index with 64-bit offsets' '
+       git multi-pack-index verify --object-dir=objects64
+'
+
+NUM_OBJECTS=63
+MIDX_OFFSET_OID_FANOUT=$((MIDX_OFFSET_PACKNAMES + 54))
+MIDX_OFFSET_OID_LOOKUP=$((MIDX_OFFSET_OID_FANOUT + 256 * $MIDX_OID_FANOUT_WIDTH))
+MIDX_OFFSET_OBJECT_OFFSETS=$(($MIDX_OFFSET_OID_LOOKUP + $NUM_OBJECTS * $HASH_LEN))
+MIDX_OFFSET_LARGE_OFFSETS=$(($MIDX_OFFSET_OBJECT_OFFSETS + $NUM_OBJECTS * $MIDX_OFFSET_WIDTH))
+MIDX_BYTE_LARGE_OFFSET=$(($MIDX_OFFSET_LARGE_OFFSETS + 3))
+
+test_expect_success 'verify incorrect 64-bit offset' '
+       corrupt_midx_and_verify $MIDX_BYTE_LARGE_OFFSET "\07" objects64 \
+               "incorrect object offset"
+'
+
 test_done
index 1b5a4a6d380f37b0e616e5ca6c5fd5b732e6383d..086f2c40f68ffaf666a09d88b86709133559fc91 100755 (executable)
@@ -50,8 +50,11 @@ pull_to_client () {
                        case "$heads" in *B*)
                            git update-ref refs/heads/B "$BTIP";;
                        esac &&
-                       git symbolic-ref HEAD refs/heads/$(echo $heads \
-                               | sed -e "s/^\(.\).*$/\1/") &&
+
+                       git symbolic-ref HEAD refs/heads/$(
+                               echo $heads |
+                               sed -e "s/^\(.\).*$/\1/"
+                       ) &&
 
                        git fsck --full &&
 
index 62f35698912d0655e44d53d50c7197b8200d2710..7bc706873c5b2341f6a0922cf2e4f79d34eee97c 100755 (executable)
@@ -133,6 +133,34 @@ committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000
 This commit object intentionally broken
 EOF
 
+test_expect_success 'setup bogus commit' '
+       commit="$(git hash-object -t commit -w --stdin <bogus-commit)"
+'
+
+test_expect_success 'fsck with no skipList input' '
+       test_must_fail git fsck 2>err &&
+       test_i18ngrep "missingEmail" err
+'
+
+test_expect_success 'setup sorted and unsorted skipLists' '
+       cat >SKIP.unsorted <<-EOF &&
+       0000000000000000000000000000000000000004
+       0000000000000000000000000000000000000002
+       $commit
+       0000000000000000000000000000000000000001
+       0000000000000000000000000000000000000003
+       EOF
+       sort SKIP.unsorted >SKIP.sorted
+'
+
+test_expect_success 'fsck with sorted skipList' '
+       git -c fsck.skipList=SKIP.sorted fsck
+'
+
+test_expect_success 'fsck with unsorted skipList' '
+       git -c fsck.skipList=SKIP.unsorted fsck
+'
+
 test_expect_success 'fsck with invalid or bogus skipList input' '
        git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck &&
        test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err &&
@@ -141,8 +169,47 @@ test_expect_success 'fsck with invalid or bogus skipList input' '
        test_i18ngrep "Invalid SHA-1: \[core\]" err
 '
 
+test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' '
+       cat >SKIP.with-comment <<-EOF &&
+       # Some bad commit
+       0000000000000000000000000000000000000001
+       EOF
+       test_must_fail git -c fsck.skipList=SKIP.with-comment fsck 2>err-with-comment &&
+       test_i18ngrep "missingEmail" err-with-comment &&
+       cat >SKIP.with-empty-line <<-EOF &&
+       0000000000000000000000000000000000000001
+
+       0000000000000000000000000000000000000002
+       EOF
+       test_must_fail git -c fsck.skipList=SKIP.with-empty-line fsck 2>err-with-empty-line &&
+       test_i18ngrep "missingEmail" err-with-empty-line
+'
+
+test_expect_success 'fsck no garbage output from comments & empty lines errors' '
+       test_line_count = 1 err-with-comment &&
+       test_line_count = 1 err-with-empty-line
+'
+
+test_expect_success 'fsck with invalid abbreviated skipList input' '
+       echo $commit | test_copy_bytes 20 >SKIP.abbreviated &&
+       test_must_fail git -c fsck.skipList=SKIP.abbreviated fsck 2>err-abbreviated &&
+       test_i18ngrep "^fatal: Invalid SHA-1: " err-abbreviated
+'
+
+test_expect_success 'fsck with exhaustive accepted skipList input (various types of comments etc.)' '
+       >SKIP.exhaustive &&
+       echo "# A commented line" >>SKIP.exhaustive &&
+       echo "" >>SKIP.exhaustive &&
+       echo " " >>SKIP.exhaustive &&
+       echo " # Comment after whitespace" >>SKIP.exhaustive &&
+       echo "$commit # Our bad commit (with leading whitespace and trailing comment)" >>SKIP.exhaustive &&
+       echo "# Some bad commit (leading whitespace)" >>SKIP.exhaustive &&
+       echo "  0000000000000000000000000000000000000001" >>SKIP.exhaustive &&
+       git -c fsck.skipList=SKIP.exhaustive fsck 2>err &&
+       test_must_be_empty err
+'
+
 test_expect_success 'push with receive.fsck.skipList' '
-       commit="$(git hash-object -t commit -w --stdin <bogus-commit)" &&
        git push . $commit:refs/heads/bogus &&
        rm -rf dst &&
        git init dst &&
@@ -169,7 +236,6 @@ test_expect_success 'push with receive.fsck.skipList' '
 '
 
 test_expect_success 'fetch with fetch.fsck.skipList' '
-       commit="$(git hash-object -t commit -w --stdin <bogus-commit)" &&
        refspec=refs/heads/bogus:refs/heads/bogus &&
        git push . $commit:refs/heads/bogus &&
        rm -rf dst &&
@@ -204,7 +270,6 @@ test_expect_success 'fsck.<unknownmsg-id> dies' '
 '
 
 test_expect_success 'push with receive.fsck.missingEmail=warn' '
-       commit="$(git hash-object -t commit -w --stdin <bogus-commit)" &&
        git push . $commit:refs/heads/bogus &&
        rm -rf dst &&
        git init dst &&
@@ -232,7 +297,6 @@ test_expect_success 'push with receive.fsck.missingEmail=warn' '
 '
 
 test_expect_success 'fetch with fetch.fsck.missingEmail=warn' '
-       commit="$(git hash-object -t commit -w --stdin <bogus-commit)" &&
        refspec=refs/heads/bogus:refs/heads/bogus &&
        git push . $commit:refs/heads/bogus &&
        rm -rf dst &&
index 771f36f9ff473d31507af374f1c96fac03192048..3dc8f8ecec2c03c63788bc5b0e9db88e55deb823 100755 (executable)
@@ -23,26 +23,26 @@ test_expect_success 'create http-accessible bare repository' '
 
 setup_askpass_helper
 
-cat >exp <<EOF
-> GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
-> Accept: */*
-> Accept-Encoding: ENCODINGS
-> Pragma: no-cache
-< HTTP/1.1 200 OK
-< Pragma: no-cache
-< Cache-Control: no-cache, max-age=0, must-revalidate
-< Content-Type: application/x-git-upload-pack-advertisement
-> POST /smart/repo.git/git-upload-pack HTTP/1.1
-> Accept-Encoding: ENCODINGS
-> Content-Type: application/x-git-upload-pack-request
-> Accept: application/x-git-upload-pack-result
-> Content-Length: xxx
-< HTTP/1.1 200 OK
-< Pragma: no-cache
-< Cache-Control: no-cache, max-age=0, must-revalidate
-< Content-Type: application/x-git-upload-pack-result
-EOF
 test_expect_success 'clone http repository' '
+       cat >exp <<-\EOF &&
+       > GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1
+       > Accept: */*
+       > Accept-Encoding: ENCODINGS
+       > Pragma: no-cache
+       < HTTP/1.1 200 OK
+       < Pragma: no-cache
+       < Cache-Control: no-cache, max-age=0, must-revalidate
+       < Content-Type: application/x-git-upload-pack-advertisement
+       > POST /smart/repo.git/git-upload-pack HTTP/1.1
+       > Accept-Encoding: ENCODINGS
+       > Content-Type: application/x-git-upload-pack-request
+       > Accept: application/x-git-upload-pack-result
+       > Content-Length: xxx
+       < HTTP/1.1 200 OK
+       < Pragma: no-cache
+       < Cache-Control: no-cache, max-age=0, must-revalidate
+       < Content-Type: application/x-git-upload-pack-result
+       EOF
        GIT_TRACE_CURL=true git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
        test_cmp file clone/file &&
        tr '\''\015'\'' Q <err |
@@ -96,13 +96,13 @@ test_expect_success 'fetch changes via http' '
        test_cmp file clone/file
 '
 
-cat >exp <<EOF
-GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/repo.git/git-upload-pack HTTP/1.1 200
-GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
-POST /smart/repo.git/git-upload-pack HTTP/1.1 200
-EOF
 test_expect_success 'used upload-pack service' '
+       cat >exp <<-\EOF &&
+       GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+       POST /smart/repo.git/git-upload-pack HTTP/1.1 200
+       GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
+       POST /smart/repo.git/git-upload-pack HTTP/1.1 200
+       EOF
        check_access_log exp
 '
 
@@ -203,19 +203,19 @@ test_expect_success 'dumb clone via http-backend respects namespace' '
        test_cmp expect actual
 '
 
-cat >cookies.txt <<EOF
-127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
-EOF
-cat >expect_cookies.txt <<EOF
-
-127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
-127.0.0.1      FALSE   /smart_cookies/repo.git/info/   FALSE   0       name    value
-EOF
 test_expect_success 'cookies stored in http.cookiefile when http.savecookies set' '
+       cat >cookies.txt <<-\EOF &&
+       127.0.0.1       FALSE   /smart_cookies/ FALSE   0       othername       othervalue
+       EOF
+       sort >expect_cookies.txt <<-\EOF &&
+
+       127.0.0.1       FALSE   /smart_cookies/ FALSE   0       othername       othervalue
+       127.0.0.1       FALSE   /smart_cookies/repo.git/info/   FALSE   0       name    value
+       EOF
        git config http.cookiefile cookies.txt &&
        git config http.savecookies true &&
        git ls-remote $HTTPD_URL/smart_cookies/repo.git master &&
-       tail -3 cookies.txt >cookies_tail.txt &&
+       tail -3 cookies.txt | sort >cookies_tail.txt &&
        test_cmp expect_cookies.txt cookies_tail.txt
 '
 
index bbbe7537dfd315a567c6dc5583804325e6f10235..6ff6146923d945d9514ad5871b845969c2efb269 100755 (executable)
@@ -34,10 +34,12 @@ test_expect_success 'setup bare clone for server' '
 # confirm partial clone was registered in the local config.
 test_expect_success 'do partial clone 1' '
        git clone --no-checkout --filter=blob:none "file://$(pwd)/srv.bare" pc1 &&
-       git -C pc1 rev-list HEAD --quiet --objects --missing=print \
-               | awk -f print_1.awk \
-               | sed "s/?//" \
-               | sort >observed.oids &&
+
+       git -C pc1 rev-list --quiet --objects --missing=print HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/?//" |
+       sort >observed.oids &&
+
        test_cmp expect_1.oids observed.oids &&
        test "$(git -C pc1 config --local core.repositoryformatversion)" = "1" &&
        test "$(git -C pc1 config --local extensions.partialclone)" = "origin" &&
@@ -46,10 +48,10 @@ test_expect_success 'do partial clone 1' '
 
 # checkout master to force dynamic object fetch of blobs at HEAD.
 test_expect_success 'verify checkout with dynamic object fetch' '
-       git -C pc1 rev-list HEAD --quiet --objects --missing=print >observed &&
+       git -C pc1 rev-list --quiet --objects --missing=print HEAD >observed &&
        test_line_count = 4 observed &&
        git -C pc1 checkout master &&
-       git -C pc1 rev-list HEAD --quiet --objects --missing=print >observed &&
+       git -C pc1 rev-list --quiet --objects --missing=print HEAD >observed &&
        test_line_count = 0 observed
 '
 
@@ -72,7 +74,8 @@ test_expect_success 'push new commits to server' '
 # have the new blobs.
 test_expect_success 'partial fetch inherits filter settings' '
        git -C pc1 fetch origin &&
-       git -C pc1 rev-list master..origin/master --quiet --objects --missing=print >observed &&
+       git -C pc1 rev-list --quiet --objects --missing=print \
+               master..origin/master >observed &&
        test_line_count = 5 observed
 '
 
@@ -80,7 +83,8 @@ test_expect_success 'partial fetch inherits filter settings' '
 # we should only get 1 new blob (for the file in origin/master).
 test_expect_success 'verify diff causes dynamic object fetch' '
        git -C pc1 diff master..origin/master -- file.1.txt &&
-       git -C pc1 rev-list master..origin/master --quiet --objects --missing=print >observed &&
+       git -C pc1 rev-list --quiet --objects --missing=print \
+                master..origin/master >observed &&
        test_line_count = 4 observed
 '
 
@@ -89,7 +93,8 @@ test_expect_success 'verify diff causes dynamic object fetch' '
 test_expect_success 'verify blame causes dynamic object fetch' '
        git -C pc1 blame origin/master -- file.1.txt >observed.blame &&
        test_cmp expect.blame observed.blame &&
-       git -C pc1 rev-list master..origin/master --quiet --objects --missing=print >observed &&
+       git -C pc1 rev-list --quiet --objects --missing=print \
+               master..origin/master >observed &&
        test_line_count = 0 observed
 '
 
@@ -109,7 +114,8 @@ test_expect_success 'push new commits to server for file.2.txt' '
 # Verify we have all the new blobs.
 test_expect_success 'override inherited filter-spec using --no-filter' '
        git -C pc1 fetch --no-filter origin &&
-       git -C pc1 rev-list master..origin/master --quiet --objects --missing=print >observed &&
+       git -C pc1 rev-list --quiet --objects --missing=print \
+               master..origin/master >observed &&
        test_line_count = 0 observed
 '
 
@@ -130,16 +136,22 @@ test_expect_success 'push new commits to server for file.3.txt' '
 # perhaps combined with a command in dry-run mode.
 test_expect_success 'manual prefetch of missing objects' '
        git -C pc1 fetch --filter=blob:none origin &&
-       git -C pc1 rev-list master..origin/master --quiet --objects --missing=print \
-               | awk -f print_1.awk \
-               | sed "s/?//" \
-               | sort >observed.oids &&
+
+       git -C pc1 rev-list --quiet --objects --missing=print \
+                master..origin/master >revs &&
+       awk -f print_1.awk revs |
+       sed "s/?//" |
+       sort >observed.oids &&
+
        test_line_count = 6 observed.oids &&
        git -C pc1 fetch-pack --stdin "file://$(pwd)/srv.bare" <observed.oids &&
-       git -C pc1 rev-list master..origin/master --quiet --objects --missing=print \
-               | awk -f print_1.awk \
-               | sed "s/?//" \
-               | sort >observed.oids &&
+
+       git -C pc1 rev-list --quiet --objects --missing=print \
+               master..origin/master >revs &&
+       awk -f print_1.awk revs |
+       sed "s/?//" |
+       sort >observed.oids &&
+
        test_line_count = 0 observed.oids
 '
 
@@ -194,7 +206,7 @@ test_expect_success 'upon cloning, check that all refs point to objects' '
 
        # Craft a packfile not including that blob.
        git -C "$SERVER" rev-parse HEAD |
-               git -C "$SERVER" pack-objects --stdout >incomplete.pack &&
+       git -C "$SERVER" pack-objects --stdout >incomplete.pack &&
 
        # Replace the existing packfile with the crafted one. The protocol
        # requires that the packfile be sent in sideband 1, hence the extra
index 75ec79e6cb839e71f6830d9301d1982d0fc68925..ae79c6bbc0d66e9a7a184b2d1726a316a0affbbe 100755 (executable)
@@ -15,13 +15,13 @@ test_expect_success 'test capability advertisement' '
        EOF
 
        git serve --advertise-capabilities >out &&
-       test-pkt-line unpack <out >actual &&
-       test_cmp actual expect
+       test-tool pkt-line unpack <out >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'stateless-rpc flag does not list capabilities' '
        # Empty request
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        0000
        EOF
        git serve --stateless-rpc >out <in &&
@@ -33,7 +33,7 @@ test_expect_success 'stateless-rpc flag does not list capabilities' '
 '
 
 test_expect_success 'request invalid capability' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        foobar
        0000
        EOF
@@ -42,7 +42,7 @@ test_expect_success 'request invalid capability' '
 '
 
 test_expect_success 'request with no command' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        agent=git/test
        0000
        EOF
@@ -51,7 +51,7 @@ test_expect_success 'request with no command' '
 '
 
 test_expect_success 'request invalid command' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=foo
        agent=git/test
        0000
@@ -71,7 +71,7 @@ test_expect_success 'setup some refs and tags' '
 '
 
 test_expect_success 'basics of ls-refs' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=ls-refs
        0000
        EOF
@@ -88,12 +88,12 @@ test_expect_success 'basics of ls-refs' '
        EOF
 
        git serve --stateless-rpc <in >out &&
-       test-pkt-line unpack <out >actual &&
-       test_cmp actual expect
+       test-tool pkt-line unpack <out >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'basic ref-prefixes' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=ls-refs
        0001
        ref-prefix refs/heads/master
@@ -108,12 +108,12 @@ test_expect_success 'basic ref-prefixes' '
        EOF
 
        git serve --stateless-rpc <in >out &&
-       test-pkt-line unpack <out >actual &&
-       test_cmp actual expect
+       test-tool pkt-line unpack <out >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'refs/heads prefix' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=ls-refs
        0001
        ref-prefix refs/heads/
@@ -128,12 +128,12 @@ test_expect_success 'refs/heads prefix' '
        EOF
 
        git serve --stateless-rpc <in >out &&
-       test-pkt-line unpack <out >actual &&
-       test_cmp actual expect
+       test-tool pkt-line unpack <out >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'peel parameter' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=ls-refs
        0001
        peel
@@ -149,12 +149,12 @@ test_expect_success 'peel parameter' '
        EOF
 
        git serve --stateless-rpc <in >out &&
-       test-pkt-line unpack <out >actual &&
-       test_cmp actual expect
+       test-tool pkt-line unpack <out >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'symrefs parameter' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=ls-refs
        0001
        symrefs
@@ -170,12 +170,12 @@ test_expect_success 'symrefs parameter' '
        EOF
 
        git serve --stateless-rpc <in >out &&
-       test-pkt-line unpack <out >actual &&
-       test_cmp actual expect
+       test-tool pkt-line unpack <out >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'sending server-options' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=ls-refs
        server-option=hello
        server-option=world
@@ -190,14 +190,14 @@ test_expect_success 'sending server-options' '
        EOF
 
        git serve --stateless-rpc <in >out &&
-       test-pkt-line unpack <out >actual &&
-       test_cmp actual expect
+       test-tool pkt-line unpack <out >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success 'unexpected lines are not allowed in fetch request' '
        git init server &&
 
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=fetch
        0001
        this-is-not-a-command
index 3beeed4546cee6c7793de94ba2735b0e6d63b073..98fbf39da325ab574f9717a03c6a6588b15f0ffa 100755 (executable)
@@ -29,7 +29,7 @@ test_expect_success 'list refs with git:// using protocol v2' '
        grep "git< version 2" log &&
 
        git ls-remote --symref "$GIT_DAEMON_URL/parent" >expect &&
-       test_cmp actual expect
+       test_cmp expect actual
 '
 
 test_expect_success 'ref advertisment is filtered with ls-remote using protocol v2' '
@@ -42,7 +42,7 @@ test_expect_success 'ref advertisment is filtered with ls-remote using protocol
        $(git -C "$daemon_parent" rev-parse refs/heads/master)$(printf "\t")refs/heads/master
        EOF
 
-       test_cmp actual expect
+       test_cmp expect actual
 '
 
 test_expect_success 'clone with git:// using protocol v2' '
@@ -138,7 +138,7 @@ test_expect_success 'list refs with file:// using protocol v2' '
        grep "git< version 2" log &&
 
        git ls-remote --symref "file://$(pwd)/file_parent" >expect &&
-       test_cmp actual expect
+       test_cmp expect actual
 '
 
 test_expect_success 'ref advertisment is filtered with ls-remote using protocol v2' '
@@ -151,7 +151,7 @@ test_expect_success 'ref advertisment is filtered with ls-remote using protocol
        $(git -C file_parent rev-parse refs/heads/master)$(printf "\t")refs/heads/master
        EOF
 
-       test_cmp actual expect
+       test_cmp expect actual
 '
 
 test_expect_success 'server-options are sent when using ls-remote' '
@@ -164,7 +164,7 @@ test_expect_success 'server-options are sent when using ls-remote' '
        $(git -C file_parent rev-parse refs/heads/master)$(printf "\t")refs/heads/master
        EOF
 
-       test_cmp actual expect &&
+       test_cmp expect actual &&
        grep "server-option=hello" log &&
        grep "server-option=world" log
 '
@@ -271,7 +271,7 @@ test_expect_success 'partial clone' '
        grep "version 2" trace &&
 
        # Ensure that the old version of the file is missing
-       git -C client rev-list master --quiet --objects --missing=print \
+       git -C client rev-list --quiet --objects --missing=print master \
                >observed.oids &&
        grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
 
@@ -297,7 +297,7 @@ test_expect_success 'partial fetch' '
        grep "version 2" trace &&
 
        # Ensure that the old version of the file is missing
-       git -C client rev-list other --quiet --objects --missing=print \
+       git -C client rev-list --quiet --objects --missing=print other \
                >observed.oids &&
        grep "$(git -C server rev-parse message1:a.txt)" observed.oids &&
 
@@ -334,7 +334,7 @@ test_expect_success 'even with handcrafted request, filter does not work if not
        git -C server config uploadpack.allowfilter 0 &&
 
        # Custom request that tries to filter even though it is not advertised.
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=fetch
        0001
        want $(git -C server rev-parse master)
index d1ccc22331338b016646de6af5f15387b3119665..3f58f05cbb49d3b4a7f50e946e0f46bbc953140a 100755 (executable)
@@ -9,14 +9,14 @@ get_actual_refs () {
                /wanted-refs/d
                /0001/d
                p
-               }' <out | test-pkt-line unpack >actual_refs
+               }' <out | test-tool pkt-line unpack >actual_refs
 }
 
 get_actual_commits () {
        sed -n -e '/packfile/,/0000/{
                /packfile/d
                p
-               }' <out | test-pkt-line unpack-sideband >o.pack &&
+               }' <out | test-tool pkt-line unpack-sideband >o.pack &&
        git index-pack o.pack &&
        git verify-pack -v o.idx | grep commit | cut -c-40 | sort >actual_commits
 }
@@ -61,7 +61,7 @@ test_expect_success 'config controls ref-in-want advertisement' '
 '
 
 test_expect_success 'invalid want-ref line' '
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=fetch
        0001
        no-progress
@@ -80,7 +80,7 @@ test_expect_success 'basic want-ref' '
        EOF
        git rev-parse f | sort >expected_commits &&
 
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=fetch
        0001
        no-progress
@@ -101,7 +101,7 @@ test_expect_success 'multiple want-ref lines' '
        EOF
        git rev-parse c d | sort >expected_commits &&
 
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=fetch
        0001
        no-progress
@@ -122,7 +122,7 @@ test_expect_success 'mix want and want-ref' '
        EOF
        git rev-parse e f | sort >expected_commits &&
 
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=fetch
        0001
        no-progress
@@ -143,7 +143,7 @@ test_expect_success 'want-ref with ref we already have commit for' '
        EOF
        >expected_commits &&
 
-       test-pkt-line pack >in <<-EOF &&
+       test-tool pkt-line pack >in <<-EOF &&
        command=fetch
        0001
        no-progress
index 20aee43f95ab3cc38b8671a233089873fe374777..51ee887a77639adca91b19c73fb297e33bc34f96 100755 (executable)
@@ -99,7 +99,7 @@ EOF
 printf "propter nomen suum." >> expect.txt
 
 test_expect_success "merge does not add LF away of change" \
-       "test_cmp test3.txt expect.txt"
+       "test_cmp expect.txt test3.txt"
 
 cp test.txt backup.txt
 test_expect_success "merge with conflicts" \
@@ -122,7 +122,7 @@ non timebo mala, quoniam tu mecum es:
 virga tua et baculus tuus ipsa me consolata sunt.
 EOF
 
-test_expect_success "expected conflict markers" "test_cmp test.txt expect.txt"
+test_expect_success "expected conflict markers" "test_cmp expect.txt test.txt"
 
 cp backup.txt test.txt
 
@@ -138,7 +138,7 @@ non timebo mala, quoniam tu mecum es:
 virga tua et baculus tuus ipsa me consolata sunt.
 EOF
 test_expect_success "merge conflicting with --ours" \
-       "git merge-file --ours test.txt orig.txt new3.txt && test_cmp test.txt expect.txt"
+       "git merge-file --ours test.txt orig.txt new3.txt && test_cmp expect.txt test.txt"
 cp backup.txt test.txt
 
 cat > expect.txt << EOF
@@ -154,7 +154,7 @@ non timebo mala, quoniam tu mecum es:
 virga tua et baculus tuus ipsa me consolata sunt.
 EOF
 test_expect_success "merge conflicting with --theirs" \
-       "git merge-file --theirs test.txt orig.txt new3.txt && test_cmp test.txt expect.txt"
+       "git merge-file --theirs test.txt orig.txt new3.txt && test_cmp expect.txt test.txt"
 cp backup.txt test.txt
 
 cat > expect.txt << EOF
@@ -171,7 +171,7 @@ non timebo mala, quoniam tu mecum es:
 virga tua et baculus tuus ipsa me consolata sunt.
 EOF
 test_expect_success "merge conflicting with --union" \
-       "git merge-file --union test.txt orig.txt new3.txt && test_cmp test.txt expect.txt"
+       "git merge-file --union test.txt orig.txt new3.txt && test_cmp expect.txt test.txt"
 cp backup.txt test.txt
 
 test_expect_success "merge with conflicts, using -L" \
@@ -195,7 +195,7 @@ virga tua et baculus tuus ipsa me consolata sunt.
 EOF
 
 test_expect_success "expected conflict markers, with -L" \
-       "test_cmp test.txt expect.txt"
+       "test_cmp expect.txt test.txt"
 
 sed "s/ tu / TU /" < new1.txt > new5.txt
 test_expect_success "conflict in removed tail" \
index 07735410b9536ba7639134c7ca0cda4f486f8291..4e6c7cb77e7dc42c9f21b8ca84f8a64b1ed7d3af 100755 (executable)
@@ -45,7 +45,7 @@ test_expect_success resolve '
                false
        else
                git ls-files -s >current
-               test_cmp current expect
+               test_cmp expect current
        fi
 '
 
@@ -60,7 +60,7 @@ test_expect_success recursive '
                false
        else
                git ls-files -s >current
-               test_cmp current expect
+               test_cmp expect current
        fi
 '
 
index 7d06461f1396583f7ec568c9bd5bb17735938e34..87741efad319237477541823637a8bf47c1a254d 100755 (executable)
@@ -61,7 +61,7 @@ do_both_modes () {
                git checkout -f a2 &&
                test_must_fail git merge -s $strategy b2 &&
                git ls-files -u >actual &&
-               test_cmp actual expect &&
+               test_cmp expect actual &&
                git ls-files -s file2 | grep ^100755
        '
 
index d4ff0b3bef61b5d3de1ab0fad4695949d80dc8fd..53975c572465314957aaef360dea040a5be2db22 100755 (executable)
@@ -21,24 +21,31 @@ test_expect_success 'setup r1' '
 
 test_expect_success 'verify blob:none omits all 5 blobs' '
        git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r1 rev-list HEAD --quiet --objects --filter-print-omitted --filter=blob:none \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+               >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r1 rev-list --quiet --objects --filter-print-omitted \
+               --filter=blob:none HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify emitted+omitted == all' '
-       git -C r1 rev-list HEAD --objects \
-               | awk -f print_1.awk \
-               | sort >expected &&
-       git -C r1 rev-list HEAD --objects --filter-print-omitted --filter=blob:none \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r1 rev-list --objects HEAD >revs &&
+       awk -f print_1.awk revs |
+       sort >expected &&
+
+       git -C r1 rev-list --objects --filter-print-omitted --filter=blob:none \
+               HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 
@@ -58,65 +65,82 @@ test_expect_success 'setup r2' '
 '
 
 test_expect_success 'verify blob:limit=500 omits all blobs' '
-       git -C r2 ls-files -s large.1000 large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r2 rev-list HEAD --quiet --objects --filter-print-omitted --filter=blob:limit=500 \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r2 rev-list --quiet --objects --filter-print-omitted \
+               --filter=blob:limit=500 HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify emitted+omitted == all' '
-       git -C r2 rev-list HEAD --objects \
-               | awk -f print_1.awk \
-               | sort >expected &&
-       git -C r2 rev-list HEAD --objects --filter-print-omitted --filter=blob:limit=500 \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r2 rev-list --objects HEAD >revs &&
+       awk -f print_1.awk revs |
+       sort >expected &&
+
+       git -C r2 rev-list --objects --filter-print-omitted \
+               --filter=blob:limit=500 HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=1000' '
-       git -C r2 ls-files -s large.1000 large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r2 rev-list HEAD --quiet --objects --filter-print-omitted --filter=blob:limit=1000 \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r2 ls-files -s large.1000 large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r2 rev-list --quiet --objects --filter-print-omitted \
+               --filter=blob:limit=1000 HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=1001' '
-       git -C r2 ls-files -s large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r2 rev-list HEAD --quiet --objects --filter-print-omitted --filter=blob:limit=1001 \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r2 ls-files -s large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r2 rev-list --quiet --objects --filter-print-omitted \
+               --filter=blob:limit=1001 HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=1k' '
-       git -C r2 ls-files -s large.10000 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r2 rev-list HEAD --quiet --objects --filter-print-omitted --filter=blob:limit=1k \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r2 ls-files -s large.10000 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r2 rev-list --quiet --objects --filter-print-omitted \
+               --filter=blob:limit=1k HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify blob:limit=1m' '
-       git -C r2 rev-list HEAD --quiet --objects --filter-print-omitted --filter=blob:limit=1m \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
+       git -C r2 rev-list --quiet --objects --filter-print-omitted \
+               --filter=blob:limit=1m HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
        test_must_be_empty observed
 '
 
@@ -141,25 +165,31 @@ test_expect_success 'setup r3' '
 '
 
 test_expect_success 'verify sparse:path=pattern1 omits top-level files' '
-       git -C r3 ls-files -s sparse1 sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r3 rev-list HEAD --quiet --objects --filter-print-omitted --filter=sparse:path=../pattern1 \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r3 ls-files -s sparse1 sparse2 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r3 rev-list --quiet --objects --filter-print-omitted \
+               --filter=sparse:path=../pattern1 HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify sparse:path=pattern2 omits both sparse2 files' '
-       git -C r3 ls-files -s sparse2 dir1/sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r3 rev-list HEAD --quiet --objects --filter-print-omitted --filter=sparse:path=../pattern2 \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r3 ls-files -s sparse2 dir1/sparse2 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r3 rev-list --quiet --objects --filter-print-omitted \
+               --filter=sparse:path=../pattern2 HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 # Test sparse:oid=<oid-ish> filter.
@@ -173,26 +203,33 @@ test_expect_success 'setup r3 part 2' '
 '
 
 test_expect_success 'verify sparse:oid=OID omits top-level files' '
-       git -C r3 ls-files -s pattern sparse1 sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+       git -C r3 ls-files -s pattern sparse1 sparse2 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        oid=$(git -C r3 ls-files -s pattern | awk -f print_2.awk) &&
-       git -C r3 rev-list HEAD --quiet --objects --filter-print-omitted --filter=sparse:oid=$oid \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r3 rev-list --quiet --objects --filter-print-omitted \
+               --filter=sparse:oid=$oid HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'verify sparse:oid=oid-ish omits top-level files' '
-       git -C r3 ls-files -s pattern sparse1 sparse2 \
-               | awk -f print_2.awk \
-               | sort >expected &&
-       git -C r3 rev-list HEAD --quiet --objects --filter-print-omitted --filter=sparse:oid=master:pattern \
-               | awk -f print_1.awk \
-               | sed "s/~//" \
-               | sort >observed &&
-       test_cmp observed expected
+       git -C r3 ls-files -s pattern sparse1 sparse2 >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
+       git -C r3 rev-list --quiet --objects --filter-print-omitted \
+               --filter=sparse:oid=master:pattern HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/~//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 # Delete some loose objects and use rev-list, but WITHOUT any filtering.
@@ -200,17 +237,21 @@ test_expect_success 'verify sparse:oid=oid-ish omits top-level files' '
 
 test_expect_success 'rev-list W/ --missing=print' '
        git -C r1 ls-files -s file.1 file.2 file.3 file.4 file.5 \
-               | awk -f print_2.awk \
-               | sort >expected &&
+               >ls_files_result &&
+       awk -f print_2.awk ls_files_result |
+       sort >expected &&
+
        for id in `cat expected | sed "s|..|&/|"`
        do
                rm r1/.git/objects/$id
        done &&
-       git -C r1 rev-list --quiet HEAD --missing=print --objects \
-               | awk -f print_1.awk \
-               | sed "s/?//" \
-               | sort >observed &&
-       test_cmp observed expected
+
+       git -C r1 rev-list --quiet --missing=print --objects HEAD >revs &&
+       awk -f print_1.awk revs |
+       sed "s/?//" |
+       sort >observed &&
+
+       test_cmp expected observed
 '
 
 test_expect_success 'rev-list W/O --missing fails' '
index 818435f04e49b50965cd674bf046eb3d494fa939..4684d06552ac2eeafff19cfd696fd36d20cef5d4 100755 (executable)
@@ -4,6 +4,7 @@ test_description='basic git gc tests
 '
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
 
 test_expect_success 'setup' '
        # do not let the amount of physical memory affects gc
@@ -99,6 +100,26 @@ test_expect_success 'auto gc with too many loose objects does not attempt to cre
        test_line_count = 2 new # There is one new pack and its .idx
 '
 
+test_expect_success 'gc --no-quiet' '
+       git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr &&
+       test_must_be_empty stdout &&
+       test_line_count = 1 stderr &&
+       test_i18ngrep "Computing commit graph generation numbers" stderr
+'
+
+test_expect_success TTY 'with TTY: gc --no-quiet' '
+       test_terminal git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr &&
+       test_must_be_empty stdout &&
+       test_i18ngrep "Enumerating objects" stderr &&
+       test_i18ngrep "Computing commit graph generation numbers" stderr
+'
+
+test_expect_success 'gc --quiet' '
+       git -c gc.writeCommitGraph=true gc --quiet >stdout 2>stderr &&
+       test_must_be_empty stdout &&
+       test_must_be_empty stderr
+'
+
 run_and_wait_for_auto_gc () {
        # We read stdout from gc for the side effect of waiting until the
        # background gc process exits, closing its fd 9.  Furthermore, the
@@ -116,11 +137,11 @@ test_expect_success 'background auto gc does not run if gc.log is present and re
        test_config gc.autopacklimit 1 &&
        test_config gc.autodetach true &&
        echo fleem >.git/gc.log &&
-       test_must_fail git gc --auto 2>err &&
-       test_i18ngrep "^error:" err &&
+       git gc --auto 2>err &&
+       test_i18ngrep "^warning:" err &&
        test_config gc.logexpiry 5.days &&
        test-tool chmtime =-345600 .git/gc.log &&
-       test_must_fail git gc --auto &&
+       git gc --auto &&
        test_config gc.logexpiry 2.days &&
        run_and_wait_for_auto_gc &&
        ls .git/objects/pack/pack-*.pack >packs &&
index 2da57fce7b12bd9a2cfac38ba4d98fc9c4af1a4c..190ae149cf3cb6daa0a89d50a5a44ccafdd2aaec 100755 (executable)
@@ -55,7 +55,7 @@ test_expect_success 'setup' '
 '
 
 test_expect_success 'untracked cache is empty' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect-empty <<EOF &&
 info/exclude 0000000000000000000000000000000000000000
 core.excludesfile 0000000000000000000000000000000000000000
@@ -106,7 +106,7 @@ EOF
 '
 
 test_expect_success 'untracked cache after first status' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../dump.expect ../actual
 '
 
@@ -126,7 +126,7 @@ EOF
 '
 
 test_expect_success 'untracked cache after second status' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../dump.expect ../actual
 '
 
@@ -157,7 +157,7 @@ EOF
 '
 
 test_expect_success 'verify untracked cache dump' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude $EMPTY_BLOB
 core.excludesfile 0000000000000000000000000000000000000000
@@ -204,7 +204,7 @@ EOF
 '
 
 test_expect_success 'verify untracked cache dump' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude $EMPTY_BLOB
 core.excludesfile 0000000000000000000000000000000000000000
@@ -248,7 +248,7 @@ EOF
 '
 
 test_expect_success 'verify untracked cache dump' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -267,7 +267,7 @@ EOF
 
 test_expect_success 'move two from tracked to untracked' '
        git rm --cached two &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -304,7 +304,7 @@ EOF
 '
 
 test_expect_success 'verify untracked cache dump' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -324,7 +324,7 @@ EOF
 
 test_expect_success 'move two from untracked to tracked' '
        git add two &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -361,7 +361,7 @@ EOF
 '
 
 test_expect_success 'verify untracked cache dump' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -405,7 +405,7 @@ EOF
 '
 
 test_expect_success 'untracked cache correct after commit' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -464,7 +464,7 @@ EOF
 '
 
 test_expect_success 'untracked cache correct after status' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -532,7 +532,7 @@ EOF
 '
 
 test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        cat >../expect-from-test-dump <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
@@ -598,66 +598,66 @@ EOF
 
 test_expect_success '--no-untracked-cache removes the cache' '
        git update-index --no-untracked-cache &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        echo "no untracked cache" >../expect-no-uc &&
        test_cmp ../expect-no-uc ../actual
 '
 
 test_expect_success 'git status does not change anything' '
        git status &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-no-uc ../actual
 '
 
 test_expect_success 'setting core.untrackedCache to true and using git status creates the cache' '
        git config core.untrackedCache true &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-no-uc ../actual &&
        git status &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-from-test-dump ../actual
 '
 
 test_expect_success 'using --no-untracked-cache does not fail when core.untrackedCache is true' '
        git update-index --no-untracked-cache &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-no-uc ../actual &&
        git update-index --untracked-cache &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-empty ../actual
 '
 
 test_expect_success 'setting core.untrackedCache to false and using git status removes the cache' '
        git config core.untrackedCache false &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-empty ../actual &&
        git status &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-no-uc ../actual
 '
 
 test_expect_success 'using --untracked-cache does not fail when core.untrackedCache is false' '
        git update-index --untracked-cache &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-empty ../actual
 '
 
 test_expect_success 'setting core.untrackedCache to keep' '
        git config core.untrackedCache keep &&
        git update-index --untracked-cache &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-empty ../actual &&
        git status &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-from-test-dump ../actual &&
        git update-index --no-untracked-cache &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-no-uc ../actual &&
        git update-index --force-untracked-cache &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-empty ../actual &&
        git status &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        test_cmp ../expect-from-test-dump ../actual
 '
 
@@ -671,23 +671,23 @@ test_expect_success 'test ident field is working' '
 
 test_expect_success 'untracked cache survives a checkout' '
        git commit --allow-empty -m empty &&
-       test-dump-untracked-cache >../before &&
+       test-tool dump-untracked-cache >../before &&
        test_when_finished  "git checkout master" &&
        git checkout -b other_branch &&
-       test-dump-untracked-cache >../after &&
+       test-tool dump-untracked-cache >../after &&
        test_cmp ../before ../after &&
        test_commit test &&
-       test-dump-untracked-cache >../before &&
+       test-tool dump-untracked-cache >../before &&
        git checkout master &&
-       test-dump-untracked-cache >../after &&
+       test-tool dump-untracked-cache >../after &&
        test_cmp ../before ../after
 '
 
 test_expect_success 'untracked cache survives a commit' '
-       test-dump-untracked-cache >../before &&
+       test-tool dump-untracked-cache >../before &&
        git add done/two &&
        git commit -m commit &&
-       test-dump-untracked-cache >../after &&
+       test-tool dump-untracked-cache >../after &&
        test_cmp ../before ../after
 '
 
@@ -751,7 +751,7 @@ test_expect_success '"status" after file replacement should be clean with UC=tru
        git checkout master &&
        avoid_racy &&
        status_is_clean &&
-       test-dump-untracked-cache >../actual &&
+       test-tool dump-untracked-cache >../actual &&
        grep -F "recurse valid" ../actual >../actual.grep &&
        cat >../expect.grep <<EOF &&
 / 0000000000000000000000000000000000000000 recurse valid
index 324933acfe94153e166783e9810e98e69da1fc7e..826987ca804fbd74bc06467446c99b7b4a27ea3e 100755 (executable)
@@ -160,7 +160,7 @@ test_expect_success 'checkout -m with merge conflict' '
        git diff master:one :3:uno |
        sed -e "1,/^@@/d" -e "/^ /d" -e "s/^-/d/" -e "s/^+/a/" >current &&
        fill d2 aT d7 aS >expect &&
-       test_cmp current expect &&
+       test_cmp expect current &&
        git diff --cached two >current &&
        test_must_be_empty current
 '
@@ -174,7 +174,7 @@ test_expect_success 'format of merge conflict from checkout -m' '
 
        git ls-files >current &&
        fill same two two two >expect &&
-       test_cmp current expect &&
+       test_cmp expect current &&
 
        cat <<-EOF >expect &&
        <<<<<<< simple
index 10dc91620a69870ab5dac213d032ae5d9938128c..e87164aa8ffdba169ba6f91af99ae3d28f28459b 100755 (executable)
@@ -789,7 +789,7 @@ test_expect_success 'submodule add places git-dir in superprojects git-dir' '
         (cd .git/modules/deeper/submodule &&
          git log > ../../../../actual
         ) &&
-        test_cmp actual expected
+        test_cmp expected actual
        )
 '
 
@@ -807,7 +807,7 @@ test_expect_success 'submodule update places git-dir in superprojects git-dir' '
         (cd .git/modules/deeper/submodule &&
          git log > ../../../../actual
         ) &&
-        test_cmp actual expected
+        test_cmp expected actual
        )
 '
 
@@ -827,7 +827,7 @@ test_expect_success 'submodule add places git-dir in superprojects git-dir recur
         git add deeper/submodule &&
         git commit -m "update submodule" &&
         git push origin : &&
-        test_cmp actual expected
+        test_cmp expected actual
        )
 '
 
@@ -874,7 +874,7 @@ test_expect_success 'submodule update places git-dir in superprojects git-dir re
         (cd .git/modules/submodule/modules/subsubmodule &&
          git log > ../../../../../actual
         ) &&
-        test_cmp actual expected
+        test_cmp expected actual
        )
 '
 
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
new file mode 100755 (executable)
index 0000000..1cd2c1c
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description='check handling of .gitmodule url with dash'
+. ./test-lib.sh
+
+test_expect_success 'create submodule with protected dash in url' '
+       git init upstream &&
+       git -C upstream commit --allow-empty -m base &&
+       mv upstream ./-upstream &&
+       git submodule add ./-upstream sub &&
+       git add sub .gitmodules &&
+       git commit -m submodule
+'
+
+test_expect_success 'clone can recurse submodule' '
+       test_when_finished "rm -rf dst" &&
+       git clone --recurse-submodules . dst &&
+       echo base >expect &&
+       git -C dst/sub log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'fsck accepts protected dash' '
+       test_when_finished "rm -rf dst" &&
+       git init --bare dst &&
+       git -C dst config transfer.fsckObjects true &&
+       git push dst HEAD
+'
+
+test_expect_success 'remove ./ protection from .gitmodules url' '
+       perl -i -pe "s{\./}{}" .gitmodules &&
+       git commit -am "drop protection"
+'
+
+test_expect_success 'clone rejects unprotected dash' '
+       test_when_finished "rm -rf dst" &&
+       test_must_fail git clone --recurse-submodules . dst 2>err &&
+       test_i18ngrep ignoring err
+'
+
+test_expect_success 'fsck rejects unprotected dash' '
+       test_when_finished "rm -rf dst" &&
+       git init --bare dst &&
+       git -C dst config transfer.fsckObjects true &&
+       test_must_fail git push dst HEAD 2>err &&
+       grep gitmodulesUrl err
+'
+
+test_done
diff --git a/t/t7417-submodule-path-url.sh b/t/t7417-submodule-path-url.sh
new file mode 100755 (executable)
index 0000000..756af8c
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+test_description='check handling of .gitmodule path with dash'
+. ./test-lib.sh
+
+test_expect_success 'create submodule with dash in path' '
+       git init upstream &&
+       git -C upstream commit --allow-empty -m base &&
+       git submodule add ./upstream sub &&
+       git mv sub ./-sub &&
+       git commit -m submodule
+'
+
+test_expect_success 'clone rejects unprotected dash' '
+       test_when_finished "rm -rf dst" &&
+       git clone --recurse-submodules . dst 2>err &&
+       test_i18ngrep ignoring err
+'
+
+test_expect_success 'fsck rejects unprotected dash' '
+       test_when_finished "rm -rf dst" &&
+       git init --bare dst &&
+       git -C dst config transfer.fsckObjects true &&
+       test_must_fail git push dst HEAD 2>err &&
+       grep gitmodulesPath err
+'
+
+test_done
index 170b4810e052cc8092cea4ead4f3c098707f0f38..31ab608b6700829427b5aeafa65222469e494d26 100755 (executable)
@@ -359,4 +359,27 @@ test_expect_success 'new line found before status message in commit template' '
        test_i18ncmp expected-template editor-input
 '
 
+test_expect_success 'setup empty commit with unstaged rename and copy' '
+       test_create_repo unstaged_rename_and_copy &&
+       (
+               cd unstaged_rename_and_copy &&
+
+               echo content >orig &&
+               git add orig &&
+               test_commit orig &&
+
+               cp orig new_copy &&
+               mv orig new_rename &&
+               git add -N new_copy new_rename
+       )
+'
+
+test_expect_success 'check commit with unstaged rename and copy' '
+       (
+               cd unstaged_rename_and_copy &&
+
+               test_must_fail git -c diff.renames=copy commit
+       )
+'
+
 test_done
index 756beb0d8eb466d78b235af363b6a36dde37c79e..8384ad258c359572d83bb38fd69f61ec6fe612e7 100755 (executable)
@@ -84,21 +84,21 @@ test_expect_success 'setup' '
 
 # test that the fsmonitor extension is off by default
 test_expect_success 'fsmonitor extension is off by default' '
-       test-dump-fsmonitor >actual &&
+       test-tool dump-fsmonitor >actual &&
        grep "^no fsmonitor" actual
 '
 
 # test that "update-index --fsmonitor" adds the fsmonitor extension
 test_expect_success 'update-index --fsmonitor" adds the fsmonitor extension' '
        git update-index --fsmonitor &&
-       test-dump-fsmonitor >actual &&
+       test-tool dump-fsmonitor >actual &&
        grep "^fsmonitor last update" actual
 '
 
 # test that "update-index --no-fsmonitor" removes the fsmonitor extension
 test_expect_success 'update-index --no-fsmonitor" removes the fsmonitor extension' '
        git update-index --no-fsmonitor &&
-       test-dump-fsmonitor >actual &&
+       test-tool dump-fsmonitor >actual &&
        grep "^no fsmonitor" actual
 '
 
@@ -307,9 +307,9 @@ test_expect_success 'splitting the index results in the same state' '
        dirty_repo &&
        git update-index --fsmonitor  &&
        git ls-files -f >expect &&
-       test-dump-fsmonitor >&2 && echo &&
+       test-tool dump-fsmonitor >&2 && echo &&
        git update-index --fsmonitor --split-index &&
-       test-dump-fsmonitor >&2 && echo &&
+       test-tool dump-fsmonitor >&2 && echo &&
        git ls-files -f >actual &&
        test_cmp expect actual
 '
@@ -333,7 +333,7 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR'
                git update-index --fsmonitor &&
                GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-before" \
                git status &&
-               test-dump-untracked-cache >../before
+               test-tool dump-untracked-cache >../before
        ) &&
        cat >>dot-git/.git/hooks/fsmonitor-test <<-\EOF &&
        printf ".git\0"
@@ -345,7 +345,7 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR'
                cd dot-git &&
                GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace-after" \
                git status &&
-               test-dump-untracked-cache >../after
+               test-tool dump-untracked-cache >../after
        ) &&
        grep "directory invalidation" trace-before >>before &&
        grep "directory invalidation" trace-after >>after &&
index 668bbee73c8dc58c6ba61c4a8002ed68206d1445..562bd215a5315757dcc7c10e311106f2c7b0ff72 100755 (executable)
@@ -557,7 +557,7 @@ test_expect_success SYMLINKS 'difftool --dir-diff --symlink without unstaged cha
        EOF
        git difftool --dir-diff --symlink \
                --extcmd "./.git/CHECK_SYMLINKS" branch HEAD &&
-       test_cmp actual expect
+       test_cmp expect actual
 '
 
 write_script modify-right-file <<\EOF
index 9af60788443a9e69f3ffa7eca079a15f5bafc457..2c309a57d98898e99b76289d2eb298a2bce8cb00 100755 (executable)
@@ -221,7 +221,7 @@ tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e
 tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4
 EOF
 
-test_expect_success POSIXPERM,SYMLINKS "$name" "test_cmp a expected"
+test_expect_success POSIXPERM,SYMLINKS "$name" "test_cmp expected a"
 
 test_expect_success 'exit if remote refs are ambigious' '
         git config --add svn-remote.svn.fetch \
index 8a5c8dc1aad6d036964776d9e3fe2ecd0a893305..c26c4b0927916fca6902eb54600a13aee5e7dea9 100755 (executable)
@@ -174,7 +174,8 @@ test_expect_success 'test create-ignore' "
        cmp ./deeply/.gitignore create-ignore.expect &&
        cmp ./deeply/nested/.gitignore create-ignore.expect &&
        cmp ./deeply/nested/directory/.gitignore create-ignore.expect &&
-       git ls-files -s | grep gitignore | cmp - create-ignore-index.expect
+       git ls-files -s >ls_files_result &&
+       grep gitignore ls_files_result | cmp - create-ignore-index.expect
        "
 
 cat >prop.expect <<\EOF
@@ -189,17 +190,21 @@ EOF
 # This test can be improved: since all the svn:ignore contain the same
 # pattern, it can pass even though the propget did not execute on the
 # right directory.
-test_expect_success 'test propget' "
-       git svn propget svn:ignore . | cmp - prop.expect &&
+test_expect_success 'test propget' '
+       test_propget () {
+               git svn propget $1 $2 >actual &&
+               cmp $3 actual
+       } &&
+       test_propget svn:ignore . prop.expect &&
        cd deeply &&
-       git svn propget svn:ignore . | cmp - ../prop.expect &&
-       git svn propget svn:entry:committed-rev nested/directory/.keep \
-         | cmp - ../prop2.expect &&
-       git svn propget svn:ignore .. | cmp - ../prop.expect &&
-       git svn propget svn:ignore nested/ | cmp - ../prop.expect &&
-       git svn propget svn:ignore ./nested | cmp - ../prop.expect &&
-       git svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
-       "
+       test_propget svn:ignore . ../prop.expect &&
+       test_propget svn:entry:committed-rev nested/directory/.keep \
+               ../prop2.expect &&
+       test_propget svn:ignore .. ../prop.expect &&
+       test_propget svn:ignore nested/ ../prop.expect &&
+       test_propget svn:ignore ./nested ../prop.expect &&
+       test_propget svn:ignore .././deeply/nested ../prop.expect
+       '
 
 cat >prop.expect <<\EOF
 Properties on '.':
@@ -218,8 +223,11 @@ Properties on 'nested/directory/.keep':
 EOF
 
 test_expect_success 'test proplist' "
-       git svn proplist . | cmp - prop.expect &&
-       git svn proplist nested/directory/.keep | cmp - prop2.expect
+       git svn proplist . >actual &&
+       cmp prop.expect actual &&
+
+       git svn proplist nested/directory/.keep >actual &&
+       cmp prop2.expect actual
        "
 
 test_done
index f3c30e63b7f584cddb91793b0170f004d866530d..f894860867a1398555876ce0586479157189a376 100755 (executable)
@@ -45,7 +45,7 @@ test_expect_success 'update git svn-cloned repo' '
                git svn rebase &&
                echo a > expect &&
                echo b >> expect &&
-               test_cmp a expect &&
+               test_cmp expect a &&
                rm expect
        )
 '
@@ -69,7 +69,7 @@ test_expect_success 'update git svn-cloned repo' '
                git svn rebase &&
                echo a > expect &&
                echo b >> expect &&
-               test_cmp a expect &&
+               test_cmp expect a &&
                rm expect
        )
 '
@@ -93,7 +93,7 @@ test_expect_success 'update git svn-cloned repo again' '
                echo a > expect &&
                echo b >> expect &&
                echo c >> expect &&
-               test_cmp a expect &&
+               test_cmp expect a &&
                rm expect
        )
 '
index 5dfee07d9add00d4a68e70c89c8711604f218ef1..251fdd66c47b5e378cf091a47ba1f804eb74c487 100755 (executable)
@@ -148,7 +148,7 @@ test_expect_success PERL 'import from a CVS working tree' '
                git cvsimport -a -z0 &&
                echo 1 >expect &&
                git log -1 --pretty=format:%s%n >actual &&
-               test_cmp actual expect
+               test_cmp expect actual
        )
 
 '
index c4c3c4954612ff317a72bc342741bee8f3c628b0..3e64b11eac5ebb7b0c01487c5f11bf39cd9855c0 100755 (executable)
@@ -29,11 +29,11 @@ test_expect_failure PERL 'import with criss cross times on revisions' '
 Rev 3
 Rev 2
 Rev 1" > expect-master &&
-    test_cmp actual-master expect-master &&
+    test_cmp expect-master actual-master &&
 
     echo "Rev 5 Branch A Wed Mar 11 19:09:10 2009 +0000
 Rev 4 Branch A Wed Mar 11 19:03:52 2009 +0000" > expect-A &&
-    test_cmp actual-A expect-A
+    test_cmp expect-A actual-A
 '
 
 test_done
index a4b3db24bd9afee29de1679b47a5371a10c9863c..2ff4aa932df44e3afed6447acceb20e8c599c4ea 100755 (executable)
@@ -31,7 +31,7 @@ test_expect_success PERL 'check timestamps are UTC (TZ=CST6CDT)' '
        Rev  2 2005-02-01 00:00:00 +0000
        Rev  1 2005-01-01 00:00:00 +0000
        EOF
-       test_cmp actual-1 expect-1
+       test_cmp expect-1 actual-1
 '
 
 test_expect_success PERL 'check timestamps with author-specific timezones' '
@@ -65,7 +65,7 @@ test_expect_success PERL 'check timestamps with author-specific timezones' '
        Rev  2 2005-01-31 18:00:00 -0600 User Two
        Rev  1 2005-01-01 00:00:00 +0000 User One
        EOF
-       test_cmp actual-2 expect-2
+       test_cmp expect-2 actual-2
 '
 
 test_done
index d82fac9d790b9349df908f684e61a03780ac58c8..78d8c3783bd301a3dd2bf7061f04e08368d7ca37 100644 (file)
@@ -1157,3 +1157,72 @@ depacketize () {
                }
        '
 }
+
+# Set the hash algorithm in use to $1.  Only useful when testing the testsuite.
+test_set_hash () {
+       test_hash_algo="$1"
+}
+
+# Detect the hash algorithm in use.
+test_detect_hash () {
+       # Currently we only support SHA-1, but in the future this function will
+       # actually detect the algorithm in use.
+       test_hash_algo='sha1'
+}
+
+# Load common hash metadata and common placeholder object IDs for use with
+# test_oid.
+test_oid_init () {
+       test -n "$test_hash_algo" || test_detect_hash &&
+       test_oid_cache <"$TEST_DIRECTORY/oid-info/hash-info" &&
+       test_oid_cache <"$TEST_DIRECTORY/oid-info/oid"
+}
+
+# Load key-value pairs from stdin suitable for use with test_oid.  Blank lines
+# and lines starting with "#" are ignored.  Keys must be shell identifier
+# characters.
+#
+# Examples:
+# rawsz sha1:20
+# rawsz sha256:32
+test_oid_cache () {
+       local tag rest k v &&
+
+       { test -n "$test_hash_algo" || test_detect_hash; } &&
+       while read tag rest
+       do
+               case $tag in
+               \#*)
+                       continue;;
+               ?*)
+                       # non-empty
+                       ;;
+               *)
+                       # blank line
+                       continue;;
+               esac &&
+
+               k="${rest%:*}" &&
+               v="${rest#*:}" &&
+
+               if ! expr "$k" : '[a-z0-9][a-z0-9]*$' >/dev/null
+               then
+                       error 'bug in the test script: bad hash algorithm'
+               fi &&
+               eval "test_oid_${k}_$tag=\"\$v\""
+       done
+}
+
+# Look up a per-hash value based on a key ($1).  The value must have been loaded
+# by test_oid_init or test_oid_cache.
+test_oid () {
+       local var="test_oid_${test_hash_algo}_$1" &&
+
+       # If the variable is unset, we must be missing an entry for this
+       # key-hash pair, so exit with an error.
+       if eval "test -z \"\${$var+set}\""
+       then
+               error "bug in the test script: undefined key '$1'" >&2
+       fi &&
+       eval "printf '%s' \"\${$var}\""
+}
index 62a1000f4401f4314f072b61046d7a19d9d04bae..540778d1ddb85b494a92bce75993c4d13d47ef82 100644 (file)
@@ -24,6 +24,7 @@
 #include "quote.h"
 #include "upload-pack.h"
 #include "serve.h"
+#include "commit-graph.h"
 #include "commit-reach.h"
 
 /* Remember to update object flag allocation in object.h */
@@ -692,6 +693,7 @@ static void deepen_by_rev_list(int ac, const char **av,
 {
        struct commit_list *result;
 
+       close_commit_graph(the_repository);
        result = get_shallow_commits_by_rev_list(ac, av, SHALLOW, NOT_SHALLOW);
        send_shallow(result);
        free_commit_list(result);