aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format13
-rw-r--r--Documentation/RelNotes/2.46.0.txt47
-rw-r--r--Documentation/config/advice.txt4
-rw-r--r--Documentation/config/http.txt31
-rw-r--r--Documentation/git-show-branch.txt2
-rw-r--r--Documentation/gitfaq.txt109
-rw-r--r--Makefile4
-rw-r--r--advice.c1
-rw-r--r--advice.h1
-rw-r--r--builtin/describe.c12
-rw-r--r--builtin/push.c21
-rwxr-xr-xci/check-directional-formatting.bash2
-rwxr-xr-xci/lib.sh1
-rw-r--r--config.mak.dev2
-rwxr-xr-xgit-send-email.perl4
-rwxr-xr-xgitweb/gitweb.perl4
-rw-r--r--http.c71
-rw-r--r--merge-ort.c169
-rw-r--r--reftable/record_test.c382
-rw-r--r--send-pack.c13
-rw-r--r--sparse-index.c28
-rw-r--r--t/.gitattributes2
-rw-r--r--t/Makefile16
-rw-r--r--t/README34
-rw-r--r--t/chainlint-cat.pl29
-rwxr-xr-xt/chainlint.pl33
-rw-r--r--t/chainlint/arithmetic-expansion.expect18
-rw-r--r--t/chainlint/arithmetic-expansion.test2
-rw-r--r--t/chainlint/bash-array.expect20
-rw-r--r--t/chainlint/bash-array.test2
-rw-r--r--t/chainlint/blank-line-before-esac.expect36
-rw-r--r--t/chainlint/blank-line-before-esac.test2
-rw-r--r--t/chainlint/blank-line.expect16
-rw-r--r--t/chainlint/blank-line.test2
-rw-r--r--t/chainlint/block-comment.expect16
-rw-r--r--t/chainlint/block-comment.test2
-rw-r--r--t/chainlint/block.expect46
-rw-r--r--t/chainlint/block.test2
-rw-r--r--t/chainlint/broken-chain.expect12
-rw-r--r--t/chainlint/broken-chain.test2
-rw-r--r--t/chainlint/case-comment.expect22
-rw-r--r--t/chainlint/case-comment.test2
-rw-r--r--t/chainlint/case.expect38
-rw-r--r--t/chainlint/case.test2
-rw-r--r--t/chainlint/chain-break-background.expect18
-rw-r--r--t/chainlint/chain-break-background.test2
-rw-r--r--t/chainlint/chain-break-continue.expect24
-rw-r--r--t/chainlint/chain-break-continue.test2
-rw-r--r--t/chainlint/chain-break-false.expect18
-rw-r--r--t/chainlint/chain-break-false.test2
-rw-r--r--t/chainlint/chain-break-return-exit.expect38
-rw-r--r--t/chainlint/chain-break-return-exit.test2
-rw-r--r--t/chainlint/chain-break-status.expect18
-rw-r--r--t/chainlint/chain-break-status.test2
-rw-r--r--t/chainlint/chained-block.expect18
-rw-r--r--t/chainlint/chained-block.test2
-rw-r--r--t/chainlint/chained-subshell.expect20
-rw-r--r--t/chainlint/chained-subshell.test2
-rw-r--r--t/chainlint/close-nested-and-parent-together.expect6
-rw-r--r--t/chainlint/close-nested-and-parent-together.test2
-rw-r--r--t/chainlint/close-subshell.expect52
-rw-r--r--t/chainlint/close-subshell.test2
-rw-r--r--t/chainlint/command-substitution-subsubshell.expect4
-rw-r--r--t/chainlint/command-substitution-subsubshell.test2
-rw-r--r--t/chainlint/command-substitution.expect18
-rw-r--r--t/chainlint/command-substitution.test2
-rw-r--r--t/chainlint/comment.expect16
-rw-r--r--t/chainlint/comment.test2
-rw-r--r--t/chainlint/complex-if-in-cuddled-loop.expect18
-rw-r--r--t/chainlint/complex-if-in-cuddled-loop.test2
-rw-r--r--t/chainlint/cuddled-if-then-else.expect12
-rw-r--r--t/chainlint/cuddled-if-then-else.test2
-rw-r--r--t/chainlint/cuddled-loop.expect8
-rw-r--r--t/chainlint/cuddled-loop.test2
-rw-r--r--t/chainlint/cuddled.expect34
-rw-r--r--t/chainlint/cuddled.test2
-rw-r--r--t/chainlint/double-here-doc.expect24
-rw-r--r--t/chainlint/double-here-doc.test2
-rw-r--r--t/chainlint/dqstring-line-splice.expect10
-rw-r--r--t/chainlint/dqstring-line-splice.test2
-rw-r--r--t/chainlint/dqstring-no-interpolate.expect24
-rw-r--r--t/chainlint/dqstring-no-interpolate.test2
-rw-r--r--t/chainlint/empty-here-doc.expect8
-rw-r--r--t/chainlint/empty-here-doc.test2
-rw-r--r--t/chainlint/exclamation.expect8
-rw-r--r--t/chainlint/exclamation.test2
-rw-r--r--t/chainlint/exit-loop.expect48
-rw-r--r--t/chainlint/exit-loop.test2
-rw-r--r--t/chainlint/exit-subshell.expect10
-rw-r--r--t/chainlint/exit-subshell.test2
-rw-r--r--t/chainlint/for-loop-abbreviated.expect10
-rw-r--r--t/chainlint/for-loop-abbreviated.test2
-rw-r--r--t/chainlint/for-loop.expect28
-rw-r--r--t/chainlint/for-loop.test2
-rw-r--r--t/chainlint/function.expect22
-rw-r--r--t/chainlint/function.test2
-rw-r--r--t/chainlint/here-doc-body-indent.expect2
-rw-r--r--t/chainlint/here-doc-body-indent.test4
-rw-r--r--t/chainlint/here-doc-body-pathological.expect7
-rw-r--r--t/chainlint/here-doc-body-pathological.test9
-rw-r--r--t/chainlint/here-doc-body.expect7
-rw-r--r--t/chainlint/here-doc-body.test9
-rw-r--r--t/chainlint/here-doc-close-subshell.expect8
-rw-r--r--t/chainlint/here-doc-close-subshell.test2
-rw-r--r--t/chainlint/here-doc-double.expect2
-rw-r--r--t/chainlint/here-doc-double.test10
-rw-r--r--t/chainlint/here-doc-indent-operator.expect22
-rw-r--r--t/chainlint/here-doc-indent-operator.test2
-rw-r--r--t/chainlint/here-doc-multi-line-command-subst.expect16
-rw-r--r--t/chainlint/here-doc-multi-line-command-subst.test2
-rw-r--r--t/chainlint/here-doc-multi-line-string.expect14
-rw-r--r--t/chainlint/here-doc-multi-line-string.test2
-rw-r--r--t/chainlint/here-doc.expect50
-rw-r--r--t/chainlint/here-doc.test2
-rw-r--r--t/chainlint/if-condition-split.expect14
-rw-r--r--t/chainlint/if-condition-split.test2
-rw-r--r--t/chainlint/if-in-loop.expect24
-rw-r--r--t/chainlint/if-in-loop.test2
-rw-r--r--t/chainlint/if-then-else.expect44
-rw-r--r--t/chainlint/if-then-else.test2
-rw-r--r--t/chainlint/incomplete-line.expect20
-rw-r--r--t/chainlint/incomplete-line.test2
-rw-r--r--t/chainlint/inline-comment.expect16
-rw-r--r--t/chainlint/inline-comment.test2
-rw-r--r--t/chainlint/loop-detect-failure.expect30
-rw-r--r--t/chainlint/loop-detect-failure.test2
-rw-r--r--t/chainlint/loop-detect-status.expect36
-rw-r--r--t/chainlint/loop-detect-status.test2
-rw-r--r--t/chainlint/loop-in-if.expect24
-rw-r--r--t/chainlint/loop-in-if.test2
-rw-r--r--t/chainlint/loop-upstream-pipe.expect20
-rw-r--r--t/chainlint/loop-upstream-pipe.test2
-rw-r--r--t/chainlint/multi-line-nested-command-substitution.expect36
-rw-r--r--t/chainlint/multi-line-nested-command-substitution.test2
-rw-r--r--t/chainlint/multi-line-string.expect28
-rw-r--r--t/chainlint/multi-line-string.test2
-rw-r--r--t/chainlint/negated-one-liner.expect10
-rw-r--r--t/chainlint/negated-one-liner.test2
-rw-r--r--t/chainlint/nested-cuddled-subshell.expect50
-rw-r--r--t/chainlint/nested-cuddled-subshell.test2
-rw-r--r--t/chainlint/nested-here-doc.expect60
-rw-r--r--t/chainlint/nested-here-doc.test2
-rw-r--r--t/chainlint/nested-loop-detect-failure.expect62
-rw-r--r--t/chainlint/nested-loop-detect-failure.test2
-rw-r--r--t/chainlint/nested-subshell-comment.expect22
-rw-r--r--t/chainlint/nested-subshell-comment.test2
-rw-r--r--t/chainlint/nested-subshell.expect26
-rw-r--r--t/chainlint/nested-subshell.test2
-rw-r--r--t/chainlint/not-heredoc.expect28
-rw-r--r--t/chainlint/not-heredoc.test2
-rw-r--r--t/chainlint/one-liner-for-loop.expect18
-rw-r--r--t/chainlint/one-liner-for-loop.test2
-rw-r--r--t/chainlint/one-liner.expect18
-rw-r--r--t/chainlint/one-liner.test2
-rw-r--r--t/chainlint/p4-filespec.expect8
-rw-r--r--t/chainlint/p4-filespec.test2
-rw-r--r--t/chainlint/pipe.expect20
-rw-r--r--t/chainlint/pipe.test2
-rw-r--r--t/chainlint/return-loop.expect10
-rw-r--r--t/chainlint/return-loop.test2
-rw-r--r--t/chainlint/semicolon.expect38
-rw-r--r--t/chainlint/semicolon.test2
-rw-r--r--t/chainlint/sqstring-in-sqstring.expect8
-rw-r--r--t/chainlint/sqstring-in-sqstring.test2
-rw-r--r--t/chainlint/subshell-here-doc.expect60
-rw-r--r--t/chainlint/subshell-here-doc.test2
-rw-r--r--t/chainlint/subshell-one-liner.expect38
-rw-r--r--t/chainlint/subshell-one-liner.test2
-rw-r--r--t/chainlint/t7900-subtree.expect44
-rw-r--r--t/chainlint/t7900-subtree.test2
-rw-r--r--t/chainlint/token-pasting.expect54
-rw-r--r--t/chainlint/token-pasting.test2
-rw-r--r--t/chainlint/unclosed-here-doc-indent.expect8
-rw-r--r--t/chainlint/unclosed-here-doc-indent.test2
-rw-r--r--t/chainlint/unclosed-here-doc.expect14
-rw-r--r--t/chainlint/unclosed-here-doc.test2
-rw-r--r--t/chainlint/while-loop.expect28
-rw-r--r--t/chainlint/while-loop.test2
-rw-r--r--t/helper/test-oidmap.c125
-rw-r--r--t/helper/test-reftable.c1
-rw-r--r--t/helper/test-tool.c1
-rw-r--r--t/helper/test-tool.h1
-rw-r--r--t/lib-bundle-uri-protocol.sh4
-rwxr-xr-xt/t0016-oidmap.sh112
-rwxr-xr-xt/t0600-reffiles-backend.sh38
-rwxr-xr-xt/t0612-reftable-jgit-compatibility.sh1
-rwxr-xr-xt/t0613-reftable-write-options.sh1
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh16
-rwxr-xr-xt/t1404-update-ref-errors.sh196
-rwxr-xr-xt/t5516-fetch-push.sh10
-rwxr-xr-xt/t5529-push-errors.sh17
-rwxr-xr-xt/t5551-http-fetch-smart.sh1
-rwxr-xr-xt/t5553-set-upstream.sh8
-rwxr-xr-xt/t5563-simple-http-auth.sh116
-rwxr-xr-xt/t6120-describe.sh36
-rwxr-xr-xt/t6406-merge-attr.sh42
-rwxr-xr-xt/t9001-send-email.sh43
-rw-r--r--t/test-lib-functions.sh32
-rw-r--r--t/test-lib.sh40
-rw-r--r--t/unit-tests/t-oidmap.c181
-rw-r--r--t/unit-tests/t-reftable-record.c551
201 files changed, 2776 insertions, 1790 deletions
diff --git a/.clang-format b/.clang-format
index 3ed4fac753..6408251577 100644
--- a/.clang-format
+++ b/.clang-format
@@ -149,20 +149,25 @@ Cpp11BracedListStyle: false
# A list of macros that should be interpreted as foreach loops instead of as
# function calls. Taken from:
-# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' \
-# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \
-# | sort | uniq
+# git grep -h '^#define [^[:space:]]*for_\?each[^[:space:]]*(' |
+# sed "s/^#define / - '/; s/(.*$/'/" | sort | uniq
ForEachMacros:
- - 'for_each_abbrev'
- 'for_each_builtin'
- 'for_each_string_list_item'
- 'for_each_ut'
- 'for_each_wanted_builtin'
+ - 'hashmap_for_each_entry'
+ - 'hashmap_for_each_entry_from'
+ - 'kh_foreach'
+ - 'kh_foreach_value'
- 'list_for_each'
- 'list_for_each_dir'
- 'list_for_each_prev'
- 'list_for_each_prev_safe'
- 'list_for_each_safe'
+ - 'strintmap_for_each_entry'
+ - 'strmap_for_each_entry'
+ - 'strset_for_each_entry'
# The maximum number of consecutive empty lines to keep.
MaxEmptyLinesToKeep: 1
diff --git a/Documentation/RelNotes/2.46.0.txt b/Documentation/RelNotes/2.46.0.txt
index a0b0b325bc..64d83fd63f 100644
--- a/Documentation/RelNotes/2.46.0.txt
+++ b/Documentation/RelNotes/2.46.0.txt
@@ -89,6 +89,11 @@ UI, Workflows & Features
variable did nothing but giving a "this does not do anything"
warning. The warning has been removed.
+ * The http transport can now be told to send request with
+ authentication material without first getting a 401 response.
+
+ * A handful of entries are added to the GitFAQ document.
+
Performance, Internal Implementation, Development Support etc.
@@ -150,7 +155,7 @@ Performance, Internal Implementation, Development Support etc.
* A new test was added to ensure git commands that are designed to
run outside repositories do work.
- * Basic unit tests for reftable have been reimplemented under the
+ * A few tests in reftable library have been rewritten using the
unit test framework.
* A pair of test helpers that essentially are unit tests on hash
@@ -208,6 +213,16 @@ Performance, Internal Implementation, Development Support etc.
* The code to deal with modified paths that are out-of-cone in a
sparsely checked out working tree has been optimized.
+ * An existing test of oidmap API has been rewritten with the
+ unit-test framework.
+
+ * The "ort" merge backend saw one bugfix for a crash that happens
+ when inner merge gets killed, and assorted code clean-ups.
+
+ * A new warning message is issued when a command has to expand a
+ sparse index to handle working tree cruft that are outside of the
+ sparse checkout.
+
Fixes since v2.45
-----------------
@@ -381,6 +396,36 @@ Fixes since v2.45
* Code clean-up.
(merge 4b837f821e rs/simplify-submodule-helper-super-prefix-invocation later to maint).
+ * "git describe --dirty --broken" forgot to refresh the index before
+ seeing if there is any chang, ("git describe --dirty" correctly did
+ so), which has been corrected.
+ (merge b8ae42e292 as/describe-broken-refresh-index-fix later to maint).
+
+ * Test suite has been taught not to unnecessarily rely on DNS failing
+ a bogus external name.
+ (merge 407cdbd271 jk/tests-without-dns later to maint).
+
+ * GitWeb update to use committer date consistently in rss/atom feeds.
+ (merge cf6ead095b am/gitweb-feed-use-committer-date later to maint).
+
+ * Custom control structures we invented more recently have been
+ taught to the clang-format file.
+ (merge 1457dff9be rs/clang-format-updates later to maint).
+
+ * Developer build procedure fix.
+ (merge df32729866 tb/dev-build-pedantic-fix later to maint).
+
+ * "git push" that pushes only deletion gave an unnecessary and
+ harmless error message when push negotiation is configured, which
+ has been corrected.
+ (merge 4d8ee0317f jc/disable-push-nego-for-deletion later to maint).
+
+ * Address-looking strings found on the trailer are now placed on the
+ Cc: list after running through sanitize_address by "git send-email".
+ (merge c852531f45 cb/send-email-sanitize-trailer-addresses later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge 493fdae046 ew/object-convert-leakfix later to maint).
(merge 00f3661a0a ss/doc-eol-attr-fix later to maint).
+ (merge 428c40da61 ri/doc-show-branch-fix later to maint).
+ (merge 58696bfcaa jc/where-is-bash-for-ci later to maint).
diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt
index fa61241756..0ba8989820 100644
--- a/Documentation/config/advice.txt
+++ b/Documentation/config/advice.txt
@@ -116,6 +116,10 @@ advice.*::
skippedCherryPicks::
Shown when linkgit:git-rebase[1] skips a commit that has already
been cherry-picked onto the upstream branch.
+ sparseIndexExpanded::
+ Shown when a sparse index is expanded to a full index, which is likely
+ due to an unexpected set of files existing outside of the
+ sparse-checkout.
statusAheadBehind::
Shown when linkgit:git-status[1] computes the ahead/behind
counts for a local ref compared to its remote tracking ref,
diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt
index 2d4e0c9b86..162b33fc52 100644
--- a/Documentation/config/http.txt
+++ b/Documentation/config/http.txt
@@ -7,6 +7,11 @@ http.proxy::
linkgit:gitcredentials[7] for more information. The syntax thus is
'[protocol://][user[:password]@]proxyhost[:port]'. This can be overridden
on a per-remote basis; see remote.<name>.proxy
++
+Any proxy, however configured, must be completely transparent and must not
+modify, transform, or buffer the request or response in any way. Proxies which
+are not completely transparent are known to cause various forms of breakage
+with Git.
http.proxyAuthMethod::
Set the method with which to authenticate against the HTTP proxy. This
@@ -56,6 +61,26 @@ http.emptyAuth::
a username in the URL, as libcurl normally requires a username for
authentication.
+http.proactiveAuth::
+ Attempt authentication without first making an unauthenticated attempt and
+ receiving a 401 response. This can be used to ensure that all requests are
+ authenticated. If `http.emptyAuth` is set to true, this value has no effect.
++
+If the credential helper used specifies an authentication scheme (i.e., via the
+`authtype` field), that value will be used; if a username and password is
+provided without a scheme, then Basic authentication is used. The value of the
+option determines the scheme requested from the helper. Possible values are:
++
+--
+* `basic` - Request Basic authentication from the helper.
+* `auto` - Allow the helper to pick an appropriate scheme.
+* `none` - Disable proactive authentication.
+--
++
+Note that TLS should always be used with this configuration, since otherwise it
+is easy to accidentally expose plaintext credentials if Basic authentication
+is selected.
+
http.delegation::
Control GSSAPI credential delegation. The delegation is disabled
by default in libcurl since version 7.21.7. Set parameter to tell
@@ -82,12 +107,16 @@ http.cookieFile::
in the Git http session, if they match the server. The file format
of the file to read cookies from should be plain HTTP headers or
the Netscape/Mozilla cookie file format (see `curl(1)`).
+ Set it to an empty string, to accept only new cookies from
+ the server and send them back in successive requests within same
+ connection.
NOTE that the file specified with http.cookieFile is used only as
input unless http.saveCookies is set.
http.saveCookies::
If set, store cookies received during requests to the file specified by
- http.cookieFile. Has no effect if http.cookieFile is unset.
+ http.cookieFile. Has no effect if http.cookieFile is unset, or set to
+ an empty string.
http.version::
Use the specified HTTP protocol version when communicating with a server.
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index c771c89770..bc31d8b6d3 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -22,7 +22,7 @@ Shows the commit ancestry graph starting from the commits named
with <rev>s or <glob>s (or all refs under refs/heads
and/or refs/tags) semi-visually.
-It cannot show more than 29 branches and commits at a time.
+It cannot show more than 26 branches and commits at a time.
It uses `showbranch.default` multi-valued configuration items if
no <rev> or <glob> is given on the command line.
diff --git a/Documentation/gitfaq.txt b/Documentation/gitfaq.txt
index 8c1f2d5675..f2917d142c 100644
--- a/Documentation/gitfaq.txt
+++ b/Documentation/gitfaq.txt
@@ -185,6 +185,58 @@ Then, you can adjust your push URL to use `git@example_author` or
`git@example_committer` instead of `git@example.org` (e.g., `git remote set-url
git@example_author:org1/project1.git`).
+Transfers
+---------
+
+[[sync-working-tree]]
+How do I sync a working tree across systems?::
+ First, decide whether you want to do this at all. Git works best when you
+ push or pull your work using the typical `git push` and `git fetch` commands
+ and isn't designed to share a working tree across systems. This is
+ potentially risky and in some cases can cause repository corruption or data
+ loss.
++
+Usually, doing so will cause `git status` to need to re-read every file in the
+working tree. Additionally, Git's security model does not permit sharing a
+working tree across untrusted users, so it is only safe to sync a working tree
+if it will only be used by a single user across all machines.
++
+It is important not to use a cloud syncing service to sync any portion of a Git
+repository, since this can cause corruption, such as missing objects, changed
+or added files, broken refs, and a wide variety of other problems. These
+services tend to sync file by file on a continuous basis and don't understand
+the structure of a Git repository. This is especially bad if they sync the
+repository in the middle of it being updated, since that is very likely to
+cause incomplete or partial updates and therefore data loss.
++
+An example of the kind of corruption that can occur is conflicts over the state
+of refs, such that both sides end up with different commits on a branch that
+the other doesn't have. This can result in important objects becoming
+unreferenced and possibly pruned by `git gc`, causing data loss.
++
+Therefore, it's better to push your work to either the other system or a central
+server using the normal push and pull mechanism. However, this doesn't always
+preserve important data, like stashes, so some people prefer to share a working
+tree across systems.
++
+If you do this, the recommended approach is to use `rsync -a --delete-after`
+(ideally with an encrypted connection such as with `ssh`) on the root of
+repository. You should ensure several things when you do this:
++
+* If you have additional worktrees or a separate Git directory, they must be
+ synced at the same time as the main working tree and repository.
+* You are comfortable with the destination directory being an exact copy of the
+ source directory, _deleting any data that is already there_.
+* The repository (including all worktrees and the Git directory) is in a
+ quiescent state for the duration of the transfer (that is, no operations of
+ any sort are taking place on it, including background operations like `git
+ gc` and operations invoked by your editor).
++
+Be aware that even with these recommendations, syncing in this way has some risk
+since it bypasses Git's normal integrity checking for repositories, so having
+backups is advised. You may also wish to do a `git fsck` to verify the
+integrity of your data on the destination system after syncing.
+
Common Issues
-------------
@@ -241,6 +293,42 @@ How do I know if I want to do a fetch or a pull?::
ignore the upstream changes. A pull consists of a fetch followed
immediately by either a merge or rebase. See linkgit:git-pull[1].
+[[proxy]]
+Can I use a proxy with Git?::
+ Yes, Git supports the use of proxies. Git honors the standard `http_proxy`,
+ `https_proxy`, and `no_proxy` environment variables commonly used on Unix, and
+ it also can be configured with `http.proxy` and similar options for HTTPS (see
+ linkgit:git-config[1]). The `http.proxy` and related options can be
+ customized on a per-URL pattern basis. In addition, Git can in theory
+ function normally with transparent proxies that exist on the network.
++
+For SSH, Git can support a proxy using OpenSSH's `ProxyCommand`. Commonly used
+tools include `netcat` and `socat`. However, they must be configured not to
+exit when seeing EOF on standard input, which usually means that `netcat` will
+require `-q` and `socat` will require a timeout with something like `-t 10`.
+This is required because the way the Git SSH server knows that no more requests
+will be made is an EOF on standard input, but when that happens, the server may
+not have yet processed the final request, so dropping the connection at that
+point would interrupt that request.
++
+An example configuration entry in `~/.ssh/config` with an HTTP proxy might look
+like this:
++
+----
+Host git.example.org
+ User git
+ ProxyCommand socat -t 10 - PROXY:proxy.example.org:%h:%p,proxyport=8080
+----
++
+Note that in all cases, for Git to work properly, the proxy must be completely
+transparent. The proxy cannot modify, tamper with, or buffer the connection in
+any way, or Git will almost certainly fail to work. Note that many proxies,
+including many TLS middleboxes, Windows antivirus and firewall programs other
+than Windows Defender and Windows Firewall, and filtering proxies fail to meet
+this standard, and as a result end up breaking Git. Because of the many
+reports of problems and their poor security history, we recommend against the
+use of these classes of software and devices.
+
Merging and Rebasing
--------------------
@@ -357,8 +445,9 @@ I'm on Windows and git diff shows my files as having a `^M` at the end.::
+
You can store the files in the repository with Unix line endings and convert
them automatically to your platform's line endings. To do that, set the
-configuration option `core.eol` to `native` and see the following entry for
-information about how to configure files as text or binary.
+configuration option `core.eol` to `native` and see
+<<recommended-storage-settings,the question on recommended storage settings>>
+for information about how to configure files as text or binary.
+
You can also control this behavior with the `core.whitespace` setting if you
don't wish to remove the carriage returns from your line endings.
@@ -420,14 +509,26 @@ references, URLs, and hashes stored in the repository.
+
We also recommend setting a linkgit:gitattributes[5] file to explicitly mark
which files are text and which are binary. If you want Git to guess, you can
-set the attribute `text=auto`. For example, the following might be appropriate
-in some projects:
+set the attribute `text=auto`.
++
+With text files, Git will generally ensure that LF endings are used in the
+repository. The `core.autocrlf` and `core.eol` configuration variables specify
+what line-ending convention is followed when any text file is checked out. You
+can also use the `eol` attribute (e.g., `eol=crlf`) to override which files get
+what line-ending treatment.
++
+For example, generally shell files must have LF endings and batch files must
+have CRLF endings, so the following might be appropriate in some projects:
+
----
# By default, guess.
* text=auto
# Mark all C files as text.
*.c text
+# Ensure all shell files have LF endings and all batch files have CRLF
+# endings in the working tree and both have LF in the repo.
+*.sh text eol=lf
+*.bat text eol=crlf
# Mark all JPEG files as binary.
*.jpg binary
----
diff --git a/Makefile b/Makefile
index 3eab701b10..d6479092a0 100644
--- a/Makefile
+++ b/Makefile
@@ -809,7 +809,6 @@ TEST_BUILTINS_OBJS += test-match-trees.o
TEST_BUILTINS_OBJS += test-mergesort.o
TEST_BUILTINS_OBJS += test-mktemp.o
TEST_BUILTINS_OBJS += test-oid-array.o
-TEST_BUILTINS_OBJS += test-oidmap.o
TEST_BUILTINS_OBJS += test-online-cpus.o
TEST_BUILTINS_OBJS += test-pack-mtimes.o
TEST_BUILTINS_OBJS += test-parse-options.o
@@ -1337,9 +1336,11 @@ UNIT_TEST_PROGRAMS += t-ctype
UNIT_TEST_PROGRAMS += t-example-decorate
UNIT_TEST_PROGRAMS += t-hash
UNIT_TEST_PROGRAMS += t-mem-pool
+UNIT_TEST_PROGRAMS += t-oidmap
UNIT_TEST_PROGRAMS += t-oidtree
UNIT_TEST_PROGRAMS += t-prio-queue
UNIT_TEST_PROGRAMS += t-reftable-basics
+UNIT_TEST_PROGRAMS += t-reftable-record
UNIT_TEST_PROGRAMS += t-strbuf
UNIT_TEST_PROGRAMS += t-strcmp-offset
UNIT_TEST_PROGRAMS += t-strvec
@@ -2681,7 +2682,6 @@ REFTABLE_TEST_OBJS += reftable/block_test.o
REFTABLE_TEST_OBJS += reftable/dump.o
REFTABLE_TEST_OBJS += reftable/merged_test.o
REFTABLE_TEST_OBJS += reftable/pq_test.o
-REFTABLE_TEST_OBJS += reftable/record_test.o
REFTABLE_TEST_OBJS += reftable/readwrite_test.o
REFTABLE_TEST_OBJS += reftable/stack_test.o
REFTABLE_TEST_OBJS += reftable/test_framework.o
diff --git a/advice.c b/advice.c
index 558a46fc0b..6b879d805c 100644
--- a/advice.c
+++ b/advice.c
@@ -78,6 +78,7 @@ static struct {
[ADVICE_SEQUENCER_IN_USE] = { "sequencerInUse" },
[ADVICE_SET_UPSTREAM_FAILURE] = { "setUpstreamFailure" },
[ADVICE_SKIPPED_CHERRY_PICKS] = { "skippedCherryPicks" },
+ [ADVICE_SPARSE_INDEX_EXPANDED] = { "sparseIndexExpanded" },
[ADVICE_STATUS_AHEAD_BEHIND_WARNING] = { "statusAheadBehindWarning" },
[ADVICE_STATUS_HINTS] = { "statusHints" },
[ADVICE_STATUS_U_OPTION] = { "statusUoption" },
diff --git a/advice.h b/advice.h
index 5105d90129..d7466bc0ef 100644
--- a/advice.h
+++ b/advice.h
@@ -45,6 +45,7 @@ enum advice_type {
ADVICE_SEQUENCER_IN_USE,
ADVICE_SET_UPSTREAM_FAILURE,
ADVICE_SKIPPED_CHERRY_PICKS,
+ ADVICE_SPARSE_INDEX_EXPANDED,
ADVICE_STATUS_AHEAD_BEHIND_WARNING,
ADVICE_STATUS_HINTS,
ADVICE_STATUS_U_OPTION,
diff --git a/builtin/describe.c b/builtin/describe.c
index e5287eddf2..cf8edc4222 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -53,6 +53,10 @@ static const char *diff_index_args[] = {
"diff-index", "--quiet", "HEAD", "--", NULL
};
+static const char *update_index_args[] = {
+ "update-index", "--unmerged", "-q", "--refresh", NULL
+};
+
struct commit_name {
struct hashmap_entry entry;
struct object_id peeled;
@@ -645,6 +649,14 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
if (argc == 0) {
if (broken) {
struct child_process cp = CHILD_PROCESS_INIT;
+
+ strvec_pushv(&cp.args, update_index_args);
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ cp.no_stdout = 1;
+ run_command(&cp);
+
+ child_process_init(&cp);
strvec_pushv(&cp.args, diff_index_args);
cp.git_cmd = 1;
cp.no_stdin = 1;
diff --git a/builtin/push.c b/builtin/push.c
index 8260c6e46a..7a67398124 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -96,9 +96,8 @@ static void refspec_append_mapped(struct refspec *refspec, const char *ref,
refspec_append(refspec, ref);
}
-static void set_refspecs(const char **refs, int nr, const char *repo)
+static void set_refspecs(const char **refs, int nr, struct remote *remote)
{
- struct remote *remote = NULL;
struct ref *local_refs = NULL;
int i;
@@ -124,17 +123,10 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
local_refs = get_local_heads();
/* Does "ref" uniquely name our ref? */
- if (count_refspec_match(ref, local_refs, &matched) != 1) {
+ if (count_refspec_match(ref, local_refs, &matched) != 1)
refspec_append(&rs, ref);
- } else {
- /* lazily grab remote */
- if (!remote)
- remote = remote_get(repo);
- if (!remote)
- BUG("must get a remote for repo '%s'", repo);
-
+ else
refspec_append_mapped(&rs, ref, remote, matched);
- }
} else
refspec_append(&rs, ref);
}
@@ -630,10 +622,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
if (tags)
refspec_append(&rs, "refs/tags/*");
- if (argc > 0) {
+ if (argc > 0)
repo = argv[0];
- set_refspecs(argv + 1, argc - 1, repo);
- }
remote = pushremote_get(repo);
if (!remote) {
@@ -649,6 +639,9 @@ int cmd_push(int argc, const char **argv, const char *prefix)
" git push <name>\n"));
}
+ if (argc > 0)
+ set_refspecs(argv + 1, argc - 1, remote);
+
if (remote->mirror)
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
diff --git a/ci/check-directional-formatting.bash b/ci/check-directional-formatting.bash
index e6211b141a..3cbbb7030e 100755
--- a/ci/check-directional-formatting.bash
+++ b/ci/check-directional-formatting.bash
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# This script verifies that the non-binary files tracked in the Git index do
# not contain any Unicode directional formatting: such formatting could be used
diff --git a/ci/lib.sh b/ci/lib.sh
index 814578ffc6..51f8f59a29 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -370,7 +370,6 @@ linux-musl)
linux-leaks|linux-reftable-leaks)
export SANITIZE=leak
export GIT_TEST_PASSING_SANITIZE_LEAK=true
- export GIT_TEST_SANITIZE_LEAK_LOG=true
;;
linux-asan-ubsan)
export SANITIZE=address,undefined
diff --git a/config.mak.dev b/config.mak.dev
index 1ce4c70613..5229c35484 100644
--- a/config.mak.dev
+++ b/config.mak.dev
@@ -10,7 +10,7 @@ endif
DEVELOPER_CFLAGS += -Wall
ifeq ($(filter no-pedantic,$(DEVOPTS)),)
DEVELOPER_CFLAGS += -pedantic
-ifneq (($or $(filter gcc5,$(COMPILER_FEATURES)),$(filter clang4,$(COMPILER_FEATURES))),)
+ifneq ($(or $(filter gcc5,$(COMPILER_FEATURES)),$(filter clang4,$(COMPILER_FEATURES))),)
DEVELOPER_CFLAGS += -Wpedantic
ifneq ($(filter gcc10,$(COMPILER_FEATURES)),)
ifeq ($(uname_S),MINGW)
diff --git a/git-send-email.perl b/git-send-email.perl
index f0be4b4560..72044e5ef3 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1847,9 +1847,9 @@ sub pre_process_file {
$what, $_) unless $quiet;
next;
}
- push @cc, $c;
+ push @cc, $sc;
printf(__("(body) Adding cc: %s from line '%s'\n"),
- $c, $_) unless $quiet;
+ $sc, $_) unless $quiet;
}
}
close $fh;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index ccd14e0e30..b09a8d0523 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -8326,10 +8326,10 @@ XML
my %co = %{$commitlist[$i]};
my $commit = $co{'id'};
# we read 150, we always show 30 and the ones more recent than 48 hours
- if (($i >= 20) && ((time - $co{'author_epoch'}) > 48*60*60)) {
+ if (($i >= 20) && ((time - $co{'committer_epoch'}) > 48*60*60)) {
last;
}
- my %cd = parse_date($co{'author_epoch'}, $co{'author_tz'});
+ my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'});
# get list of changed files
open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
diff --git a/http.c b/http.c
index 13fa94bef3..623ed23489 100644
--- a/http.c
+++ b/http.c
@@ -108,12 +108,19 @@ static struct {
};
#endif
+enum proactive_auth {
+ PROACTIVE_AUTH_NONE = 0,
+ PROACTIVE_AUTH_IF_CREDENTIALS,
+ PROACTIVE_AUTH_AUTO,
+ PROACTIVE_AUTH_BASIC,
+};
+
static struct credential proxy_auth = CREDENTIAL_INIT;
static const char *curl_proxyuserpwd;
static char *curl_cookie_file;
static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT;
-static int http_proactive_auth;
+static enum proactive_auth http_proactive_auth;
static char *user_agent;
static int curl_empty_auth = -1;
@@ -148,6 +155,12 @@ static int http_schannel_check_revoke = 1;
*/
static int http_schannel_use_ssl_cainfo;
+static int always_auth_proactively(void)
+{
+ return http_proactive_auth != PROACTIVE_AUTH_NONE &&
+ http_proactive_auth != PROACTIVE_AUTH_IF_CREDENTIALS;
+}
+
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
{
size_t size = eltsize * nmemb;
@@ -539,6 +552,20 @@ static int http_options(const char *var, const char *value,
return 0;
}
+ if (!strcmp("http.proactiveauth", var)) {
+ if (!value)
+ return config_error_nonbool(var);
+ if (!strcmp(value, "auto"))
+ http_proactive_auth = PROACTIVE_AUTH_AUTO;
+ else if (!strcmp(value, "basic"))
+ http_proactive_auth = PROACTIVE_AUTH_BASIC;
+ else if (!strcmp(value, "none"))
+ http_proactive_auth = PROACTIVE_AUTH_NONE;
+ else
+ warning(_("Unknown value for http.proactiveauth"));
+ return 0;
+ }
+
/* Fall back on the default ones */
return git_default_config(var, value, ctx, data);
}
@@ -580,14 +607,29 @@ static void init_curl_http_auth(CURL *result)
{
if ((!http_auth.username || !*http_auth.username) &&
(!http_auth.credential || !*http_auth.credential)) {
- if (curl_empty_auth_enabled())
+ int empty_auth = curl_empty_auth_enabled();
+ if ((empty_auth != -1 && !always_auth_proactively()) || empty_auth == 1) {
curl_easy_setopt(result, CURLOPT_USERPWD, ":");
- return;
+ return;
+ } else if (!always_auth_proactively()) {
+ return;
+ } else if (http_proactive_auth == PROACTIVE_AUTH_BASIC) {
+ strvec_push(&http_auth.wwwauth_headers, "Basic");
+ }
}
credential_fill(&http_auth, 1);
if (http_auth.password) {
+ if (always_auth_proactively()) {
+ /*
+ * We got a credential without an authtype and we don't
+ * know what's available. Since our only two options at
+ * the moment are auto (which defaults to basic) and
+ * basic, use basic for now.
+ */
+ curl_easy_setopt(result, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ }
curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
}
@@ -1050,7 +1092,7 @@ static CURL *get_curl_handle(void)
#endif
}
- if (http_proactive_auth)
+ if (http_proactive_auth != PROACTIVE_AUTH_NONE)
init_curl_http_auth(result);
if (getenv("GIT_SSL_VERSION"))
@@ -1294,7 +1336,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
die("curl_global_init failed");
- http_proactive_auth = proactive_auth;
+ if (proactive_auth && http_proactive_auth == PROACTIVE_AUTH_NONE)
+ http_proactive_auth = PROACTIVE_AUTH_IF_CREDENTIALS;
if (remote && remote->http_proxy)
curl_http_proxy = xstrdup(remote->http_proxy);
@@ -1466,7 +1509,16 @@ struct active_request_slot *get_active_slot(void)
slot->finished = NULL;
slot->callback_data = NULL;
slot->callback_func = NULL;
+
+ if (curl_cookie_file && !strcmp(curl_cookie_file, "-")) {
+ warning(_("refusing to read cookies from http.cookiefile '-'"));
+ FREE_AND_NULL(curl_cookie_file);
+ }
curl_easy_setopt(slot->curl, CURLOPT_COOKIEFILE, curl_cookie_file);
+ if (curl_save_cookies && (!curl_cookie_file || !curl_cookie_file[0])) {
+ curl_save_cookies = 0;
+ warning(_("ignoring http.savecookies for empty http.cookiefile"));
+ }
if (curl_save_cookies)
curl_easy_setopt(slot->curl, CURLOPT_COOKIEJAR, curl_cookie_file);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
@@ -1790,6 +1842,8 @@ static int handle_curl_result(struct slot_results *results)
return HTTP_REAUTH;
}
credential_reject(&http_auth);
+ if (always_auth_proactively())
+ http_proactive_auth = PROACTIVE_AUTH_NONE;
return HTTP_NOAUTH;
} else {
http_auth_methods &= ~CURLAUTH_GSSNEGOTIATE;
@@ -2186,7 +2240,12 @@ static int http_request_reauth(const char *url,
struct http_get_options *options)
{
int i = 3;
- int ret = http_request(url, result, target, options);
+ int ret;
+
+ if (always_auth_proactively())
+ credential_fill(&http_auth, 1);
+
+ ret = http_request(url, result, target, options);
if (ret != HTTP_OK && ret != HTTP_REAUTH)
return ret;
diff --git a/merge-ort.c b/merge-ort.c
index ffbdb8fc8e..e9d01ac7f7 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -545,17 +545,35 @@ enum conflict_and_info_types {
CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE,
CONFLICT_SUBMODULE_MAY_HAVE_REWINDS,
CONFLICT_SUBMODULE_NULL_MERGE_BASE,
- CONFLICT_SUBMODULE_CORRUPT,
+
+ /* INSERT NEW ENTRIES HERE */
+
+ /*
+ * Keep this entry after all regular conflict and info types; only
+ * errors (failures causing immediate abort of the merge) should
+ * come after this.
+ */
+ NB_REGULAR_CONFLICT_TYPES,
+
+ /*
+ * Something is seriously wrong; cannot even perform merge;
+ * Keep this group _last_ other than NB_TOTAL_TYPES
+ */
+ ERROR_SUBMODULE_CORRUPT,
+ ERROR_THREEWAY_CONTENT_MERGE_FAILED,
+ ERROR_OBJECT_WRITE_FAILED,
+ ERROR_OBJECT_READ_FAILED,
+ ERROR_OBJECT_NOT_A_BLOB,
/* Keep this entry _last_ in the list */
- NB_CONFLICT_TYPES,
+ NB_TOTAL_TYPES,
};
/*
* Short description of conflict type, relied upon by external tools.
*
* We can add more entries, but DO NOT change any of these strings. Also,
- * Order MUST match conflict_info_and_types.
+ * please ensure the order matches what is used in conflict_info_and_types.
*/
static const char *type_short_descriptions[] = {
/*** "Simple" conflicts and informational messages ***/
@@ -599,8 +617,18 @@ static const char *type_short_descriptions[] = {
"CONFLICT (submodule may have rewinds)",
[CONFLICT_SUBMODULE_NULL_MERGE_BASE] =
"CONFLICT (submodule lacks merge base)",
- [CONFLICT_SUBMODULE_CORRUPT] =
- "CONFLICT (submodule corrupt)"
+
+ /* Something is seriously wrong; cannot even perform merge */
+ [ERROR_SUBMODULE_CORRUPT] =
+ "ERROR (submodule corrupt)",
+ [ERROR_THREEWAY_CONTENT_MERGE_FAILED] =
+ "ERROR (three-way content merge failed)",
+ [ERROR_OBJECT_WRITE_FAILED] =
+ "ERROR (object write failed)",
+ [ERROR_OBJECT_READ_FAILED] =
+ "ERROR (object read failed)",
+ [ERROR_OBJECT_NOT_A_BLOB] =
+ "ERROR (object is not a blob)",
};
struct logical_conflict_info {
@@ -764,7 +792,8 @@ static void path_msg(struct merge_options *opt,
/* Sanity checks */
assert(omittable_hint ==
- !starts_with(type_short_descriptions[type], "CONFLICT") ||
+ (!starts_with(type_short_descriptions[type], "CONFLICT") &&
+ !starts_with(type_short_descriptions[type], "ERROR")) ||
type == CONFLICT_DIR_RENAME_SUGGESTED);
if (opt->record_conflict_msgs_as_headers && omittable_hint)
return; /* Do not record mere hints in headers */
@@ -1819,9 +1848,9 @@ static int merge_submodule(struct merge_options *opt,
/* check whether both changes are forward */
ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_a);
if (ret2 < 0) {
- path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path_msg(opt, ERROR_SUBMODULE_CORRUPT, 0,
path, NULL, NULL, NULL,
- _("Failed to merge submodule %s "
+ _("error: failed to merge submodule %s "
"(repository corrupt)"),
path);
ret = -1;
@@ -1830,9 +1859,9 @@ static int merge_submodule(struct merge_options *opt,
if (ret2 > 0)
ret2 = repo_in_merge_bases(&subrepo, commit_o, commit_b);
if (ret2 < 0) {
- path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path_msg(opt, ERROR_SUBMODULE_CORRUPT, 0,
path, NULL, NULL, NULL,
- _("Failed to merge submodule %s "
+ _("error: failed to merge submodule %s "
"(repository corrupt)"),
path);
ret = -1;
@@ -1850,9 +1879,9 @@ static int merge_submodule(struct merge_options *opt,
/* Case #1: a is contained in b or vice versa */
ret2 = repo_in_merge_bases(&subrepo, commit_a, commit_b);
if (ret2 < 0) {
- path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path_msg(opt, ERROR_SUBMODULE_CORRUPT, 0,
path, NULL, NULL, NULL,
- _("Failed to merge submodule %s "
+ _("error: failed to merge submodule %s "
"(repository corrupt)"),
path);
ret = -1;
@@ -1869,9 +1898,9 @@ static int merge_submodule(struct merge_options *opt,
}
ret2 = repo_in_merge_bases(&subrepo, commit_b, commit_a);
if (ret2 < 0) {
- path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path_msg(opt, ERROR_SUBMODULE_CORRUPT, 0,
path, NULL, NULL, NULL,
- _("Failed to merge submodule %s "
+ _("error: failed to merge submodule %s "
"(repository corrupt)"),
path);
ret = -1;
@@ -1903,9 +1932,9 @@ static int merge_submodule(struct merge_options *opt,
&merges);
switch (parent_count) {
case -1:
- path_msg(opt, CONFLICT_SUBMODULE_CORRUPT, 0,
+ path_msg(opt, ERROR_SUBMODULE_CORRUPT, 0,
path, NULL, NULL, NULL,
- _("Failed to merge submodule %s "
+ _("error: failed to merge submodule %s "
"(repository corrupt)"),
path);
ret = -1;
@@ -2111,7 +2140,7 @@ static int handle_content_merge(struct merge_options *opt,
* merges, which happens for example with rename/rename(2to1) and
* rename/add conflicts.
*/
- unsigned clean = 1;
+ int clean = 1;
/*
* handle_content_merge() needs both files to be of the same type, i.e.
@@ -2175,18 +2204,28 @@ static int handle_content_merge(struct merge_options *opt,
pathnames, extra_marker_size,
&result_buf);
- if ((merge_status < 0) || !result_buf.ptr)
- ret = error(_("failed to execute internal merge"));
+ if ((merge_status < 0) || !result_buf.ptr) {
+ path_msg(opt, ERROR_THREEWAY_CONTENT_MERGE_FAILED, 0,
+ pathnames[0], pathnames[1], pathnames[2], NULL,
+ _("error: failed to execute internal merge for %s"),
+ path);
+ ret = -1;
+ }
if (!ret &&
write_object_file(result_buf.ptr, result_buf.size,
- OBJ_BLOB, &result->oid))
- ret = error(_("unable to add %s to database"), path);
-
+ OBJ_BLOB, &result->oid)) {
+ path_msg(opt, ERROR_OBJECT_WRITE_FAILED, 0,
+ pathnames[0], pathnames[1], pathnames[2], NULL,
+ _("error: unable to add %s to database"), path);
+ ret = -1;
+ }
free(result_buf.ptr);
+
if (ret)
return -1;
- clean &= (merge_status == 0);
+ if (merge_status > 0)
+ clean = 0;
path_msg(opt, INFO_AUTO_MERGING, 1, path, NULL, NULL, NULL,
_("Auto-merging %s"), path);
} else if (S_ISGITLINK(a->mode)) {
@@ -2194,6 +2233,8 @@ static int handle_content_merge(struct merge_options *opt,
clean = merge_submodule(opt, pathnames[0],
two_way ? null_oid() : &o->oid,
&a->oid, &b->oid, &result->oid);
+ if (clean < 0)
+ return -1;
if (opt->priv->call_depth && two_way && !clean) {
result->mode = o->mode;
oidcpy(&result->oid, &o->oid);
@@ -3559,18 +3600,27 @@ static int sort_dirs_next_to_their_children(const char *one, const char *two)
return c1 - c2;
}
-static int read_oid_strbuf(const struct object_id *oid,
- struct strbuf *dst)
+static int read_oid_strbuf(struct merge_options *opt,
+ const struct object_id *oid,
+ struct strbuf *dst,
+ const char *path)
{
void *buf;
enum object_type type;
unsigned long size;
buf = repo_read_object_file(the_repository, oid, &type, &size);
- if (!buf)
- return error(_("cannot read object %s"), oid_to_hex(oid));
+ if (!buf) {
+ path_msg(opt, ERROR_OBJECT_READ_FAILED, 0,
+ path, NULL, NULL, NULL,
+ _("error: cannot read object %s"), oid_to_hex(oid));
+ return -1;
+ }
if (type != OBJ_BLOB) {
free(buf);
- return error(_("object %s is not a blob"), oid_to_hex(oid));
+ path_msg(opt, ERROR_OBJECT_NOT_A_BLOB, 0,
+ path, NULL, NULL, NULL,
+ _("error: object %s is not a blob"), oid_to_hex(oid));
+ return -1;
}
strbuf_attach(dst, buf, size, size + 1);
return 0;
@@ -3594,8 +3644,8 @@ static int blob_unchanged(struct merge_options *opt,
if (oideq(&base->oid, &side->oid))
return 1;
- if (read_oid_strbuf(&base->oid, &basebuf) ||
- read_oid_strbuf(&side->oid, &sidebuf))
+ if (read_oid_strbuf(opt, &base->oid, &basebuf, path) ||
+ read_oid_strbuf(opt, &side->oid, &sidebuf, path))
goto error_return;
/*
* Note: binary | is used so that both renormalizations are
@@ -4645,6 +4695,7 @@ void merge_display_update_messages(struct merge_options *opt,
struct hashmap_iter iter;
struct strmap_entry *e;
struct string_list olist = STRING_LIST_INIT_NODUP;
+ FILE *o = stdout;
if (opt->record_conflict_msgs_as_headers)
BUG("Either display conflict messages or record them as headers, not both");
@@ -4661,6 +4712,10 @@ void merge_display_update_messages(struct merge_options *opt,
}
string_list_sort(&olist);
+ /* Print to stderr if we hit errors rather than just conflicts */
+ if (result->clean < 0)
+ o = stderr;
+
/* Iterate over the items, printing them */
for (int path_nr = 0; path_nr < olist.nr; ++path_nr) {
struct string_list *conflicts = olist.items[path_nr].util;
@@ -4668,25 +4723,31 @@ void merge_display_update_messages(struct merge_options *opt,
struct logical_conflict_info *info =
conflicts->items[i].util;
+ /* On failure, ignore regular conflict types */
+ if (result->clean < 0 &&
+ info->type < NB_REGULAR_CONFLICT_TYPES)
+ continue;
+
if (detailed) {
- printf("%lu", (unsigned long)info->paths.nr);
- putchar('\0');
+ fprintf(o, "%lu", (unsigned long)info->paths.nr);
+ fputc('\0', o);
for (int n = 0; n < info->paths.nr; n++) {
- fputs(info->paths.v[n], stdout);
- putchar('\0');
+ fputs(info->paths.v[n], o);
+ fputc('\0', o);
}
- fputs(type_short_descriptions[info->type],
- stdout);
- putchar('\0');
+ fputs(type_short_descriptions[info->type], o);
+ fputc('\0', o);
}
- puts(conflicts->items[i].string);
+ fputs(conflicts->items[i].string, o);
+ fputc('\n', o);
if (detailed)
- putchar('\0');
+ fputc('\0', o);
}
}
string_list_clear(&olist, 0);
- print_submodule_conflict_suggestion(&opti->conflicted_submodules);
+ if (result->clean >= 0)
+ print_submodule_conflict_suggestion(&opti->conflicted_submodules);
/* Also include needed rename limit adjustment now */
diff_warn_rename_limit("merge.renamelimit",
@@ -5002,6 +5063,26 @@ static void merge_check_renames_reusable(struct merge_result *result,
/*** Function Grouping: merge_incore_*() and their internal variants ***/
+static void move_opt_priv_to_result_priv(struct merge_options *opt,
+ struct merge_result *result)
+{
+ /*
+ * opt->priv and result->priv are a bit weird. opt->priv contains
+ * information that we can re-use in subsequent merge operations to
+ * enable our cached renames optimization. The best way to provide
+ * that to subsequent merges is putting it in result->priv.
+ * However, putting it directly there would mean retrofitting lots
+ * of functions in this file to also take a merge_result pointer,
+ * which is ugly and annoying. So, we just make sure at the end of
+ * the merge (the outer merge if there are internal recursive ones)
+ * to move it.
+ */
+ assert(opt->priv && !result->priv);
+ result->priv = opt->priv;
+ result->_properly_initialized = RESULT_INITIALIZED;
+ opt->priv = NULL;
+}
+
/*
* Originally from merge_trees_internal(); heavily adapted, though.
*/
@@ -5032,6 +5113,7 @@ redo:
oid_to_hex(&side1->object.oid),
oid_to_hex(&side2->object.oid));
result->clean = -1;
+ move_opt_priv_to_result_priv(opt, result);
return;
}
trace2_region_leave("merge", "collect_merge_info", opt->repo);
@@ -5062,11 +5144,8 @@ redo:
/* existence of conflicted entries implies unclean */
result->clean &= strmap_empty(&opt->priv->conflicted);
}
- if (!opt->priv->call_depth) {
- result->priv = opt->priv;
- result->_properly_initialized = RESULT_INITIALIZED;
- opt->priv = NULL;
- }
+ if (!opt->priv->call_depth || result->clean < 0)
+ move_opt_priv_to_result_priv(opt, result);
}
/*
diff --git a/reftable/record_test.c b/reftable/record_test.c
deleted file mode 100644
index 58290bdba3..0000000000
--- a/reftable/record_test.c
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- Copyright 2020 Google LLC
-
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file or at
- https://developers.google.com/open-source/licenses/bsd
-*/
-
-#include "record.h"
-
-#include "system.h"
-#include "basics.h"
-#include "constants.h"
-#include "test_framework.h"
-#include "reftable-tests.h"
-
-static void test_copy(struct reftable_record *rec)
-{
- struct reftable_record copy;
- uint8_t typ;
-
- typ = reftable_record_type(rec);
- reftable_record_init(&copy, typ);
- reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ);
- /* do it twice to catch memory leaks */
- reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ);
- EXPECT(reftable_record_equal(rec, &copy, GIT_SHA1_RAWSZ));
-
- puts("testing print coverage:\n");
- reftable_record_print(&copy, GIT_SHA1_RAWSZ);
-
- reftable_record_release(&copy);
-}
-
-static void test_varint_roundtrip(void)
-{
- uint64_t inputs[] = { 0,
- 1,
- 27,
- 127,
- 128,
- 257,
- 4096,
- ((uint64_t)1 << 63),
- ((uint64_t)1 << 63) + ((uint64_t)1 << 63) - 1 };
- int i = 0;
- for (i = 0; i < ARRAY_SIZE(inputs); i++) {
- uint8_t dest[10];
-
- struct string_view out = {
- .buf = dest,
- .len = sizeof(dest),
- };
- uint64_t in = inputs[i];
- int n = put_var_int(&out, in);
- uint64_t got = 0;
-
- EXPECT(n > 0);
- out.len = n;
- n = get_var_int(&got, &out);
- EXPECT(n > 0);
-
- EXPECT(got == in);
- }
-}
-
-static void set_hash(uint8_t *h, int j)
-{
- int i = 0;
- for (i = 0; i < hash_size(GIT_SHA1_FORMAT_ID); i++) {
- h[i] = (j >> i) & 0xff;
- }
-}
-
-static void test_reftable_ref_record_roundtrip(void)
-{
- struct strbuf scratch = STRBUF_INIT;
- int i = 0;
-
- for (i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) {
- struct reftable_record in = {
- .type = BLOCK_TYPE_REF,
- };
- struct reftable_record out = { .type = BLOCK_TYPE_REF };
- struct strbuf key = STRBUF_INIT;
- uint8_t buffer[1024] = { 0 };
- struct string_view dest = {
- .buf = buffer,
- .len = sizeof(buffer),
- };
- int n, m;
-
- in.u.ref.value_type = i;
- switch (i) {
- case REFTABLE_REF_DELETION:
- break;
- case REFTABLE_REF_VAL1:
- set_hash(in.u.ref.value.val1, 1);
- break;
- case REFTABLE_REF_VAL2:
- set_hash(in.u.ref.value.val2.value, 1);
- set_hash(in.u.ref.value.val2.target_value, 2);
- break;
- case REFTABLE_REF_SYMREF:
- in.u.ref.value.symref = xstrdup("target");
- break;
- }
- in.u.ref.refname = xstrdup("refs/heads/master");
-
- test_copy(&in);
-
- EXPECT(reftable_record_val_type(&in) == i);
-
- reftable_record_key(&in, &key);
- n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
- EXPECT(n > 0);
-
- /* decode into a non-zero reftable_record to test for leaks. */
- m = reftable_record_decode(&out, key, i, dest, GIT_SHA1_RAWSZ, &scratch);
- EXPECT(n == m);
-
- EXPECT(reftable_ref_record_equal(&in.u.ref, &out.u.ref,
- GIT_SHA1_RAWSZ));
- reftable_record_release(&in);
-
- strbuf_release(&key);
- reftable_record_release(&out);
- }
-
- strbuf_release(&scratch);
-}
-
-static void test_reftable_log_record_equal(void)
-{
- struct reftable_log_record in[2] = {
- {
- .refname = xstrdup("refs/heads/master"),
- .update_index = 42,
- },
- {
- .refname = xstrdup("refs/heads/master"),
- .update_index = 22,
- }
- };
-
- EXPECT(!reftable_log_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
- in[1].update_index = in[0].update_index;
- EXPECT(reftable_log_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
- reftable_log_record_release(&in[0]);
- reftable_log_record_release(&in[1]);
-}
-
-static void test_reftable_log_record_roundtrip(void)
-{
- int i;
- struct reftable_log_record in[] = {
- {
- .refname = xstrdup("refs/heads/master"),
- .update_index = 42,
- .value_type = REFTABLE_LOG_UPDATE,
- .value = {
- .update = {
- .name = xstrdup("han-wen"),
- .email = xstrdup("hanwen@google.com"),
- .message = xstrdup("test"),
- .time = 1577123507,
- .tz_offset = 100,
- },
- }
- },
- {
- .refname = xstrdup("refs/heads/master"),
- .update_index = 22,
- .value_type = REFTABLE_LOG_DELETION,
- },
- {
- .refname = xstrdup("branch"),
- .update_index = 33,
- .value_type = REFTABLE_LOG_UPDATE,
- }
- };
- struct strbuf scratch = STRBUF_INIT;
-
- set_test_hash(in[0].value.update.new_hash, 1);
- set_test_hash(in[0].value.update.old_hash, 2);
- set_test_hash(in[2].value.update.new_hash, 3);
- set_test_hash(in[2].value.update.old_hash, 4);
- for (i = 0; i < ARRAY_SIZE(in); i++) {
- struct reftable_record rec = { .type = BLOCK_TYPE_LOG };
- struct strbuf key = STRBUF_INIT;
- uint8_t buffer[1024] = { 0 };
- struct string_view dest = {
- .buf = buffer,
- .len = sizeof(buffer),
- };
- /* populate out, to check for leaks. */
- struct reftable_record out = {
- .type = BLOCK_TYPE_LOG,
- .u.log = {
- .refname = xstrdup("old name"),
- .value_type = REFTABLE_LOG_UPDATE,
- .value = {
- .update = {
- .name = xstrdup("old name"),
- .email = xstrdup("old@email"),
- .message = xstrdup("old message"),
- },
- },
- },
- };
- int n, m, valtype;
-
- rec.u.log = in[i];
-
- test_copy(&rec);
-
- reftable_record_key(&rec, &key);
-
- n = reftable_record_encode(&rec, dest, GIT_SHA1_RAWSZ);
- EXPECT(n >= 0);
- valtype = reftable_record_val_type(&rec);
- m = reftable_record_decode(&out, key, valtype, dest,
- GIT_SHA1_RAWSZ, &scratch);
- EXPECT(n == m);
-
- EXPECT(reftable_log_record_equal(&in[i], &out.u.log,
- GIT_SHA1_RAWSZ));
- reftable_log_record_release(&in[i]);
- strbuf_release(&key);
- reftable_record_release(&out);
- }
-
- strbuf_release(&scratch);
-}
-
-static void test_key_roundtrip(void)
-{
- uint8_t buffer[1024] = { 0 };
- struct string_view dest = {
- .buf = buffer,
- .len = sizeof(buffer),
- };
- struct strbuf last_key = STRBUF_INIT;
- struct strbuf key = STRBUF_INIT;
- struct strbuf roundtrip = STRBUF_INIT;
- int restart;
- uint8_t extra;
- int n, m;
- uint8_t rt_extra;
-
- strbuf_addstr(&last_key, "refs/heads/master");
- strbuf_addstr(&key, "refs/tags/bla");
- extra = 6;
- n = reftable_encode_key(&restart, dest, last_key, key, extra);
- EXPECT(!restart);
- EXPECT(n > 0);
-
- strbuf_addstr(&roundtrip, "refs/heads/master");
- m = reftable_decode_key(&roundtrip, &rt_extra, dest);
- EXPECT(n == m);
- EXPECT(0 == strbuf_cmp(&key, &roundtrip));
- EXPECT(rt_extra == extra);
-
- strbuf_release(&last_key);
- strbuf_release(&key);
- strbuf_release(&roundtrip);
-}
-
-static void test_reftable_obj_record_roundtrip(void)
-{
- uint8_t testHash1[GIT_SHA1_RAWSZ] = { 1, 2, 3, 4, 0 };
- uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 };
- struct reftable_obj_record recs[3] = {
- {
- .hash_prefix = testHash1,
- .hash_prefix_len = 5,
- .offsets = till9,
- .offset_len = 3,
- },
- {
- .hash_prefix = testHash1,
- .hash_prefix_len = 5,
- .offsets = till9,
- .offset_len = 9,
- },
- {
- .hash_prefix = testHash1,
- .hash_prefix_len = 5,
- },
- };
- struct strbuf scratch = STRBUF_INIT;
- int i = 0;
-
- for (i = 0; i < ARRAY_SIZE(recs); i++) {
- uint8_t buffer[1024] = { 0 };
- struct string_view dest = {
- .buf = buffer,
- .len = sizeof(buffer),
- };
- struct reftable_record in = {
- .type = BLOCK_TYPE_OBJ,
- .u = {
- .obj = recs[i],
- },
- };
- struct strbuf key = STRBUF_INIT;
- struct reftable_record out = { .type = BLOCK_TYPE_OBJ };
- int n, m;
- uint8_t extra;
-
- test_copy(&in);
- reftable_record_key(&in, &key);
- n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
- EXPECT(n > 0);
- extra = reftable_record_val_type(&in);
- m = reftable_record_decode(&out, key, extra, dest,
- GIT_SHA1_RAWSZ, &scratch);
- EXPECT(n == m);
-
- EXPECT(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));
- strbuf_release(&key);
- reftable_record_release(&out);
- }
-
- strbuf_release(&scratch);
-}
-
-static void test_reftable_index_record_roundtrip(void)
-{
- struct reftable_record in = {
- .type = BLOCK_TYPE_INDEX,
- .u.idx = {
- .offset = 42,
- .last_key = STRBUF_INIT,
- },
- };
- uint8_t buffer[1024] = { 0 };
- struct string_view dest = {
- .buf = buffer,
- .len = sizeof(buffer),
- };
- struct strbuf scratch = STRBUF_INIT;
- struct strbuf key = STRBUF_INIT;
- struct reftable_record out = {
- .type = BLOCK_TYPE_INDEX,
- .u.idx = { .last_key = STRBUF_INIT },
- };
- int n, m;
- uint8_t extra;
-
- strbuf_addstr(&in.u.idx.last_key, "refs/heads/master");
- reftable_record_key(&in, &key);
- test_copy(&in);
-
- EXPECT(0 == strbuf_cmp(&key, &in.u.idx.last_key));
- n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
- EXPECT(n > 0);
-
- extra = reftable_record_val_type(&in);
- m = reftable_record_decode(&out, key, extra, dest, GIT_SHA1_RAWSZ,
- &scratch);
- EXPECT(m == n);
-
- EXPECT(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));
-
- reftable_record_release(&out);
- strbuf_release(&key);
- strbuf_release(&scratch);
- strbuf_release(&in.u.idx.last_key);
-}
-
-int record_test_main(int argc, const char *argv[])
-{
- RUN_TEST(test_reftable_log_record_equal);
- RUN_TEST(test_reftable_log_record_roundtrip);
- RUN_TEST(test_reftable_ref_record_roundtrip);
- RUN_TEST(test_varint_roundtrip);
- RUN_TEST(test_key_roundtrip);
- RUN_TEST(test_reftable_obj_record_roundtrip);
- RUN_TEST(test_reftable_index_record_roundtrip);
- return 0;
-}
diff --git a/send-pack.c b/send-pack.c
index 713da582d7..fa2f5eec17 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -427,17 +427,26 @@ static void get_commons_through_negotiation(const char *url,
struct child_process child = CHILD_PROCESS_INIT;
const struct ref *ref;
int len = the_hash_algo->hexsz + 1; /* hash + NL */
+ int nr_negotiation_tip = 0;
child.git_cmd = 1;
child.no_stdin = 1;
child.out = -1;
strvec_pushl(&child.args, "fetch", "--negotiate-only", NULL);
for (ref = remote_refs; ref; ref = ref->next) {
- if (!is_null_oid(&ref->new_oid))
- strvec_pushf(&child.args, "--negotiation-tip=%s", oid_to_hex(&ref->new_oid));
+ if (!is_null_oid(&ref->new_oid)) {
+ strvec_pushf(&child.args, "--negotiation-tip=%s",
+ oid_to_hex(&ref->new_oid));
+ nr_negotiation_tip++;
+ }
}
strvec_push(&child.args, url);
+ if (!nr_negotiation_tip) {
+ child_process_clear(&child);
+ return;
+ }
+
if (start_command(&child))
die(_("send-pack: unable to fork off fetch subprocess"));
diff --git a/sparse-index.c b/sparse-index.c
index 9913a6078c..9958656ded 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -12,6 +12,22 @@
#include "config.h"
#include "dir.h"
#include "fsmonitor-ll.h"
+#include "advice.h"
+
+/**
+ * This global is used by expand_index() to determine if we should give the
+ * advice for advice.sparseIndexExpanded when expanding a sparse index to a full
+ * one. However, this is sometimes done on purpose, such as in the sparse-checkout
+ * builtin, even when index.sparse=false. This may be disabled in
+ * convert_to_sparse().
+ */
+static int give_advice_on_expansion = 1;
+#define ADVICE_MSG \
+ "The sparse index is expanding to a full index, a slow operation.\n" \
+ "Your working directory likely has contents that are outside of\n" \
+ "your sparse-checkout patterns. Use 'git sparse-checkout list' to\n" \
+ "see your sparse-checkout definition and compare it to your working\n" \
+ "directory contents. Running 'git clean' may assist in this cleanup."
struct modify_index_context {
struct index_state *write;
@@ -184,6 +200,12 @@ int convert_to_sparse(struct index_state *istate, int flags)
return 0;
/*
+ * If we are purposefully collapsing a full index, then don't give
+ * advice when it is expanded later.
+ */
+ give_advice_on_expansion = 0;
+
+ /*
* NEEDSWORK: If we have unmerged entries, then stay full.
* Unmerged entries prevent the cache-tree extension from working.
*/
@@ -328,6 +350,12 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
pl = NULL;
}
+ if (!pl && give_advice_on_expansion) {
+ give_advice_on_expansion = 0;
+ advise_if_enabled(ADVICE_SPARSE_INDEX_EXPANDED,
+ _(ADVICE_MSG));
+ }
+
/*
* A NULL pattern set indicates we are expanding a full index, so
* we use a special region name that indicates the full expansion.
diff --git a/t/.gitattributes b/t/.gitattributes
index b9cea1795d..7664c6e027 100644
--- a/t/.gitattributes
+++ b/t/.gitattributes
@@ -1,5 +1,5 @@
t[0-9][0-9][0-9][0-9]/* -whitespace
-/chainlint/*.expect eol=lf
+/chainlint/*.expect eol=lf -whitespace
/t0110/url-* binary
/t3206/* eol=lf
/t3900/*.txt eol=lf
diff --git a/t/Makefile b/t/Makefile
index b2eb9f770b..4c30e7c06f 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -108,20 +108,8 @@ clean-chainlint:
check-chainlint:
@mkdir -p '$(CHAINLINTTMP_SQ)' && \
- for i in $(CHAINLINTTESTS); do \
- echo "test_expect_success '$$i' '" && \
- sed -e '/^# LINT: /d' chainlint/$$i.test && \
- echo "'"; \
- done >'$(CHAINLINTTMP_SQ)'/tests && \
- { \
- echo "# chainlint: $(CHAINLINTTMP_SQ)/tests" && \
- for i in $(CHAINLINTTESTS); do \
- echo "# chainlint: $$i" && \
- cat chainlint/$$i.expect; \
- done \
- } >'$(CHAINLINTTMP_SQ)'/expect && \
- $(CHAINLINT) --emit-all '$(CHAINLINTTMP_SQ)'/tests | \
- sed -e 's/^[1-9][0-9]* //' >'$(CHAINLINTTMP_SQ)'/actual && \
+ '$(PERL_PATH_SQ)' chainlint-cat.pl '$(CHAINLINTTMP_SQ)' $(CHAINLINTTESTS) && \
+ { $(CHAINLINT) --emit-all '$(CHAINLINTTMP_SQ)'/tests >'$(CHAINLINTTMP_SQ)'/actual || true; } && \
diff -u '$(CHAINLINTTMP_SQ)'/expect '$(CHAINLINTTMP_SQ)'/actual
test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \
diff --git a/t/README b/t/README
index d9e0e07506..724ee58195 100644
--- a/t/README
+++ b/t/README
@@ -382,33 +382,9 @@ mapping between "TEST_PASSES_SANITIZE_LEAK=true" and those tests that
pass under "SANITIZE=leak". This is especially useful when testing a
series that fixes various memory leaks with "git rebase -x".
-GIT_TEST_SANITIZE_LEAK_LOG=true will log memory leaks to
-"test-results/$TEST_NAME.leak/trace.*" files. The logs include a
-"dedup_token" (see +"ASAN_OPTIONS=help=1 ./git") and other options to
-make logs +machine-readable.
-
-With GIT_TEST_SANITIZE_LEAK_LOG=true we'll look at the leak logs
-before exiting and exit on failure if the logs showed that we had a
-memory leak, even if the test itself would have otherwise passed. This
-allows us to catch e.g. missing &&-chaining. This is especially useful
-when combined with "GIT_TEST_PASSING_SANITIZE_LEAK", see below.
-
GIT_TEST_PASSING_SANITIZE_LEAK=check when combined with "--immediate"
will run to completion faster, and result in the same failing
-tests. The only practical reason to run
-GIT_TEST_PASSING_SANITIZE_LEAK=check without "--immediate" is to
-combine it with "GIT_TEST_SANITIZE_LEAK_LOG=true". If we stop at the
-first failing test case our leak logs won't show subsequent leaks we
-might have run into.
-
-GIT_TEST_PASSING_SANITIZE_LEAK=(true|check) will not catch all memory
-leaks unless combined with GIT_TEST_SANITIZE_LEAK_LOG=true. Some tests
-run "git" (or "test-tool" etc.) without properly checking the exit
-code, or git will invoke itself and fail to ferry the abort() exit
-code to the original caller. When the two modes are combined we'll
-look at the "test-results/$TEST_NAME.leak/trace.*" files at the end of
-the test run to see if had memory leaks which the test itself didn't
-catch.
+tests.
GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version'
default to n.
@@ -906,6 +882,14 @@ see test-lib-functions.sh for the full list and their options.
'git-write-tree should be able to write an empty tree.' \
'tree=$(git-write-tree)'
+ If <script> is `-` (a single dash), then the script to run is read
+ from stdin. This lets you more easily use single quotes within the
+ script by using a here-doc. For example:
+
+ test_expect_success 'output contains expected string' - <<\EOT
+ grep "this string has 'quotes' in it" output
+ EOT
+
If you supply three parameters the first will be taken to be a
prerequisite; see the test_set_prereq and test_have_prereq
documentation below:
diff --git a/t/chainlint-cat.pl b/t/chainlint-cat.pl
new file mode 100644
index 0000000000..388f6e1e41
--- /dev/null
+++ b/t/chainlint-cat.pl
@@ -0,0 +1,29 @@
+#!/usr/bin/env perl
+
+my $outdir = shift;
+open(my $tests, '>', "$outdir/tests")
+ or die "unable to open $outdir/tests: $!";
+open(my $expect, '>', "$outdir/expect")
+ or die "unable to open $outdir/expect: $!";
+
+print $expect "# chainlint: $outdir/tests\n";
+
+my $offset = 0;
+for my $script (@ARGV) {
+ print $expect "# chainlint: $script\n";
+
+ open(my $expect_in, '<', "chainlint/$script.expect")
+ or die "unable to open chainlint/$script.expect: $!";
+ while (<$expect_in>) {
+ s/^\d+/$& + $offset/e;
+ print $expect $_;
+ }
+
+ open(my $test_in, '<', "chainlint/$script.test")
+ or die "unable to open chainlint/$script.test: $!";
+ while (<$test_in>) {
+ /^# LINT: / and next;
+ print $tests $_;
+ $offset++;
+ }
+}
diff --git a/t/chainlint.pl b/t/chainlint.pl
index 1bbd985b78..5361f23b1d 100755
--- a/t/chainlint.pl
+++ b/t/chainlint.pl
@@ -174,6 +174,10 @@ sub swallow_heredocs {
$$b =~ /(?:\G|\n)$indent\Q$$tag[0]\E(?:\n|\z)/gc;
if (pos($$b) > $start) {
my $body = substr($$b, $start, pos($$b) - $start);
+ $self->{parser}->{heredocs}->{$$tag[0]} = {
+ content => substr($body, 0, length($body) - length($&)),
+ start_line => $self->{lineno},
+ };
$self->{lineno} += () = $body =~ /\n/sg;
next;
}
@@ -232,7 +236,8 @@ sub new {
my $self = bless {
buff => [],
stop => [],
- output => []
+ output => [],
+ heredocs => {},
} => $class;
$self->{lexer} = Lexer->new($self, $s);
return $self;
@@ -616,14 +621,21 @@ sub unwrap {
sub check_test {
my $self = shift @_;
- my ($title, $body) = map(unwrap, @_);
+ my $title = unwrap(shift @_);
+ my $body = shift @_;
+ my $lineno = $body->[3];
+ $body = unwrap($body);
+ if ($body eq '-') {
+ my $herebody = shift @_;
+ $body = $herebody->{content};
+ $lineno = $herebody->{start_line};
+ }
$self->{ntests}++;
my $parser = TestParser->new(\$body);
my @tokens = $parser->parse();
my $problems = $parser->{problems};
return unless $emit_all || @$problems;
my $c = main::fd_colors(1);
- my $lineno = $_[1]->[3];
my $start = 0;
my $checked = '';
for (sort {$a->[1]->[2] <=> $b->[1]->[2]} @$problems) {
@@ -649,8 +661,13 @@ sub parse_cmd {
return @tokens unless @tokens && $tokens[0]->[0] =~ /^test_expect_(?:success|failure)$/;
my $n = $#tokens;
$n-- while $n >= 0 && $tokens[$n]->[0] =~ /^(?:[;&\n|]|&&|\|\|)$/;
- $self->check_test($tokens[1], $tokens[2]) if $n == 2; # title body
- $self->check_test($tokens[2], $tokens[3]) if $n > 2; # prereq title body
+ my $herebody;
+ if ($n >= 2 && $tokens[$n-1]->[0] eq '-' && $tokens[$n]->[0] =~ /^<<-?(.+)$/) {
+ $herebody = $self->{heredocs}->{$1};
+ $n--;
+ }
+ $self->check_test($tokens[1], $tokens[2], $herebody) if $n == 2; # title body
+ $self->check_test($tokens[2], $tokens[3], $herebody) if $n > 2; # prereq title body
return @tokens;
}
@@ -762,7 +779,7 @@ sub check_script {
while (my $path = $next_script->()) {
$nscripts++;
my $fh;
- unless (open($fh, "<", $path)) {
+ unless (open($fh, "<:unix:crlf", $path)) {
$emit->("?!ERR?! $path: $!\n");
next;
}
@@ -806,8 +823,10 @@ unless (@scripts) {
show_stats($start_time, \@stats) if $show_stats;
exit;
}
+$jobs = @scripts if @scripts < $jobs;
-unless ($Config{useithreads} && eval {
+unless ($jobs > 1 &&
+ $Config{useithreads} && eval {
require threads; threads->import();
require Thread::Queue; Thread::Queue->import();
1;
diff --git a/t/chainlint/arithmetic-expansion.expect b/t/chainlint/arithmetic-expansion.expect
index 46ee1046af..338ecd5861 100644
--- a/t/chainlint/arithmetic-expansion.expect
+++ b/t/chainlint/arithmetic-expansion.expect
@@ -1,9 +1,9 @@
-(
- foo &&
- bar=$((42 + 1)) &&
- baz
-) &&
-(
- bar=$((42 + 1)) ?!AMP?!
- baz
-)
+2 (
+3 foo &&
+4 bar=$((42 + 1)) &&
+5 baz
+6 ) &&
+7 (
+8 bar=$((42 + 1)) ?!AMP?!
+9 baz
+10 )
diff --git a/t/chainlint/arithmetic-expansion.test b/t/chainlint/arithmetic-expansion.test
index 16206960d8..7b4c5c9a41 100644
--- a/t/chainlint/arithmetic-expansion.test
+++ b/t/chainlint/arithmetic-expansion.test
@@ -1,3 +1,4 @@
+test_expect_success 'arithmetic-expansion' '
(
foo &&
# LINT: closing ")" of $((...)) not misinterpreted as subshell-closing ")"
@@ -9,3 +10,4 @@
bar=$((42 + 1))
baz
)
+'
diff --git a/t/chainlint/bash-array.expect b/t/chainlint/bash-array.expect
index 4c34eaee45..435dc8bdc8 100644
--- a/t/chainlint/bash-array.expect
+++ b/t/chainlint/bash-array.expect
@@ -1,10 +1,10 @@
-(
- foo &&
- bar=(gumbo stumbo wumbo) &&
- baz
-) &&
-(
- foo &&
- bar=${#bar[@]} &&
- baz
-)
+2 (
+3 foo &&
+4 bar=(gumbo stumbo wumbo) &&
+5 baz
+6 ) &&
+7 (
+8 foo &&
+9 bar=${#bar[@]} &&
+10 baz
+11 )
diff --git a/t/chainlint/bash-array.test b/t/chainlint/bash-array.test
index 92bbb777b8..4ca977d299 100644
--- a/t/chainlint/bash-array.test
+++ b/t/chainlint/bash-array.test
@@ -1,3 +1,4 @@
+test_expect_success 'bash-array' '
(
foo &&
# LINT: ")" in Bash array assignment not misinterpreted as subshell-closing ")"
@@ -10,3 +11,4 @@
bar=${#bar[@]} &&
baz
)
+'
diff --git a/t/chainlint/blank-line-before-esac.expect b/t/chainlint/blank-line-before-esac.expect
index 056e03003d..b88ba919eb 100644
--- a/t/chainlint/blank-line-before-esac.expect
+++ b/t/chainlint/blank-line-before-esac.expect
@@ -1,18 +1,18 @@
-test_done () {
- case "$test_failure" in
- 0)
- test_at_end_hook_
-
- exit 0 ;;
-
- *)
- if test $test_external_has_tap -eq 0
- then
- say_color error "# failed $test_failure among $msg"
- say "1..$test_count"
- fi
-
- exit 1 ;;
-
- esac
-}
+2 test_done () {
+3 case "$test_failure" in
+4 0)
+5 test_at_end_hook_
+6
+7 exit 0 ;;
+8
+9 *)
+10 if test $test_external_has_tap -eq 0
+11 then
+12 say_color error "# failed $test_failure among $msg"
+13 say "1..$test_count"
+14 fi
+15
+16 exit 1 ;;
+17
+18 esac
+19 }
diff --git a/t/chainlint/blank-line-before-esac.test b/t/chainlint/blank-line-before-esac.test
index cecccad19f..51f02ea0c5 100644
--- a/t/chainlint/blank-line-before-esac.test
+++ b/t/chainlint/blank-line-before-esac.test
@@ -1,3 +1,4 @@
+test_expect_success 'blank-line-before-esac' '
# LINT: blank line before "esac"
test_done () {
case "$test_failure" in
@@ -17,3 +18,4 @@ test_done () {
esac
}
+'
diff --git a/t/chainlint/blank-line.expect b/t/chainlint/blank-line.expect
index b47827d749..6ae39dd174 100644
--- a/t/chainlint/blank-line.expect
+++ b/t/chainlint/blank-line.expect
@@ -1,8 +1,8 @@
-(
-
- nothing &&
-
- something
-
-
-)
+2 (
+3
+4 nothing &&
+5
+6 something
+7
+8
+9 )
diff --git a/t/chainlint/blank-line.test b/t/chainlint/blank-line.test
index 0fdf15b3e1..6f29a491de 100644
--- a/t/chainlint/blank-line.test
+++ b/t/chainlint/blank-line.test
@@ -1,3 +1,4 @@
+test_expect_success 'blank-line' '
(
nothing &&
@@ -8,3 +9,4 @@
)
+'
diff --git a/t/chainlint/block-comment.expect b/t/chainlint/block-comment.expect
index df2beea888..7926936c18 100644
--- a/t/chainlint/block-comment.expect
+++ b/t/chainlint/block-comment.expect
@@ -1,8 +1,8 @@
-(
- {
- # show a
- echo a &&
- # show b
- echo b
- }
-)
+2 (
+3 {
+4 # show a
+5 echo a &&
+6 # show b
+7 echo b
+8 }
+9 )
diff --git a/t/chainlint/block-comment.test b/t/chainlint/block-comment.test
index df2beea888..934ef4113a 100644
--- a/t/chainlint/block-comment.test
+++ b/t/chainlint/block-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'block-comment' '
(
{
# show a
@@ -6,3 +7,4 @@
echo b
}
)
+'
diff --git a/t/chainlint/block.expect b/t/chainlint/block.expect
index 1c87326364..b62e3d58c3 100644
--- a/t/chainlint/block.expect
+++ b/t/chainlint/block.expect
@@ -1,23 +1,23 @@
-(
- foo &&
- {
- echo a ?!AMP?!
- echo b
- } &&
- bar &&
- {
- echo c
- } ?!AMP?!
- baz
-) &&
-
-{
- echo a; ?!AMP?! echo b
-} &&
-{ echo a; ?!AMP?! echo b; } &&
-
-{
- echo "${var}9" &&
- echo "done"
-} &&
-finis
+2 (
+3 foo &&
+4 {
+5 echo a ?!AMP?!
+6 echo b
+7 } &&
+8 bar &&
+9 {
+10 echo c
+11 } ?!AMP?!
+12 baz
+13 ) &&
+14
+15 {
+16 echo a; ?!AMP?! echo b
+17 } &&
+18 { echo a; ?!AMP?! echo b; } &&
+19
+20 {
+21 echo "${var}9" &&
+22 echo "done"
+23 } &&
+24 finis
diff --git a/t/chainlint/block.test b/t/chainlint/block.test
index 4ab69a4afc..a1b6b4dd32 100644
--- a/t/chainlint/block.test
+++ b/t/chainlint/block.test
@@ -1,3 +1,4 @@
+test_expect_success 'block' '
(
# LINT: missing "&&" after first "echo"
foo &&
@@ -25,3 +26,4 @@
echo "done"
} &&
finis
+'
diff --git a/t/chainlint/broken-chain.expect b/t/chainlint/broken-chain.expect
index cfb58fb6b9..9a1838736f 100644
--- a/t/chainlint/broken-chain.expect
+++ b/t/chainlint/broken-chain.expect
@@ -1,6 +1,6 @@
-(
- foo &&
- bar ?!AMP?!
- baz &&
- wop
-)
+2 (
+3 foo &&
+4 bar ?!AMP?!
+5 baz &&
+6 wop
+7 )
diff --git a/t/chainlint/broken-chain.test b/t/chainlint/broken-chain.test
index 2a44aa73b7..1966499ef9 100644
--- a/t/chainlint/broken-chain.test
+++ b/t/chainlint/broken-chain.test
@@ -1,3 +1,4 @@
+test_expect_success 'broken-chain' '
(
foo &&
# LINT: missing "&&" from "bar"
@@ -6,3 +7,4 @@
# LINT: final statement before closing ")" legitimately lacks "&&"
wop
)
+'
diff --git a/t/chainlint/case-comment.expect b/t/chainlint/case-comment.expect
index 641c157b98..2442dd5f25 100644
--- a/t/chainlint/case-comment.expect
+++ b/t/chainlint/case-comment.expect
@@ -1,11 +1,11 @@
-(
- case "$x" in
- # found foo
- x) foo ;;
- # found other
- *)
- # treat it as bar
- bar
- ;;
- esac
-)
+2 (
+3 case "$x" in
+4 # found foo
+5 x) foo ;;
+6 # found other
+7 *)
+8 # treat it as bar
+9 bar
+10 ;;
+11 esac
+12 )
diff --git a/t/chainlint/case-comment.test b/t/chainlint/case-comment.test
index 641c157b98..3f31ae9010 100644
--- a/t/chainlint/case-comment.test
+++ b/t/chainlint/case-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'case-comment' '
(
case "$x" in
# found foo
@@ -9,3 +10,4 @@
;;
esac
)
+'
diff --git a/t/chainlint/case.expect b/t/chainlint/case.expect
index 31f280d8ce..c04c61ff36 100644
--- a/t/chainlint/case.expect
+++ b/t/chainlint/case.expect
@@ -1,19 +1,19 @@
-(
- case "$x" in
- x) foo ;;
- *) bar ;;
- esac &&
- foobar
-) &&
-(
- case "$x" in
- x) foo ;;
- *) bar ;;
- esac ?!AMP?!
- foobar
-) &&
-(
- case "$x" in 1) true;; esac &&
- case "$y" in 2) false;; esac ?!AMP?!
- foobar
-)
+2 (
+3 case "$x" in
+4 x) foo ;;
+5 *) bar ;;
+6 esac &&
+7 foobar
+8 ) &&
+9 (
+10 case "$x" in
+11 x) foo ;;
+12 *) bar ;;
+13 esac ?!AMP?!
+14 foobar
+15 ) &&
+16 (
+17 case "$x" in 1) true;; esac &&
+18 case "$y" in 2) false;; esac ?!AMP?!
+19 foobar
+20 )
diff --git a/t/chainlint/case.test b/t/chainlint/case.test
index 4cb086bf87..bea21fee4f 100644
--- a/t/chainlint/case.test
+++ b/t/chainlint/case.test
@@ -1,3 +1,4 @@
+test_expect_success 'case' '
(
# LINT: "...)" arms in "case" not misinterpreted as subshell-closing ")"
case "$x" in
@@ -21,3 +22,4 @@
case "$y" in 2) false;; esac
foobar
)
+'
diff --git a/t/chainlint/chain-break-background.expect b/t/chainlint/chain-break-background.expect
index 20d0bb5333..d06deadae7 100644
--- a/t/chainlint/chain-break-background.expect
+++ b/t/chainlint/chain-break-background.expect
@@ -1,9 +1,9 @@
-JGIT_DAEMON_PID= &&
-git init --bare empty.git &&
->empty.git/git-daemon-export-ok &&
-mkfifo jgit_daemon_output &&
-{
- jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
- JGIT_DAEMON_PID=$!
-} &&
-test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+2 JGIT_DAEMON_PID= &&
+3 git init --bare empty.git &&
+4 >empty.git/git-daemon-export-ok &&
+5 mkfifo jgit_daemon_output &&
+6 {
+7 jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
+8 JGIT_DAEMON_PID=$!
+9 } &&
+10 test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
diff --git a/t/chainlint/chain-break-background.test b/t/chainlint/chain-break-background.test
index e10f656b05..c68e1b04d5 100644
--- a/t/chainlint/chain-break-background.test
+++ b/t/chainlint/chain-break-background.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-background' '
JGIT_DAEMON_PID= &&
git init --bare empty.git &&
>empty.git/git-daemon-export-ok &&
@@ -8,3 +9,4 @@ mkfifo jgit_daemon_output &&
JGIT_DAEMON_PID=$!
} &&
test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+'
diff --git a/t/chainlint/chain-break-continue.expect b/t/chainlint/chain-break-continue.expect
index 47a3457710..4bb60aae25 100644
--- a/t/chainlint/chain-break-continue.expect
+++ b/t/chainlint/chain-break-continue.expect
@@ -1,12 +1,12 @@
-git ls-tree --name-only -r refs/notes/many_notes |
-while read path
-do
- test "$path" = "foobar/non-note.txt" && continue
- test "$path" = "deadbeef" && continue
- test "$path" = "de/adbeef" && continue
-
- if test $(expr length "$path") -ne $hexsz
- then
- return 1
- fi
-done
+2 git ls-tree --name-only -r refs/notes/many_notes |
+3 while read path
+4 do
+5 test "$path" = "foobar/non-note.txt" && continue
+6 test "$path" = "deadbeef" && continue
+7 test "$path" = "de/adbeef" && continue
+8
+9 if test $(expr length "$path") -ne $hexsz
+10 then
+11 return 1
+12 fi
+13 done
diff --git a/t/chainlint/chain-break-continue.test b/t/chainlint/chain-break-continue.test
index f0af71d8bd..de8119b204 100644
--- a/t/chainlint/chain-break-continue.test
+++ b/t/chainlint/chain-break-continue.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-continue' '
git ls-tree --name-only -r refs/notes/many_notes |
while read path
do
@@ -11,3 +12,4 @@ do
return 1
fi
done
+'
diff --git a/t/chainlint/chain-break-false.expect b/t/chainlint/chain-break-false.expect
index 989766fb85..4f815f8e14 100644
--- a/t/chainlint/chain-break-false.expect
+++ b/t/chainlint/chain-break-false.expect
@@ -1,9 +1,9 @@
-if condition not satisified
-then
- echo it did not work...
- echo failed!
- false
-else
- echo it went okay ?!AMP?!
- congratulate user
-fi
+2 if condition not satisified
+3 then
+4 echo it did not work...
+5 echo failed!
+6 false
+7 else
+8 echo it went okay ?!AMP?!
+9 congratulate user
+10 fi
diff --git a/t/chainlint/chain-break-false.test b/t/chainlint/chain-break-false.test
index a5aaff8c8a..f78ad911fc 100644
--- a/t/chainlint/chain-break-false.test
+++ b/t/chainlint/chain-break-false.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-false' '
# LINT: broken &&-chain okay if explicit "false" signals failure
if condition not satisified
then
@@ -8,3 +9,4 @@ else
echo it went okay
congratulate user
fi
+'
diff --git a/t/chainlint/chain-break-return-exit.expect b/t/chainlint/chain-break-return-exit.expect
index 4cd18e2edf..ba0ec51aa0 100644
--- a/t/chainlint/chain-break-return-exit.expect
+++ b/t/chainlint/chain-break-return-exit.expect
@@ -1,19 +1,19 @@
-case "$(git ls-files)" in
-one) echo pass one ;;
-*) echo bad one; return 1 ;;
-esac &&
-(
- case "$(git ls-files)" in
- two) echo pass two ;;
- *) echo bad two; exit 1 ;;
- esac
-) &&
-case "$(git ls-files)" in
-dir/two"$LF"one) echo pass both ;;
-*) echo bad; return 1 ;;
-esac &&
-
-for i in 1 2 3 4 ; do
- git checkout main -b $i || return $?
- test_commit $i $i $i tag$i || return $?
-done
+2 case "$(git ls-files)" in
+3 one) echo pass one ;;
+4 *) echo bad one; return 1 ;;
+5 esac &&
+6 (
+7 case "$(git ls-files)" in
+8 two) echo pass two ;;
+9 *) echo bad two; exit 1 ;;
+10 esac
+11 ) &&
+12 case "$(git ls-files)" in
+13 dir/two"$LF"one) echo pass both ;;
+14 *) echo bad; return 1 ;;
+15 esac &&
+16
+17 for i in 1 2 3 4 ; do
+18 git checkout main -b $i || return $?
+19 test_commit $i $i $i tag$i || return $?
+20 done
diff --git a/t/chainlint/chain-break-return-exit.test b/t/chainlint/chain-break-return-exit.test
index 46542edf88..b6f519bb4d 100644
--- a/t/chainlint/chain-break-return-exit.test
+++ b/t/chainlint/chain-break-return-exit.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-return-exit' '
case "$(git ls-files)" in
one) echo pass one ;;
# LINT: broken &&-chain okay if explicit "return 1" signals failuire
@@ -21,3 +22,4 @@ for i in 1 2 3 4 ; do
git checkout main -b $i || return $?
test_commit $i $i $i tag$i || return $?
done
+'
diff --git a/t/chainlint/chain-break-status.expect b/t/chainlint/chain-break-status.expect
index e6b3b2193e..23c0caa7d8 100644
--- a/t/chainlint/chain-break-status.expect
+++ b/t/chainlint/chain-break-status.expect
@@ -1,9 +1,9 @@
-OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&
-test_match_signal 13 "$OUT" &&
-
-{ test-tool sigchain >actual; ret=$?; } &&
-{
- test_match_signal 15 "$ret" ||
- test "$ret" = 3
-} &&
-test_cmp expect actual
+2 OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&
+3 test_match_signal 13 "$OUT" &&
+4
+5 { test-tool sigchain >actual; ret=$?; } &&
+6 {
+7 test_match_signal 15 "$ret" ||
+8 test "$ret" = 3
+9 } &&
+10 test_cmp expect actual
diff --git a/t/chainlint/chain-break-status.test b/t/chainlint/chain-break-status.test
index a6602a7b99..d9fee190d9 100644
--- a/t/chainlint/chain-break-status.test
+++ b/t/chainlint/chain-break-status.test
@@ -1,3 +1,4 @@
+test_expect_success 'chain-break-status' '
# LINT: broken &&-chain okay if next command handles "$?" explicitly
OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&
test_match_signal 13 "$OUT" &&
@@ -9,3 +10,4 @@ test_match_signal 13 "$OUT" &&
test "$ret" = 3
} &&
test_cmp expect actual
+'
diff --git a/t/chainlint/chained-block.expect b/t/chainlint/chained-block.expect
index 574cdceb07..a546b714a6 100644
--- a/t/chainlint/chained-block.expect
+++ b/t/chainlint/chained-block.expect
@@ -1,9 +1,9 @@
-echo nobody home && {
- test the doohicky ?!AMP?!
- right now
-} &&
-
-GIT_EXTERNAL_DIFF=echo git diff | {
- read path oldfile oldhex oldmode newfile newhex newmode &&
- test "z$oh" = "z$oldhex"
-}
+2 echo nobody home && {
+3 test the doohicky ?!AMP?!
+4 right now
+5 } &&
+6
+7 GIT_EXTERNAL_DIFF=echo git diff | {
+8 read path oldfile oldhex oldmode newfile newhex newmode &&
+9 test "z$oh" = "z$oldhex"
+10 }
diff --git a/t/chainlint/chained-block.test b/t/chainlint/chained-block.test
index 86f81ece63..71ef1d0b7f 100644
--- a/t/chainlint/chained-block.test
+++ b/t/chainlint/chained-block.test
@@ -1,3 +1,4 @@
+test_expect_success 'chained-block' '
# LINT: start of block chained to preceding command
echo nobody home && {
test the doohicky
@@ -9,3 +10,4 @@ GIT_EXTERNAL_DIFF=echo git diff | {
read path oldfile oldhex oldmode newfile newhex newmode &&
test "z$oh" = "z$oldhex"
}
+'
diff --git a/t/chainlint/chained-subshell.expect b/t/chainlint/chained-subshell.expect
index 83810ea7ec..f78b268291 100644
--- a/t/chainlint/chained-subshell.expect
+++ b/t/chainlint/chained-subshell.expect
@@ -1,10 +1,10 @@
-mkdir sub && (
- cd sub &&
- foo the bar ?!AMP?!
- nuff said
-) &&
-
-cut "-d " -f actual | (read s1 s2 s3 &&
-test -f $s1 ?!AMP?!
-test $(cat $s2) = tree2path1 &&
-test $(cat $s3) = tree3path1)
+2 mkdir sub && (
+3 cd sub &&
+4 foo the bar ?!AMP?!
+5 nuff said
+6 ) &&
+7
+8 cut "-d " -f actual | (read s1 s2 s3 &&
+9 test -f $s1 ?!AMP?!
+10 test $(cat $s2) = tree2path1 &&
+11 test $(cat $s3) = tree3path1)
diff --git a/t/chainlint/chained-subshell.test b/t/chainlint/chained-subshell.test
index 4ff6ddd8cb..1f11f65398 100644
--- a/t/chainlint/chained-subshell.test
+++ b/t/chainlint/chained-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'chained-subshell' '
# LINT: start of subshell chained to preceding command
mkdir sub && (
cd sub &&
@@ -11,3 +12,4 @@ test -f $s1
test $(cat $s2) = tree2path1 &&
# LINT: closing subshell ")" correctly detected on same line as "$(...)"
test $(cat $s3) = tree3path1)
+'
diff --git a/t/chainlint/close-nested-and-parent-together.expect b/t/chainlint/close-nested-and-parent-together.expect
index 72d482f76d..4167e54a59 100644
--- a/t/chainlint/close-nested-and-parent-together.expect
+++ b/t/chainlint/close-nested-and-parent-together.expect
@@ -1,3 +1,3 @@
-(cd foo &&
- (bar &&
- baz))
+2 (cd foo &&
+3 (bar &&
+4 baz))
diff --git a/t/chainlint/close-nested-and-parent-together.test b/t/chainlint/close-nested-and-parent-together.test
index 72d482f76d..56b28b186b 100644
--- a/t/chainlint/close-nested-and-parent-together.test
+++ b/t/chainlint/close-nested-and-parent-together.test
@@ -1,3 +1,5 @@
+test_expect_success 'close-nested-and-parent-together' '
(cd foo &&
(bar &&
baz))
+'
diff --git a/t/chainlint/close-subshell.expect b/t/chainlint/close-subshell.expect
index 2192a2870a..a272cfe72e 100644
--- a/t/chainlint/close-subshell.expect
+++ b/t/chainlint/close-subshell.expect
@@ -1,26 +1,26 @@
-(
- foo
-) &&
-(
- bar
-) >out &&
-(
- baz
-) 2>err &&
-(
- boo
-) <input &&
-(
- bip
-) | wuzzle &&
-(
- bop
-) | fazz \
- fozz &&
-(
- bup
-) |
-fuzzle &&
-(
- yop
-)
+2 (
+3 foo
+4 ) &&
+5 (
+6 bar
+7 ) >out &&
+8 (
+9 baz
+10 ) 2>err &&
+11 (
+12 boo
+13 ) <input &&
+14 (
+15 bip
+16 ) | wuzzle &&
+17 (
+18 bop
+19 ) | fazz \
+20 fozz &&
+21 (
+22 bup
+23 ) |
+24 fuzzle &&
+25 (
+26 yop
+27 )
diff --git a/t/chainlint/close-subshell.test b/t/chainlint/close-subshell.test
index 508ca447fd..b99f80569d 100644
--- a/t/chainlint/close-subshell.test
+++ b/t/chainlint/close-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'close-subshell' '
# LINT: closing ")" with various decorations ("&&", ">", "|", etc.)
(
foo
@@ -25,3 +26,4 @@ fuzzle &&
(
yop
)
+'
diff --git a/t/chainlint/command-substitution-subsubshell.expect b/t/chainlint/command-substitution-subsubshell.expect
index ec42f2c30c..f2a9312dc8 100644
--- a/t/chainlint/command-substitution-subsubshell.expect
+++ b/t/chainlint/command-substitution-subsubshell.expect
@@ -1,2 +1,2 @@
-OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
-test_match_signal 13 "$OUT"
+2 OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
+3 test_match_signal 13 "$OUT"
diff --git a/t/chainlint/command-substitution-subsubshell.test b/t/chainlint/command-substitution-subsubshell.test
index 321de2951c..4ea772d60a 100644
--- a/t/chainlint/command-substitution-subsubshell.test
+++ b/t/chainlint/command-substitution-subsubshell.test
@@ -1,3 +1,5 @@
+test_expect_success 'command-substitution-subsubshell' '
# LINT: subshell nested in subshell nested in command substitution
OUT=$( ((large_git 1>&3) | :) 3>&1 ) &&
test_match_signal 13 "$OUT"
+'
diff --git a/t/chainlint/command-substitution.expect b/t/chainlint/command-substitution.expect
index c72e4df9e7..5e31b36db6 100644
--- a/t/chainlint/command-substitution.expect
+++ b/t/chainlint/command-substitution.expect
@@ -1,9 +1,9 @@
-(
- foo &&
- bar=$(gobble) &&
- baz
-) &&
-(
- bar=$(gobble blocks) ?!AMP?!
- baz
-)
+2 (
+3 foo &&
+4 bar=$(gobble) &&
+5 baz
+6 ) &&
+7 (
+8 bar=$(gobble blocks) ?!AMP?!
+9 baz
+10 )
diff --git a/t/chainlint/command-substitution.test b/t/chainlint/command-substitution.test
index 3bbb002a4c..494d671e80 100644
--- a/t/chainlint/command-substitution.test
+++ b/t/chainlint/command-substitution.test
@@ -1,3 +1,4 @@
+test_expect_success 'command-substitution' '
(
foo &&
# LINT: closing ")" of $(...) not misinterpreted as subshell-closing ")"
@@ -9,3 +10,4 @@
bar=$(gobble blocks)
baz
)
+'
diff --git a/t/chainlint/comment.expect b/t/chainlint/comment.expect
index a68f1f9d7c..584098d6ba 100644
--- a/t/chainlint/comment.expect
+++ b/t/chainlint/comment.expect
@@ -1,8 +1,8 @@
-(
- # comment 1
- nothing &&
- # comment 2
- something
- # comment 3
- # comment 4
-)
+2 (
+3 # comment 1
+4 nothing &&
+5 # comment 2
+6 something
+7 # comment 3
+8 # comment 4
+9 )
diff --git a/t/chainlint/comment.test b/t/chainlint/comment.test
index 113c0c466f..c488beac0d 100644
--- a/t/chainlint/comment.test
+++ b/t/chainlint/comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'comment' '
(
# LINT: swallow comment lines
# comment 1
@@ -9,3 +10,4 @@
# comment 3
# comment 4
)
+'
diff --git a/t/chainlint/complex-if-in-cuddled-loop.expect b/t/chainlint/complex-if-in-cuddled-loop.expect
index dac2d0fd1d..3a740103db 100644
--- a/t/chainlint/complex-if-in-cuddled-loop.expect
+++ b/t/chainlint/complex-if-in-cuddled-loop.expect
@@ -1,9 +1,9 @@
-(for i in a b c; do
- if test "$(echo $(waffle bat))" = "eleventeen" &&
- test "$x" = "$y"; then
- :
- else
- echo >file
- fi ?!LOOP?!
- done) &&
-test ! -f file
+2 (for i in a b c; do
+3 if test "$(echo $(waffle bat))" = "eleventeen" &&
+4 test "$x" = "$y"; then
+5 :
+6 else
+7 echo >file
+8 fi ?!LOOP?!
+9 done) &&
+10 test ! -f file
diff --git a/t/chainlint/complex-if-in-cuddled-loop.test b/t/chainlint/complex-if-in-cuddled-loop.test
index 5efeda58b2..f98ae4c42d 100644
--- a/t/chainlint/complex-if-in-cuddled-loop.test
+++ b/t/chainlint/complex-if-in-cuddled-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'complex-if-in-cuddled-loop' '
# LINT: "for" loop cuddled with "(" and ")" and nested "if" with complex
# LINT: multi-line condition; indented with spaces, not tabs
(for i in a b c; do
@@ -9,3 +10,4 @@
fi
done) &&
test ! -f file
+'
diff --git a/t/chainlint/cuddled-if-then-else.expect b/t/chainlint/cuddled-if-then-else.expect
index 1d8ed58c49..72da8794cb 100644
--- a/t/chainlint/cuddled-if-then-else.expect
+++ b/t/chainlint/cuddled-if-then-else.expect
@@ -1,6 +1,6 @@
-(if test -z ""; then
- echo empty
- else
- echo bizzy
- fi) &&
-echo foobar
+2 (if test -z ""; then
+3 echo empty
+4 else
+5 echo bizzy
+6 fi) &&
+7 echo foobar
diff --git a/t/chainlint/cuddled-if-then-else.test b/t/chainlint/cuddled-if-then-else.test
index 7c53f4efe3..b1b42e1aac 100644
--- a/t/chainlint/cuddled-if-then-else.test
+++ b/t/chainlint/cuddled-if-then-else.test
@@ -1,3 +1,4 @@
+test_expect_success 'cuddled-if-then-else' '
# LINT: "if" cuddled with "(" and ")"; indented with spaces, not tabs
(if test -z ""; then
echo empty
@@ -5,3 +6,4 @@
echo bizzy
fi) &&
echo foobar
+'
diff --git a/t/chainlint/cuddled-loop.expect b/t/chainlint/cuddled-loop.expect
index 9cf260708e..c38585c756 100644
--- a/t/chainlint/cuddled-loop.expect
+++ b/t/chainlint/cuddled-loop.expect
@@ -1,4 +1,4 @@
-( while read x
- do foobar bop || exit 1
- done <file ) &&
-outside subshell
+2 ( while read x
+3 do foobar bop || exit 1
+4 done <file ) &&
+5 outside subshell
diff --git a/t/chainlint/cuddled-loop.test b/t/chainlint/cuddled-loop.test
index 3c2a62f751..6fccb6ac22 100644
--- a/t/chainlint/cuddled-loop.test
+++ b/t/chainlint/cuddled-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'cuddled-loop' '
# LINT: "while" loop cuddled with "(" and ")", with embedded (allowed)
# LINT: "|| exit {n}" to exit loop early, and using redirection "<" to feed
# LINT: loop; indented with spaces, not tabs
@@ -5,3 +6,4 @@
do foobar bop || exit 1
done <file ) &&
outside subshell
+'
diff --git a/t/chainlint/cuddled.expect b/t/chainlint/cuddled.expect
index c3e0be4047..b06d638311 100644
--- a/t/chainlint/cuddled.expect
+++ b/t/chainlint/cuddled.expect
@@ -1,17 +1,17 @@
-(cd foo &&
- bar
-) &&
-
-(cd foo ?!AMP?!
- bar
-) &&
-
-(
- cd foo &&
- bar) &&
-
-(cd foo &&
- bar) &&
-
-(cd foo ?!AMP?!
- bar)
+2 (cd foo &&
+3 bar
+4 ) &&
+5
+6 (cd foo ?!AMP?!
+7 bar
+8 ) &&
+9
+10 (
+11 cd foo &&
+12 bar) &&
+13
+14 (cd foo &&
+15 bar) &&
+16
+17 (cd foo ?!AMP?!
+18 bar)
diff --git a/t/chainlint/cuddled.test b/t/chainlint/cuddled.test
index 257b5b5eed..5a6ef7a4a6 100644
--- a/t/chainlint/cuddled.test
+++ b/t/chainlint/cuddled.test
@@ -1,3 +1,4 @@
+test_expect_success 'cuddled' '
# LINT: first subshell statement cuddled with opening "("
(cd foo &&
bar
@@ -20,3 +21,4 @@
# LINT: same with missing "&&"
(cd foo
bar)
+'
diff --git a/t/chainlint/double-here-doc.expect b/t/chainlint/double-here-doc.expect
index cd584a4357..48c04ecd58 100644
--- a/t/chainlint/double-here-doc.expect
+++ b/t/chainlint/double-here-doc.expect
@@ -1,12 +1,12 @@
-run_sub_test_lib_test_err run-inv-range-start \
- "--run invalid range start" \
- --run="a-5" <<-\EOF &&
-test_expect_success "passing test #1" "true"
-test_done
-EOF
-check_sub_test_lib_test_err run-inv-range-start \
- <<-\EOF_OUT 3<<-EOF_ERR
-> FATAL: Unexpected exit with code 1
-EOF_OUT
-> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
-EOF_ERR
+2 run_sub_test_lib_test_err run-inv-range-start \
+3 "--run invalid range start" \
+4 --run="a-5" <<-\EOF &&
+5 test_expect_success "passing test #1" "true"
+6 test_done
+7 EOF
+8 check_sub_test_lib_test_err run-inv-range-start \
+9 <<-\EOF_OUT 3<<-EOF_ERR
+10 > FATAL: Unexpected exit with code 1
+11 EOF_OUT
+12 > error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
+13 EOF_ERR
diff --git a/t/chainlint/double-here-doc.test b/t/chainlint/double-here-doc.test
index cd584a4357..1b69b7a651 100644
--- a/t/chainlint/double-here-doc.test
+++ b/t/chainlint/double-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'double-here-doc' '
run_sub_test_lib_test_err run-inv-range-start \
"--run invalid range start" \
--run="a-5" <<-\EOF &&
@@ -10,3 +11,4 @@ check_sub_test_lib_test_err run-inv-range-start \
EOF_OUT
> error: --run: invalid non-numeric in range start: ${SQ}a-5${SQ}
EOF_ERR
+'
diff --git a/t/chainlint/dqstring-line-splice.expect b/t/chainlint/dqstring-line-splice.expect
index 37eab80738..2ca1c92cd6 100644
--- a/t/chainlint/dqstring-line-splice.expect
+++ b/t/chainlint/dqstring-line-splice.expect
@@ -1,5 +1,5 @@
-
-echo 'fatal: reword option of --fixup is mutually exclusive with' '--patch/--interactive/--all/--include/--only' >expect &&
-test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
-test_cmp expect actual
-
+2
+3 echo 'fatal: reword option of --fixup is mutually exclusive with' '--patch/--interactive/--all/--include/--only' >expect &&
+4 test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
+5 test_cmp expect actual
+6
diff --git a/t/chainlint/dqstring-line-splice.test b/t/chainlint/dqstring-line-splice.test
index b40714439f..f6aa637be8 100644
--- a/t/chainlint/dqstring-line-splice.test
+++ b/t/chainlint/dqstring-line-splice.test
@@ -1,3 +1,4 @@
+test_expect_success 'dqstring-line-splice' '
# LINT: line-splice within DQ-string
'"
echo 'fatal: reword option of --fixup is mutually exclusive with'\
@@ -5,3 +6,4 @@ echo 'fatal: reword option of --fixup is mutually exclusive with'\
test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
test_cmp expect actual
"'
+'
diff --git a/t/chainlint/dqstring-no-interpolate.expect b/t/chainlint/dqstring-no-interpolate.expect
index 087eda15e4..c9f75849c5 100644
--- a/t/chainlint/dqstring-no-interpolate.expect
+++ b/t/chainlint/dqstring-no-interpolate.expect
@@ -1,12 +1,12 @@
-grep "^ ! [rejected][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
-
-grep "^\.git$" output.txt &&
-
-
-(
- cd client$version &&
- GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. $(cat ../input)
-) >output &&
- cut -d ' ' -f 2 <output | sort >actual &&
- test_cmp expect actual
-
+2 grep "^ ! [rejected][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
+3
+4 grep "^\.git$" output.txt &&
+5
+6
+7 (
+8 cd client$version &&
+9 GIT_TEST_PROTOCOL_VERSION=$version git fetch-pack --no-progress .. $(cat ../input)
+10 ) >output &&
+11 cut -d ' ' -f 2 <output | sort >actual &&
+12 test_cmp expect actual
+13
diff --git a/t/chainlint/dqstring-no-interpolate.test b/t/chainlint/dqstring-no-interpolate.test
index d2f4219cbb..7ae079b558 100644
--- a/t/chainlint/dqstring-no-interpolate.test
+++ b/t/chainlint/dqstring-no-interpolate.test
@@ -1,3 +1,4 @@
+test_expect_success 'dqstring-no-interpolate' '
# LINT: regex dollar-sign eol anchor in double-quoted string not special
grep "^ ! \[rejected\][ ]*$BRANCH -> $BRANCH (non-fast-forward)$" out &&
@@ -13,3 +14,4 @@ grep "^\\.git\$" output.txt &&
cut -d ' ' -f 2 <output | sort >actual &&
test_cmp expect actual
"'
+'
diff --git a/t/chainlint/empty-here-doc.expect b/t/chainlint/empty-here-doc.expect
index 8507721192..54b33f823a 100644
--- a/t/chainlint/empty-here-doc.expect
+++ b/t/chainlint/empty-here-doc.expect
@@ -1,4 +1,4 @@
-git ls-tree $tree path >current &&
-cat >expected <<\EOF &&
-EOF
-test_output
+2 git ls-tree $tree path >current &&
+3 cat >expected <<\EOF &&
+4 EOF
+5 test_output
diff --git a/t/chainlint/empty-here-doc.test b/t/chainlint/empty-here-doc.test
index 24fc165de3..8b7ab6eb5f 100644
--- a/t/chainlint/empty-here-doc.test
+++ b/t/chainlint/empty-here-doc.test
@@ -1,5 +1,7 @@
+test_expect_success 'empty-here-doc' '
git ls-tree $tree path >current &&
# LINT: empty here-doc
cat >expected <<\EOF &&
EOF
test_output
+'
diff --git a/t/chainlint/exclamation.expect b/t/chainlint/exclamation.expect
index 765a35bb4c..078744b61b 100644
--- a/t/chainlint/exclamation.expect
+++ b/t/chainlint/exclamation.expect
@@ -1,4 +1,4 @@
-if ! condition; then echo nope; else yep; fi &&
-test_prerequisite !MINGW &&
-mail uucp!address &&
-echo !whatever!
+2 if ! condition; then echo nope; else yep; fi &&
+3 test_prerequisite !MINGW &&
+4 mail uucp!address &&
+5 echo !whatever!
diff --git a/t/chainlint/exclamation.test b/t/chainlint/exclamation.test
index 323595b5bd..796de21b7c 100644
--- a/t/chainlint/exclamation.test
+++ b/t/chainlint/exclamation.test
@@ -1,3 +1,4 @@
+test_expect_success 'exclamation' '
# LINT: "! word" is two tokens
if ! condition; then echo nope; else yep; fi &&
# LINT: "!word" is single token, not two tokens "!" and "word"
@@ -6,3 +7,4 @@ test_prerequisite !MINGW &&
mail uucp!address &&
# LINT: "!word!" is single token, not three tokens "!", "word", and "!"
echo !whatever!
+'
diff --git a/t/chainlint/exit-loop.expect b/t/chainlint/exit-loop.expect
index f76aa60466..407278094c 100644
--- a/t/chainlint/exit-loop.expect
+++ b/t/chainlint/exit-loop.expect
@@ -1,24 +1,24 @@
-(
- for i in a b c
- do
- foo || exit 1
- bar &&
- baz
- done
-) &&
-(
- while true
- do
- foo || exit 1
- bar &&
- baz
- done
-) &&
-(
- i=0 &&
- while test $i -lt 10
- do
- echo $i || exit
- i=$(($i + 1))
- done
-)
+2 (
+3 for i in a b c
+4 do
+5 foo || exit 1
+6 bar &&
+7 baz
+8 done
+9 ) &&
+10 (
+11 while true
+12 do
+13 foo || exit 1
+14 bar &&
+15 baz
+16 done
+17 ) &&
+18 (
+19 i=0 &&
+20 while test $i -lt 10
+21 do
+22 echo $i || exit
+23 i=$(($i + 1))
+24 done
+25 )
diff --git a/t/chainlint/exit-loop.test b/t/chainlint/exit-loop.test
index 2f038207e1..7e8b68b465 100644
--- a/t/chainlint/exit-loop.test
+++ b/t/chainlint/exit-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'exit-loop' '
(
for i in a b c
do
@@ -25,3 +26,4 @@
i=$(($i + 1))
done
)
+'
diff --git a/t/chainlint/exit-subshell.expect b/t/chainlint/exit-subshell.expect
index da80339f78..793db12453 100644
--- a/t/chainlint/exit-subshell.expect
+++ b/t/chainlint/exit-subshell.expect
@@ -1,5 +1,5 @@
-(
- foo || exit 1
- bar &&
- baz
-)
+2 (
+3 foo || exit 1
+4 bar &&
+5 baz
+6 )
diff --git a/t/chainlint/exit-subshell.test b/t/chainlint/exit-subshell.test
index 4e6ab69b88..05dff55cd7 100644
--- a/t/chainlint/exit-subshell.test
+++ b/t/chainlint/exit-subshell.test
@@ -1,6 +1,8 @@
+test_expect_success 'exit-subshell' '
(
# LINT: "|| exit {n}" valid subshell escape without hurting &&-chain
foo || exit 1
bar &&
baz
)
+'
diff --git a/t/chainlint/for-loop-abbreviated.expect b/t/chainlint/for-loop-abbreviated.expect
index 02c0d15cca..5574831976 100644
--- a/t/chainlint/for-loop-abbreviated.expect
+++ b/t/chainlint/for-loop-abbreviated.expect
@@ -1,5 +1,5 @@
-for it
-do
- path=$(expr "$it" : ([^:]*)) &&
- git update-index --add "$path" || exit
-done
+2 for it
+3 do
+4 path=$(expr "$it" : ([^:]*)) &&
+5 git update-index --add "$path" || exit
+6 done
diff --git a/t/chainlint/for-loop-abbreviated.test b/t/chainlint/for-loop-abbreviated.test
index 1084eccb89..1dd14f2a44 100644
--- a/t/chainlint/for-loop-abbreviated.test
+++ b/t/chainlint/for-loop-abbreviated.test
@@ -1,6 +1,8 @@
+test_expect_success 'for-loop-abbreviated' '
# LINT: for-loop lacking optional "in [word...]" before "do"
for it
do
path=$(expr "$it" : '\([^:]*\)') &&
git update-index --add "$path" || exit
done
+'
diff --git a/t/chainlint/for-loop.expect b/t/chainlint/for-loop.expect
index d2237f1e38..908aeedf96 100644
--- a/t/chainlint/for-loop.expect
+++ b/t/chainlint/for-loop.expect
@@ -1,14 +1,14 @@
-(
- for i in a b c
- do
- echo $i ?!AMP?!
- cat <<-\EOF ?!LOOP?!
- bar
- EOF
- done ?!AMP?!
-
- for i in a b c; do
- echo $i &&
- cat $i ?!LOOP?!
- done
-)
+2 (
+3 for i in a b c
+4 do
+5 echo $i ?!AMP?!
+6 cat <<-\EOF ?!LOOP?!
+7 bar
+8 EOF
+9 done ?!AMP?!
+10
+11 for i in a b c; do
+12 echo $i &&
+13 cat $i ?!LOOP?!
+14 done
+15 )
diff --git a/t/chainlint/for-loop.test b/t/chainlint/for-loop.test
index 6cb3428158..6f2489eb19 100644
--- a/t/chainlint/for-loop.test
+++ b/t/chainlint/for-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'for-loop' '
(
# LINT: "for", "do", "done" do not need "&&"
for i in a b c
@@ -17,3 +18,4 @@
cat $i
done
)
+'
diff --git a/t/chainlint/function.expect b/t/chainlint/function.expect
index dd7c997a3c..c226246b25 100644
--- a/t/chainlint/function.expect
+++ b/t/chainlint/function.expect
@@ -1,11 +1,11 @@
-sha1_file() {
- echo "$*" | sed "s#..#.git/objects/&/#"
-} &&
-
-remove_object() {
- file=$(sha1_file "$*") &&
- test -e "$file" ?!AMP?!
- rm -f "$file"
-} ?!AMP?!
-
-sha1_file arg && remove_object arg
+2 sha1_file() {
+3 echo "$*" | sed "s#..#.git/objects/&/#"
+4 } &&
+5
+6 remove_object() {
+7 file=$(sha1_file "$*") &&
+8 test -e "$file" ?!AMP?!
+9 rm -f "$file"
+10 } ?!AMP?!
+11
+12 sha1_file arg && remove_object arg
diff --git a/t/chainlint/function.test b/t/chainlint/function.test
index 5ee59562c9..763fcf3f87 100644
--- a/t/chainlint/function.test
+++ b/t/chainlint/function.test
@@ -1,3 +1,4 @@
+test_expect_success 'function' '
# LINT: "()" in function definition not mistaken for subshell
sha1_file() {
echo "$*" | sed "s#..#.git/objects/&/#"
@@ -11,3 +12,4 @@ remove_object() {
}
sha1_file arg && remove_object arg
+'
diff --git a/t/chainlint/here-doc-body-indent.expect b/t/chainlint/here-doc-body-indent.expect
new file mode 100644
index 0000000000..4323acc93d
--- /dev/null
+++ b/t/chainlint/here-doc-body-indent.expect
@@ -0,0 +1,2 @@
+2 echo "we should find this" ?!AMP?!
+3 echo "even though our heredoc has its indent stripped"
diff --git a/t/chainlint/here-doc-body-indent.test b/t/chainlint/here-doc-body-indent.test
new file mode 100644
index 0000000000..39ff970ef3
--- /dev/null
+++ b/t/chainlint/here-doc-body-indent.test
@@ -0,0 +1,4 @@
+test_expect_success 'here-doc-body-indent' - <<-\EOT
+ echo "we should find this"
+ echo "even though our heredoc has its indent stripped"
+EOT
diff --git a/t/chainlint/here-doc-body-pathological.expect b/t/chainlint/here-doc-body-pathological.expect
new file mode 100644
index 0000000000..a93a1fa3aa
--- /dev/null
+++ b/t/chainlint/here-doc-body-pathological.expect
@@ -0,0 +1,7 @@
+2 echo "outer here-doc does not allow indented end-tag" ?!AMP?!
+3 cat >file <<-\EOF &&
+4 but this inner here-doc
+5 does allow indented EOF
+6 EOF
+7 echo "missing chain after" ?!AMP?!
+8 echo "but this line is OK because it's the end"
diff --git a/t/chainlint/here-doc-body-pathological.test b/t/chainlint/here-doc-body-pathological.test
new file mode 100644
index 0000000000..7d2daa44f9
--- /dev/null
+++ b/t/chainlint/here-doc-body-pathological.test
@@ -0,0 +1,9 @@
+test_expect_success 'here-doc-body-pathological' - <<\EOF
+ echo "outer here-doc does not allow indented end-tag"
+ cat >file <<-\EOF &&
+ but this inner here-doc
+ does allow indented EOF
+ EOF
+ echo "missing chain after"
+ echo "but this line is OK because it's the end"
+EOF
diff --git a/t/chainlint/here-doc-body.expect b/t/chainlint/here-doc-body.expect
new file mode 100644
index 0000000000..ddf1c412af
--- /dev/null
+++ b/t/chainlint/here-doc-body.expect
@@ -0,0 +1,7 @@
+2 echo "missing chain before" ?!AMP?!
+3 cat >file <<-\EOF &&
+4 inside inner here-doc
+5 these are not shell commands
+6 EOF
+7 echo "missing chain after" ?!AMP?!
+8 echo "but this line is OK because it's the end"
diff --git a/t/chainlint/here-doc-body.test b/t/chainlint/here-doc-body.test
new file mode 100644
index 0000000000..989ac2f4e1
--- /dev/null
+++ b/t/chainlint/here-doc-body.test
@@ -0,0 +1,9 @@
+test_expect_success 'here-doc-body' - <<\EOT
+ echo "missing chain before"
+ cat >file <<-\EOF &&
+ inside inner here-doc
+ these are not shell commands
+ EOF
+ echo "missing chain after"
+ echo "but this line is OK because it's the end"
+EOT
diff --git a/t/chainlint/here-doc-close-subshell.expect b/t/chainlint/here-doc-close-subshell.expect
index 7d9c2b5607..965813f463 100644
--- a/t/chainlint/here-doc-close-subshell.expect
+++ b/t/chainlint/here-doc-close-subshell.expect
@@ -1,4 +1,4 @@
-(
- cat <<-\INPUT)
- fizz
- INPUT
+2 (
+3 cat <<-\INPUT)
+4 fizz
+5 INPUT
diff --git a/t/chainlint/here-doc-close-subshell.test b/t/chainlint/here-doc-close-subshell.test
index b857ff5467..2458f3323b 100644
--- a/t/chainlint/here-doc-close-subshell.test
+++ b/t/chainlint/here-doc-close-subshell.test
@@ -1,5 +1,7 @@
+test_expect_success 'here-doc-close-subshell' '
(
# LINT: line contains here-doc and closes nested subshell
cat <<-\INPUT)
fizz
INPUT
+'
diff --git a/t/chainlint/here-doc-double.expect b/t/chainlint/here-doc-double.expect
new file mode 100644
index 0000000000..20dba4b452
--- /dev/null
+++ b/t/chainlint/here-doc-double.expect
@@ -0,0 +1,2 @@
+8 echo "actual test commands" ?!AMP?!
+9 echo "that should be checked"
diff --git a/t/chainlint/here-doc-double.test b/t/chainlint/here-doc-double.test
new file mode 100644
index 0000000000..777389f0d9
--- /dev/null
+++ b/t/chainlint/here-doc-double.test
@@ -0,0 +1,10 @@
+# This is obviously a ridiculous thing to do, but we should be able
+# to handle two here-docs on the same line, and attribute them
+# correctly.
+test_expect_success "$(cat <<END_OF_PREREQS)" 'here-doc-double' - <<\EOT
+SOME
+PREREQS
+END_OF_PREREQS
+ echo "actual test commands"
+ echo "that should be checked"
+EOT
diff --git a/t/chainlint/here-doc-indent-operator.expect b/t/chainlint/here-doc-indent-operator.expect
index f92a7ce999..277a11202d 100644
--- a/t/chainlint/here-doc-indent-operator.expect
+++ b/t/chainlint/here-doc-indent-operator.expect
@@ -1,11 +1,11 @@
-cat >expect <<- EOF &&
-header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
-num_commits: $1
-chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
-EOF
-
-cat >expect << -EOF ?!AMP?!
-this is not indented
--EOF
-
-cleanup
+2 cat >expect <<- EOF &&
+3 header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
+4 num_commits: $1
+5 chunks: oid_fanout oid_lookup commit_metadata generation_data bloom_indexes bloom_data
+6 EOF
+7
+8 cat >expect << -EOF ?!AMP?!
+9 this is not indented
+10 -EOF
+11
+12 cleanup
diff --git a/t/chainlint/here-doc-indent-operator.test b/t/chainlint/here-doc-indent-operator.test
index c8a6f18eb4..a2656f47c1 100644
--- a/t/chainlint/here-doc-indent-operator.test
+++ b/t/chainlint/here-doc-indent-operator.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc-indent-operator' '
# LINT: whitespace between operator "<<-" and tag legal
cat >expect <<- EOF &&
header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0
@@ -11,3 +12,4 @@ this is not indented
-EOF
cleanup
+'
diff --git a/t/chainlint/here-doc-multi-line-command-subst.expect b/t/chainlint/here-doc-multi-line-command-subst.expect
index b7364c82c8..41b55f6437 100644
--- a/t/chainlint/here-doc-multi-line-command-subst.expect
+++ b/t/chainlint/here-doc-multi-line-command-subst.expect
@@ -1,8 +1,8 @@
-(
- x=$(bobble <<-\END &&
- fossil
- vegetable
- END
- wiffle) ?!AMP?!
- echo $x
-)
+2 (
+3 x=$(bobble <<-\END &&
+4 fossil
+5 vegetable
+6 END
+7 wiffle) ?!AMP?!
+8 echo $x
+9 )
diff --git a/t/chainlint/here-doc-multi-line-command-subst.test b/t/chainlint/here-doc-multi-line-command-subst.test
index 899bc5de8b..8710a8c483 100644
--- a/t/chainlint/here-doc-multi-line-command-subst.test
+++ b/t/chainlint/here-doc-multi-line-command-subst.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc-multi-line-command-subst' '
(
# LINT: line contains here-doc and opens multi-line $(...)
x=$(bobble <<-\END &&
@@ -7,3 +8,4 @@
wiffle)
echo $x
)
+'
diff --git a/t/chainlint/here-doc-multi-line-string.expect b/t/chainlint/here-doc-multi-line-string.expect
index 6c13bdcbfb..c71828589e 100644
--- a/t/chainlint/here-doc-multi-line-string.expect
+++ b/t/chainlint/here-doc-multi-line-string.expect
@@ -1,7 +1,7 @@
-(
- cat <<-\TXT && echo "multi-line
- string" ?!AMP?!
- fizzle
- TXT
- bap
-)
+2 (
+3 cat <<-\TXT && echo "multi-line
+4 string" ?!AMP?!
+5 fizzle
+6 TXT
+7 bap
+8 )
diff --git a/t/chainlint/here-doc-multi-line-string.test b/t/chainlint/here-doc-multi-line-string.test
index a53edbcc8d..2f496002fd 100644
--- a/t/chainlint/here-doc-multi-line-string.test
+++ b/t/chainlint/here-doc-multi-line-string.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc-multi-line-string' '
(
# LINT: line contains here-doc and opens multi-line string
cat <<-\TXT && echo "multi-line
@@ -6,3 +7,4 @@
TXT
bap
)
+'
diff --git a/t/chainlint/here-doc.expect b/t/chainlint/here-doc.expect
index 91b961242a..2c382dd8eb 100644
--- a/t/chainlint/here-doc.expect
+++ b/t/chainlint/here-doc.expect
@@ -1,25 +1,25 @@
-boodle wobba \
- gorgo snoot \
- wafta snurb <<EOF &&
-quoth the raven,
-nevermore...
-EOF
-
-cat <<-Arbitrary_Tag_42 >foo &&
-snoz
-boz
-woz
-Arbitrary_Tag_42
-
-cat <<"zump" >boo &&
-snoz
-boz
-woz
-zump
-
-horticulture <<\EOF
-gomez
-morticia
-wednesday
-pugsly
-EOF
+2 boodle wobba \
+3 gorgo snoot \
+4 wafta snurb <<EOF &&
+5 quoth the raven,
+6 nevermore...
+7 EOF
+8
+9 cat <<-Arbitrary_Tag_42 >foo &&
+10 snoz
+11 boz
+12 woz
+13 Arbitrary_Tag_42
+14
+15 cat <<"zump" >boo &&
+16 snoz
+17 boz
+18 woz
+19 zump
+20
+21 horticulture <<\EOF
+22 gomez
+23 morticia
+24 wednesday
+25 pugsly
+26 EOF
diff --git a/t/chainlint/here-doc.test b/t/chainlint/here-doc.test
index 3f5f92cad3..c91b695319 100644
--- a/t/chainlint/here-doc.test
+++ b/t/chainlint/here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'here-doc' '
# LINT: stitch together incomplete \-ending lines
# LINT: swallow here-doc to avoid false positives in content
boodle wobba \
@@ -28,3 +29,4 @@ morticia
wednesday
pugsly
EOF
+'
diff --git a/t/chainlint/if-condition-split.expect b/t/chainlint/if-condition-split.expect
index ee745ef8d7..9daf3d294a 100644
--- a/t/chainlint/if-condition-split.expect
+++ b/t/chainlint/if-condition-split.expect
@@ -1,7 +1,7 @@
-if bob &&
- marcia ||
- kevin
-then
- echo "nomads" ?!AMP?!
- echo "for sure"
-fi
+2 if bob &&
+3 marcia ||
+4 kevin
+5 then
+6 echo "nomads" ?!AMP?!
+7 echo "for sure"
+8 fi
diff --git a/t/chainlint/if-condition-split.test b/t/chainlint/if-condition-split.test
index 240daa9fd5..9a3b3ed04a 100644
--- a/t/chainlint/if-condition-split.test
+++ b/t/chainlint/if-condition-split.test
@@ -1,3 +1,4 @@
+test_expect_success 'if-condition-split' '
# LINT: "if" condition split across multiple lines at "&&" or "||"
if bob &&
marcia ||
@@ -6,3 +7,4 @@ then
echo "nomads"
echo "for sure"
fi
+'
diff --git a/t/chainlint/if-in-loop.expect b/t/chainlint/if-in-loop.expect
index d6514ae749..ff8c60dbdb 100644
--- a/t/chainlint/if-in-loop.expect
+++ b/t/chainlint/if-in-loop.expect
@@ -1,12 +1,12 @@
-(
- for i in a b c
- do
- if false
- then
- echo "err"
- exit 1
- fi ?!AMP?!
- foo
- done ?!AMP?!
- bar
-)
+2 (
+3 for i in a b c
+4 do
+5 if false
+6 then
+7 echo "err"
+8 exit 1
+9 fi ?!AMP?!
+10 foo
+11 done ?!AMP?!
+12 bar
+13 )
diff --git a/t/chainlint/if-in-loop.test b/t/chainlint/if-in-loop.test
index 90c23976fe..5be9d1cfa5 100644
--- a/t/chainlint/if-in-loop.test
+++ b/t/chainlint/if-in-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'if-in-loop' '
(
for i in a b c
do
@@ -13,3 +14,4 @@
done
bar
)
+'
diff --git a/t/chainlint/if-then-else.expect b/t/chainlint/if-then-else.expect
index cbaaf857d4..965d7e41a2 100644
--- a/t/chainlint/if-then-else.expect
+++ b/t/chainlint/if-then-else.expect
@@ -1,22 +1,22 @@
-(
- if test -n ""
- then
- echo very ?!AMP?!
- echo empty
- elif test -z ""
- then
- echo foo
- else
- echo foo &&
- cat <<-\EOF
- bar
- EOF
- fi ?!AMP?!
- echo poodle
-) &&
-(
- if test -n ""; then
- echo very &&
- echo empty
- fi
-)
+2 (
+3 if test -n ""
+4 then
+5 echo very ?!AMP?!
+6 echo empty
+7 elif test -z ""
+8 then
+9 echo foo
+10 else
+11 echo foo &&
+12 cat <<-\EOF
+13 bar
+14 EOF
+15 fi ?!AMP?!
+16 echo poodle
+17 ) &&
+18 (
+19 if test -n ""; then
+20 echo very &&
+21 echo empty
+22 fi
+23 )
diff --git a/t/chainlint/if-then-else.test b/t/chainlint/if-then-else.test
index 2055336c2b..6582a7f440 100644
--- a/t/chainlint/if-then-else.test
+++ b/t/chainlint/if-then-else.test
@@ -1,3 +1,4 @@
+test_expect_success 'if-then-else' '
(
# LINT: "if", "then", "elif", "else", "fi" do not need "&&"
if test -n ""
@@ -27,3 +28,4 @@
echo empty
fi
)
+'
diff --git a/t/chainlint/incomplete-line.expect b/t/chainlint/incomplete-line.expect
index 134d3a14f5..b15e00b901 100644
--- a/t/chainlint/incomplete-line.expect
+++ b/t/chainlint/incomplete-line.expect
@@ -1,10 +1,10 @@
-line 1 \
-line 2 \
-line 3 \
-line 4 &&
-(
- line 5 \
- line 6 \
- line 7 \
- line 8
-)
+2 line 1 \
+3 line 2 \
+4 line 3 \
+5 line 4 &&
+6 (
+7 line 5 \
+8 line 6 \
+9 line 7 \
+10 line 8
+11 )
diff --git a/t/chainlint/incomplete-line.test b/t/chainlint/incomplete-line.test
index d856658083..74a93021eb 100644
--- a/t/chainlint/incomplete-line.test
+++ b/t/chainlint/incomplete-line.test
@@ -1,3 +1,4 @@
+test_expect_success 'incomplete-line' '
# LINT: stitch together all incomplete \-ending lines
line 1 \
line 2 \
@@ -10,3 +11,4 @@ line 4 &&
line 7 \
line 8
)
+'
diff --git a/t/chainlint/inline-comment.expect b/t/chainlint/inline-comment.expect
index 6bad218530..0285c0b22c 100644
--- a/t/chainlint/inline-comment.expect
+++ b/t/chainlint/inline-comment.expect
@@ -1,8 +1,8 @@
-(
- foobar && # comment 1
- barfoo ?!AMP?! # wrong position for &&
- flibble "not a # comment"
-) &&
-
-(cd foo &&
- flibble "not a # comment")
+2 (
+3 foobar && # comment 1
+4 barfoo ?!AMP?! # wrong position for &&
+5 flibble "not a # comment"
+6 ) &&
+7
+8 (cd foo &&
+9 flibble "not a # comment")
diff --git a/t/chainlint/inline-comment.test b/t/chainlint/inline-comment.test
index 8f26856e77..4fbbf1058a 100644
--- a/t/chainlint/inline-comment.test
+++ b/t/chainlint/inline-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'inline-comment' '
(
# LINT: swallow inline comment (leaving command intact)
foobar && # comment 1
@@ -10,3 +11,4 @@
# LINT: "#" in string in cuddled subshell not misinterpreted as comment
(cd foo &&
flibble "not a # comment")
+'
diff --git a/t/chainlint/loop-detect-failure.expect b/t/chainlint/loop-detect-failure.expect
index a66025c39d..40c06f0d53 100644
--- a/t/chainlint/loop-detect-failure.expect
+++ b/t/chainlint/loop-detect-failure.expect
@@ -1,15 +1,15 @@
-git init r1 &&
-for n in 1 2 3 4 5
-do
- echo "This is file: $n" > r1/file.$n &&
- git -C r1 add file.$n &&
- git -C r1 commit -m "$n" || return 1
-done &&
-
-git init r2 &&
-for n in 1000 10000
-do
- printf "%"$n"s" X > r2/large.$n &&
- git -C r2 add large.$n &&
- git -C r2 commit -m "$n" ?!LOOP?!
-done
+2 git init r1 &&
+3 for n in 1 2 3 4 5
+4 do
+5 echo "This is file: $n" > r1/file.$n &&
+6 git -C r1 add file.$n &&
+7 git -C r1 commit -m "$n" || return 1
+8 done &&
+9
+10 git init r2 &&
+11 for n in 1000 10000
+12 do
+13 printf "%"$n"s" X > r2/large.$n &&
+14 git -C r2 add large.$n &&
+15 git -C r2 commit -m "$n" ?!LOOP?!
+16 done
diff --git a/t/chainlint/loop-detect-failure.test b/t/chainlint/loop-detect-failure.test
index b9791cc802..44673aa394 100644
--- a/t/chainlint/loop-detect-failure.test
+++ b/t/chainlint/loop-detect-failure.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-detect-failure' '
git init r1 &&
# LINT: loop handles failure explicitly with "|| return 1"
for n in 1 2 3 4 5
@@ -15,3 +16,4 @@ do
git -C r2 add large.$n &&
git -C r2 commit -m "$n"
done
+'
diff --git a/t/chainlint/loop-detect-status.expect b/t/chainlint/loop-detect-status.expect
index 7ce3a34806..0f180b08de 100644
--- a/t/chainlint/loop-detect-status.expect
+++ b/t/chainlint/loop-detect-status.expect
@@ -1,18 +1,18 @@
-(while test $i -le $blobcount
- do
- printf "Generating blob $i/$blobcount\r" >&2 &&
- printf "blob\nmark :$i\ndata $blobsize\n" &&
- #test-tool genrandom $i $blobsize &&
- printf "%-${blobsize}s" $i &&
- echo "M 100644 :$i $i" >> commit &&
- i=$(($i+1)) ||
- echo $? > exit-status
- done &&
- echo "commit refs/heads/main" &&
- echo "author A U Thor <author@email.com> 123456789 +0000" &&
- echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
- echo "data 5" &&
- echo ">2gb" &&
- cat commit) |
-git fast-import --big-file-threshold=2 &&
-test ! -f exit-status
+2 (while test $i -le $blobcount
+3 do
+4 printf "Generating blob $i/$blobcount\r" >&2 &&
+5 printf "blob\nmark :$i\ndata $blobsize\n" &&
+6 #test-tool genrandom $i $blobsize &&
+7 printf "%-${blobsize}s" $i &&
+8 echo "M 100644 :$i $i" >> commit &&
+9 i=$(($i+1)) ||
+10 echo $? > exit-status
+11 done &&
+12 echo "commit refs/heads/main" &&
+13 echo "author A U Thor <author@email.com> 123456789 +0000" &&
+14 echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
+15 echo "data 5" &&
+16 echo ">2gb" &&
+17 cat commit) |
+18 git fast-import --big-file-threshold=2 &&
+19 test ! -f exit-status
diff --git a/t/chainlint/loop-detect-status.test b/t/chainlint/loop-detect-status.test
index 1c6c23cfc9..8b639be073 100644
--- a/t/chainlint/loop-detect-status.test
+++ b/t/chainlint/loop-detect-status.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-detect-status' '
# LINT: "$?" handled explicitly within loop body
(while test $i -le $blobcount
do
@@ -17,3 +18,4 @@
cat commit) |
git fast-import --big-file-threshold=2 &&
test ! -f exit-status
+'
diff --git a/t/chainlint/loop-in-if.expect b/t/chainlint/loop-in-if.expect
index 6c5d6e5b24..4e8c67c914 100644
--- a/t/chainlint/loop-in-if.expect
+++ b/t/chainlint/loop-in-if.expect
@@ -1,12 +1,12 @@
-(
- if true
- then
- while true
- do
- echo "pop" ?!AMP?!
- echo "glup" ?!LOOP?!
- done ?!AMP?!
- foo
- fi ?!AMP?!
- bar
-)
+2 (
+3 if true
+4 then
+5 while true
+6 do
+7 echo "pop" ?!AMP?!
+8 echo "glup" ?!LOOP?!
+9 done ?!AMP?!
+10 foo
+11 fi ?!AMP?!
+12 bar
+13 )
diff --git a/t/chainlint/loop-in-if.test b/t/chainlint/loop-in-if.test
index dfcc3f98fb..b0d0d393cf 100644
--- a/t/chainlint/loop-in-if.test
+++ b/t/chainlint/loop-in-if.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-in-if' '
(
if true
then
@@ -13,3 +14,4 @@
fi
bar
)
+'
diff --git a/t/chainlint/loop-upstream-pipe.expect b/t/chainlint/loop-upstream-pipe.expect
index 0b82ecc4b9..bef82479ca 100644
--- a/t/chainlint/loop-upstream-pipe.expect
+++ b/t/chainlint/loop-upstream-pipe.expect
@@ -1,10 +1,10 @@
-(
- git rev-list --objects --no-object-names base..loose |
- while read oid
- do
- path="$objdir/$(test_oid_to_path "$oid")" &&
- printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" ||
- echo "object list generation failed for $oid"
- done |
- sort -k1
-) >expect &&
+2 (
+3 git rev-list --objects --no-object-names base..loose |
+4 while read oid
+5 do
+6 path="$objdir/$(test_oid_to_path "$oid")" &&
+7 printf "%s %d\n" "$oid" "$(test-tool chmtime --get "$path")" ||
+8 echo "object list generation failed for $oid"
+9 done |
+10 sort -k1
+11 ) >expect &&
diff --git a/t/chainlint/loop-upstream-pipe.test b/t/chainlint/loop-upstream-pipe.test
index efb77da897..8415a4db27 100644
--- a/t/chainlint/loop-upstream-pipe.test
+++ b/t/chainlint/loop-upstream-pipe.test
@@ -1,3 +1,4 @@
+test_expect_success 'loop-upstream-pipe' '
(
git rev-list --objects --no-object-names base..loose |
while read oid
@@ -9,3 +10,4 @@
done |
sort -k1
) >expect &&
+'
diff --git a/t/chainlint/multi-line-nested-command-substitution.expect b/t/chainlint/multi-line-nested-command-substitution.expect
index 300058341b..ad27e43e05 100644
--- a/t/chainlint/multi-line-nested-command-substitution.expect
+++ b/t/chainlint/multi-line-nested-command-substitution.expect
@@ -1,18 +1,18 @@
-(
- foo &&
- x=$(
- echo bar |
- cat
- ) &&
- echo ok
-) |
-sort &&
-(
- bar &&
- x=$(echo bar |
- cat
- ) &&
- y=$(echo baz |
- fip) &&
- echo fail
-)
+2 (
+3 foo &&
+4 x=$(
+5 echo bar |
+6 cat
+7 ) &&
+8 echo ok
+9 ) |
+10 sort &&
+11 (
+12 bar &&
+13 x=$(echo bar |
+14 cat
+15 ) &&
+16 y=$(echo baz |
+17 fip) &&
+18 echo fail
+19 )
diff --git a/t/chainlint/multi-line-nested-command-substitution.test b/t/chainlint/multi-line-nested-command-substitution.test
index 300058341b..e811c63f2b 100644
--- a/t/chainlint/multi-line-nested-command-substitution.test
+++ b/t/chainlint/multi-line-nested-command-substitution.test
@@ -1,3 +1,4 @@
+test_expect_success 'multi-line-nested-command-substitution' '
(
foo &&
x=$(
@@ -16,3 +17,4 @@ sort &&
fip) &&
echo fail
)
+'
diff --git a/t/chainlint/multi-line-string.expect b/t/chainlint/multi-line-string.expect
index 27ff95218e..62c54e3a5e 100644
--- a/t/chainlint/multi-line-string.expect
+++ b/t/chainlint/multi-line-string.expect
@@ -1,14 +1,14 @@
-(
- x="line 1
- line 2
- line 3" &&
- y="line 1
- line2" ?!AMP?!
- foobar
-) &&
-(
- echo "xyz" "abc
- def
- ghi" &&
- barfoo
-)
+2 (
+3 x="line 1
+4 line 2
+5 line 3" &&
+6 y="line 1
+7 line2" ?!AMP?!
+8 foobar
+9 ) &&
+10 (
+11 echo "xyz" "abc
+12 def
+13 ghi" &&
+14 barfoo
+15 )
diff --git a/t/chainlint/multi-line-string.test b/t/chainlint/multi-line-string.test
index 4a0af2107d..7b5048d2ea 100644
--- a/t/chainlint/multi-line-string.test
+++ b/t/chainlint/multi-line-string.test
@@ -1,3 +1,4 @@
+test_expect_success 'multi-line-string' '
(
x="line 1
line 2
@@ -13,3 +14,4 @@
ghi" &&
barfoo
)
+'
diff --git a/t/chainlint/negated-one-liner.expect b/t/chainlint/negated-one-liner.expect
index ad4c2d949e..a6ce52a1da 100644
--- a/t/chainlint/negated-one-liner.expect
+++ b/t/chainlint/negated-one-liner.expect
@@ -1,5 +1,5 @@
-! (foo && bar) &&
-! (foo && bar) >baz &&
-
-! (foo; ?!AMP?! bar) &&
-! (foo; ?!AMP?! bar) >baz
+2 ! (foo && bar) &&
+3 ! (foo && bar) >baz &&
+4
+5 ! (foo; ?!AMP?! bar) &&
+6 ! (foo; ?!AMP?! bar) >baz
diff --git a/t/chainlint/negated-one-liner.test b/t/chainlint/negated-one-liner.test
index c9598e9153..30f4cc5a9b 100644
--- a/t/chainlint/negated-one-liner.test
+++ b/t/chainlint/negated-one-liner.test
@@ -1,3 +1,4 @@
+test_expect_success 'negated-one-liner' '
# LINT: top-level one-liner subshell
! (foo && bar) &&
! (foo && bar) >baz &&
@@ -5,3 +6,4 @@
# LINT: top-level one-liner subshell missing internal "&&"
! (foo; bar) &&
! (foo; bar) >baz
+'
diff --git a/t/chainlint/nested-cuddled-subshell.expect b/t/chainlint/nested-cuddled-subshell.expect
index 3836049cc4..0191c9c294 100644
--- a/t/chainlint/nested-cuddled-subshell.expect
+++ b/t/chainlint/nested-cuddled-subshell.expect
@@ -1,25 +1,25 @@
-(
- (cd foo &&
- bar
- ) &&
-
- (cd foo &&
- bar
- ) ?!AMP?!
-
- (
- cd foo &&
- bar) &&
-
- (
- cd foo &&
- bar) ?!AMP?!
-
- (cd foo &&
- bar) &&
-
- (cd foo &&
- bar) ?!AMP?!
-
- foobar
-)
+2 (
+3 (cd foo &&
+4 bar
+5 ) &&
+6
+7 (cd foo &&
+8 bar
+9 ) ?!AMP?!
+10
+11 (
+12 cd foo &&
+13 bar) &&
+14
+15 (
+16 cd foo &&
+17 bar) ?!AMP?!
+18
+19 (cd foo &&
+20 bar) &&
+21
+22 (cd foo &&
+23 bar) ?!AMP?!
+24
+25 foobar
+26 )
diff --git a/t/chainlint/nested-cuddled-subshell.test b/t/chainlint/nested-cuddled-subshell.test
index 8fd656c7b5..31e92d3be4 100644
--- a/t/chainlint/nested-cuddled-subshell.test
+++ b/t/chainlint/nested-cuddled-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-cuddled-subshell' '
(
# LINT: opening "(" cuddled with first nested subshell statement
(cd foo &&
@@ -29,3 +30,4 @@
foobar
)
+'
diff --git a/t/chainlint/nested-here-doc.expect b/t/chainlint/nested-here-doc.expect
index 29b3832a98..70d9b68dc9 100644
--- a/t/chainlint/nested-here-doc.expect
+++ b/t/chainlint/nested-here-doc.expect
@@ -1,30 +1,30 @@
-cat <<ARBITRARY >foop &&
-naddle
-fub <<EOF
- nozzle
- noodle
-EOF
-formp
-ARBITRARY
-
-(
- cat <<-\INPUT_END &&
- fish are mice
- but geese go slow
- data <<EOF
- perl is lerp
- and nothing else
- EOF
- toink
- INPUT_END
-
- cat <<-\EOT ?!AMP?!
- text goes here
- data <<EOF
- data goes here
- EOF
- more test here
- EOT
-
- foobar
-)
+2 cat <<ARBITRARY >foop &&
+3 naddle
+4 fub <<EOF
+5 nozzle
+6 noodle
+7 EOF
+8 formp
+9 ARBITRARY
+10
+11 (
+12 cat <<-\INPUT_END &&
+13 fish are mice
+14 but geese go slow
+15 data <<EOF
+16 perl is lerp
+17 and nothing else
+18 EOF
+19 toink
+20 INPUT_END
+21
+22 cat <<-\EOT ?!AMP?!
+23 text goes here
+24 data <<EOF
+25 data goes here
+26 EOF
+27 more test here
+28 EOT
+29
+30 foobar
+31 )
diff --git a/t/chainlint/nested-here-doc.test b/t/chainlint/nested-here-doc.test
index f35404bf0f..9505c47a34 100644
--- a/t/chainlint/nested-here-doc.test
+++ b/t/chainlint/nested-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-here-doc' '
# LINT: inner "EOF" not misintrepreted as closing ARBITRARY here-doc
cat <<ARBITRARY >foop &&
naddle
@@ -31,3 +32,4 @@ ARBITRARY
foobar
)
+'
diff --git a/t/chainlint/nested-loop-detect-failure.expect b/t/chainlint/nested-loop-detect-failure.expect
index 3461df40e5..c13c4d2f90 100644
--- a/t/chainlint/nested-loop-detect-failure.expect
+++ b/t/chainlint/nested-loop-detect-failure.expect
@@ -1,31 +1,31 @@
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" ?!LOOP?!
- done ?!LOOP?!
-done &&
-
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" || return 1
- done
-done &&
-
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" ?!LOOP?!
- done || return 1
-done &&
-
-for i in 0 1 2 3 4 5 6 7 8 9;
-do
- for j in 0 1 2 3 4 5 6 7 8 9;
- do
- echo "$i$j" >"path$i$j" || return 1
- done || return 1
-done
+2 for i in 0 1 2 3 4 5 6 7 8 9;
+3 do
+4 for j in 0 1 2 3 4 5 6 7 8 9;
+5 do
+6 echo "$i$j" >"path$i$j" ?!LOOP?!
+7 done ?!LOOP?!
+8 done &&
+9
+10 for i in 0 1 2 3 4 5 6 7 8 9;
+11 do
+12 for j in 0 1 2 3 4 5 6 7 8 9;
+13 do
+14 echo "$i$j" >"path$i$j" || return 1
+15 done
+16 done &&
+17
+18 for i in 0 1 2 3 4 5 6 7 8 9;
+19 do
+20 for j in 0 1 2 3 4 5 6 7 8 9;
+21 do
+22 echo "$i$j" >"path$i$j" ?!LOOP?!
+23 done || return 1
+24 done &&
+25
+26 for i in 0 1 2 3 4 5 6 7 8 9;
+27 do
+28 for j in 0 1 2 3 4 5 6 7 8 9;
+29 do
+30 echo "$i$j" >"path$i$j" || return 1
+31 done || return 1
+32 done
diff --git a/t/chainlint/nested-loop-detect-failure.test b/t/chainlint/nested-loop-detect-failure.test
index e6f0c1acfb..3d4b657412 100644
--- a/t/chainlint/nested-loop-detect-failure.test
+++ b/t/chainlint/nested-loop-detect-failure.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-loop-detect-failure' '
# LINT: neither loop handles failure explicitly with "|| return 1"
for i in 0 1 2 3 4 5 6 7 8 9;
do
@@ -33,3 +34,4 @@ do
echo "$i$j" >"path$i$j" || return 1
done || return 1
done
+'
diff --git a/t/chainlint/nested-subshell-comment.expect b/t/chainlint/nested-subshell-comment.expect
index 9138cf386d..f89a8d03a8 100644
--- a/t/chainlint/nested-subshell-comment.expect
+++ b/t/chainlint/nested-subshell-comment.expect
@@ -1,11 +1,11 @@
-(
- foo &&
- (
- bar &&
- # bottles wobble while fiddles gobble
- # minor numbers of cows (or do they?)
- baz &&
- snaff
- ) ?!AMP?!
- fuzzy
-)
+2 (
+3 foo &&
+4 (
+5 bar &&
+6 # bottles wobble while fiddles gobble
+7 # minor numbers of cows (or do they?)
+8 baz &&
+9 snaff
+10 ) ?!AMP?!
+11 fuzzy
+12 )
diff --git a/t/chainlint/nested-subshell-comment.test b/t/chainlint/nested-subshell-comment.test
index 0215cdb192..b430580ce0 100644
--- a/t/chainlint/nested-subshell-comment.test
+++ b/t/chainlint/nested-subshell-comment.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-subshell-comment' '
(
foo &&
(
@@ -11,3 +12,4 @@
)
fuzzy
)
+'
diff --git a/t/chainlint/nested-subshell.expect b/t/chainlint/nested-subshell.expect
index 73ff28546a..811e8a7912 100644
--- a/t/chainlint/nested-subshell.expect
+++ b/t/chainlint/nested-subshell.expect
@@ -1,13 +1,13 @@
-(
- cd foo &&
- (
- echo a &&
- echo b
- ) >file &&
-
- cd foo &&
- (
- echo a ?!AMP?!
- echo b
- ) >file
-)
+2 (
+3 cd foo &&
+4 (
+5 echo a &&
+6 echo b
+7 ) >file &&
+8
+9 cd foo &&
+10 (
+11 echo a ?!AMP?!
+12 echo b
+13 ) >file
+14 )
diff --git a/t/chainlint/nested-subshell.test b/t/chainlint/nested-subshell.test
index 440ee9992d..c31da34b73 100644
--- a/t/chainlint/nested-subshell.test
+++ b/t/chainlint/nested-subshell.test
@@ -1,3 +1,4 @@
+test_expect_success 'nested-subshell' '
(
cd foo &&
(
@@ -11,3 +12,4 @@
echo b
) >file
)
+'
diff --git a/t/chainlint/not-heredoc.expect b/t/chainlint/not-heredoc.expect
index 2e9bb135fe..611b7b75cb 100644
--- a/t/chainlint/not-heredoc.expect
+++ b/t/chainlint/not-heredoc.expect
@@ -1,14 +1,14 @@
-echo "<<<<<<< ours" &&
-echo ourside &&
-echo "=======" &&
-echo theirside &&
-echo ">>>>>>> theirs" &&
-
-(
- echo "<<<<<<< ours" &&
- echo ourside &&
- echo "=======" &&
- echo theirside &&
- echo ">>>>>>> theirs" ?!AMP?!
- poodle
-) >merged
+2 echo "<<<<<<< ours" &&
+3 echo ourside &&
+4 echo "=======" &&
+5 echo theirside &&
+6 echo ">>>>>>> theirs" &&
+7
+8 (
+9 echo "<<<<<<< ours" &&
+10 echo ourside &&
+11 echo "=======" &&
+12 echo theirside &&
+13 echo ">>>>>>> theirs" ?!AMP?!
+14 poodle
+15 ) >merged
diff --git a/t/chainlint/not-heredoc.test b/t/chainlint/not-heredoc.test
index 9aa57346cd..09711e45e0 100644
--- a/t/chainlint/not-heredoc.test
+++ b/t/chainlint/not-heredoc.test
@@ -1,3 +1,4 @@
+test_expect_success 'not-heredoc' '
# LINT: "<< ours" inside string is not here-doc
echo "<<<<<<< ours" &&
echo ourside &&
@@ -14,3 +15,4 @@ echo ">>>>>>> theirs" &&
echo ">>>>>>> theirs"
poodle
) >merged
+'
diff --git a/t/chainlint/one-liner-for-loop.expect b/t/chainlint/one-liner-for-loop.expect
index 51a3dc7c54..49dcf065ef 100644
--- a/t/chainlint/one-liner-for-loop.expect
+++ b/t/chainlint/one-liner-for-loop.expect
@@ -1,9 +1,9 @@
-git init dir-rename-and-content &&
-(
- cd dir-rename-and-content &&
- test_write_lines 1 2 3 4 5 >foo &&
- mkdir olddir &&
- for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?!
- git add foo olddir &&
- git commit -m "original" &&
-)
+2 git init dir-rename-and-content &&
+3 (
+4 cd dir-rename-and-content &&
+5 test_write_lines 1 2 3 4 5 >foo &&
+6 mkdir olddir &&
+7 for i in a b c; do echo $i >olddir/$i; ?!LOOP?! done ?!AMP?!
+8 git add foo olddir &&
+9 git commit -m "original" &&
+10 )
diff --git a/t/chainlint/one-liner-for-loop.test b/t/chainlint/one-liner-for-loop.test
index 4bd8c066c7..00afd7ef76 100644
--- a/t/chainlint/one-liner-for-loop.test
+++ b/t/chainlint/one-liner-for-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'one-liner-for-loop' '
git init dir-rename-and-content &&
(
cd dir-rename-and-content &&
@@ -8,3 +9,4 @@ git init dir-rename-and-content &&
git add foo olddir &&
git commit -m "original" &&
)
+'
diff --git a/t/chainlint/one-liner.expect b/t/chainlint/one-liner.expect
index 57a7a444c1..9861811283 100644
--- a/t/chainlint/one-liner.expect
+++ b/t/chainlint/one-liner.expect
@@ -1,9 +1,9 @@
-(foo && bar) &&
-(foo && bar) |
-(foo && bar) >baz &&
-
-(foo; ?!AMP?! bar) &&
-(foo; ?!AMP?! bar) |
-(foo; ?!AMP?! bar) >baz &&
-
-(foo "bar; baz")
+2 (foo && bar) &&
+3 (foo && bar) |
+4 (foo && bar) >baz &&
+5
+6 (foo; ?!AMP?! bar) &&
+7 (foo; ?!AMP?! bar) |
+8 (foo; ?!AMP?! bar) >baz &&
+9
+10 (foo "bar; baz")
diff --git a/t/chainlint/one-liner.test b/t/chainlint/one-liner.test
index be9858fa29..6e42ee1b5e 100644
--- a/t/chainlint/one-liner.test
+++ b/t/chainlint/one-liner.test
@@ -1,3 +1,4 @@
+test_expect_success 'one-liner' '
# LINT: top-level one-liner subshell
(foo && bar) &&
(foo && bar) |
@@ -10,3 +11,4 @@
# LINT: ";" in string not misinterpreted as broken &&-chain
(foo "bar; baz")
+'
diff --git a/t/chainlint/p4-filespec.expect b/t/chainlint/p4-filespec.expect
index 1290fd1ff2..cff3e4e3d1 100644
--- a/t/chainlint/p4-filespec.expect
+++ b/t/chainlint/p4-filespec.expect
@@ -1,4 +1,4 @@
-(
- p4 print -1 //depot/fiddle#42 >file &&
- foobar
-)
+2 (
+3 p4 print -1 //depot/fiddle#42 >file &&
+4 foobar
+5 )
diff --git a/t/chainlint/p4-filespec.test b/t/chainlint/p4-filespec.test
index 4fd2d6e2b8..8ba6b911dc 100644
--- a/t/chainlint/p4-filespec.test
+++ b/t/chainlint/p4-filespec.test
@@ -1,5 +1,7 @@
+test_expect_success 'p4-filespec' '
(
# LINT: Perforce revspec in filespec not misinterpreted as in-line comment
p4 print -1 //depot/fiddle#42 >file &&
foobar
)
+'
diff --git a/t/chainlint/pipe.expect b/t/chainlint/pipe.expect
index 811971b1a3..1bbe5a2ce1 100644
--- a/t/chainlint/pipe.expect
+++ b/t/chainlint/pipe.expect
@@ -1,10 +1,10 @@
-(
- foo |
- bar |
- baz &&
-
- fish |
- cow ?!AMP?!
-
- sunder
-)
+2 (
+3 foo |
+4 bar |
+5 baz &&
+6
+7 fish |
+8 cow ?!AMP?!
+9
+10 sunder
+11 )
diff --git a/t/chainlint/pipe.test b/t/chainlint/pipe.test
index dd82534c66..1af81c243b 100644
--- a/t/chainlint/pipe.test
+++ b/t/chainlint/pipe.test
@@ -1,3 +1,4 @@
+test_expect_success 'pipe' '
(
# LINT: no "&&" needed on line ending with "|"
foo |
@@ -10,3 +11,4 @@
sunder
)
+'
diff --git a/t/chainlint/return-loop.expect b/t/chainlint/return-loop.expect
index cfc0549bef..da8f9abea3 100644
--- a/t/chainlint/return-loop.expect
+++ b/t/chainlint/return-loop.expect
@@ -1,5 +1,5 @@
-while test $i -lt $((num - 5))
-do
- git notes add -m "notes for commit$i" HEAD~$i || return 1
- i=$((i + 1))
-done
+2 while test $i -lt $((num - 5))
+3 do
+4 git notes add -m "notes for commit$i" HEAD~$i || return 1
+5 i=$((i + 1))
+6 done
diff --git a/t/chainlint/return-loop.test b/t/chainlint/return-loop.test
index f90b171300..ea76c3593a 100644
--- a/t/chainlint/return-loop.test
+++ b/t/chainlint/return-loop.test
@@ -1,6 +1,8 @@
+test_expect_success 'return-loop' '
while test $i -lt $((num - 5))
do
# LINT: "|| return {n}" valid loop escape outside subshell; no "&&" needed
git notes add -m "notes for commit$i" HEAD~$i || return 1
i=$((i + 1))
done
+'
diff --git a/t/chainlint/semicolon.expect b/t/chainlint/semicolon.expect
index 3aa2259f36..866438310c 100644
--- a/t/chainlint/semicolon.expect
+++ b/t/chainlint/semicolon.expect
@@ -1,19 +1,19 @@
-(
- cat foo ; ?!AMP?! echo bar ?!AMP?!
- cat foo ; ?!AMP?! echo bar
-) &&
-(
- cat foo ; ?!AMP?! echo bar &&
- cat foo ; ?!AMP?! echo bar
-) &&
-(
- echo "foo; bar" &&
- cat foo; ?!AMP?! echo bar
-) &&
-(
- foo;
-) &&
-(cd foo &&
- for i in a b c; do
- echo; ?!LOOP?!
- done)
+2 (
+3 cat foo ; ?!AMP?! echo bar ?!AMP?!
+4 cat foo ; ?!AMP?! echo bar
+5 ) &&
+6 (
+7 cat foo ; ?!AMP?! echo bar &&
+8 cat foo ; ?!AMP?! echo bar
+9 ) &&
+10 (
+11 echo "foo; bar" &&
+12 cat foo; ?!AMP?! echo bar
+13 ) &&
+14 (
+15 foo;
+16 ) &&
+17 (cd foo &&
+18 for i in a b c; do
+19 echo; ?!LOOP?!
+20 done)
diff --git a/t/chainlint/semicolon.test b/t/chainlint/semicolon.test
index 67e1192c50..fc0ba1b539 100644
--- a/t/chainlint/semicolon.test
+++ b/t/chainlint/semicolon.test
@@ -1,3 +1,4 @@
+test_expect_success 'semicolon' '
(
# LINT: missing internal "&&" and ending "&&"
cat foo ; echo bar
@@ -23,3 +24,4 @@
# LINT: semicolon unnecessary but legitimate
echo;
done)
+'
diff --git a/t/chainlint/sqstring-in-sqstring.expect b/t/chainlint/sqstring-in-sqstring.expect
index cf0b591cf7..ba5d3c3a6d 100644
--- a/t/chainlint/sqstring-in-sqstring.expect
+++ b/t/chainlint/sqstring-in-sqstring.expect
@@ -1,4 +1,4 @@
-perl -e '
- defined($_ = -s $_) or die for @ARGV;
- exit 1 if $ARGV[0] <= $ARGV[1];
-' test-2-$packname_2.pack test-3-$packname_3.pack
+2 perl -e '
+3 defined($_ = -s $_) or die for @ARGV;
+4 exit 1 if $ARGV[0] <= $ARGV[1];
+5 ' test-2-$packname_2.pack test-3-$packname_3.pack
diff --git a/t/chainlint/sqstring-in-sqstring.test b/t/chainlint/sqstring-in-sqstring.test
index 77a425e0c7..24169724a5 100644
--- a/t/chainlint/sqstring-in-sqstring.test
+++ b/t/chainlint/sqstring-in-sqstring.test
@@ -1,5 +1,7 @@
+test_expect_success 'sqstring-in-sqstring' '
# LINT: SQ-string Perl code fragment within SQ-string
perl -e '\''
defined($_ = -s $_) or die for @ARGV;
exit 1 if $ARGV[0] <= $ARGV[1];
'\'' test-2-$packname_2.pack test-3-$packname_3.pack
+'
diff --git a/t/chainlint/subshell-here-doc.expect b/t/chainlint/subshell-here-doc.expect
index 75d6f607e2..5647500c82 100644
--- a/t/chainlint/subshell-here-doc.expect
+++ b/t/chainlint/subshell-here-doc.expect
@@ -1,30 +1,30 @@
-(
- echo wobba \
- gorgo snoot \
- wafta snurb <<-EOF &&
- quoth the raven,
- nevermore...
- EOF
-
- cat <<EOF >bip ?!AMP?!
- fish fly high
-EOF
-
- echo <<-\EOF >bop
- gomez
- morticia
- wednesday
- pugsly
- EOF
-) &&
-(
- cat <<-\ARBITRARY >bup &&
- glink
- FIZZ
- ARBITRARY
- cat <<-"ARBITRARY3" >bup3 &&
- glink
- FIZZ
- ARBITRARY3
- meep
-)
+2 (
+3 echo wobba \
+4 gorgo snoot \
+5 wafta snurb <<-EOF &&
+6 quoth the raven,
+7 nevermore...
+8 EOF
+9
+10 cat <<EOF >bip ?!AMP?!
+11 fish fly high
+12 EOF
+13
+14 echo <<-\EOF >bop
+15 gomez
+16 morticia
+17 wednesday
+18 pugsly
+19 EOF
+20 ) &&
+21 (
+22 cat <<-\ARBITRARY >bup &&
+23 glink
+24 FIZZ
+25 ARBITRARY
+26 cat <<-"ARBITRARY3" >bup3 &&
+27 glink
+28 FIZZ
+29 ARBITRARY3
+30 meep
+31 )
diff --git a/t/chainlint/subshell-here-doc.test b/t/chainlint/subshell-here-doc.test
index d40eb65583..4a38f47f01 100644
--- a/t/chainlint/subshell-here-doc.test
+++ b/t/chainlint/subshell-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'subshell-here-doc' '
(
# LINT: stitch together incomplete \-ending lines
# LINT: swallow here-doc to avoid false positives in content
@@ -33,3 +34,4 @@ EOF
ARBITRARY3
meep
)
+'
diff --git a/t/chainlint/subshell-one-liner.expect b/t/chainlint/subshell-one-liner.expect
index 8f694990e8..214316c6a0 100644
--- a/t/chainlint/subshell-one-liner.expect
+++ b/t/chainlint/subshell-one-liner.expect
@@ -1,19 +1,19 @@
-(
- (foo && bar) &&
- (foo && bar) |
- (foo && bar) >baz &&
-
- (foo; ?!AMP?! bar) &&
- (foo; ?!AMP?! bar) |
- (foo; ?!AMP?! bar) >baz &&
-
- (foo || exit 1) &&
- (foo || exit 1) |
- (foo || exit 1) >baz &&
-
- (foo && bar) ?!AMP?!
-
- (foo && bar; ?!AMP?! baz) ?!AMP?!
-
- foobar
-)
+2 (
+3 (foo && bar) &&
+4 (foo && bar) |
+5 (foo && bar) >baz &&
+6
+7 (foo; ?!AMP?! bar) &&
+8 (foo; ?!AMP?! bar) |
+9 (foo; ?!AMP?! bar) >baz &&
+10
+11 (foo || exit 1) &&
+12 (foo || exit 1) |
+13 (foo || exit 1) >baz &&
+14
+15 (foo && bar) ?!AMP?!
+16
+17 (foo && bar; ?!AMP?! baz) ?!AMP?!
+18
+19 foobar
+20 )
diff --git a/t/chainlint/subshell-one-liner.test b/t/chainlint/subshell-one-liner.test
index 37fa643c20..dac536afcc 100644
--- a/t/chainlint/subshell-one-liner.test
+++ b/t/chainlint/subshell-one-liner.test
@@ -1,3 +1,4 @@
+test_expect_success 'subshell-one-liner' '
(
# LINT: nested one-liner subshell
(foo && bar) &&
@@ -22,3 +23,4 @@
foobar
)
+'
diff --git a/t/chainlint/t7900-subtree.expect b/t/chainlint/t7900-subtree.expect
index 02f3129232..9e60338bcf 100644
--- a/t/chainlint/t7900-subtree.expect
+++ b/t/chainlint/t7900-subtree.expect
@@ -1,22 +1,22 @@
-(
- chks="sub1
-sub2
-sub3
-sub4" &&
- chks_sub=$(cat <<TXT | sed "s,^,sub dir/,"
-$chks
-TXT
-) &&
- chkms="main-sub1
-main-sub2
-main-sub3
-main-sub4" &&
- chkms_sub=$(cat <<TXT | sed "s,^,sub dir/,"
-$chkms
-TXT
-) &&
-
- subfiles=$(git ls-files) &&
- check_equal "$subfiles" "$chkms
-$chks"
-)
+2 (
+3 chks="sub1
+4 sub2
+5 sub3
+6 sub4" &&
+7 chks_sub=$(cat <<TXT | sed "s,^,sub dir/,"
+8 $chks
+9 TXT
+10 ) &&
+11 chkms="main-sub1
+12 main-sub2
+13 main-sub3
+14 main-sub4" &&
+15 chkms_sub=$(cat <<TXT | sed "s,^,sub dir/,"
+16 $chkms
+17 TXT
+18 ) &&
+19
+20 subfiles=$(git ls-files) &&
+21 check_equal "$subfiles" "$chkms
+22 $chks"
+23 )
diff --git a/t/chainlint/t7900-subtree.test b/t/chainlint/t7900-subtree.test
index 02f3129232..1f4f03300f 100644
--- a/t/chainlint/t7900-subtree.test
+++ b/t/chainlint/t7900-subtree.test
@@ -1,3 +1,4 @@
+test_expect_success 't7900-subtree' '
(
chks="sub1
sub2
@@ -20,3 +21,4 @@ TXT
check_equal "$subfiles" "$chkms
$chks"
)
+'
diff --git a/t/chainlint/token-pasting.expect b/t/chainlint/token-pasting.expect
index 6a387917a7..64f3235d26 100644
--- a/t/chainlint/token-pasting.expect
+++ b/t/chainlint/token-pasting.expect
@@ -1,27 +1,27 @@
-git config filter.rot13.smudge ./rot13.sh &&
-git config filter.rot13.clean ./rot13.sh &&
-
-{
- echo "*.t filter=rot13" ?!AMP?!
- echo "*.i ident"
-} >.gitattributes &&
-
-{
- echo a b c d e f g h i j k l m ?!AMP?!
- echo n o p q r s t u v w x y z ?!AMP?!
- echo '$Id$'
-} >test &&
-cat test >test.t &&
-cat test >test.o &&
-cat test >test.i &&
-git add test test.t test.i &&
-rm -f test test.t test.i &&
-git checkout -- test test.t test.i &&
-
-echo "content-test2" >test2.o &&
-echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!AMP?!
-
-downstream_url_for_sed=$(
- printf "%sn" "$downstream_url" |
- sed -e 's/\/\\/g' -e 's/[[/.*^$]/\&/g'
-)
+2 git config filter.rot13.smudge ./rot13.sh &&
+3 git config filter.rot13.clean ./rot13.sh &&
+4
+5 {
+6 echo "*.t filter=rot13" ?!AMP?!
+7 echo "*.i ident"
+8 } >.gitattributes &&
+9
+10 {
+11 echo a b c d e f g h i j k l m ?!AMP?!
+12 echo n o p q r s t u v w x y z ?!AMP?!
+13 echo '$Id$'
+14 } >test &&
+15 cat test >test.t &&
+16 cat test >test.o &&
+17 cat test >test.i &&
+18 git add test test.t test.i &&
+19 rm -f test test.t test.i &&
+20 git checkout -- test test.t test.i &&
+21
+22 echo "content-test2" >test2.o &&
+23 echo "content-test3 - filename with special characters" >"test3 'sq',$x=.o" ?!AMP?!
+24
+25 downstream_url_for_sed=$(
+26 printf "%sn" "$downstream_url" |
+27 sed -e 's/\/\\/g' -e 's/[[/.*^$]/\&/g'
+28 )
diff --git a/t/chainlint/token-pasting.test b/t/chainlint/token-pasting.test
index b4610ce815..590914b733 100644
--- a/t/chainlint/token-pasting.test
+++ b/t/chainlint/token-pasting.test
@@ -1,3 +1,4 @@
+test_expect_success 'token-pasting' '
# LINT: single token; composite of multiple strings
git config filter.rot13.smudge ./rot13.sh &&
git config filter.rot13.clean ./rot13.sh &&
@@ -30,3 +31,4 @@ downstream_url_for_sed=$(
# LINT: exit/enter string context; "&" inside string not command terminator
sed -e '\''s/\\/\\\\/g'\'' -e '\''s/[[/.*^$]/\\&/g'\''
)
+'
diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect
index 7c30a1a024..f78e23cb63 100644
--- a/t/chainlint/unclosed-here-doc-indent.expect
+++ b/t/chainlint/unclosed-here-doc-indent.expect
@@ -1,4 +1,4 @@
-command_which_is_run &&
-cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! &&
-we forget to end the here-doc
-command_which_is_gobbled
+2 command_which_is_run &&
+3 cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! &&
+4 we forget to end the here-doc
+5 command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc-indent.test b/t/chainlint/unclosed-here-doc-indent.test
index 5c841a9dfd..7ac9d0f7d7 100644
--- a/t/chainlint/unclosed-here-doc-indent.test
+++ b/t/chainlint/unclosed-here-doc-indent.test
@@ -1,4 +1,6 @@
+test_expect_success 'unclosed-here-doc-indent' '
command_which_is_run &&
cat >expect <<-\EOF &&
we forget to end the here-doc
command_which_is_gobbled
+'
diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect
index d65e50f78d..51304672cf 100644
--- a/t/chainlint/unclosed-here-doc.expect
+++ b/t/chainlint/unclosed-here-doc.expect
@@ -1,7 +1,7 @@
-command_which_is_run &&
-cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! &&
- we try to end the here-doc below,
- but the indentation throws us off
- since the operator is not "<<-".
- EOF
-command_which_is_gobbled
+2 command_which_is_run &&
+3 cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! &&
+4 we try to end the here-doc below,
+5 but the indentation throws us off
+6 since the operator is not "<<-".
+7 EOF
+8 command_which_is_gobbled
diff --git a/t/chainlint/unclosed-here-doc.test b/t/chainlint/unclosed-here-doc.test
index 69d3786c34..68e78f06f3 100644
--- a/t/chainlint/unclosed-here-doc.test
+++ b/t/chainlint/unclosed-here-doc.test
@@ -1,3 +1,4 @@
+test_expect_success 'unclosed-here-doc' '
command_which_is_run &&
cat >expect <<\EOF &&
we try to end the here-doc below,
@@ -5,3 +6,4 @@ cat >expect <<\EOF &&
since the operator is not "<<-".
EOF
command_which_is_gobbled
+'
diff --git a/t/chainlint/while-loop.expect b/t/chainlint/while-loop.expect
index 06c1567f48..5ffabd5a93 100644
--- a/t/chainlint/while-loop.expect
+++ b/t/chainlint/while-loop.expect
@@ -1,14 +1,14 @@
-(
- while true
- do
- echo foo ?!AMP?!
- cat <<-\EOF ?!LOOP?!
- bar
- EOF
- done ?!AMP?!
-
- while true; do
- echo foo &&
- cat bar ?!LOOP?!
- done
-)
+2 (
+3 while true
+4 do
+5 echo foo ?!AMP?!
+6 cat <<-\EOF ?!LOOP?!
+7 bar
+8 EOF
+9 done ?!AMP?!
+10
+11 while true; do
+12 echo foo &&
+13 cat bar ?!LOOP?!
+14 done
+15 )
diff --git a/t/chainlint/while-loop.test b/t/chainlint/while-loop.test
index d09fb016e4..33a201906a 100644
--- a/t/chainlint/while-loop.test
+++ b/t/chainlint/while-loop.test
@@ -1,3 +1,4 @@
+test_expect_success 'while-loop' '
(
# LINT: "while", "do", "done" do not need "&&"
while true
@@ -17,3 +18,4 @@
cat bar
done
)
+'
diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
deleted file mode 100644
index c03cfa5ecf..0000000000
--- a/t/helper/test-oidmap.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#define USE_THE_REPOSITORY_VARIABLE
-
-#include "test-tool.h"
-#include "hex.h"
-#include "object-name.h"
-#include "oidmap.h"
-#include "repository.h"
-#include "setup.h"
-#include "strbuf.h"
-#include "string-list.h"
-
-/* key is an oid and value is a name (could be a refname for example) */
-struct test_entry {
- struct oidmap_entry entry;
- char name[FLEX_ARRAY];
-};
-
-#define DELIM " \t\r\n"
-
-/*
- * Read stdin line by line and print result of commands to stdout:
- *
- * hash oidkey -> sha1hash(oidkey)
- * put oidkey namevalue -> NULL / old namevalue
- * get oidkey -> NULL / namevalue
- * remove oidkey -> NULL / old namevalue
- * iterate -> oidkey1 namevalue1\noidkey2 namevalue2\n...
- *
- */
-int cmd__oidmap(int argc UNUSED, const char **argv UNUSED)
-{
- struct string_list parts = STRING_LIST_INIT_NODUP;
- struct strbuf line = STRBUF_INIT;
- struct oidmap map = OIDMAP_INIT;
-
- setup_git_directory();
-
- /* init oidmap */
- oidmap_init(&map, 0);
-
- /* process commands from stdin */
- while (strbuf_getline(&line, stdin) != EOF) {
- char *cmd, *p1, *p2;
- struct test_entry *entry;
- struct object_id oid;
-
- /* break line into command and up to two parameters */
- string_list_setlen(&parts, 0);
- string_list_split_in_place(&parts, line.buf, DELIM, 2);
- string_list_remove_empty_items(&parts, 0);
-
- /* ignore empty lines */
- if (!parts.nr)
- continue;
- if (!*parts.items[0].string || *parts.items[0].string == '#')
- continue;
-
- cmd = parts.items[0].string;
- p1 = parts.nr >= 1 ? parts.items[1].string : NULL;
- p2 = parts.nr >= 2 ? parts.items[2].string : NULL;
-
- if (!strcmp("put", cmd) && p1 && p2) {
-
- if (repo_get_oid(the_repository, p1, &oid)) {
- printf("Unknown oid: %s\n", p1);
- continue;
- }
-
- /* create entry with oid_key = p1, name_value = p2 */
- FLEX_ALLOC_STR(entry, name, p2);
- oidcpy(&entry->entry.oid, &oid);
-
- /* add / replace entry */
- entry = oidmap_put(&map, entry);
-
- /* print and free replaced entry, if any */
- puts(entry ? entry->name : "NULL");
- free(entry);
-
- } else if (!strcmp("get", cmd) && p1) {
-
- if (repo_get_oid(the_repository, p1, &oid)) {
- printf("Unknown oid: %s\n", p1);
- continue;
- }
-
- /* lookup entry in oidmap */
- entry = oidmap_get(&map, &oid);
-
- /* print result */
- puts(entry ? entry->name : "NULL");
-
- } else if (!strcmp("remove", cmd) && p1) {
-
- if (repo_get_oid(the_repository, p1, &oid)) {
- printf("Unknown oid: %s\n", p1);
- continue;
- }
-
- /* remove entry from oidmap */
- entry = oidmap_remove(&map, &oid);
-
- /* print result and free entry*/
- puts(entry ? entry->name : "NULL");
- free(entry);
-
- } else if (!strcmp("iterate", cmd)) {
-
- struct oidmap_iter iter;
- oidmap_iter_init(&map, &iter);
- while ((entry = oidmap_iter_next(&iter)))
- printf("%s %s\n", oid_to_hex(&entry->entry.oid), entry->name);
-
- } else {
-
- printf("Unknown command %s\n", cmd);
-
- }
- }
-
- string_list_clear(&parts, 0);
- strbuf_release(&line);
- oidmap_free(&map, 1);
- return 0;
-}
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 9160bc5da6..aa6538a8da 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -5,7 +5,6 @@
int cmd__reftable(int argc, const char **argv)
{
/* test from simple to complex. */
- record_test_main(argc, argv);
block_test_main(argc, argv);
tree_test_main(argc, argv);
pq_test_main(argc, argv);
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 93436a82ae..da3e69128a 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -44,7 +44,6 @@ static struct test_cmd cmds[] = {
{ "mergesort", cmd__mergesort },
{ "mktemp", cmd__mktemp },
{ "oid-array", cmd__oid_array },
- { "oidmap", cmd__oidmap },
{ "online-cpus", cmd__online_cpus },
{ "pack-mtimes", cmd__pack_mtimes },
{ "parse-options", cmd__parse_options },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index d9033d14e1..642a34578c 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -37,7 +37,6 @@ int cmd__lazy_init_name_hash(int argc, const char **argv);
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__oidmap(int argc, const char **argv);
int cmd__online_cpus(int argc, const char **argv);
int cmd__pack_mtimes(int argc, const char **argv);
int cmd__parse_options(int argc, const char **argv);
diff --git a/t/lib-bundle-uri-protocol.sh b/t/lib-bundle-uri-protocol.sh
index a4a1af8d02..de09b6b02e 100644
--- a/t/lib-bundle-uri-protocol.sh
+++ b/t/lib-bundle-uri-protocol.sh
@@ -18,7 +18,7 @@ git)
start_git_daemon --export-all --enable=receive-pack
BUNDLE_URI_PARENT="$GIT_DAEMON_DOCUMENT_ROOT_PATH/parent"
BUNDLE_URI_REPO_URI="$GIT_DAEMON_URL/parent"
- BUNDLE_URI_BUNDLE_URI="https://example.com/fake.bdl"
+ BUNDLE_URI_BUNDLE_URI="$BUNDLE_URI_REPO_URI/fake.bdl"
test_set_prereq BUNDLE_URI_GIT
;;
http)
@@ -26,7 +26,7 @@ http)
start_httpd
BUNDLE_URI_PARENT="$HTTPD_DOCUMENT_ROOT_PATH/http_parent"
BUNDLE_URI_REPO_URI="$HTTPD_URL/smart/http_parent"
- BUNDLE_URI_BUNDLE_URI="https://example.com/fake.bdl"
+ BUNDLE_URI_BUNDLE_URI="$BUNDLE_URI_REPO_URL/fake.bdl"
test_set_prereq BUNDLE_URI_HTTP
;;
*)
diff --git a/t/t0016-oidmap.sh b/t/t0016-oidmap.sh
deleted file mode 100755
index 0faef1f4f1..0000000000
--- a/t/t0016-oidmap.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/bin/sh
-
-test_description='test oidmap'
-
-TEST_PASSES_SANITIZE_LEAK=true
-. ./test-lib.sh
-
-# This purposefully is very similar to t0011-hashmap.sh
-
-test_oidmap () {
- echo "$1" | test-tool oidmap $3 >actual &&
- echo "$2" >expect &&
- test_cmp expect actual
-}
-
-
-test_expect_success 'setup' '
-
- test_commit one &&
- test_commit two &&
- test_commit three &&
- test_commit four
-
-'
-
-test_expect_success 'put' '
-
-test_oidmap "put one 1
-put two 2
-put invalidOid 4
-put three 3" "NULL
-NULL
-Unknown oid: invalidOid
-NULL"
-
-'
-
-test_expect_success 'replace' '
-
-test_oidmap "put one 1
-put two 2
-put three 3
-put invalidOid 4
-put two deux
-put one un" "NULL
-NULL
-NULL
-Unknown oid: invalidOid
-2
-1"
-
-'
-
-test_expect_success 'get' '
-
-test_oidmap "put one 1
-put two 2
-put three 3
-get two
-get four
-get invalidOid
-get one" "NULL
-NULL
-NULL
-2
-NULL
-Unknown oid: invalidOid
-1"
-
-'
-
-test_expect_success 'remove' '
-
-test_oidmap "put one 1
-put two 2
-put three 3
-remove one
-remove two
-remove invalidOid
-remove four" "NULL
-NULL
-NULL
-1
-2
-Unknown oid: invalidOid
-NULL"
-
-'
-
-test_expect_success 'iterate' '
- test-tool oidmap >actual.raw <<-\EOF &&
- put one 1
- put two 2
- put three 3
- iterate
- EOF
-
- # sort "expect" too so we do not rely on the order of particular oids
- sort >expect <<-EOF &&
- NULL
- NULL
- NULL
- $(git rev-parse one) 1
- $(git rev-parse two) 2
- $(git rev-parse three) 3
- EOF
-
- sort <actual.raw >actual &&
- test_cmp expect actual
-'
-
-test_done
diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh
index b2a771ff2b..20df336cc3 100755
--- a/t/t0600-reffiles-backend.sh
+++ b/t/t0600-reffiles-backend.sh
@@ -91,82 +91,82 @@ test_expect_success 'empty directory should not fool 1-arg delete' '
git update-ref --stdin
'
-test_expect_success 'non-empty directory blocks create' '
+test_expect_success 'non-empty directory blocks create' - <<\EOT
prefix=refs/ne-create &&
mkdir -p .git/$prefix/foo/bar &&
: >.git/$prefix/foo/bar/baz.lock &&
test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/foo': there is a non-empty directory '.git/$prefix/foo' blocking reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/foo $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/foo $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'broken reference blocks create' '
+test_expect_success 'broken reference blocks create' - <<\EOT
prefix=refs/broken-create &&
mkdir -p .git/$prefix &&
echo "gobbledigook" >.git/$prefix/foo &&
test_when_finished "rm -f .git/$prefix/foo" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/foo $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/foo $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'non-empty directory blocks indirect create' '
+test_expect_success 'non-empty directory blocks indirect create' - <<\EOT
prefix=refs/ne-indirect-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
mkdir -p .git/$prefix/foo/bar &&
: >.git/$prefix/foo/bar/baz.lock &&
test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/symref': there is a non-empty directory '.git/$prefix/foo' blocking reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/symref $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/symref $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'broken reference blocks indirect create' '
+test_expect_success 'broken reference blocks indirect create' - <<\EOT
prefix=refs/broken-indirect-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
echo "gobbledigook" >.git/$prefix/foo &&
test_when_finished "rm -f .git/$prefix/foo" &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/symref $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo': reference broken
EOF
printf "%s\n" "update $prefix/symref $D $C" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
test_expect_success 'no bogus intermediate values during delete' '
prefix=refs/slow-transaction &&
@@ -224,7 +224,7 @@ test_expect_success 'no bogus intermediate values during delete' '
test_must_fail git rev-parse --verify --quiet $prefix/foo
'
-test_expect_success 'delete fails cleanly if packed-refs file is locked' '
+test_expect_success 'delete fails cleanly if packed-refs file is locked' - <<\EOT
prefix=refs/locked-packed-refs &&
# Set up a reference with differing loose and packed versions:
git update-ref $prefix/foo $C &&
@@ -236,9 +236,9 @@ test_expect_success 'delete fails cleanly if packed-refs file is locked' '
test_when_finished "rm -f .git/packed-refs.lock" &&
test_must_fail git update-ref -d $prefix/foo >out 2>err &&
git for-each-ref $prefix >actual &&
- test_grep "Unable to create $SQ.*packed-refs.lock$SQ: " err &&
+ test_grep "Unable to create '.*packed-refs.lock': " err &&
test_cmp unchanged actual
-'
+EOT
test_expect_success 'delete fails cleanly if packed-refs.new write fails' '
# Setup and expectations are similar to the test above.
diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh
index d0d7e80b49..84922153ab 100755
--- a/t/t0612-reftable-jgit-compatibility.sh
+++ b/t/t0612-reftable-jgit-compatibility.sh
@@ -11,6 +11,7 @@ export GIT_TEST_DEFAULT_REF_FORMAT
GIT_TEST_SPLIT_INDEX=0
export GIT_TEST_SPLIT_INDEX
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
if ! test_have_prereq JGIT
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
index e2708e11d5..b1c6c97524 100755
--- a/t/t0613-reftable-write-options.sh
+++ b/t/t0613-reftable-write-options.sh
@@ -16,6 +16,7 @@ export GIT_TEST_DEFAULT_HASH
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'default write options' '
diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
index 2f1ae5fd3b..a2c0e1b4dc 100755
--- a/t/t1092-sparse-checkout-compatibility.sh
+++ b/t/t1092-sparse-checkout-compatibility.sh
@@ -159,7 +159,10 @@ init_repos () {
git -C sparse-checkout sparse-checkout set deep &&
git -C sparse-index sparse-checkout init --cone --sparse-index &&
test_cmp_config -C sparse-index true index.sparse &&
- git -C sparse-index sparse-checkout set deep
+ git -C sparse-index sparse-checkout set deep &&
+
+ # Disable this message to keep stderr the same.
+ git -C sparse-index config advice.sparseIndexExpanded false
}
init_repos_as_submodules () {
@@ -2331,4 +2334,15 @@ test_expect_success 'sparse-index is not expanded: check-attr' '
ensure_not_expanded check-attr -a --cached -- folder1/a
'
+test_expect_success 'advice.sparseIndexExpanded' '
+ init_repos &&
+
+ git -C sparse-index config --unset advice.sparseIndexExpanded &&
+ git -C sparse-index sparse-checkout set deep/deeper1 &&
+ mkdir -p sparse-index/deep/deeper2/deepest &&
+ touch sparse-index/deep/deeper2/deepest/bogus &&
+ git -C sparse-index status 2>err &&
+ grep "The sparse index is expanding to a full index" err
+'
+
test_done
diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh
index 67ebd81a4c..df90112618 100755
--- a/t/t1404-update-ref-errors.sh
+++ b/t/t1404-update-ref-errors.sh
@@ -100,13 +100,13 @@ df_test() {
printf "%s\n" "delete $delname" "create $addname $D"
fi >commands &&
test_must_fail git update-ref --stdin <commands 2>output.err &&
- grep -E "fatal:( cannot lock ref $SQ$addname$SQ:)? $SQ$delref$SQ exists; cannot create $SQ$addref$SQ" output.err &&
+ grep -E "fatal:( cannot lock ref '$addname':)? '$delref' exists; cannot create '$addref'" output.err &&
printf "%s\n" "$C $delref" >expected-refs &&
git for-each-ref --format="%(objectname) %(refname)" $prefix/r >actual-refs &&
test_cmp expected-refs actual-refs
}
-test_expect_success 'setup' '
+test_expect_success 'setup' - <<\EOT
git commit --allow-empty -m Initial &&
C=$(git rev-parse HEAD) &&
@@ -114,283 +114,283 @@ test_expect_success 'setup' '
D=$(git rev-parse HEAD) &&
git commit --allow-empty -m Third &&
E=$(git rev-parse HEAD)
-'
+EOT
-test_expect_success 'existing loose ref is a simple prefix of new' '
+test_expect_success 'existing loose ref is a simple prefix of new' - <<\EOT
prefix=refs/1l &&
test_update_rejected "a c e" false "b c/x d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x'"
-'
+EOT
-test_expect_success 'existing packed ref is a simple prefix of new' '
+test_expect_success 'existing packed ref is a simple prefix of new' - <<\EOT
prefix=refs/1p &&
test_update_rejected "a c e" true "b c/x d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x'"
-'
+EOT
-test_expect_success 'existing loose ref is a deeper prefix of new' '
+test_expect_success 'existing loose ref is a deeper prefix of new' - <<\EOT
prefix=refs/2l &&
test_update_rejected "a c e" false "b c/x/y d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x/y'"
-'
+EOT
-test_expect_success 'existing packed ref is a deeper prefix of new' '
+test_expect_success 'existing packed ref is a deeper prefix of new' - <<\EOT
prefix=refs/2p &&
test_update_rejected "a c e" true "b c/x/y d" \
- "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ"
+ "'$prefix/c' exists; cannot create '$prefix/c/x/y'"
-'
+EOT
-test_expect_success 'new ref is a simple prefix of existing loose' '
+test_expect_success 'new ref is a simple prefix of existing loose' - <<\EOT
prefix=refs/3l &&
test_update_rejected "a c/x e" false "b c d" \
- "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'new ref is a simple prefix of existing packed' '
+test_expect_success 'new ref is a simple prefix of existing packed' - <<\EOT
prefix=refs/3p &&
test_update_rejected "a c/x e" true "b c d" \
- "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'new ref is a deeper prefix of existing loose' '
+test_expect_success 'new ref is a deeper prefix of existing loose' - <<\EOT
prefix=refs/4l &&
test_update_rejected "a c/x/y e" false "b c d" \
- "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x/y' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'new ref is a deeper prefix of existing packed' '
+test_expect_success 'new ref is a deeper prefix of existing packed' - <<\EOT
prefix=refs/4p &&
test_update_rejected "a c/x/y e" true "b c d" \
- "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ"
+ "'$prefix/c/x/y' exists; cannot create '$prefix/c'"
-'
+EOT
-test_expect_success 'one new ref is a simple prefix of another' '
+test_expect_success 'one new ref is a simple prefix of another' - <<\EOT
prefix=refs/5 &&
test_update_rejected "a e" false "b c c/x d" \
- "cannot process $SQ$prefix/c$SQ and $SQ$prefix/c/x$SQ at the same time"
+ "cannot process '$prefix/c' and '$prefix/c/x' at the same time"
-'
+EOT
-test_expect_success 'D/F conflict prevents add long + delete short' '
+test_expect_success 'D/F conflict prevents add long + delete short' - <<\EOT
df_test refs/df-al-ds --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents add short + delete long' '
+test_expect_success 'D/F conflict prevents add short + delete long' - <<\EOT
df_test refs/df-as-dl --add-del foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents delete long + add short' '
+test_expect_success 'D/F conflict prevents delete long + add short' - <<\EOT
df_test refs/df-dl-as --del-add foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents delete short + add long' '
+test_expect_success 'D/F conflict prevents delete short + add long' - <<\EOT
df_test refs/df-ds-al --del-add foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents add long + delete short packed' '
+test_expect_success 'D/F conflict prevents add long + delete short packed' - <<\EOT
df_test refs/df-al-dsp --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents add short + delete long packed' '
+test_expect_success 'D/F conflict prevents add short + delete long packed' - <<\EOT
df_test refs/df-as-dlp --pack --add-del foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents delete long packed + add short' '
+test_expect_success 'D/F conflict prevents delete long packed + add short' - <<\EOT
df_test refs/df-dlp-as --pack --del-add foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents delete short packed + add long' '
+test_expect_success 'D/F conflict prevents delete short packed + add long' - <<\EOT
df_test refs/df-dsp-al --pack --del-add foo foo/bar
-'
+EOT
# Try some combinations involving symbolic refs...
-test_expect_success 'D/F conflict prevents indirect add long + delete short' '
+test_expect_success 'D/F conflict prevents indirect add long + delete short' - <<\EOT
df_test refs/df-ial-ds --sym-add --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' '
+test_expect_success 'D/F conflict prevents indirect add long + indirect delete short' - <<\EOT
df_test refs/df-ial-ids --sym-add --sym-del --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' '
+test_expect_success 'D/F conflict prevents indirect add short + indirect delete long' - <<\EOT
df_test refs/df-ias-idl --sym-add --sym-del --add-del foo foo/bar
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' '
+test_expect_success 'D/F conflict prevents indirect delete long + indirect add short' - <<\EOT
df_test refs/df-idl-ias --sym-add --sym-del --del-add foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add long + delete short packed' '
+test_expect_success 'D/F conflict prevents indirect add long + delete short packed' - <<\EOT
df_test refs/df-ial-dsp --sym-add --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' '
+test_expect_success 'D/F conflict prevents indirect add long + indirect delete short packed' - <<\EOT
df_test refs/df-ial-idsp --sym-add --sym-del --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents add long + indirect delete short packed' '
+test_expect_success 'D/F conflict prevents add long + indirect delete short packed' - <<\EOT
df_test refs/df-al-idsp --sym-del --pack --add-del foo/bar foo
-'
+EOT
-test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' '
+test_expect_success 'D/F conflict prevents indirect delete long packed + indirect add short' - <<\EOT
df_test refs/df-idlp-ias --sym-add --sym-del --pack --del-add foo/bar foo
-'
+EOT
# Test various errors when reading the old values of references...
-test_expect_success 'missing old value blocks update' '
+test_expect_success 'missing old value blocks update' - <<\EOT
prefix=refs/missing-update &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/foo': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/foo $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks update' '
+test_expect_success 'incorrect old value blocks update' - <<\EOT
prefix=refs/incorrect-update &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/foo': is at $C but expected $D
EOF
printf "%s\n" "update $prefix/foo $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'existing old value blocks create' '
+test_expect_success 'existing old value blocks create' - <<\EOT
prefix=refs/existing-create &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: reference already exists
+ fatal: cannot lock ref '$prefix/foo': reference already exists
EOF
printf "%s\n" "create $prefix/foo $E" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks delete' '
+test_expect_success 'incorrect old value blocks delete' - <<\EOT
prefix=refs/incorrect-delete &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/foo': is at $C but expected $D
EOF
printf "%s\n" "delete $prefix/foo $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'missing old value blocks indirect update' '
+test_expect_success 'missing old value blocks indirect update' - <<\EOT
prefix=refs/missing-indirect-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ
+ fatal: cannot lock ref '$prefix/symref': unable to resolve reference '$prefix/foo'
EOF
printf "%s\n" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect update' '
+test_expect_success 'incorrect old value blocks indirect update' - <<\EOT
prefix=refs/incorrect-indirect-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'existing old value blocks indirect create' '
+test_expect_success 'existing old value blocks indirect create' - <<\EOT
prefix=refs/existing-indirect-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists
+ fatal: cannot lock ref '$prefix/symref': reference already exists
EOF
printf "%s\n" "create $prefix/symref $E" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect delete' '
+test_expect_success 'incorrect old value blocks indirect delete' - <<\EOT
prefix=refs/incorrect-indirect-delete &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "delete $prefix/symref $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'missing old value blocks indirect no-deref update' '
+test_expect_success 'missing old value blocks indirect no-deref update' - <<\EOT
prefix=refs/missing-noderef-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: reference is missing but expected $D
+ fatal: cannot lock ref '$prefix/symref': reference is missing but expected $D
EOF
printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect no-deref update' '
+test_expect_success 'incorrect old value blocks indirect no-deref update' - <<\EOT
prefix=refs/incorrect-noderef-update &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'existing old value blocks indirect no-deref create' '
+test_expect_success 'existing old value blocks indirect no-deref create' - <<\EOT
prefix=refs/existing-noderef-create &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists
+ fatal: cannot lock ref '$prefix/symref': reference already exists
EOF
printf "%s\n" "option no-deref" "create $prefix/symref $E" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
-test_expect_success 'incorrect old value blocks indirect no-deref delete' '
+test_expect_success 'incorrect old value blocks indirect no-deref delete' - <<\EOT
prefix=refs/incorrect-noderef-delete &&
git symbolic-ref $prefix/symref $prefix/foo &&
git update-ref $prefix/foo $C &&
cat >expected <<-EOF &&
- fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D
+ fatal: cannot lock ref '$prefix/symref': is at $C but expected $D
EOF
printf "%s\n" "option no-deref" "delete $prefix/symref $D" |
test_must_fail git update-ref --stdin 2>output.err &&
test_cmp expected output.err
-'
+EOT
test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 2e7c0e1648..9d693eb57f 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -230,6 +230,16 @@ test_expect_success 'push with negotiation proceeds anyway even if negotiation f
test_grep "push negotiation failed" err
'
+test_expect_success 'push deletion with negotiation' '
+ mk_empty testrepo &&
+ git push testrepo $the_first_commit:refs/heads/master &&
+ git -c push.negotiate=1 push testrepo \
+ :master $the_first_commit:refs/heads/next 2>errors-2 &&
+ test_grep ! "negotiate-only needs one or " errors-2 &&
+ git -c push.negotiate=1 push testrepo :next 2>errors-1 &&
+ test_grep ! "negotiate-only needs one or " errors-1
+'
+
test_expect_success 'push with negotiation does not attempt to fetch submodules' '
mk_empty submodule_upstream &&
test_commit -C submodule_upstream submodule_commit &&
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index 0247137cb3..17d7257892 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -2,6 +2,9 @@
test_description='detect some push errors early (before contacting remote)'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
@@ -38,6 +41,20 @@ test_expect_success 'detect missing sha1 expressions early' '
test_cmp expect rp-ran
'
+# We use an existing local_ref, since it follows a different flow in
+# 'builtin/push.c:set_refspecs()' and we want to test that regression.
+test_expect_success 'detect empty remote with existing local ref' '
+ test_must_fail git push "" main 2> stderr &&
+ grep "fatal: bad repository ${SQ}${SQ}" stderr
+'
+
+# While similar to the previous test, here we want to ensure that
+# even targeted refspecs are handled.
+test_expect_success 'detect empty remote with targeted refspec' '
+ test_must_fail git push "" HEAD:refs/heads/main 2> stderr &&
+ grep "fatal: bad repository ${SQ}${SQ}" stderr
+'
+
test_expect_success 'detect ambiguous refs early' '
git branch foo &&
git tag foo &&
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index a623a1058c..7b5ab0eae1 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -643,7 +643,6 @@ test_expect_success 'clone empty SHA-256 repository with protocol v0' '
test_expect_success 'passing hostname resolution information works' '
BOGUS_HOST=gitbogusexamplehost.invalid &&
BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT &&
- test_must_fail git ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null &&
git -c "http.curloptResolve=$BOGUS_HOST:$LIB_HTTPD_PORT:127.0.0.1" ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null
'
diff --git a/t/t5553-set-upstream.sh b/t/t5553-set-upstream.sh
index 48050162c2..70e3376d31 100755
--- a/t/t5553-set-upstream.sh
+++ b/t/t5553-set-upstream.sh
@@ -73,10 +73,10 @@ test_expect_success 'fetch --set-upstream main:other does not set the branch oth
check_config_missing other2
'
-test_expect_success 'fetch --set-upstream http://nosuchdomain.example.com fails with invalid url' '
+test_expect_success 'fetch --set-upstream ./does-not-exist fails with invalid url' '
# main explicitly not cleared, we check that it is not touched from previous value
clear_config other other2 &&
- test_must_fail git fetch --set-upstream http://nosuchdomain.example.com &&
+ test_must_fail git fetch --set-upstream ./does-not-exist &&
check_config main upstream refs/heads/other &&
check_config_missing other &&
check_config_missing other2
@@ -143,10 +143,10 @@ test_expect_success 'pull --set-upstream upstream tag does not set the tag' '
check_config_missing three
'
-test_expect_success 'pull --set-upstream http://nosuchdomain.example.com fails with invalid url' '
+test_expect_success 'pull --set-upstream ./does-not-exist fails with invalid url' '
# main explicitly not cleared, we check that it is not touched from previous value
clear_config other other2 three &&
- test_must_fail git pull --set-upstream http://nosuchdomain.example.com &&
+ test_must_fail git pull --set-upstream ./does-not-exist &&
check_config main upstream refs/heads/other &&
check_config_missing other &&
check_config_missing other2 &&
diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh
index 4af796de67..ba03f6a09f 100755
--- a/t/t5563-simple-http-auth.sh
+++ b/t/t5563-simple-http-auth.sh
@@ -178,6 +178,122 @@ test_expect_success 'access using basic auth invalid credentials' '
EOF
'
+test_expect_success 'access using basic proactive auth' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default status=403
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_config_global http.proactiveAuth basic &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=Basic
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using auto proactive auth with basic default' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ username=alice
+ password=secret-passwd
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default status=403
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_config_global http.proactiveAuth auto &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+
+ expect_credential_query store <<-EOF
+ protocol=http
+ host=$HTTPD_DEST
+ username=alice
+ password=secret-passwd
+ EOF
+'
+
+test_expect_success 'access using auto proactive auth with authtype from credential helper' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ capability[]=authtype
+ authtype=Bearer
+ credential=YS1naXQtdG9rZW4=
+ EOF
+
+ # Basic base64(a-git-token)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Bearer YS1naXQtdG9rZW4=
+ EOF
+
+ CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default status=403
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_config_global http.proactiveAuth auto &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+
+ expect_credential_query store <<-EOF
+ capability[]=authtype
+ authtype=Bearer
+ credential=YS1naXQtdG9rZW4=
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+'
+
test_expect_success 'access using basic auth with extra challenges' '
test_when_finished "per_test_cleanup" &&
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index e78315d23d..79e0f19deb 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -671,4 +671,40 @@ test_expect_success 'setup misleading taggerdates' '
check_describe newer-tag-older-commit~1 --contains unique-file~2
+test_expect_success 'describe --dirty with a file with changed stat' '
+ test_when_finished "rm -fr stat-dirty" &&
+ git init stat-dirty &&
+ (
+ cd stat-dirty &&
+
+ echo A >file &&
+ git add file &&
+ git commit -m A &&
+ git tag A -a -m A &&
+ echo "A" >expect &&
+
+ test-tool chmtime -10 file &&
+ git describe --dirty >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'describe --broken --dirty with a file with changed stat' '
+ test_when_finished "rm -fr stat-dirty" &&
+ git init stat-dirty &&
+ (
+ cd stat-dirty &&
+
+ echo A >file &&
+ git add file &&
+ git commit -m A &&
+ git tag A -a -m A &&
+ echo "A" >expect &&
+
+ test-tool chmtime -10 file &&
+ git describe --dirty --broken >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh
index 156a1efacf..9bf9524934 100755
--- a/t/t6406-merge-attr.sh
+++ b/t/t6406-merge-attr.sh
@@ -185,7 +185,7 @@ test_expect_success !WINDOWS 'custom merge driver that is killed with a signal'
>./please-abort &&
echo "* merge=custom" >.gitattributes &&
- test_must_fail git merge main 2>err &&
+ test_expect_code 2 git merge main 2>err &&
grep "^error: failed to execute internal merge" err &&
git ls-files -u >output &&
git diff --name-only HEAD >>output &&
@@ -261,4 +261,44 @@ test_expect_success 'binary files with union attribute' '
grep -i "warning.*cannot merge.*HEAD vs. bin-main" output
'
+test_expect_success !WINDOWS 'custom merge driver that is killed with a signal on recursive merge' '
+ test_when_finished "rm -f output please-abort" &&
+ test_when_finished "git checkout side" &&
+
+ git reset --hard anchor &&
+
+ git checkout -b base-a main^ &&
+ echo base-a >text &&
+ git commit -m base-a text &&
+
+ git checkout -b base-b main^ &&
+ echo base-b >text &&
+ git commit -m base-b text &&
+
+ git checkout -b recursive-a base-a &&
+ test_must_fail git merge base-b &&
+ echo recursive-a >text &&
+ git add text &&
+ git commit -m recursive-a &&
+
+ git checkout -b recursive-b base-b &&
+ test_must_fail git merge base-a &&
+ echo recursive-b >text &&
+ git add text &&
+ git commit -m recursive-b &&
+
+ git config --replace-all \
+ merge.custom.driver "./custom-merge %O %A %B 0 %P %S %X %Y" &&
+ git config --replace-all \
+ merge.custom.name "custom merge driver for testing" &&
+
+ >./please-abort &&
+ echo "* merge=custom" >.gitattributes &&
+ test_expect_code 2 git merge recursive-a 2>err &&
+ grep "error: failed to execute internal merge" err &&
+ git ls-files -u >output &&
+ git diff --name-only HEAD >>output &&
+ test_must_be_empty output
+'
+
test_done
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 58699f8e4e..64a4ab3736 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1299,6 +1299,49 @@ test_expect_success $PREREQ 'utf8 sender is not duplicated' '
test_line_count = 1 msgfrom
'
+test_expect_success $PREREQ 'setup expect for cc list' "
+cat >expected-cc <<\EOF
+!recipient@example.com!
+!author@example.com!
+!one@example.com!
+!os@example.com!
+!odd_?=mail@example.com!
+!doug@example.com!
+!codev@example.com!
+!thor.au@example.com!
+EOF
+"
+
+test_expect_success $PREREQ 'cc list is sanitized' '
+ clean_fake_sendmail &&
+ test_commit weird_cc_body &&
+ test_when_finished "git reset --hard HEAD^" &&
+ git commit --amend -F - <<-EOF &&
+ Test Cc: sanitization.
+
+ Cc: Person, One <one@example.com>
+ Cc: Ronnie O${SQ}Sullivan <os@example.com>
+ Reviewed-by: Füñný Nâmé <odd_?=mail@example.com>
+ Reported-by: bugger on Jira
+ Reported-by: Douglas Reporter <doug@example.com> [from Jira profile]
+ BugID: 12345
+ Co-developed-by: "C. O. Developer" <codev@example.com>
+ Signed-off-by: A. U. Thor <thor.au@example.com>
+ EOF
+ git send-email -1 --to=recipient@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" >actual-show-all-headers &&
+ test_cmp expected-cc commandline1 &&
+ test_grep "^(body) Adding cc: \"Person, One\" <one@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: Ronnie O${SQ}Sullivan <os@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: =?UTF-8?q?F=C3=BC=C3=B1n=C3=BD=20N=C3=A2m=C3=A9?="\
+" <odd_?=mail@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Ignoring Reported-by .* bugger on Jira" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: Douglas Reporter <doug@example.com>" actual-show-all-headers &&
+ test_grep ! "12345" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: \"C. O. Developer\" <codev@example.com>" actual-show-all-headers &&
+ test_grep "^(body) Adding cc: \"A. U. Thor\" <thor.au@example.com>" actual-show-all-headers
+'
+
test_expect_success $PREREQ 'sendemail.composeencoding works' '
clean_fake_sendmail &&
git config sendemail.composeencoding iso-8859-1 &&
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 1ea9f31225..fde9bf54fc 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -872,6 +872,24 @@ test_verify_prereq () {
BUG "'$test_prereq' does not look like a prereq"
}
+# assign the variable named by "$1" with the contents of "$2";
+# if "$2" is "-", then read stdin into "$1" instead
+test_body_or_stdin () {
+ if test "$2" != "-"
+ then
+ eval "$1=\$2"
+ return
+ fi
+
+ # start with a newline, to match hanging newline from open-quote style
+ eval "$1=\$LF"
+ local test_line
+ while IFS= read -r test_line
+ do
+ eval "$1=\${$1}\${test_line}\${LF}"
+ done
+}
+
test_expect_failure () {
test_start_ "$@"
test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
@@ -881,9 +899,11 @@ test_expect_failure () {
export test_prereq
if ! test_skip "$@"
then
+ local test_body
+ test_body_or_stdin test_body "$2"
test -n "$test_skip_test_preamble" ||
- say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $2"
- if test_run_ "$2" expecting_failure
+ say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $test_body"
+ if test_run_ "$test_body" expecting_failure
then
test_known_broken_ok_ "$1"
else
@@ -902,13 +922,15 @@ test_expect_success () {
export test_prereq
if ! test_skip "$@"
then
+ local test_body
+ test_body_or_stdin test_body "$2"
test -n "$test_skip_test_preamble" ||
- say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $2"
- if test_run_ "$2"
+ say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $test_body"
+ if test_run_ "$test_body"
then
test_ok_ "$1"
else
- test_failure_ "$@"
+ test_failure_ "$1" "$test_body"
fi
fi
test_finish_
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 79d3e0e7d9..54247604cb 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -1269,9 +1269,12 @@ check_test_results_san_file_ () {
then
say "As TEST_PASSES_SANITIZE_LEAK=true isn't set the above leak is 'ok' with GIT_TEST_PASSING_SANITIZE_LEAK=check" &&
invert_exit_code=t
- else
- say "With GIT_TEST_SANITIZE_LEAK_LOG=true our logs revealed a memory leak, exit non-zero!" &&
+ elif test "$test_failure" = 0
+ then
+ say "Our logs revealed a memory leak, exit non-zero!" &&
invert_exit_code=t
+ else
+ say "Our logs revealed a memory leak..."
fi
}
@@ -1575,33 +1578,28 @@ then
test_done
fi
- if test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
+ if ! mkdir -p "$TEST_RESULTS_SAN_DIR"
then
- if ! mkdir -p "$TEST_RESULTS_SAN_DIR"
- then
- BAIL_OUT "cannot create $TEST_RESULTS_SAN_DIR"
- fi &&
- TEST_RESULTS_SAN_FILE="$TEST_RESULTS_SAN_DIR/$TEST_RESULTS_SAN_FILE_PFX"
+ BAIL_OUT "cannot create $TEST_RESULTS_SAN_DIR"
+ fi &&
+ TEST_RESULTS_SAN_FILE="$TEST_RESULTS_SAN_DIR/$TEST_RESULTS_SAN_FILE_PFX"
- # In case "test-results" is left over from a previous
- # run: Only report if new leaks show up.
- TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP=$(nr_san_dir_leaks_)
+ # In case "test-results" is left over from a previous
+ # run: Only report if new leaks show up.
+ TEST_RESULTS_SAN_DIR_NR_LEAKS_STARTUP=$(nr_san_dir_leaks_)
- # Don't litter *.leak dirs if there was nothing to report
- test_atexit "rmdir \"$TEST_RESULTS_SAN_DIR\" 2>/dev/null || :"
+ # Don't litter *.leak dirs if there was nothing to report
+ test_atexit "rmdir \"$TEST_RESULTS_SAN_DIR\" 2>/dev/null || :"
+
+ prepend_var LSAN_OPTIONS : dedup_token_length=9999
+ prepend_var LSAN_OPTIONS : log_exe_name=1
+ prepend_var LSAN_OPTIONS : log_path=\"$TEST_RESULTS_SAN_FILE\"
+ export LSAN_OPTIONS
- prepend_var LSAN_OPTIONS : dedup_token_length=9999
- prepend_var LSAN_OPTIONS : log_exe_name=1
- prepend_var LSAN_OPTIONS : log_path=\"$TEST_RESULTS_SAN_FILE\"
- export LSAN_OPTIONS
- fi
elif test "$GIT_TEST_PASSING_SANITIZE_LEAK" = "check" ||
test_bool_env GIT_TEST_PASSING_SANITIZE_LEAK false
then
BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_PASSING_SANITIZE_LEAK=true"
-elif test_bool_env GIT_TEST_SANITIZE_LEAK_LOG false
-then
- BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true"
fi
if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 &&
diff --git a/t/unit-tests/t-oidmap.c b/t/unit-tests/t-oidmap.c
new file mode 100644
index 0000000000..b22e52d08b
--- /dev/null
+++ b/t/unit-tests/t-oidmap.c
@@ -0,0 +1,181 @@
+#include "test-lib.h"
+#include "lib-oid.h"
+#include "oidmap.h"
+#include "hash.h"
+#include "hex.h"
+
+/*
+ * Elements we will put in oidmap structs are made of a key: the entry.oid
+ * field, which is of type struct object_id, and a value: the name field (could
+ * be a refname for example).
+ */
+struct test_entry {
+ struct oidmap_entry entry;
+ char name[FLEX_ARRAY];
+};
+
+static const char *const key_val[][2] = { { "11", "one" },
+ { "22", "two" },
+ { "33", "three" } };
+
+static void setup(void (*f)(struct oidmap *map))
+{
+ struct oidmap map = OIDMAP_INIT;
+ int ret = 0;
+
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++){
+ struct test_entry *entry;
+
+ FLEX_ALLOC_STR(entry, name, key_val[i][1]);
+ if ((ret = get_oid_arbitrary_hex(key_val[i][0], &entry->entry.oid))) {
+ free(entry);
+ break;
+ }
+ entry = oidmap_put(&map, entry);
+ if (!check(entry == NULL))
+ free(entry);
+ }
+
+ if (!ret)
+ f(&map);
+ oidmap_free(&map, 1);
+}
+
+static void t_replace(struct oidmap *map)
+{
+ struct test_entry *entry, *prev;
+
+ FLEX_ALLOC_STR(entry, name, "un");
+ if (get_oid_arbitrary_hex("11", &entry->entry.oid))
+ return;
+ prev = oidmap_put(map, entry);
+ if (!check(prev != NULL))
+ return;
+ check_str(prev->name, "one");
+ free(prev);
+
+ FLEX_ALLOC_STR(entry, name, "deux");
+ if (get_oid_arbitrary_hex("22", &entry->entry.oid))
+ return;
+ prev = oidmap_put(map, entry);
+ if (!check(prev != NULL))
+ return;
+ check_str(prev->name, "two");
+ free(prev);
+}
+
+static void t_get(struct oidmap *map)
+{
+ struct test_entry *entry;
+ struct object_id oid;
+
+ if (get_oid_arbitrary_hex("22", &oid))
+ return;
+ entry = oidmap_get(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "two");
+
+ if (get_oid_arbitrary_hex("44", &oid))
+ return;
+ check(oidmap_get(map, &oid) == NULL);
+
+ if (get_oid_arbitrary_hex("11", &oid))
+ return;
+ entry = oidmap_get(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "one");
+}
+
+static void t_remove(struct oidmap *map)
+{
+ struct test_entry *entry;
+ struct object_id oid;
+
+ if (get_oid_arbitrary_hex("11", &oid))
+ return;
+ entry = oidmap_remove(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "one");
+ check(oidmap_get(map, &oid) == NULL);
+ free(entry);
+
+ if (get_oid_arbitrary_hex("22", &oid))
+ return;
+ entry = oidmap_remove(map, &oid);
+ if (!check(entry != NULL))
+ return;
+ check_str(entry->name, "two");
+ check(oidmap_get(map, &oid) == NULL);
+ free(entry);
+
+ if (get_oid_arbitrary_hex("44", &oid))
+ return;
+ check(oidmap_remove(map, &oid) == NULL);
+}
+
+static int key_val_contains(struct test_entry *entry, char seen[])
+{
+ for (size_t i = 0; i < ARRAY_SIZE(key_val); i++) {
+ struct object_id oid;
+
+ if (get_oid_arbitrary_hex(key_val[i][0], &oid))
+ return -1;
+
+ if (oideq(&entry->entry.oid, &oid)) {
+ if (seen[i])
+ return 2;
+ seen[i] = 1;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void t_iterate(struct oidmap *map)
+{
+ struct oidmap_iter iter;
+ struct test_entry *entry;
+ char seen[ARRAY_SIZE(key_val)] = { 0 };
+ int count = 0;
+
+ oidmap_iter_init(map, &iter);
+ while ((entry = oidmap_iter_next(&iter))) {
+ int ret;
+ if (!check_int((ret = key_val_contains(entry, seen)), ==, 0)) {
+ switch (ret) {
+ case -1:
+ break; /* error message handled by get_oid_arbitrary_hex() */
+ case 1:
+ test_msg("obtained entry was not given in the input\n"
+ " name: %s\n oid: %s\n",
+ entry->name, oid_to_hex(&entry->entry.oid));
+ break;
+ case 2:
+ test_msg("duplicate entry detected\n"
+ " name: %s\n oid: %s\n",
+ entry->name, oid_to_hex(&entry->entry.oid));
+ break;
+ default:
+ test_msg("BUG: invalid return value (%d) from key_val_contains()",
+ ret);
+ break;
+ }
+ } else {
+ count++;
+ }
+ }
+ check_int(count, ==, ARRAY_SIZE(key_val));
+ check_int(hashmap_get_size(&map->map), ==, ARRAY_SIZE(key_val));
+}
+
+int cmd_main(int argc UNUSED, const char **argv UNUSED)
+{
+ TEST(setup(t_replace), "replace works");
+ TEST(setup(t_get), "get works");
+ TEST(setup(t_remove), "remove works");
+ TEST(setup(t_iterate), "iterate works");
+ return test_done();
+}
diff --git a/t/unit-tests/t-reftable-record.c b/t/unit-tests/t-reftable-record.c
new file mode 100644
index 0000000000..cb649ee419
--- /dev/null
+++ b/t/unit-tests/t-reftable-record.c
@@ -0,0 +1,551 @@
+/*
+ Copyright 2020 Google LLC
+
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file or at
+ https://developers.google.com/open-source/licenses/bsd
+*/
+
+#include "test-lib.h"
+#include "reftable/constants.h"
+#include "reftable/record.h"
+
+static void t_copy(struct reftable_record *rec)
+{
+ struct reftable_record copy;
+ uint8_t typ;
+
+ typ = reftable_record_type(rec);
+ reftable_record_init(&copy, typ);
+ reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ);
+ /* do it twice to catch memory leaks */
+ reftable_record_copy_from(&copy, rec, GIT_SHA1_RAWSZ);
+ check(reftable_record_equal(rec, &copy, GIT_SHA1_RAWSZ));
+
+ reftable_record_release(&copy);
+}
+
+static void t_varint_roundtrip(void)
+{
+ uint64_t inputs[] = { 0,
+ 1,
+ 27,
+ 127,
+ 128,
+ 257,
+ 4096,
+ ((uint64_t)1 << 63),
+ ((uint64_t)1 << 63) + ((uint64_t)1 << 63) - 1 };
+
+ for (size_t i = 0; i < ARRAY_SIZE(inputs); i++) {
+ uint8_t dest[10];
+
+ struct string_view out = {
+ .buf = dest,
+ .len = sizeof(dest),
+ };
+ uint64_t in = inputs[i];
+ int n = put_var_int(&out, in);
+ uint64_t got = 0;
+
+ check_int(n, >, 0);
+ out.len = n;
+ n = get_var_int(&got, &out);
+ check_int(n, >, 0);
+
+ check_int(got, ==, in);
+ }
+}
+
+static void set_hash(uint8_t *h, int j)
+{
+ for (int i = 0; i < hash_size(GIT_SHA1_FORMAT_ID); i++)
+ h[i] = (j >> i) & 0xff;
+}
+
+static void t_reftable_ref_record_comparison(void)
+{
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.refname = (char *) "refs/heads/master",
+ .u.ref.value_type = REFTABLE_REF_VAL1,
+ },
+ {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.refname = (char *) "refs/heads/master",
+ .u.ref.value_type = REFTABLE_REF_DELETION,
+ },
+ {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.refname = (char *) "HEAD",
+ .u.ref.value_type = REFTABLE_REF_SYMREF,
+ .u.ref.value.symref = (char *) "refs/heads/master",
+ },
+ };
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+
+ in[1].u.ref.value_type = in[0].u.ref.value_type;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+}
+
+static void t_reftable_ref_record_compare_name(void)
+{
+ struct reftable_ref_record recs[3] = {
+ {
+ .refname = (char *) "refs/heads/a"
+ },
+ {
+ .refname = (char *) "refs/heads/b"
+ },
+ {
+ .refname = (char *) "refs/heads/a"
+ },
+ };
+
+ check_int(reftable_ref_record_compare_name(&recs[0], &recs[1]), <, 0);
+ check_int(reftable_ref_record_compare_name(&recs[1], &recs[0]), >, 0);
+ check_int(reftable_ref_record_compare_name(&recs[0], &recs[2]), ==, 0);
+}
+
+static void t_reftable_ref_record_roundtrip(void)
+{
+ struct strbuf scratch = STRBUF_INIT;
+
+ for (int i = REFTABLE_REF_DELETION; i < REFTABLE_NR_REF_VALUETYPES; i++) {
+ struct reftable_record in = {
+ .type = BLOCK_TYPE_REF,
+ .u.ref.value_type = i,
+ };
+ struct reftable_record out = { .type = BLOCK_TYPE_REF };
+ struct strbuf key = STRBUF_INIT;
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ int n, m;
+
+ in.u.ref.value_type = i;
+ switch (i) {
+ case REFTABLE_REF_DELETION:
+ break;
+ case REFTABLE_REF_VAL1:
+ set_hash(in.u.ref.value.val1, 1);
+ break;
+ case REFTABLE_REF_VAL2:
+ set_hash(in.u.ref.value.val2.value, 1);
+ set_hash(in.u.ref.value.val2.target_value, 2);
+ break;
+ case REFTABLE_REF_SYMREF:
+ in.u.ref.value.symref = xstrdup("target");
+ break;
+ }
+ in.u.ref.refname = xstrdup("refs/heads/master");
+
+ t_copy(&in);
+
+ check_int(reftable_record_val_type(&in), ==, i);
+ check_int(reftable_record_is_deletion(&in), ==, i == REFTABLE_REF_DELETION);
+
+ reftable_record_key(&in, &key);
+ n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >, 0);
+
+ /* decode into a non-zero reftable_record to test for leaks. */
+ m = reftable_record_decode(&out, key, i, dest, GIT_SHA1_RAWSZ, &scratch);
+ check_int(n, ==, m);
+
+ check(reftable_ref_record_equal(&in.u.ref, &out.u.ref,
+ GIT_SHA1_RAWSZ));
+ reftable_record_release(&in);
+
+ strbuf_release(&key);
+ reftable_record_release(&out);
+ }
+
+ strbuf_release(&scratch);
+}
+
+static void t_reftable_log_record_comparison(void)
+{
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_LOG,
+ .u.log.refname = (char *) "refs/heads/master",
+ .u.log.update_index = 42,
+ },
+ {
+ .type = BLOCK_TYPE_LOG,
+ .u.log.refname = (char *) "refs/heads/master",
+ .u.log.update_index = 22,
+ },
+ {
+ .type = BLOCK_TYPE_LOG,
+ .u.log.refname = (char *) "refs/heads/main",
+ .u.log.update_index = 22,
+ },
+ };
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+ /* comparison should be reversed for equal keys, because
+ * comparison is now performed on the basis of update indices */
+ check_int(reftable_record_cmp(&in[0], &in[1]), <, 0);
+
+ in[1].u.log.update_index = in[0].u.log.update_index;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+}
+
+static void t_reftable_log_record_compare_key(void)
+{
+ struct reftable_log_record logs[3] = {
+ {
+ .refname = (char *) "refs/heads/a",
+ .update_index = 1,
+ },
+ {
+ .refname = (char *) "refs/heads/b",
+ .update_index = 2,
+ },
+ {
+ .refname = (char *) "refs/heads/a",
+ .update_index = 3,
+ },
+ };
+
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0);
+ check_int(reftable_log_record_compare_key(&logs[1], &logs[0]), >, 0);
+
+ logs[1].update_index = logs[0].update_index;
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[1]), <, 0);
+
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), >, 0);
+ check_int(reftable_log_record_compare_key(&logs[2], &logs[0]), <, 0);
+ logs[2].update_index = logs[0].update_index;
+ check_int(reftable_log_record_compare_key(&logs[0], &logs[2]), ==, 0);
+}
+
+static void t_reftable_log_record_roundtrip(void)
+{
+ struct reftable_log_record in[] = {
+ {
+ .refname = xstrdup("refs/heads/master"),
+ .update_index = 42,
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value = {
+ .update = {
+ .name = xstrdup("han-wen"),
+ .email = xstrdup("hanwen@google.com"),
+ .message = xstrdup("test"),
+ .time = 1577123507,
+ .tz_offset = 100,
+ },
+ }
+ },
+ {
+ .refname = xstrdup("refs/heads/master"),
+ .update_index = 22,
+ .value_type = REFTABLE_LOG_DELETION,
+ },
+ {
+ .refname = xstrdup("branch"),
+ .update_index = 33,
+ .value_type = REFTABLE_LOG_UPDATE,
+ }
+ };
+ struct strbuf scratch = STRBUF_INIT;
+ set_hash(in[0].value.update.new_hash, 1);
+ set_hash(in[0].value.update.old_hash, 2);
+ set_hash(in[2].value.update.new_hash, 3);
+ set_hash(in[2].value.update.old_hash, 4);
+
+ check(!reftable_log_record_is_deletion(&in[0]));
+ check(reftable_log_record_is_deletion(&in[1]));
+ check(!reftable_log_record_is_deletion(&in[2]));
+
+ for (size_t i = 0; i < ARRAY_SIZE(in); i++) {
+ struct reftable_record rec = { .type = BLOCK_TYPE_LOG };
+ struct strbuf key = STRBUF_INIT;
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ /* populate out, to check for leaks. */
+ struct reftable_record out = {
+ .type = BLOCK_TYPE_LOG,
+ .u.log = {
+ .refname = xstrdup("old name"),
+ .value_type = REFTABLE_LOG_UPDATE,
+ .value = {
+ .update = {
+ .name = xstrdup("old name"),
+ .email = xstrdup("old@email"),
+ .message = xstrdup("old message"),
+ },
+ },
+ },
+ };
+ int n, m, valtype;
+
+ rec.u.log = in[i];
+
+ t_copy(&rec);
+
+ reftable_record_key(&rec, &key);
+
+ n = reftable_record_encode(&rec, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >=, 0);
+ valtype = reftable_record_val_type(&rec);
+ m = reftable_record_decode(&out, key, valtype, dest,
+ GIT_SHA1_RAWSZ, &scratch);
+ check_int(n, ==, m);
+
+ check(reftable_log_record_equal(&in[i], &out.u.log,
+ GIT_SHA1_RAWSZ));
+ reftable_log_record_release(&in[i]);
+ strbuf_release(&key);
+ reftable_record_release(&out);
+ }
+
+ strbuf_release(&scratch);
+}
+
+static void t_key_roundtrip(void)
+{
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ struct strbuf last_key = STRBUF_INIT;
+ struct strbuf key = STRBUF_INIT;
+ struct strbuf roundtrip = STRBUF_INIT;
+ int restart;
+ uint8_t extra;
+ int n, m;
+ uint8_t rt_extra;
+
+ strbuf_addstr(&last_key, "refs/heads/master");
+ strbuf_addstr(&key, "refs/tags/bla");
+ extra = 6;
+ n = reftable_encode_key(&restart, dest, last_key, key, extra);
+ check(!restart);
+ check_int(n, >, 0);
+
+ strbuf_addstr(&roundtrip, "refs/heads/master");
+ m = reftable_decode_key(&roundtrip, &rt_extra, dest);
+ check_int(n, ==, m);
+ check(!strbuf_cmp(&key, &roundtrip));
+ check_int(rt_extra, ==, extra);
+
+ strbuf_release(&last_key);
+ strbuf_release(&key);
+ strbuf_release(&roundtrip);
+}
+
+static void t_reftable_obj_record_comparison(void)
+{
+
+ uint8_t id_bytes[] = { 0, 1, 2, 3, 4, 5, 6 };
+ uint64_t offsets[] = { 0, 16, 32, 48, 64, 80, 96, 112};
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_OBJ,
+ .u.obj.hash_prefix = id_bytes,
+ .u.obj.hash_prefix_len = 7,
+ .u.obj.offsets = offsets,
+ .u.obj.offset_len = 8,
+ },
+ {
+ .type = BLOCK_TYPE_OBJ,
+ .u.obj.hash_prefix = id_bytes,
+ .u.obj.hash_prefix_len = 7,
+ .u.obj.offsets = offsets,
+ .u.obj.offset_len = 5,
+ },
+ {
+ .type = BLOCK_TYPE_OBJ,
+ .u.obj.hash_prefix = id_bytes,
+ .u.obj.hash_prefix_len = 5,
+ },
+ };
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+
+ in[1].u.obj.offset_len = in[0].u.obj.offset_len;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+}
+
+static void t_reftable_obj_record_roundtrip(void)
+{
+ uint8_t testHash1[GIT_SHA1_RAWSZ] = { 1, 2, 3, 4, 0 };
+ uint64_t till9[] = { 1, 2, 3, 4, 500, 600, 700, 800, 9000 };
+ struct reftable_obj_record recs[3] = {
+ {
+ .hash_prefix = testHash1,
+ .hash_prefix_len = 5,
+ .offsets = till9,
+ .offset_len = 3,
+ },
+ {
+ .hash_prefix = testHash1,
+ .hash_prefix_len = 5,
+ .offsets = till9,
+ .offset_len = 9,
+ },
+ {
+ .hash_prefix = testHash1,
+ .hash_prefix_len = 5,
+ },
+ };
+ struct strbuf scratch = STRBUF_INIT;
+
+ for (size_t i = 0; i < ARRAY_SIZE(recs); i++) {
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ struct reftable_record in = {
+ .type = BLOCK_TYPE_OBJ,
+ .u = {
+ .obj = recs[i],
+ },
+ };
+ struct strbuf key = STRBUF_INIT;
+ struct reftable_record out = { .type = BLOCK_TYPE_OBJ };
+ int n, m;
+ uint8_t extra;
+
+ check(!reftable_record_is_deletion(&in));
+ t_copy(&in);
+ reftable_record_key(&in, &key);
+ n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >, 0);
+ extra = reftable_record_val_type(&in);
+ m = reftable_record_decode(&out, key, extra, dest,
+ GIT_SHA1_RAWSZ, &scratch);
+ check_int(n, ==, m);
+
+ check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));
+ strbuf_release(&key);
+ reftable_record_release(&out);
+ }
+
+ strbuf_release(&scratch);
+}
+
+static void t_reftable_index_record_comparison(void)
+{
+ struct reftable_record in[3] = {
+ {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx.offset = 22,
+ .u.idx.last_key = STRBUF_INIT,
+ },
+ {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx.offset = 32,
+ .u.idx.last_key = STRBUF_INIT,
+ },
+ {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx.offset = 32,
+ .u.idx.last_key = STRBUF_INIT,
+ },
+ };
+ strbuf_addstr(&in[0].u.idx.last_key, "refs/heads/master");
+ strbuf_addstr(&in[1].u.idx.last_key, "refs/heads/master");
+ strbuf_addstr(&in[2].u.idx.last_key, "refs/heads/branch");
+
+ check(!reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ check(!reftable_record_equal(&in[1], &in[2], GIT_SHA1_RAWSZ));
+ check_int(reftable_record_cmp(&in[1], &in[2]), >, 0);
+
+ in[1].u.idx.offset = in[0].u.idx.offset;
+ check(reftable_record_equal(&in[0], &in[1], GIT_SHA1_RAWSZ));
+ check(!reftable_record_cmp(&in[0], &in[1]));
+
+ for (size_t i = 0; i < ARRAY_SIZE(in); i++)
+ reftable_record_release(&in[i]);
+}
+
+static void t_reftable_index_record_roundtrip(void)
+{
+ struct reftable_record in = {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx = {
+ .offset = 42,
+ .last_key = STRBUF_INIT,
+ },
+ };
+ uint8_t buffer[1024] = { 0 };
+ struct string_view dest = {
+ .buf = buffer,
+ .len = sizeof(buffer),
+ };
+ struct strbuf scratch = STRBUF_INIT;
+ struct strbuf key = STRBUF_INIT;
+ struct reftable_record out = {
+ .type = BLOCK_TYPE_INDEX,
+ .u.idx = { .last_key = STRBUF_INIT },
+ };
+ int n, m;
+ uint8_t extra;
+
+ strbuf_addstr(&in.u.idx.last_key, "refs/heads/master");
+ reftable_record_key(&in, &key);
+ t_copy(&in);
+
+ check(!reftable_record_is_deletion(&in));
+ check(!strbuf_cmp(&key, &in.u.idx.last_key));
+ n = reftable_record_encode(&in, dest, GIT_SHA1_RAWSZ);
+ check_int(n, >, 0);
+
+ extra = reftable_record_val_type(&in);
+ m = reftable_record_decode(&out, key, extra, dest, GIT_SHA1_RAWSZ,
+ &scratch);
+ check_int(m, ==, n);
+
+ check(reftable_record_equal(&in, &out, GIT_SHA1_RAWSZ));
+
+ reftable_record_release(&out);
+ strbuf_release(&key);
+ strbuf_release(&scratch);
+ strbuf_release(&in.u.idx.last_key);
+}
+
+int cmd_main(int argc, const char *argv[])
+{
+ TEST(t_reftable_ref_record_comparison(), "comparison operations work on ref record");
+ TEST(t_reftable_log_record_comparison(), "comparison operations work on log record");
+ TEST(t_reftable_index_record_comparison(), "comparison operations work on index record");
+ TEST(t_reftable_obj_record_comparison(), "comparison operations work on obj record");
+ TEST(t_reftable_ref_record_compare_name(), "reftable_ref_record_compare_name works");
+ TEST(t_reftable_log_record_compare_key(), "reftable_log_record_compare_key works");
+ TEST(t_reftable_log_record_roundtrip(), "record operations work on log record");
+ TEST(t_reftable_ref_record_roundtrip(), "record operations work on ref record");
+ TEST(t_varint_roundtrip(), "put_var_int and get_var_int work");
+ TEST(t_key_roundtrip(), "reftable_encode_key and reftable_decode_key work");
+ TEST(t_reftable_obj_record_roundtrip(), "record operations work on obj record");
+ TEST(t_reftable_index_record_roundtrip(), "record operations work on index record");
+
+ return test_done();
+}