{"thread":{"id":"52269","subject":"[PATCH 00/27] t: general test cleanup + `set -o pipefail`","startedAt":"2019-11-15T01:00:36Z","lastAt":"2021-01-23T21:36:27Z","messageCount":228,"participants":["Denton Liu","Jeff King","Junio C Hamano","Eric Sunshine","Danh Doan","Ævar Arnfjörð Bjarmason","SZEDER Gábor"],"isPatch":true,"patchVersion":1,"patchTotal":27},"messages":[{"id":"386216","messageId":"cover.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":null,"subject":"[PATCH 00/27] t: general test cleanup + `set -o pipefail`","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:29Z","receivedAt":"2019-11-15T01:00:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Patches 1-20 perform some general test cleanup to modernise the style.\nThey should be relatively uncontroversial and can be merged earlier (or\nas a separate series) if desired. The reason these tests were identified\nfor cleanup was because they failed under `set -o pipefail`.\n\nPatches 21-27 should be considered RFC. In an attempt to catch git\ncommands failing in the upstream of a pipe, we enable `set -o pipefail`\non Bash. This may result in some funny-looking shell script constructs\n(e.g. needing to wrap `grep` since it may \"fail\") but overall, I think it\nis an improvement since we catch failure in more cases.\n\nThis change should be backwards compatible with shells that don't\nsupport pipefail since tests that pass under pipefail should be a subset\nof tests that can pass without pipefail.\n\nI've tested these patches on Linux, MacOS and Travis[1], although I skipped\nCVS, SVN, Apache2 tests (and maybe others?). I'd appreciate help testing\nthese patches on that regard.\n\n[1]: https://travis-ci.org/Denton-L/git/builds/612133448\n\nDenton Liu (27):\n  lib-bash.sh: move `then` onto its own line\n  t0014: remove git command upstream of pipe\n  t0090: stop losing return codes of git commands\n  t3301: stop losing return codes of git commands\n  t3600: use test_line_count() where possible\n  t3600: stop losing return codes of git commands\n  t3600: comment on inducing SIGPIPE in `git rm`\n  t4015: stop losing return codes of git commands\n  t4015: use test_write_lines()\n  t4138: stop losing return codes of git commands\n  t5317: stop losing return codes of git commands\n  t5317: use ! grep to check for no matching lines\n  t5703: stop losing return codes of git commands\n  t7501: remove spaces after redirect operators\n  t7501: stop losing return codes of git commands\n  t7700: drop redirections to /dev/null\n  t7700: remove spaces after redirect operators\n  t7700: move keywords onto their own line\n  t7700: s/test -f/test_path_is_file/\n  t7700: stop losing return codes of git commands\n  t: define test_grep_return_success()\n  t0090: mask failing grep status\n  t3600: mark git command as failing\n  t5004: ignore SIGPIPE in zipinfo\n  t5703: mask failing grep status\n  t9902: disable pipefail\n  t: run tests with `set -o pipefail` on Bash\n\n t/README                               |   4 +\n t/lib-bash.sh                          |   3 +-\n t/t0014-alias.sh                       |   4 +-\n t/t0090-cache-tree.sh                  |   5 +-\n t/t3301-notes.sh                       | 230 ++++++++++++++++++-------\n t/t3600-rm.sh                          |  16 +-\n t/t4015-diff-whitespace.sh             | 123 +++++++------\n t/t4138-apply-ws-expansion.sh          |  16 +-\n t/t5004-archive-corner-cases.sh        |   4 +-\n t/t5317-pack-objects-filter-objects.sh |  34 ++--\n t/t5703-upload-pack-ref-in-want.sh     |  52 ++++--\n t/t7501-commit-basic-functionality.sh  |  83 +++++----\n t/t7700-repack.sh                      | 125 ++++++++------\n t/t9902-completion.sh                  |   6 +\n t/test-lib-functions.sh                |   5 +\n t/test-lib.sh                          |  12 ++\n 16 files changed, 458 insertions(+), 264 deletions(-)\n\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386217","messageId":"b4442fb408c80cf6c4d8fd05b474c0094e243126.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 01/27] lib-bash.sh: move `then` onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:33Z","receivedAt":"2019-11-15T01:00:41Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move the `then` onto its own line so that it conforms with the\ntest style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-bash.sh | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/t/lib-bash.sh b/t/lib-bash.sh\nindex 2be955fafb..6a2c21cd24 100644\n--- a/t/lib-bash.sh\n+++ b/t/lib-bash.sh\n@@ -2,7 +2,8 @@\n # to run under Bash; primarily intended for tests of the completion\n # script.\n \n-if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"; then\n+if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+then\n \t# we are in full-on bash mode\n \ttrue\n elif type bash >/dev/null 2>&1; then\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386218","messageId":"b60687989d1c55782d1c589bb7aae1c971fa1e77.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 02/27] t0014: remove git command upstream of pipe","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:35Z","receivedAt":"2019-11-15T01:00:41Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, the `git frotz` command would fail but its return code was\nhidden since it was in the upstream of a pipe. Break the pipeline into\ntwo commands so that the return code is no longer lost. Also, mark\n`git frotz` with test_must_fail since it's supposed to fail.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0014-alias.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0014-alias.sh b/t/t0014-alias.sh\nindex 2694c81afd..8d3d9144c0 100755\n--- a/t/t0014-alias.sh\n+++ b/t/t0014-alias.sh\n@@ -38,8 +38,8 @@ test_expect_success 'looping aliases - internal execution' '\n #'\n \n test_expect_success 'run-command formats empty args properly' '\n-    GIT_TRACE=1 git frotz a \"\" b \" \" c 2>&1 |\n-    sed -ne \"/run_command:/s/.*trace: run_command: //p\" >actual &&\n+    test_must_fail env GIT_TRACE=1 git frotz a \"\" b \" \" c 2>actual.raw &&\n+    sed -ne \"/run_command:/s/.*trace: run_command: //p\" actual.raw >actual &&\n     echo \"git-frotz a '\\'''\\'' b '\\'' '\\'' c\" >expect &&\n     test_cmp expect actual\n '\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386219","messageId":"d987b5748b30d0b18102f823e1c42bc9ceaa1d5e.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 03/27] t0090: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:37Z","receivedAt":"2019-11-15T01:00:44Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In generate_expected_cache_tree_rec(), there are currently two instances\nof `git ls-files` in the upstream of a pipe. In the case where the\nupstream git command fails, its return code will be lost. Extract the\n`git ls-files` into its own call so that if it ever fails, its return\ncode is not lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0090-cache-tree.sh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex ce9a4a5f32..5a633690bf 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -21,9 +21,10 @@ generate_expected_cache_tree_rec () {\n \tparent=\"$2\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n-\tsubtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&\n+\tgit ls-files >files &&\n+\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n \tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n-\tentries=$(git ls-files|wc -l) &&\n+\tentries=$(wc -l <files) &&\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n \tfor subtree in $subtrees\n \tdo\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386220","messageId":"caa82e98e4b83c39d8aa2fbbb020f0f47ba50a9c.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 04/27] t3301: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:40Z","receivedAt":"2019-11-15T01:00:50Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nThis patch fixes a real buggy test: in 'copy note with \"git notes\ncopy\"', `git notes` was mistyped as `git note`.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3301-notes.sh | 230 +++++++++++++++++++++++++++++++++--------------\n 1 file changed, 163 insertions(+), 67 deletions(-)\n\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex d66a5f6faa..8f43303007 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -54,7 +54,9 @@ test_expect_success 'create notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b4\" = \"$(git notes show)\" &&\n+\techo b4 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -79,14 +81,21 @@ test_expect_success 'edit existing notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n \n test_expect_success 'show notes from treeish' '\n-\ttest \"b3\" = \"$(git notes --ref commits^{tree} show)\" &&\n-\ttest \"b4\" = \"$(git notes --ref commits@{1} show)\"\n+\techo b3 >expect &&\n+\tgit notes --ref commits^{tree} show >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo b4 >expect &&\n+\tgit notes --ref commits@{1} show >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot edit notes from non-ref' '\n@@ -99,7 +108,9 @@ test_expect_success 'cannot \"git notes add -m\" where notes already exists' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -109,7 +120,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f -m\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -119,7 +132,9 @@ test_expect_success 'add w/no options on existing note morphs into edit' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b2\" = \"$(git notes show)\" &&\n+\techo b2 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -129,7 +144,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -146,7 +163,8 @@ test_expect_success 'show notes' '\n \t\tNotes:\n \t\t${indent}b1\n \tEOF\n-\t! (git cat-file commit HEAD | grep b1) &&\n+\tgit cat-file commit HEAD >commits &&\n+\t! grep b1 commits &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -472,9 +490,11 @@ test_expect_success 'removing with --stdin --ignore-missing' '\n test_expect_success 'list notes with \"git notes list\"' '\n \tcommit_2=$(git rev-parse 2nd) &&\n \tcommit_3=$(git rev-parse 3rd) &&\n+\tnote_2=$(git rev-parse refs/notes/commits:$commit_2) &&\n+\tnote_3=$(git rev-parse refs/notes/commits:$commit_3) &&\n \tsort -t\" \" -k2 >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect actual\n@@ -486,9 +506,7 @@ test_expect_success 'list notes with \"git notes\"' '\n '\n \n test_expect_success 'list specific note with \"git notes list <object>\"' '\n-\tcat >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_3)\n-\tEOF\n+\tgit rev-parse refs/notes/commits:$commit_3 >expect &&\n \tgit notes list HEAD^^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -512,10 +530,11 @@ test_expect_success 'append to existing note with \"git notes append\"' '\n \n test_expect_success '\"git notes list\" does not expand to \"git notes list HEAD\"' '\n \tcommit_5=$(git rev-parse 5th) &&\n+\tnote_5=$(git rev-parse refs/notes/commits:$commit_5) &&\n \tsort -t\" \" -k2 >expect_list <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n-\t\t$(git rev-parse refs/notes/commits:$commit_5) $commit_5\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n+\t\t$note_5 $commit_5\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect_list actual\n@@ -721,7 +740,8 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '\n \tgit notes show HEAD: >actual &&\n \ttest_cmp expect actual &&\n \techo \"Note on a blob\" >expect &&\n-\tfilename=$(git ls-tree --name-only HEAD | head -n1) &&\n+\tgit ls-tree --name-only HEAD >files &&\n+\tfilename=$(head -n1 files) &&\n \tgit notes add -m \"Note on a blob\" HEAD:$filename &&\n \tgit notes show HEAD:$filename >actual &&\n \ttest_cmp expect actual &&\n@@ -745,10 +765,13 @@ test_expect_success 'create note from other note with \"git notes add -C\"' '\n \t\tNotes:\n \t\t${indent}order test\n \tEOF\n-\tgit notes add -C $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes add -C $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'create note from non-existing note with \"git notes add -C\" fails' '\n@@ -777,11 +800,12 @@ test_expect_success 'create note from blob with \"git notes add -C\" reuses blob i\n \t\tNotes:\n \t\t${indent}This is a blob object\n \tEOF\n-\tblob=$(echo \"This is a blob object\" | git hash-object -w --stdin) &&\n-\tgit notes add -C $blob &&\n+\techo \"This is a blob object\" | git hash-object -w --stdin >blob &&\n+\tgit notes add -C $(cat blob) &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$blob\"\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp blob actual\n '\n \n test_expect_success 'create note from other note with \"git notes add -c\"' '\n@@ -797,7 +821,8 @@ test_expect_success 'create note from other note with \"git notes add -c\"' '\n \t\tNotes:\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes add -c $(git notes list HEAD^^) &&\n+\tnote=$(git notes list HEAD^^) &&\n+\tMSG=\"yet another note\" git notes add -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -822,7 +847,8 @@ test_expect_success 'append to note from other note with \"git notes append -C\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tgit notes append -C $(git notes list HEAD^) HEAD^ &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes append -C $note HEAD^ &&\n \tgit log -1 HEAD^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -839,7 +865,8 @@ test_expect_success 'create note from other note with \"git notes append -c\"' '\n \t\tNotes:\n \t\t${indent}other note\n \tEOF\n-\tMSG=\"other note\" git notes append -c $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tMSG=\"other note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -858,7 +885,8 @@ test_expect_success 'append to note from other note with \"git notes append -c\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes append -c $(git notes list HEAD) &&\n+\tnote=$(git notes list HEAD) &&\n+\tMSG=\"yet another note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -878,7 +906,9 @@ test_expect_success 'copy note with \"git notes copy\"' '\n \tgit notes copy 8th 4th &&\n \tgit log 3rd..4th >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git note list 4th)\" = \"$(git note list 8th)\"\n+\tgit notes list 4th >expect &&\n+\tgit notes list 8th >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'copy note with \"git notes copy\" with default' '\n@@ -899,14 +929,30 @@ test_expect_success 'copy note with \"git notes copy\" with default' '\n \tgit notes copy HEAD^ &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'prevent overwrite with \"git notes copy\"' '\n \ttest_must_fail git notes copy HEAD~2 HEAD &&\n+\tcat >expect <<-EOF &&\n+\t\tcommit $commit\n+\t\tAuthor: A U Thor <author@example.com>\n+\t\tDate:   Thu Apr 7 15:23:13 2005 -0700\n+\n+\t\t${indent}11th\n+\n+\t\tNotes:\n+\t\t${indent}other note\n+\t\t${indent}\n+\t\t${indent}yet another note\n+\tEOF\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n@@ -924,7 +970,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n \tgit notes copy -f HEAD~3 HEAD &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n@@ -944,7 +992,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n \tgit notes copy -f HEAD~2 &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot copy note from object without notes' '\n@@ -979,13 +1029,21 @@ test_expect_success 'git notes copy --stdin' '\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --stdin &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --stdin <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\" &&\n-\ttest \"$(git notes list HEAD^)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual &&\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD^ >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n@@ -1006,9 +1064,13 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n \n \t\t${indent}14th\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1041,17 +1103,23 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '\n \tEOF\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (disabled)' '\n \ttest_config notes.rewrite.bar false &&\n-\techo $(git rev-parse HEAD~3) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=bar &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=bar <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1071,8 +1139,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n \tgit notes add -f -m\"a fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1080,8 +1150,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n test_expect_success 'git notes copy --for-rewrite (ignore)' '\n \ttest_config notes.rewriteMode ignore &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1103,8 +1175,10 @@ test_expect_success 'git notes copy --for-rewrite (append)' '\n \tgit notes add -f -m\"another fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1131,9 +1205,13 @@ test_expect_success 'git notes copy --for-rewrite (append two to one)' '\n \tgit notes add -f -m\"append 2\" HEAD^^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD^) $(git rev-parse HEAD) &&\n-\techo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD^^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1142,8 +1220,10 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '\n \tgit notes remove HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1163,8 +1243,10 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n \tgit notes add -f -m\"replacement note 1\" HEAD^ &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1184,9 +1266,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF works' '\n \tgit notes add -f -m\"replacement note 2\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_unconfig notes.rewriteRef &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1195,9 +1279,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '\n \tgit notes add -f -m\"replacement note 3\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef refs/notes/other &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \tgrep \"replacement note 3\" actual\n '\n@@ -1212,26 +1298,36 @@ test_expect_success 'git notes copy diagnoses too many or too few parameters' '\n test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes --ref=refs/heads/master get-ref)\" = \"refs/notes/refs/heads/master\"\n+\techo refs/notes/refs/heads/master >expect &&\n+\tgit notes --ref=refs/heads/master get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (no overrides)' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/commits\"\n+\techo refs/notes/commits >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (core.notesRef)' '\n \ttest_config core.notesRef refs/notes/foo &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/foo\"\n+\techo refs/notes/foo >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (GIT_NOTES_REF)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes get-ref)\" = \"refs/notes/bar\"\n+\techo refs/notes/bar >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (--ref)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref)\" = \"refs/notes/baz\"\n+\techo refs/notes/baz >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'setup testing of empty notes' '\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386221","messageId":"96872839cf50b5cdbe77b233816ffe40b02cded4.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 06/27] t3600: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:45Z","receivedAt":"2019-11-15T01:00:50Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"When a command is in a non-assignment command substitution, the return\ncode will be lost in favour of the surrounding command's. As a result,\nif a git command fails, we won't know about it. Rewrite instances of\nthis so that git commands are either run in an assignment-only command\nsubstitution so that their return codes aren't lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex f6e659b7e9..0c3bf10edd 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -304,7 +304,8 @@ EOF\n \n test_expect_success 'rm removes empty submodules from work tree' '\n \tmkdir submod &&\n-\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) submod &&\n+\thash=$(git rev-parse HEAD) &&\n+\tgit update-index --add --cacheinfo 160000 \"$hash\" submod &&\n \tgit config -f .gitmodules submodule.sub.url ./. &&\n \tgit config -f .gitmodules submodule.sub.path submod &&\n \tgit submodule init &&\n@@ -623,7 +624,8 @@ test_expect_success 'setup subsubmodule' '\n \tgit submodule update &&\n \t(\n \t\tcd submod &&\n-\t\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) subsubmod &&\n+\t\thash=$(git rev-parse HEAD) &&\n+\t\tgit update-index --add --cacheinfo 160000 \"$hash\" subsubmod &&\n \t\tgit config -f .gitmodules submodule.sub.url ../. &&\n \t\tgit config -f .gitmodules submodule.sub.path subsubmod &&\n \t\tgit submodule init &&\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386222","messageId":"1767492b81a9dae3e4227f9a1952a081619ff7d3.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 05/27] t3600: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:43Z","receivedAt":"2019-11-15T01:00:50Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have a helper function that can test the number of lines in a\nfile that gives better debugging information on failure, use\ntest_line_count() to test the number of lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 8c8cca5bfb..f6e659b7e9 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -113,9 +113,10 @@ test_expect_success '\"rm\" command printed' '\n \techo frotz >test-file &&\n \tgit add test-file &&\n \tgit commit -m \"add file for rm test\" &&\n-\tgit rm test-file >rm-output &&\n-\ttest $(grep \"^rm \" rm-output | wc -l) = 1 &&\n-\trm -f test-file rm-output &&\n+\tgit rm test-file >rm-output.raw &&\n+\tgrep \"^rm \" rm-output.raw >rm-output &&\n+\ttest_line_count = 1 rm-output &&\n+\trm -f test-file rm-output.raw rm-output &&\n \tgit commit -m \"remove file from rm test\"\n '\n \n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386223","messageId":"a34b78fc348f7997b53b2883a0a2a03f0713bfb2.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 07/27] t3600: comment on inducing SIGPIPE in `git rm`","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:47Z","receivedAt":"2019-11-15T01:00:53Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Add a comment about intentionally inducing SIGPIPE since this is unusual\nand future developers should be aware. Also, even though we are trying\nto refactor git commands out of the upstream of pipes, we cannot do it\nhere since we rely on it being upstream to induce SIGPIPE. Comment on\nthat as well so that future developers do not try to change it.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 0c3bf10edd..0ea858d652 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -251,6 +251,7 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\techo \"100644 $hash 0\tsome-file-$i\"\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n+\t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n \tgit rm -n \"some-file-*\" | : &&\n \ttest_path_is_missing .git/index.lock\n '\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386224","messageId":"d27bc8bad35aaecaa1f73045f8247c9e5fe053aa.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 09/27] t4015: use test_write_lines()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:53Z","receivedAt":"2019-11-15T01:00:57Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Instead of rolling our own method to write out some lines into a file,\nuse the existing test_write_lines().\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex 7fb83c8eff..4c540b1d70 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -771,9 +771,9 @@ test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n-\t{ echo a; echo b; echo; echo; } >x &&\n+\ttest_write_lines a b \"\" \"\" >x &&\n \tgit add x &&\n-\t{ echo a; echo; echo; echo; echo; } >x &&\n+\ttest_write_lines a \"\" \"\" \"\" \"\" >x &&\n \ttest_must_fail git diff --check >check &&\n \tgrep \"new blank line\" check\n '\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386225","messageId":"ea17bfa60eefd446c06702e111908f9d46d7a8d6.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 08/27] t4015: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:49Z","receivedAt":"2019-11-15T01:00:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 119 ++++++++++++++++++++++---------------\n 1 file changed, 72 insertions(+), 47 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex eadaf57262..7fb83c8eff 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -16,7 +16,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t} while (0);\n \tEOF\n \tgit update-index --add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \tcat <<-\\EOF >x &&\n \tdo\n@@ -25,7 +26,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t}\n \twhile (0);\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -63,7 +65,8 @@ test_expect_success 'another test, without options' '\n \tEOF\n \n \tgit update-index x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \ttr \"_\" \" \" <<-\\EOF >x &&\n \t_\twhitespace at beginning\n@@ -73,7 +76,8 @@ test_expect_success 'another test, without options' '\n \tunchanged line\n \tCR at end\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \ttr \"Q_\" \"\\015 \" <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -526,13 +530,15 @@ test_expect_success 'ignore-blank-lines: mix changes and blank lines' '\n test_expect_success 'check mixed spaces and tabs in indent' '\n \t# This is indented with SP HT SP.\n \techo \" \t foo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check mixed tabs and spaces in indent' '\n \t# This is indented with HT SP HT.\n \techo \"\t \tfoo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check with no whitespace errors' '\n@@ -753,20 +759,23 @@ test_expect_success 'check tab-in-indent excluded from wildcard whitespace attri\n test_expect_success 'line numbers in --check output are correct' '\n \techo \"\" >x &&\n \techo \"foo(); \" >>x &&\n-\tgit diff --check | grep \"x:2:\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"x:2:\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n \techo \"foo();\" >x &&\n \techo \"\" >>x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n \t{ echo a; echo b; echo; echo; } >x &&\n \tgit add x &&\n \t{ echo a; echo; echo; echo; echo; } >x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff allows new blank lines' '\n@@ -794,14 +803,16 @@ test_expect_success 'whitespace-only changes reported across renames' '\n \tgit reset --hard &&\n \tfor i in 1 2 3 4 5 6 7 8 9; do echo \"$i$i$i$i$i$i\"; done >x &&\n \tgit add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\thash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$hash_x\") &&\n \tgit commit -m \"base\" &&\n \tsed -e \"5s/^/ /\" x >z &&\n \tgit rm x &&\n \tgit add z &&\n-\tafter=$(git rev-parse --short $(git hash-object z)) &&\n-\tgit diff -w -M --cached |\n-\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" >actual &&\n+\thash_z=$(git hash-object z) &&\n+\tafter=$(git rev-parse --short \"$hash_z\") &&\n+\tgit diff -w -M --cached >actual.raw &&\n+\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" actual.raw >actual &&\n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/z\n \tsimilarity index NUM%\n@@ -840,7 +851,8 @@ test_expect_success 'combined diff with autocrlf conversion' '\n \tgit config core.autocrlf true &&\n \ttest_must_fail git merge master &&\n \n-\tgit diff | sed -e \"1,/^@@@/d\" >actual &&\n+\tgit diff >actual.raw &&\n+\tsed -e \"1,/^@@@/d\" actual.raw >actual &&\n \t! grep \"^-\" actual\n \n '\n@@ -864,11 +876,14 @@ test_expect_success 'diff that introduces a line with only tabs' '\n \tgit config core.whitespace blank-at-eol &&\n \tgit reset --hard &&\n \techo \"test\" >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -m \"initial\" x &&\n \techo \"{NTN}\" | tr \"NT\" \"\\n\\t\" >>x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n-\tgit diff --color | test_decode_color >current &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -891,17 +906,19 @@ test_expect_success 'diff that introduces and removes ws breakages' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n-\tgit diff --color |\n-\ttest_decode_color >current &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -925,14 +942,16 @@ test_expect_success 'ws-error-highlight test setup' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat >expect.default-old <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -974,32 +993,32 @@ test_expect_success 'ws-error-highlight test setup' '\n \n test_expect_success 'test --ws-error-highlight option' '\n \n-\tgit diff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit diff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit diff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n \n test_expect_success 'test diff.wsErrorHighlight config' '\n \n-\tgit -c diff.wsErrorHighlight=default,old diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=default,old diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit -c diff.wsErrorHighlight=all diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=all diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit -c diff.wsErrorHighlight=none diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=none diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1007,18 +1026,18 @@ test_expect_success 'test diff.wsErrorHighlight config' '\n test_expect_success 'option overrides diff.wsErrorHighlight' '\n \n \tgit -c diff.wsErrorHighlight=none \\\n-\t\tdiff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n \tgit -c diff.wsErrorHighlight=default \\\n-\t\tdiff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n \tgit -c diff.wsErrorHighlight=all \\\n-\t\tdiff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1038,7 +1057,8 @@ test_expect_success 'detect moved code, complete file' '\n \tgit mv test.c main.c &&\n \ttest_config color.diff.oldMoved \"normal red\" &&\n \ttest_config color.diff.newMoved \"normal green\" &&\n-\tgit diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&\n+\tgit diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>new file mode 100644<RESET>\n@@ -1141,9 +1161,12 @@ test_expect_success 'detect malicious moved code, inside file' '\n \t\t\tbar();\n \t\t}\n \tEOF\n-\tafter_main=$(git rev-parse --short $(git hash-object main.c)) &&\n-\tafter_test=$(git rev-parse --short $(git hash-object test.c)) &&\n-\tgit diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&\n+\thash_main=$(git hash-object main.c) &&\n+\tafter_main=$(git rev-parse --short \"$hash_main\") &&\n+\thash_test=$(git hash-object test.c) &&\n+\tafter_test=$(git rev-parse --short \"$hash_test\") &&\n+\tgit diff HEAD --no-renames --color-moved=zebra --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1192,7 +1215,8 @@ test_expect_success 'plain moved code, inside file' '\n \ttest_config color.diff.oldMovedAlternative \"blue\" &&\n \ttest_config color.diff.newMovedAlternative \"yellow\" &&\n \t# needs previous test as setup\n-\tgit diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&\n+\tgit diff HEAD --no-renames --color-moved=plain --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1771,7 +1795,8 @@ test_expect_success 'move detection with submodules' '\n \t! grep BRED decoded_actual &&\n \n \t# nor did we mess with it another way\n-\tgit diff --submodule=diff --color | test_decode_color >expect &&\n+\tgit diff --submodule=diff --color >expect.raw &&\n+\ttest_decode_color <expect.raw >expect &&\n \ttest_cmp expect decoded_actual &&\n \trm -rf bananas &&\n \tgit submodule deinit bananas\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386227","messageId":"d617cbaaf1232e45b077786afaa9d3465a9bbd35.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 10/27] t4138: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:55Z","receivedAt":"2019-11-15T01:01:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4138-apply-ws-expansion.sh | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh\nindex 3b636a63a3..60435d6d41 100755\n--- a/t/t4138-apply-ws-expansion.sh\n+++ b/t/t4138-apply-ws-expansion.sh\n@@ -17,8 +17,8 @@ test_expect_success setup '\n \tprintf \"\\t%s\\n\" 1 2 3 >after &&\n \tprintf \"%64s\\n\" a b c >>after &&\n \tprintf \"\\t%s\\n\" 4 5 6 >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" >patch1.patch &&\n+\ttest_must_fail git diff --no-index before after >patch1.patch.raw &&\n+\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" patch1.patch.raw >patch1.patch &&\n \tprintf \"%64s\\n\" 1 2 3 4 5 6 >test-1 &&\n \tprintf \"%64s\\n\" 1 2 3 a b c 4 5 6 >expect-1 &&\n \n@@ -33,8 +33,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" >patch2.patch &&\n+\ttest_must_fail git diff --no-index before after >patch2.patch.raw &&\n+\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" patch2.patch.raw >patch2.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-2 &&\n \tprintf \"%64s\\n\" a b c >expect-2 &&\n \tx=1 &&\n@@ -56,8 +56,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" >patch3.patch &&\n+\ttest_must_fail git diff --no-index before after >patch3.patch.raw &&\n+\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" patch3.patch.raw >patch3.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-3 &&\n \tprintf \"%64s\\n\" a b c >expect-3 &&\n \tx=0 &&\n@@ -84,8 +84,8 @@ test_expect_success setup '\n \t\tprintf \"\\t%02d\\n\" $x >>after\n \t\tx=$(( $x + 1 ))\n \tdone &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" >patch4.patch &&\n+\ttest_must_fail git diff --no-index before after >patch4.patch.raw &&\n+\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" patch4.patch.raw >patch4.patch &&\n \t>test-4 &&\n \tx=0 &&\n \twhile test $x -lt 50\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386226","messageId":"105f0a7a873fce4c741ffdb7bfa458a85311ac79.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 11/27] t5317: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:57Z","receivedAt":"2019-11-15T01:01:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands output to a\nfile and surrounding commands only call command substitutions with\nnon-git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 13 +++++++------\n 1 file changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex 2d2f5d0229..a8bbad74e2 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -72,7 +72,8 @@ test_expect_success 'get an error for missing tree object' '\n \techo foo >r5/foo &&\n \tgit -C r5 add foo &&\n \tgit -C r5 commit -m \"foo\" &&\n-\tdel=$(git -C r5 rev-parse HEAD^{tree} | sed \"s|..|&/|\") &&\n+\tgit -C r5 rev-parse HEAD^{tree} >tree &&\n+\tdel=$(sed \"s|..|&/|\" tree) &&\n \trm r5/.git/objects/$del &&\n \ttest_must_fail git -C r5 pack-objects --revs --stdout 2>bad_tree <<-EOF &&\n \tHEAD\n@@ -230,10 +231,9 @@ test_expect_success 'verify explicitly specifying oversized blob in input' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&\n-\tHEAD\n-\t$(git -C r2 rev-parse HEAD:large.10000)\n-\tEOF\n+\techo HEAD >objects &&\n+\tgit -C r2 rev-parse HEAD:large.10000 >>objects &&\n+\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k <objects >filter.pack &&\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n@@ -377,7 +377,8 @@ test_expect_success 'verify sparse:oid=OID' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\toid=$(git -C r4 ls-files -s pattern | awk -f print_2.awk) &&\n+\tgit -C r4 ls-files -s pattern >staged &&\n+\toid=$(awk -f print_2.awk staged) &&\n \tgit -C r4 pack-objects --revs --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF &&\n \tHEAD\n \tEOF\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386228","messageId":"52836aa59a84bf61781cd3501679011a36ac41e7.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 12/27] t5317: use ! grep to check for no matching lines","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:00:59Z","receivedAt":"2019-11-15T01:01:04Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Several times in t5317, we would use `wc -l` to ensure that a grep\nresult is empty. However, grep already has a way to do that... Its\nreturn code! Use ! grep in the cases where we are ensuring that there\nare no matching lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 21 +++------------------\n 1 file changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex a8bbad74e2..dc0446574b 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -45,12 +45,7 @@ test_expect_success 'verify blob:none packfile has no blobs' '\n \tgit -C r1 index-pack ../filter.pack &&\n \n \tgit -C r1 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify normal and blob:none packfiles have same commits/trees' '\n@@ -149,12 +144,7 @@ test_expect_success 'verify blob:limit=500 omits all blobs' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1000' '\n@@ -164,12 +154,7 @@ test_expect_success 'verify blob:limit=1000' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1001' '\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386229","messageId":"8fc59e67d74faabf43965a5eac1a4147124c56d5.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 13/27] t5703: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:01Z","receivedAt":"2019-11-15T01:01:06Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands are in an\nassignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 52 +++++++++++++++++++-----------\n 1 file changed, 33 insertions(+), 19 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 3a2c143c6d..9f6d837720 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -18,14 +18,16 @@ get_actual_commits () {\n \t\tp\n \t\t}' <out | test-tool pkt-line unpack-sideband >o.pack &&\n \tgit index-pack o.pack &&\n-\tgit verify-pack -v o.idx | grep commit | cut -c-40 | sort >actual_commits\n+\tgit verify-pack -v o.idx >objs &&\n+\tgrep commit objs | cut -c-40 | sort >actual_commits\n }\n \n check_output () {\n \tget_actual_refs &&\n \ttest_cmp expected_refs actual_refs &&\n \tget_actual_commits &&\n-\ttest_cmp expected_commits actual_commits\n+\tsort expected_commits >sorted_commits &&\n+\ttest_cmp sorted_commits actual_commits\n }\n \n # c(o/foo) d(o/bar)\n@@ -75,17 +77,19 @@ test_expect_success 'invalid want-ref line' '\n '\n \n test_expect_success 'basic want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse f | sort >expected_commits &&\n+\tgit rev-parse f >expected_commits &&\n \n+\toid=$(git rev-parse a) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/master\n-\thave $(git rev-parse a)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -95,19 +99,22 @@ test_expect_success 'basic want-ref' '\n '\n \n test_expect_success 'multiple want-ref lines' '\n+\toid_c=$(git rev-parse c) &&\n+\toid_d=$(git rev-parse d) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n-\t$(git rev-parse d) refs/heads/o/bar\n+\t$oid_c refs/heads/o/foo\n+\t$oid_d refs/heads/o/bar\n \tEOF\n-\tgit rev-parse c d | sort >expected_commits &&\n+\tgit rev-parse c d >expected_commits &&\n \n+\toid=$(git rev-parse b) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n \twant-ref refs/heads/o/bar\n-\thave $(git rev-parse b)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -117,10 +124,11 @@ test_expect_success 'multiple want-ref lines' '\n '\n \n test_expect_success 'mix want and want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse e f | sort >expected_commits &&\n+\tgit rev-parse e f >expected_commits &&\n \n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n@@ -138,17 +146,19 @@ test_expect_success 'mix want and want-ref' '\n '\n \n test_expect_success 'want-ref with ref we already have commit for' '\n+\toid=$(git rev-parse c) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n+\t$oid refs/heads/o/foo\n \tEOF\n \t>expected_commits &&\n \n+\toid=$(git rev-parse c) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n-\thave $(git rev-parse c)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -211,13 +221,14 @@ test_expect_success 'fetching with exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse d) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\t$(git -C \"$REPO\" rev-parse d):refs/heads/actual &&\n+\t\t\"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"d\" >expected &&\n \tgit -C local rev-parse refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse d)\" log\n+\tgrep \"want $oid\" log\n '\n \n test_expect_success 'fetching multiple refs' '\n@@ -239,13 +250,14 @@ test_expect_success 'fetching ref and exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse b) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\tmaster $(git -C \"$REPO\" rev-parse b):refs/heads/actual &&\n+\t\tmaster \"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"master\" \"b\" >expected &&\n \tgit -C local rev-parse refs/remotes/origin/master refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse b)\" log &&\n+\tgrep \"want $oid\" log &&\n \tgrep \"want-ref refs/heads/master\" log\n '\n \n@@ -312,9 +324,11 @@ inconsistency () {\n \t# repository appears to change during negotiation, for example, when\n \t# different servers in a load-balancing arrangement serve (stateless)\n \t# RPCs during a single negotiation.\n+\toid1=$(git -C \"$REPO\" rev-parse $1) &&\n+\toid2=$(git -C \"$REPO\" rev-parse $2) &&\n \tprintf \"s/%s/%s/\" \\\n-\t       $(git -C \"$REPO\" rev-parse $1 | tr -d \"\\n\") \\\n-\t       $(git -C \"$REPO\" rev-parse $2 | tr -d \"\\n\") \\\n+\t       $(echo \"$oid1\" | tr -d \"\\n\") \\\n+\t       $(echo \"$oid2\" | tr -d \"\\n\") \\\n \t       >\"$HTTPD_ROOT_PATH/one-time-sed\"\n }\n \n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386230","messageId":"3cb65b5954f5c0297e465f6d5261437debdfdfe6.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 14/27] t7501: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:03Z","receivedAt":"2019-11-15T01:01:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex f1349af56e..5765d33c53 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -150,7 +150,7 @@ test_expect_success 'setup: commit message from file' '\n test_expect_success 'amend commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/a file/an amend commit/g\" < \"$1\" > \"$1-\"\n+\tsed -e \"s/a file/an amend commit/g\" <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -263,7 +263,7 @@ test_expect_success 'using message from other commit' '\n test_expect_success 'editing message from other commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/amend/older/g\"  < \"$1\" > \"$1-\"\n+\tsed -e \"s/amend/older/g\"  <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -367,7 +367,7 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -382,7 +382,7 @@ test_expect_success 'amend commit to fix date' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --date=\"$newtick\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -448,7 +448,7 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -468,7 +468,7 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -489,7 +489,7 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +506,7 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -560,14 +560,14 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n \n test_expect_success 'git commit <file> with dirty index' '\n-\techo tacocat > elif &&\n-\techo tehlulz > chz &&\n+\techo tacocat >elif &&\n+\techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n \tgit show --stat | grep elif &&\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386231","messageId":"f6dc7b7a97783d03900eba2e4607b2a38e963256.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 15/27] t7501: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:06Z","receivedAt":"2019-11-15T01:01:10Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 69 +++++++++++++++------------\n 1 file changed, 39 insertions(+), 30 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex 5765d33c53..110b4bf459 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -285,9 +285,8 @@ test_expect_success 'overriding author from command line' '\n '\n \n test_expect_success PERL 'interactive add' '\n-\techo 7 |\n-\tgit commit --interactive |\n-\tgrep \"What now\"\n+\techo 7 | test_must_fail git commit --interactive >out &&\n+\tgrep \"What now\" out\n '\n \n test_expect_success PERL \"commit --interactive doesn't change index if editor aborts\" '\n@@ -362,10 +361,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -377,10 +376,10 @@ test_expect_success 'amend commit to fix date' '\n \ttest_tick &&\n \tnewtick=$GIT_AUTHOR_DATE &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $newtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --date=\"$newtick\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -409,12 +408,13 @@ test_expect_success 'sign off (1)' '\n \techo 1 >positive &&\n \tgit add positive &&\n \tgit commit -s -m \"thank you\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -428,13 +428,14 @@ test_expect_success 'sign off (2)' '\n \tgit commit -s -m \"thank you\n \n $existing\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n \t\techo $existing &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -448,13 +449,14 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo $alt &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -468,15 +470,16 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo We have now &&\n \t\techo $alt &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -489,7 +492,8 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +510,8 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -538,7 +543,8 @@ test_expect_success 'multiple -m' '\n \t>negative &&\n \tgit add negative &&\n \tgit commit -m \"one\" -m \"two\" -m \"three\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo one &&\n \t\techo &&\n@@ -555,10 +561,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -570,8 +576,10 @@ test_expect_success 'git commit <file> with dirty index' '\n \techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n-\tgit show --stat | grep elif &&\n-\tgit diff --cached | grep chz\n+\tgit show --stat >stat &&\n+\tgrep elif stat &&\n+\tgit diff --cached >diff &&\n+\tgrep chz diff\n '\n \n test_expect_success 'same tree (single parent)' '\n@@ -584,7 +592,8 @@ test_expect_success 'same tree (single parent)' '\n test_expect_success 'same tree (single parent) --allow-empty' '\n \n \tgit commit --allow-empty -m \"forced empty\" &&\n-\tgit cat-file commit HEAD | grep forced\n+\tgit cat-file commit HEAD >commit &&\n+\tgrep forced commit\n \n '\n \n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386232","messageId":"f1bf3355143d787d708fe9367c04c41530f8568a.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 16/27] t7700: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:08Z","receivedAt":"2019-11-15T01:01:13Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nIn one case where the output of stdout is consumed, redirect the output\nof test_commit to stderr.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 4e855bc21b..e1a689d6a9 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -5,7 +5,7 @@ test_description='git repack works correctly'\n . ./test-lib.sh\n \n commit_and_pack() {\n-\ttest_commit \"$@\" >/dev/null &&\n+\ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n@@ -19,7 +19,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n \tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack > /dev/null &&\n+\t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n \tpacksha1=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n@@ -235,7 +235,7 @@ test_expect_success 'incremental repack does not complain' '\n \n test_expect_success 'bitmaps can be disabled on bare repos' '\n \tgit -c repack.writeBitmaps=false -C bare.git repack -ad &&\n-\tbitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) &&\n+\tbitmap=$(ls bare.git/objects/pack/*.bitmap || :) &&\n \ttest -z \"$bitmap\"\n '\n \n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386233","messageId":"206ac68a91f4fabe184403e41496bc341f3f18d1.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 17/27] t7700: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:10Z","receivedAt":"2019-11-15T01:01:15Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 18 +++++++++---------\n 1 file changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex e1a689d6a9..8936928387 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -11,8 +11,8 @@ commit_and_pack() {\n }\n \n test_expect_success 'objects in packs marked .keep are not repacked' '\n-\techo content1 > file1 &&\n-\techo content2 > file2 &&\n+\techo content1 >file1 &&\n+\techo content2 >file2 &&\n \tgit add . &&\n \ttest_tick &&\n \tgit commit -m initial_commit &&\n@@ -75,8 +75,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n-\techo content3 > file3 &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n+\techo content3 >file3 &&\n \tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n@@ -111,7 +111,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n \trm -f .git/objects/pack/* &&\n-\techo new_content >> file1 &&\n+\techo new_content >>file1 &&\n \tgit add file1 &&\n \ttest_tick &&\n \tgit commit -m more_content &&\n@@ -169,12 +169,12 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n@@ -186,7 +186,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n@@ -196,7 +196,7 @@ test_expect_success 'objects made unreachable by grafts only are kept' '\n \tH0=$(git rev-parse HEAD) &&\n \tH1=$(git rev-parse HEAD^) &&\n \tH2=$(git rev-parse HEAD^^) &&\n-\techo \"$H0 $H2\" > .git/info/grafts &&\n+\techo \"$H0 $H2\" >.git/info/grafts &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n \tgit repack -a -d &&\n \tgit cat-file -t $H1\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386235","messageId":"70cbd273aec3da27d10e0b08d63a7494321a7b9b.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 19/27] t7700: s/test -f/test_path_is_file/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:15Z","receivedAt":"2019-11-15T01:01:19Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have debugging-friendly alternatives to `test -f`, replace\ninstances of `test -f` with `test_path_is_file` so that if a command\never fails, we get better debugging information.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex a96e876c4e..1d14ddcbdb 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -106,7 +106,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -129,7 +129,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -148,7 +148,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tfor p in alt_objects/pack/*.pack\n \tdo\n \t\tbase_name=$(basename $p .pack) &&\n-\t\tif test -f alt_objects/pack/$base_name.keep\n+\t\tif test_path_is_file alt_objects/pack/$base_name.keep\n \t\tthen\n \t\t\trm alt_objects/pack/$base_name.keep\n \t\telse\n@@ -157,7 +157,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tdone &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386234","messageId":"0d776372553d223ecf11d7dc773125bd0a549200.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 18/27] t7700: move keywords onto their own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:13Z","receivedAt":"2019-11-15T01:01:20Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move keywords onto their own line so that they conform with\nthe test style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 51 +++++++++++++++++++++++++++++++----------------\n 1 file changed, 34 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 8936928387..a96e876c4e 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -29,10 +29,12 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -45,10 +47,12 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -61,10 +65,12 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -83,8 +89,10 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -99,10 +107,13 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -119,10 +130,13 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -144,10 +158,13 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386236","messageId":"d9dcb23662bd09bb1325f20478475a8263e4a21b.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 20/27] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:17Z","receivedAt":"2019-11-15T01:01:22Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 64 ++++++++++++++++++++++++++++-------------------\n 1 file changed, 38 insertions(+), 26 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 1d14ddcbdb..ff50722e26 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -18,14 +18,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit commit -m initial_commit &&\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n-\tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack &&\n+\tgit rev-list --objects --all >objs &&\n+\tgrep -v file2 objs | git pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpacksha1=$(git rev-list --objects --all | grep file2 |\n-\t\tgit pack-objects pack) &&\n+\tpacksha1=$(grep file2 objs | git pack-objects pack) &&\n \t>pack-$packsha1.keep &&\n-\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n-\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n+\tgit verify-pack -v pack-$packsha1.idx >packlist &&\n+\tobjsha1=$(head -n 1 packlist | sed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -33,7 +32,8 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -51,7 +51,8 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -69,7 +70,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -91,7 +93,8 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit prune-packed &&\n \tfor p in .git/objects/pack/*.idx\n \tdo\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -109,15 +112,18 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n@@ -132,15 +138,18 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n@@ -160,15 +169,18 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n@@ -184,8 +196,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! egrep \"^$csha1 \" packlist &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n@@ -201,8 +213,8 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! egrep \"^$csha1 \" &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386237","messageId":"3f79d23b40c0586d0351f4d721097be4f7ba26b8.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 21/27] t: define test_grep_return_success()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:19Z","receivedAt":"2019-11-15T01:01:23Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a future patch, we plan on running tests with `set -o pipefail`.\nHowever, since grep can return failure in the case that no lines are\nmatched, this can trigger a failure in a pipe in the case where grep is\nbeing used as a filter.\n\nDefine the test_grep_return_success() function which acts as a wrapper\naround grep but always returns 0 so that it can be used in the situation\ndescribed above.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/test-lib-functions.sh | 5 +++++\n 1 file changed, 5 insertions(+)\n\ndiff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\nindex b299ecc326..dddc4cc3b1 100644\n--- a/t/test-lib-functions.sh\n+++ b/t/test-lib-functions.sh\n@@ -990,6 +990,11 @@ test_i18ngrep () {\n \treturn 1\n }\n \n+# Calls grep but returns zero even if no matching lines are found.\n+test_grep_return_success () {\n+\tgrep \"$@\" || :\n+}\n+\n # Call any command \"$@\" but be more verbose about its\n # failure. This is handy for commands like \"test\" which do\n # not output anything when they fail.\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386238","messageId":"0f3d1c04a1283675db0c6704bbdd2566d405163e.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 22/27] t0090: mask failing grep status","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:22Z","receivedAt":"2019-11-15T01:01:26Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a future patch, we plan on running tests with `set -o pipefail`.\nHowever, since grep can return failure in the case that no lines are\nmatched, this can trigger a failure in a pipe in the case where grep is\nbeing used as a filter.\n\nUse test_grep_return_success() instead of grep so that we don't fail\neven if we have no matching lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0090-cache-tree.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 5a633690bf..b0f3b69d1d 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -22,7 +22,7 @@ generate_expected_cache_tree_rec () {\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n \tgit ls-files >files &&\n-\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n+\tsubtrees=$(test_grep_return_success / files|cut -d / -f 1|uniq) &&\n \tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n \tentries=$(wc -l <files) &&\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386239","messageId":"bc4c208f7814c3362fa5949af3cb8d2d2904f386.1573779465.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 23/27] t3600: mark git command as failing","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:24Z","receivedAt":"2019-11-15T01:01:28Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a future patch, we plan on running tests with `set -o pipefail`.\nSince we intentionally induce SIGPIPE, before the return code\nwas being masked away. However, now `git rm` will cause an error code to\nbe returned because of the SIGPIPE.\n\nMark the failing command with `test_must_fail ok=sigpipe` so that\nfailures induced by SIGPIPE don't propogate.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 0ea858d652..d1b3703edb 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -252,7 +252,7 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n \t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n-\tgit rm -n \"some-file-*\" | : &&\n+\ttest_must_fail ok=sigpipe git rm -n \"some-file-*\" | : &&\n \ttest_path_is_missing .git/index.lock\n '\n \n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386240","messageId":"d27ee1e627339f2fc6a8fdf3b1be79435c9a4bc6.1573779466.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 24/27] t5004: ignore SIGPIPE in zipinfo","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:26Z","receivedAt":"2019-11-15T01:01:30Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a future patch, we plan on running tests with `set -o pipefail`.\nSince zipinfo is killed by SIGPIPE, it will return an error code which\nwill propogate as a result of the pipefail.\n\nMask away the return code of zipinfo so that the failure as a result of\nthe SIGPIPE does not propogate.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5004-archive-corner-cases.sh | 4 +++-\n 1 file changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh\nindex 3e7b23cb32..4c6d42d474 100755\n--- a/t/t5004-archive-corner-cases.sh\n+++ b/t/t5004-archive-corner-cases.sh\n@@ -153,7 +153,9 @@ test_expect_success ZIPINFO 'zip archive with many entries' '\n \n \t# check the number of entries in the ZIP file directory\n \texpr 65536 + 256 >expect &&\n-\t\"$ZIPINFO\" many.zip | head -2 | sed -n \"2s/.* //p\" >actual &&\n+\t{\n+\t\t\"$ZIPINFO\" many.zip || :\n+\t} | head -2 | sed -n \"2s/.* //p\" >actual &&\n \ttest_cmp expect actual\n '\n \n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386241","messageId":"d259d55656140a3c35c8585b093afac13a49e5c6.1573779466.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 25/27] t5703: mask failing grep status","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:28Z","receivedAt":"2019-11-15T01:01:32Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a future patch, we plan on running tests with `set -o pipefail`.\nHowever, since grep can return failure in the case that no lines are\nmatched, this can trigger a failure in a pipe in the case where grep is\nbeing used as a filter.\n\nUse test_grep_return_success() instead of grep so that we don't fail\neven if we have no matching lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 9f6d837720..c4f9698398 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -19,7 +19,7 @@ get_actual_commits () {\n \t\t}' <out | test-tool pkt-line unpack-sideband >o.pack &&\n \tgit index-pack o.pack &&\n \tgit verify-pack -v o.idx >objs &&\n-\tgrep commit objs | cut -c-40 | sort >actual_commits\n+\ttest_grep_return_success commit objs | cut -c-40 | sort >actual_commits\n }\n \n check_output () {\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386242","messageId":"95806f55e7e0ad1ac187ea162a74d5883fa86e67.1573779466.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 26/27] t9902: disable pipefail","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:30Z","receivedAt":"2019-11-15T01:01:34Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a future patch, we plan on running tests with `set -o pipefail`.\nHowever, these tests cannot run with pipefail. Since git-completion.bash\nis not a testing script, it does not follow the same return code\nconventions and it's expected that commands can fail within a pipeline.\n\nRun `set +o pipefail` to disable pipefail in this script.\n\nNote that this is being unconditionally run because this test will be\nskipped if its not running on Bash.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t9902-completion.sh | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex e90ac565e1..75a512669e 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -7,6 +7,12 @@ test_description='test bash completion'\n \n . ./lib-bash.sh\n \n+# These tests cannot run with pipefail. Since git-completion.bash is not\n+# a testing script, it does not follow the same return code conventions\n+# and it's expected that commands can fail within a pipeline. Ignore\n+# these failures.\n+set +o pipefail\n+\n complete ()\n {\n \t# do nothing\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386243","messageId":"bc3f226edf284d96dc7fff15c188ecfbc32162d6.1573779466.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH 27/27] t: run tests with `set -o pipefail` on Bash","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-15T01:01:32Z","receivedAt":"2019-11-15T01:01:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The current convention is to ensure that git commands are not placed in\nthe upstream of a pipe. If they are, they could fail in an undetectable\nmanner since a pipe's return code is the last command in the pipe.\nHowever, many old tests are still written with git commands in the\nupstream of a pipe.\n\nIn the spirit of catching these failures, run tests with\n`set -o pipefail` if the underlying shell is Bash. This way, we can\ncatch failures of Git commands that may occur even in the middle of a\npipeline.\n\nIn the future, more shells that support `set -o pipefail` may have it\nenabled but let's start small for now.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/README      |  4 ++++\n t/test-lib.sh | 12 ++++++++++++\n 2 files changed, 16 insertions(+)\n\ndiff --git a/t/README b/t/README\nindex 60d5b77bcc..ba96b6d113 100644\n--- a/t/README\n+++ b/t/README\n@@ -415,6 +415,10 @@ GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=<boolean>, when true (which is\n the default when running tests), errors out when an abbreviated option\n is used.\n \n+GIT_TEST_PIPEFAIL=<boolean>, when true, run 'set -o pipefail' to catch\n+failures in commands that aren't the last in a pipe. Defaults to true on\n+Bash and false otherwise.\n+\n Naming Tests\n ------------\n \ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 46c4440843..c0c43dfce9 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -64,6 +64,18 @@ then\n \texport GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS\n fi\n \n+# Use set -o pipefail on platforms that support it\n+GIT_TEST_PIPEFAIL_DEFAULT=false\n+# TODO: detect more platforms that support `set -o pipefail`\n+if test -n \"$BASH_VERSION\"\n+then\n+\tGIT_TEST_PIPEFAIL_DEFAULT=true\n+fi\n+if git env--helper --type=bool --default=\"$GIT_TEST_PIPEFAIL_DEFAULT\" --exit-code GIT_TEST_PIPEFAIL\n+then\n+\tset -o pipefail\n+fi\n+\n ################################################################\n # It appears that people try to run tests without building...\n \"${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X\" >/dev/null\n-- \n2.24.0.399.gf8350c9437\n\n"},{"id":"386248","messageId":"20191115040909.GA21654@sigill.intra.peff.net","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 00/27] t: general test cleanup + `set -o pipefail`","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2019-11-15T04:09:09Z","receivedAt":"2019-11-15T04:09:11Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 14, 2019 at 05:00:29PM -0800, Denton Liu wrote:\n\n> Patches 1-20 perform some general test cleanup to modernise the style.\n> They should be relatively uncontroversial and can be merged earlier (or\n> as a separate series) if desired. The reason these tests were identified\n> for cleanup was because they failed under `set -o pipefail`.\n> \n> Patches 21-27 should be considered RFC. In an attempt to catch git\n> commands failing in the upstream of a pipe, we enable `set -o pipefail`\n> on Bash. This may result in some funny-looking shell script constructs\n> (e.g. needing to wrap `grep` since it may \"fail\") but overall, I think it\n> is an improvement since we catch failure in more cases.\n\nUsing pipefail can have unexpected consequences for other commands if\nthey rely on SIGPIPE/EPIPE to signal the left-hand side of the pipe.\nE.g., this:\n\n  $ set -o pipefail\n  $ yes | head >/dev/null\n  $ echo $?\n\nwill consistently yield 141, since \"yes\" will always die to SIGPIPE\nafter \"head\" stops reading from it.\n\nBut much worse, this can be racy. Take something like this (which is a\nreal snippet in our test suite):\n\n  git status -s -b | head -1\n\nThe \"head\" process will quit after reading one line. What's the exit\ncode of \"git status\"? It's either \"0\", if it managed to write everything\ninto the pipe buffer before the simultaneously-running \"head\" closed the\npipe. Or it's 141, if it didn't and got SIGPIPE.\n\nYou could argue that \"git status\" should not be on the left-hand side of\na pipe, but the same holds for any command on the left-hand side. E.g.,\ngrepping in our test scripts yields some bits like:\n\n  t/t7003-filter-branch.sh:       echo \"$faux_gpg_tag\" | sed -e s/XXXXXX/$sha1/ | head -n 6 > expect &&\n  t/t9400-git-cvsserver-server.sh:   test \"$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | head -n 1))\" = \"empty/1.1/\" &&\n\nAnd it's not just \"head\" that doesn't read all of its input. Another\ncommon one is \"grep -q\", which can quit as soon as it sees a match.\n\nSo I have a feeling that pipefail is going to create more headaches than\nit solves.\n\n-Peff\n"},{"id":"386255","messageId":"xmqq1ru990c8.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"3f79d23b40c0586d0351f4d721097be4f7ba26b8.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 21/27] t: define test_grep_return_success()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-15T05:26:31Z","receivedAt":"2019-11-15T05:26:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> +# Calls grep but returns zero even if no matching lines are found.\n> +test_grep_return_success () {\n> +\tgrep \"$@\" || :\n> +}\n\nIt makes sense to have a helper like this, but the name is quite a\nmouthful.  I wonder if we can call it with a shorter name, e.g.\n\"test_filter\" or something.\n\n"},{"id":"386256","messageId":"xmqqsgmp7ld6.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"bc4c208f7814c3362fa5949af3cb8d2d2904f386.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 23/27] t3600: mark git command as failing","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-15T05:35:17Z","receivedAt":"2019-11-15T05:35:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> In a future patch, we plan on running tests with `set -o pipefail`.\n> Since we intentionally induce SIGPIPE, before the return code\n> was being masked away. However, now `git rm` will cause an error code to\n> be returned because of the SIGPIPE.\n>\n> Mark the failing command with `test_must_fail ok=sigpipe` so that\n> failures induced by SIGPIPE don't propogate.\n\nHmph, would this pipeline _always_ fail?  I somehow thought that a\nprocess that writes into a pipe that is not being read would fail\nonly if the downstream dies and closes before it write(2)s, and if\nthe output from this \"git rm -n\" is small enough (say to fit within\nthe pipe buffer) and downstream no-op is slow enough to die, the\nupstream may probably not notice and happily and successfully exit.\n\n    : with slow downstream\n    $ ( ( printf \"%s\\n\" a b c d e); echo \"my exit $?\" 1>&2 ) |\n      ( sleep 2; echo \"downstream exit $?\" ); echo \"overall exit $?\"\n    my exit 0\n    downstream exit 0\n    overall exit 0\n\n    : with slow upstream\n    $ ( (sleep 2; printf \"%s\\n\" a b c d e); echo \"my exit $?\" 1>&2 ) |\n      ( echo \"downstream exit $?\" ); echo \"overall exit $?\"\n    downstream exit 0\n    my exit 141\n    overall exit 0\n\nSo, no, I do not think this is a good idea.  It would be racy.\n\n\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n>  t/t3600-rm.sh | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n>\n> diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\n> index 0ea858d652..d1b3703edb 100755\n> --- a/t/t3600-rm.sh\n> +++ b/t/t3600-rm.sh\n> @@ -252,7 +252,7 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n>  \t\ti=$(( $i + 1 ))\n>  \tdone | git update-index --index-info &&\n>  \t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n> -\tgit rm -n \"some-file-*\" | : &&\n> +\ttest_must_fail ok=sigpipe git rm -n \"some-file-*\" | : &&\n>  \ttest_path_is_missing .git/index.lock\n>  '\n"},{"id":"386257","messageId":"xmqqo8xd7laz.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"d27ee1e627339f2fc6a8fdf3b1be79435c9a4bc6.1573779466.git.liu.denton@gmail.com","subject":"Re: [PATCH 24/27] t5004: ignore SIGPIPE in zipinfo","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-15T05:36:36Z","receivedAt":"2019-11-15T05:36:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> In a future patch, we plan on running tests with `set -o pipefail`.\n> Since zipinfo is killed by SIGPIPE, it will return an error code which\n\ns/is killed/may be killed/ for the reasons I wrote for 23/27, I think.\n\nOtherwise the idea behind the patch is good.\n\nThanks.\n\n> will propogate as a result of the pipefail.\n>\n> Mask away the return code of zipinfo so that the failure as a result of\n> the SIGPIPE does not propogate.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n>  t/t5004-archive-corner-cases.sh | 4 +++-\n>  1 file changed, 3 insertions(+), 1 deletion(-)\n>\n> diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh\n> index 3e7b23cb32..4c6d42d474 100755\n> --- a/t/t5004-archive-corner-cases.sh\n> +++ b/t/t5004-archive-corner-cases.sh\n> @@ -153,7 +153,9 @@ test_expect_success ZIPINFO 'zip archive with many entries' '\n>  \n>  \t# check the number of entries in the ZIP file directory\n>  \texpr 65536 + 256 >expect &&\n> -\t\"$ZIPINFO\" many.zip | head -2 | sed -n \"2s/.* //p\" >actual &&\n> +\t{\n> +\t\t\"$ZIPINFO\" many.zip || :\n> +\t} | head -2 | sed -n \"2s/.* //p\" >actual &&\n>  \ttest_cmp expect actual\n>  '\n"},{"id":"386339","messageId":"CAPig+cQx=kOZrsR9d05qK9KTnR5X8gAXf0jMysK+njPbX-_6SQ@mail.gmail.com","threadId":"52269","inReplyTo":"b4442fb408c80cf6c4d8fd05b474c0094e243126.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 01/27] lib-bash.sh: move `then` onto its own line","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-15T18:22:09Z","receivedAt":"2019-11-15T18:22:24Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Nov 14, 2019 at 8:00 PM Denton Liu <liu.denton@gmail.com> wrote:\n> The code style for tests is to have statements on their own line if\n> possible. Move the `then` onto its own line so that it conforms with the\n> test style.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/t/lib-bash.sh b/t/lib-bash.sh\n> @@ -2,7 +2,8 @@\n> -if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"; then\n> +if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n> +then\n\nOkay...\n\n>         # we are in full-on bash mode\n>         true\n>  elif type bash >/dev/null 2>&1; then\n\n... but why not move this 'then' to its own line, as well?\n"},{"id":"386357","messageId":"xmqq4kz45ybn.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"CAPig+cQx=kOZrsR9d05qK9KTnR5X8gAXf0jMysK+njPbX-_6SQ@mail.gmail.com","subject":"Re: [PATCH 01/27] lib-bash.sh: move `then` onto its own line","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-16T02:50:36Z","receivedAt":"2019-11-16T02:50:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> On Thu, Nov 14, 2019 at 8:00 PM Denton Liu <liu.denton@gmail.com> wrote:\n>> The code style for tests is to have statements on their own line if\n>> possible. Move the `then` onto its own line so that it conforms with the\n>> test style.\n>>\n>> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n>> ---\n>> diff --git a/t/lib-bash.sh b/t/lib-bash.sh\n>> @@ -2,7 +2,8 @@\n>> -if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"; then\n>> +if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n>> +then\n>\n> Okay...\n>\n>>         # we are in full-on bash mode\n>>         true\n>>  elif type bash >/dev/null 2>&1; then\n>\n> ... but why not move this 'then' to its own line, as well?\n\nGood eyes ;-)\n"},{"id":"386366","messageId":"CAPig+cSFoksyqTGeL7tNh7sjXWVPi9HYS6+6qui6C-VE0LqedA@mail.gmail.com","threadId":"52269","inReplyTo":"d617cbaaf1232e45b077786afaa9d3465a9bbd35.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 10/27] t4138: stop losing return codes of git commands","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-16T09:00:35Z","receivedAt":"2019-11-16T09:00:57Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Nov 14, 2019 at 8:01 PM Denton Liu <liu.denton@gmail.com> wrote:\n> In a pipe, only the return code of the last command is used. Thus, all\n> other commands will have their return codes masked. Rewrite pipes so\n> that there are no git commands upstream so that we will know if a\n> command fails.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh\n> @@ -17,8 +17,8 @@ test_expect_success setup '\n> -       git diff --no-index before after |\n> -               sed -e \"s/before/test-1/\" -e \"s/after/test-1/\" >patch1.patch &&\n> +       test_must_fail git diff --no-index before after >patch1.patch.raw &&\n> +       sed -e \"s/before/test-1/\" -e \"s/after/test-1/\" patch1.patch.raw >patch1.patch &&\n\nI think this is a semantically incorrect use of test_must_fail(). What\nyou're interested here is that git-diff found differences (as opposed\nto not finding any), so you want to test its exit code which reflects\nwhether or not the files were different. Hence, the following would be\nmore appropriate:\n\n    test_expect_code 1 git diff --no-index before after >patch1.patch.raw &&\n\nSame comment applies to remaining changes in this patch.\n"},{"id":"386367","messageId":"CAPig+cT_co53B66P8hKzFai=0HbXHLfNO5-Dbx_qZZa7Vj-4WA@mail.gmail.com","threadId":"52269","inReplyTo":"52836aa59a84bf61781cd3501679011a36ac41e7.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 12/27] t5317: use ! grep to check for no matching lines","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-16T09:27:08Z","receivedAt":"2019-11-16T09:27:23Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Nov 14, 2019 at 8:01 PM Denton Liu <liu.denton@gmail.com> wrote:\n> Several times in t5317, we would use `wc -l` to ensure that a grep\n> result is empty. However, grep already has a way to do that... Its\n> return code! Use ! grep in the cases where we are ensuring that there\n> are no matching lines.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\n> @@ -45,12 +45,7 @@ test_expect_success 'verify blob:none packfile has no blobs' '\n>         git -C r1 verify-pack -v ../filter.pack >verify_result &&\n> -       grep blob verify_result |\n> -       awk -f print_1.awk |\n> -       sort >observed &&\n> -\n> -       nr=$(wc -l <observed) &&\n> -       test 0 -eq $nr\n> +       ! grep blob verify_result\n\nIt's curious that this and other tests were doing so much unnecessary\nextra work ('awk' and 'sort'). While it's clear that it's safe to drop\nthe 'awk' and 'sed' invocations, nevertheless, as a reviewer, I had to\nspend extra time digging into it in order to understand why it was\nlike this in the first place, since I wanted to convince myself that\nsome earlier change hadn't broken the test in some unnoticed way.\n\nIt turns out that these tests were simply born this way[1], doing all\nthis unnecessary work for no reason, probably due to copy/paste\nprogramming, and it seems no reviewer caught it. Likewise, the\nunnecessary work wasn't noticed even when the code was later touched\nfor various cleanups[2,3].\n\nTo save future reviewers (and future readers of the commit history)\nthe effort of having to convince themselves of the safety of this\nchange, it might be a good idea to say something in the commit message\nabout the code's history.\n\n[1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n[2]: bdbc17e86a (tests: standardize pipe placement, 2018-10-05)\n[3]: 61de0ff695 (tests: don't swallow Git errors upstream of pipes, 2018-10-05)\n"},{"id":"386368","messageId":"CAPig+cTj5qOCFRoD4cZOg7BjVvetQWTgdRHzSvAfgtX2YgUXPg@mail.gmail.com","threadId":"52269","inReplyTo":"8fc59e67d74faabf43965a5eac1a4147124c56d5.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 13/27] t5703: stop losing return codes of git commands","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-16T10:11:12Z","receivedAt":"2019-11-16T10:11:53Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Nov 14, 2019 at 8:01 PM Denton Liu <liu.denton@gmail.com> wrote:\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\n> @@ -312,9 +324,11 @@ inconsistency () {\n> +       oid1=$(git -C \"$REPO\" rev-parse $1) &&\n> +       oid2=$(git -C \"$REPO\" rev-parse $2) &&\n>         printf \"s/%s/%s/\" \\\n> -              $(git -C \"$REPO\" rev-parse $1 | tr -d \"\\n\") \\\n> -              $(git -C \"$REPO\" rev-parse $2 | tr -d \"\\n\") \\\n> +              $(echo \"$oid1\" | tr -d \"\\n\") \\\n> +              $(echo \"$oid2\" | tr -d \"\\n\") \\\n>                >\"$HTTPD_ROOT_PATH/one-time-sed\"\n\nThis code is rather odd. The $(...) substitution already takes care of\nstripping out newlines, so the 'tr' invocations in both the original\nand the revised code are superfluous. As this patch series\nincorporates various other cleanups, it would not be inappropriate to\ncreate a patch which removes the unnecessary 'tr' invocations\npreparatory to this patch. The final result should be a simple:\n\n    printf \"s/%s/%s/\" $oid1 $oid2 >\"$HTTPD_ROOT_PATH/one-time-sed\"\n\nor even simpler:\n\n    printf \"s/$oid1/$oid2/\" >\"$HTTPD_ROOT_PATH/one-time-sed\"\n\nIn fact, given the way the tests actually employ \"one-time-sed\" via\n$(cat one-time-sed) in t/lib-httpd/apply-one-time-sed.sh, it could\neven be as simple as:\n\n    echo \"s/$oid1/$oid2/\" >\"$HTTPD_ROOT_PATH/one-time-sed\"\n\nwhich makes it consistent with the final \"server loses a ref - ref in\nwant\" test, which does use 'echo' rather than 'printf'. (That change\nmight also deserve its own patch.)\n"},{"id":"386369","messageId":"CAPig+cR-CkALYM1m1yaWaOBW+vpZyjDbn9MoZV=q+KXR6_ZCmg@mail.gmail.com","threadId":"52269","inReplyTo":"f6dc7b7a97783d03900eba2e4607b2a38e963256.1573779465.git.liu.denton@gmail.com","subject":"Re: [PATCH 15/27] t7501: stop losing return codes of git commands","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-16T10:35:21Z","receivedAt":"2019-11-16T10:35:35Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Nov 14, 2019 at 8:01 PM Denton Liu <liu.denton@gmail.com> wrote:\n> In a pipe, only the return code of the last command is used. Thus, all\n> other commands will have their return codes masked. Rewrite pipes so\n> that there are no git commands upstream so that we will know if a\n> command fails.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\n> @@ -285,9 +285,8 @@ test_expect_success 'overriding author from command line' '\n>  test_expect_success PERL 'interactive add' '\n> -       echo 7 |\n> -       git commit --interactive |\n> -       grep \"What now\"\n> +       echo 7 | test_must_fail git commit --interactive >out &&\n> +       grep \"What now\" out\n>  '\n\ngit-commit documentation does not talk about the command's exit code,\nso it's not immediately clear why this test should be using\ntest_must_fail() for the invocation. The implementation of git-commit\nis more illuminating, showing that 1 is returned when there are no\nchanges to commit, and 0 for a successful commit. So, that raises the\nquestion of whether this should be using \"test_expect_code 1\" rather\nthan test_must_fail(), however, there is existing precedence which\ngives some guidance. In particular, the \"nothing to commit\" test of\nt7501-commit-basic-functionality.sh does use test_must_fail() when\nattempting to commit with no changes. It may make sense, therefore, to\nmention something about this in the commit message to save future\nreaders from wondering why the command is \"expected to fail\".\n"},{"id":"386671","messageId":"cover.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1573779465.git.liu.denton@gmail.com","subject":"[PATCH v2 00/21] t: test cleanup stemming from experimentally enabling pipefail","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:45:45Z","receivedAt":"2019-11-21T00:45:51Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"These patches perform some general test cleanup to modernise the style.\nThey should be relatively uncontroversial. The reason these tests were\nidentified for cleanup was because they failed under `set -o pipefail`.\n\nI've gotten rid of the RFC part that actually enables `set -o pipefail`\non supported platforms. As Peff pointed out, there are a lot of\nopportunities for racy SIGPIPE failures so that part still needs a lot\nof work to be ironed out.\n\nThose changes shouldn't hold back the first part of the series, however.\nLet's try to get this test cleanup merged in sooner than later so that\nany new test cases done by copy-paste will have their changes\nrepresented.\n\nChanges since v1:\n\n* Removed the `set -o pipefail` changes\n\n* Addressed Junio and Eric's comments on the first part of the series\n\nDenton Liu (21):\n  lib-bash.sh: move `then` onto its own line\n  t0014: remove git command upstream of pipe\n  t0090: stop losing return codes of git commands\n  t3301: stop losing return codes of git commands\n  t3600: use test_line_count() where possible\n  t3600: stop losing return codes of git commands\n  t3600: comment on inducing SIGPIPE in `git rm`\n  t4015: stop losing return codes of git commands\n  t4015: use test_write_lines()\n  t4138: stop losing return codes of git commands\n  t5317: stop losing return codes of git commands\n  t5317: use ! grep to check for no matching lines\n  t5703: simplify one-time-sed generation logic\n  t5703: stop losing return codes of git commands\n  t7501: remove spaces after redirect operators\n  t7501: stop losing return codes of git commands\n  t7700: drop redirections to /dev/null\n  t7700: remove spaces after redirect operators\n  t7700: move keywords onto their own line\n  t7700: s/test -f/test_path_is_file/\n  t7700: stop losing return codes of git commands\n\n t/lib-bash.sh                          |   6 +-\n t/t0014-alias.sh                       |   4 +-\n t/t0090-cache-tree.sh                  |   5 +-\n t/t3301-notes.sh                       | 230 ++++++++++++++++++-------\n t/t3600-rm.sh                          |  14 +-\n t/t4015-diff-whitespace.sh             | 123 +++++++------\n t/t4138-apply-ws-expansion.sh          |  16 +-\n t/t5317-pack-objects-filter-objects.sh |  34 ++--\n t/t5703-upload-pack-ref-in-want.sh     |  53 +++---\n t/t7501-commit-basic-functionality.sh  |  83 +++++----\n t/t7700-repack.sh                      | 125 ++++++++------\n 11 files changed, 428 insertions(+), 265 deletions(-)\n\nRange-diff against v1:\n 1:  a1a1199254 !  1:  da6ff63918 lib-bash.sh: move `then` onto its own line\n    @@ t/lib-bash.sh\n     +then\n      \t# we are in full-on bash mode\n      \ttrue\n    - elif type bash >/dev/null 2>&1; then\n    +-elif type bash >/dev/null 2>&1; then\n    ++elif type bash >/dev/null 2>&1\n    ++then\n    + \t# execute in full-on bash mode\n    + \tunset POSIXLY_CORRECT\n    + \texec bash \"$0\" \"$@\"\n 2:  735d3fce93 =  2:  c0a513145d t0014: remove git command upstream of pipe\n 3:  c29a54880a =  3:  52d8933ac9 t0090: stop losing return codes of git commands\n 4:  5d634f8e5d =  4:  e8eafa1551 t3301: stop losing return codes of git commands\n 5:  49069d12c0 =  5:  97ad3604dd t3600: use test_line_count() where possible\n 6:  e4c43b686a =  6:  e0152ff3c1 t3600: stop losing return codes of git commands\n 7:  91001a5be3 =  7:  54e9e78e03 t3600: comment on inducing SIGPIPE in `git rm`\n 8:  738e0f1c27 =  8:  7c9e9a4b81 t4015: stop losing return codes of git commands\n 9:  63b0028057 =  9:  9fb33ea04e t4015: use test_write_lines()\n10:  8f9945bb16 ! 10:  6c91594492 t4138: stop losing return codes of git commands\n    @@ t/t4138-apply-ws-expansion.sh: test_expect_success setup '\n      \tprintf \"\\t%s\\n\" 4 5 6 >>after &&\n     -\tgit diff --no-index before after |\n     -\t\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" >patch1.patch &&\n    -+\ttest_must_fail git diff --no-index before after >patch1.patch.raw &&\n    ++\ttest_expect_code 1 git diff --no-index before after >patch1.patch.raw &&\n     +\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" patch1.patch.raw >patch1.patch &&\n      \tprintf \"%64s\\n\" 1 2 3 4 5 6 >test-1 &&\n      \tprintf \"%64s\\n\" 1 2 3 a b c 4 5 6 >expect-1 &&\n    @@ t/t4138-apply-ws-expansion.sh: test_expect_success setup '\n      \tprintf \"\\t%s\\n\" d e f >>after &&\n     -\tgit diff --no-index before after |\n     -\t\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" >patch2.patch &&\n    -+\ttest_must_fail git diff --no-index before after >patch2.patch.raw &&\n    ++\ttest_expect_code 1 git diff --no-index before after >patch2.patch.raw &&\n     +\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" patch2.patch.raw >patch2.patch &&\n      \tprintf \"%64s\\n\" a b c d e f >test-2 &&\n      \tprintf \"%64s\\n\" a b c >expect-2 &&\n    @@ t/t4138-apply-ws-expansion.sh: test_expect_success setup '\n      \tprintf \"\\t%s\\n\" d e f >>after &&\n     -\tgit diff --no-index before after |\n     -\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" >patch3.patch &&\n    -+\ttest_must_fail git diff --no-index before after >patch3.patch.raw &&\n    ++\ttest_expect_code 1 git diff --no-index before after >patch3.patch.raw &&\n     +\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" patch3.patch.raw >patch3.patch &&\n      \tprintf \"%64s\\n\" a b c d e f >test-3 &&\n      \tprintf \"%64s\\n\" a b c >expect-3 &&\n    @@ t/t4138-apply-ws-expansion.sh: test_expect_success setup '\n      \tdone &&\n     -\tgit diff --no-index before after |\n     -\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" >patch4.patch &&\n    -+\ttest_must_fail git diff --no-index before after >patch4.patch.raw &&\n    ++\ttest_expect_code 1 git diff --no-index before after >patch4.patch.raw &&\n     +\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" patch4.patch.raw >patch4.patch &&\n      \t>test-4 &&\n      \tx=0 &&\n11:  823ed38115 = 11:  04beafae8e t5317: stop losing return codes of git commands\n12:  6342f480d5 ! 12:  b24745bd60 t5317: use ! grep to check for no matching lines\n    @@ Commit message\n     \n         Several times in t5317, we would use `wc -l` to ensure that a grep\n         result is empty. However, grep already has a way to do that... Its\n    -    return code! Use ! grep in the cases where we are ensuring that there\n    +    return code! Use `! grep` in the cases where we are ensuring that there\n         are no matching lines.\n     \n    +    It turns out that these tests were simply born this way[1], doing all\n    +    this unnecessary work for no reason, probably due to copy/paste\n    +    programming, and it seems no reviewer caught it. Likewise, the\n    +    unnecessary work wasn't noticed even when the code was later touched\n    +    for various cleanups[2,3].\n    +\n    +    [1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n    +    [2]: bdbc17e86a (tests: standardize pipe placement, 2018-10-05)\n    +    [3]: 61de0ff695 (tests: don't swallow Git errors upstream of pipes, 2018-10-05)\n    +\n    +    Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n     \n    +\n    + ## Notes ##\n    +    Thanks for your help, Eric. I shamelessly stole your message text for\n    +    the commit message.\n    +\n      ## t/t5317-pack-objects-filter-objects.sh ##\n     @@ t/t5317-pack-objects-filter-objects.sh: test_expect_success 'verify blob:none packfile has no blobs' '\n      \tgit -C r1 index-pack ../filter.pack &&\n -:  ---------- > 13:  d5fb60be6b t5703: simplify one-time-sed generation logic\n13:  89b68fc876 ! 14:  4071168d8b t5703: stop losing return codes of git commands\n    @@ t/t5703-upload-pack-ref-in-want.sh: test_expect_success 'fetching ref and exact\n      \tgrep \"want-ref refs/heads/master\" log\n      '\n      \n    -@@ t/t5703-upload-pack-ref-in-want.sh: inconsistency () {\n    - \t# repository appears to change during negotiation, for example, when\n    - \t# different servers in a load-balancing arrangement serve (stateless)\n    - \t# RPCs during a single negotiation.\n    -+\toid1=$(git -C \"$REPO\" rev-parse $1) &&\n    -+\toid2=$(git -C \"$REPO\" rev-parse $2) &&\n    - \tprintf \"s/%s/%s/\" \\\n    --\t       $(git -C \"$REPO\" rev-parse $1 | tr -d \"\\n\") \\\n    --\t       $(git -C \"$REPO\" rev-parse $2 | tr -d \"\\n\") \\\n    -+\t       $(echo \"$oid1\" | tr -d \"\\n\") \\\n    -+\t       $(echo \"$oid2\" | tr -d \"\\n\") \\\n    - \t       >\"$HTTPD_ROOT_PATH/one-time-sed\"\n    - }\n    - \n14:  6ab0dafb54 = 15:  63eebe1df6 t7501: remove spaces after redirect operators\n15:  952d3fdfe4 ! 16:  4675d3dbc4 t7501: stop losing return codes of git commands\n    @@ Commit message\n         that there are no git commands upstream so that we will know if a\n         command fails.\n     \n    +    In the 'interactive add' test case, we prepend a `test_must_fail` to\n    +    `git commit --interactive`. When there are no changes to commit,\n    +    `git commit` will exit with status code 1. Following along with the rest\n    +    of the file, we use `test_must_fail` to test for this case.\n    +\n         Signed-off-by: Denton Liu <liu.denton@gmail.com>\n     \n      ## t/t7501-commit-basic-functionality.sh ##\n16:  e30db4d20e = 17:  3cc6e4455c t7700: drop redirections to /dev/null\n17:  664145360d = 18:  43f184dbd5 t7700: remove spaces after redirect operators\n18:  6a63a98b1c = 19:  9389a74fe0 t7700: move keywords onto their own line\n19:  4749dbcb88 = 20:  079a42c45b t7700: s/test -f/test_path_is_file/\n20:  6821af454c = 21:  a455fbb625 t7700: stop losing return codes of git commands\n21:  6d0243d9bc <  -:  ---------- t: define test_grep_return_success()\n22:  d56a851930 <  -:  ---------- t0090: mask failing grep status\n23:  df8fab5f1c <  -:  ---------- t3600: mark git command as failing\n24:  ca29fdaddd <  -:  ---------- t5004: ignore SIGPIPE in zipinfo\n25:  4d3c28d90e <  -:  ---------- t5703: mask failing grep status\n26:  d89c2c24ae <  -:  ---------- t9902: disable pipefail\n27:  7036c96fc7 <  -:  ---------- t: run tests with `set -o pipefail` on Bash\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386672","messageId":"da6ff639186c6e1ece4e3a69576f61e03ec3bb7f.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 01/21] lib-bash.sh: move `then` onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:45:48Z","receivedAt":"2019-11-21T00:45:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move the `then` onto its own line so that it conforms with the\ntest style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-bash.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/lib-bash.sh b/t/lib-bash.sh\nindex 2be955fafb..b0b6060929 100644\n--- a/t/lib-bash.sh\n+++ b/t/lib-bash.sh\n@@ -2,10 +2,12 @@\n # to run under Bash; primarily intended for tests of the completion\n # script.\n \n-if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"; then\n+if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+then\n \t# we are in full-on bash mode\n \ttrue\n-elif type bash >/dev/null 2>&1; then\n+elif type bash >/dev/null 2>&1\n+then\n \t# execute in full-on bash mode\n \tunset POSIXLY_CORRECT\n \texec bash \"$0\" \"$@\"\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386673","messageId":"c0a513145deea51a5b216cb6344b1b3a17c54423.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 02/21] t0014: remove git command upstream of pipe","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:45:50Z","receivedAt":"2019-11-21T00:45:55Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, the `git frotz` command would fail but its return code was\nhidden since it was in the upstream of a pipe. Break the pipeline into\ntwo commands so that the return code is no longer lost. Also, mark\n`git frotz` with test_must_fail since it's supposed to fail.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0014-alias.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0014-alias.sh b/t/t0014-alias.sh\nindex 2694c81afd..8d3d9144c0 100755\n--- a/t/t0014-alias.sh\n+++ b/t/t0014-alias.sh\n@@ -38,8 +38,8 @@ test_expect_success 'looping aliases - internal execution' '\n #'\n \n test_expect_success 'run-command formats empty args properly' '\n-    GIT_TRACE=1 git frotz a \"\" b \" \" c 2>&1 |\n-    sed -ne \"/run_command:/s/.*trace: run_command: //p\" >actual &&\n+    test_must_fail env GIT_TRACE=1 git frotz a \"\" b \" \" c 2>actual.raw &&\n+    sed -ne \"/run_command:/s/.*trace: run_command: //p\" actual.raw >actual &&\n     echo \"git-frotz a '\\'''\\'' b '\\'' '\\'' c\" >expect &&\n     test_cmp expect actual\n '\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386674","messageId":"52d8933ac9daabcb7c2693e338c11f6c6d335ecf.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 03/21] t0090: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:45:53Z","receivedAt":"2019-11-21T00:45:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In generate_expected_cache_tree_rec(), there are currently two instances\nof `git ls-files` in the upstream of a pipe. In the case where the\nupstream git command fails, its return code will be lost. Extract the\n`git ls-files` into its own call so that if it ever fails, its return\ncode is not lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0090-cache-tree.sh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex ce9a4a5f32..5a633690bf 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -21,9 +21,10 @@ generate_expected_cache_tree_rec () {\n \tparent=\"$2\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n-\tsubtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&\n+\tgit ls-files >files &&\n+\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n \tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n-\tentries=$(git ls-files|wc -l) &&\n+\tentries=$(wc -l <files) &&\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n \tfor subtree in $subtrees\n \tdo\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386675","messageId":"e8eafa1551163d89b4c643c8e46c79d6aaa02fb5.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 04/21] t3301: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:45:55Z","receivedAt":"2019-11-21T00:46:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nThis patch fixes a real buggy test: in 'copy note with \"git notes\ncopy\"', `git notes` was mistyped as `git note`.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3301-notes.sh | 230 +++++++++++++++++++++++++++++++++--------------\n 1 file changed, 163 insertions(+), 67 deletions(-)\n\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex d66a5f6faa..8f43303007 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -54,7 +54,9 @@ test_expect_success 'create notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b4\" = \"$(git notes show)\" &&\n+\techo b4 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -79,14 +81,21 @@ test_expect_success 'edit existing notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n \n test_expect_success 'show notes from treeish' '\n-\ttest \"b3\" = \"$(git notes --ref commits^{tree} show)\" &&\n-\ttest \"b4\" = \"$(git notes --ref commits@{1} show)\"\n+\techo b3 >expect &&\n+\tgit notes --ref commits^{tree} show >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo b4 >expect &&\n+\tgit notes --ref commits@{1} show >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot edit notes from non-ref' '\n@@ -99,7 +108,9 @@ test_expect_success 'cannot \"git notes add -m\" where notes already exists' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -109,7 +120,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f -m\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -119,7 +132,9 @@ test_expect_success 'add w/no options on existing note morphs into edit' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b2\" = \"$(git notes show)\" &&\n+\techo b2 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -129,7 +144,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -146,7 +163,8 @@ test_expect_success 'show notes' '\n \t\tNotes:\n \t\t${indent}b1\n \tEOF\n-\t! (git cat-file commit HEAD | grep b1) &&\n+\tgit cat-file commit HEAD >commits &&\n+\t! grep b1 commits &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -472,9 +490,11 @@ test_expect_success 'removing with --stdin --ignore-missing' '\n test_expect_success 'list notes with \"git notes list\"' '\n \tcommit_2=$(git rev-parse 2nd) &&\n \tcommit_3=$(git rev-parse 3rd) &&\n+\tnote_2=$(git rev-parse refs/notes/commits:$commit_2) &&\n+\tnote_3=$(git rev-parse refs/notes/commits:$commit_3) &&\n \tsort -t\" \" -k2 >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect actual\n@@ -486,9 +506,7 @@ test_expect_success 'list notes with \"git notes\"' '\n '\n \n test_expect_success 'list specific note with \"git notes list <object>\"' '\n-\tcat >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_3)\n-\tEOF\n+\tgit rev-parse refs/notes/commits:$commit_3 >expect &&\n \tgit notes list HEAD^^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -512,10 +530,11 @@ test_expect_success 'append to existing note with \"git notes append\"' '\n \n test_expect_success '\"git notes list\" does not expand to \"git notes list HEAD\"' '\n \tcommit_5=$(git rev-parse 5th) &&\n+\tnote_5=$(git rev-parse refs/notes/commits:$commit_5) &&\n \tsort -t\" \" -k2 >expect_list <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n-\t\t$(git rev-parse refs/notes/commits:$commit_5) $commit_5\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n+\t\t$note_5 $commit_5\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect_list actual\n@@ -721,7 +740,8 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '\n \tgit notes show HEAD: >actual &&\n \ttest_cmp expect actual &&\n \techo \"Note on a blob\" >expect &&\n-\tfilename=$(git ls-tree --name-only HEAD | head -n1) &&\n+\tgit ls-tree --name-only HEAD >files &&\n+\tfilename=$(head -n1 files) &&\n \tgit notes add -m \"Note on a blob\" HEAD:$filename &&\n \tgit notes show HEAD:$filename >actual &&\n \ttest_cmp expect actual &&\n@@ -745,10 +765,13 @@ test_expect_success 'create note from other note with \"git notes add -C\"' '\n \t\tNotes:\n \t\t${indent}order test\n \tEOF\n-\tgit notes add -C $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes add -C $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'create note from non-existing note with \"git notes add -C\" fails' '\n@@ -777,11 +800,12 @@ test_expect_success 'create note from blob with \"git notes add -C\" reuses blob i\n \t\tNotes:\n \t\t${indent}This is a blob object\n \tEOF\n-\tblob=$(echo \"This is a blob object\" | git hash-object -w --stdin) &&\n-\tgit notes add -C $blob &&\n+\techo \"This is a blob object\" | git hash-object -w --stdin >blob &&\n+\tgit notes add -C $(cat blob) &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$blob\"\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp blob actual\n '\n \n test_expect_success 'create note from other note with \"git notes add -c\"' '\n@@ -797,7 +821,8 @@ test_expect_success 'create note from other note with \"git notes add -c\"' '\n \t\tNotes:\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes add -c $(git notes list HEAD^^) &&\n+\tnote=$(git notes list HEAD^^) &&\n+\tMSG=\"yet another note\" git notes add -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -822,7 +847,8 @@ test_expect_success 'append to note from other note with \"git notes append -C\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tgit notes append -C $(git notes list HEAD^) HEAD^ &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes append -C $note HEAD^ &&\n \tgit log -1 HEAD^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -839,7 +865,8 @@ test_expect_success 'create note from other note with \"git notes append -c\"' '\n \t\tNotes:\n \t\t${indent}other note\n \tEOF\n-\tMSG=\"other note\" git notes append -c $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tMSG=\"other note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -858,7 +885,8 @@ test_expect_success 'append to note from other note with \"git notes append -c\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes append -c $(git notes list HEAD) &&\n+\tnote=$(git notes list HEAD) &&\n+\tMSG=\"yet another note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -878,7 +906,9 @@ test_expect_success 'copy note with \"git notes copy\"' '\n \tgit notes copy 8th 4th &&\n \tgit log 3rd..4th >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git note list 4th)\" = \"$(git note list 8th)\"\n+\tgit notes list 4th >expect &&\n+\tgit notes list 8th >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'copy note with \"git notes copy\" with default' '\n@@ -899,14 +929,30 @@ test_expect_success 'copy note with \"git notes copy\" with default' '\n \tgit notes copy HEAD^ &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'prevent overwrite with \"git notes copy\"' '\n \ttest_must_fail git notes copy HEAD~2 HEAD &&\n+\tcat >expect <<-EOF &&\n+\t\tcommit $commit\n+\t\tAuthor: A U Thor <author@example.com>\n+\t\tDate:   Thu Apr 7 15:23:13 2005 -0700\n+\n+\t\t${indent}11th\n+\n+\t\tNotes:\n+\t\t${indent}other note\n+\t\t${indent}\n+\t\t${indent}yet another note\n+\tEOF\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n@@ -924,7 +970,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n \tgit notes copy -f HEAD~3 HEAD &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n@@ -944,7 +992,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n \tgit notes copy -f HEAD~2 &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot copy note from object without notes' '\n@@ -979,13 +1029,21 @@ test_expect_success 'git notes copy --stdin' '\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --stdin &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --stdin <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\" &&\n-\ttest \"$(git notes list HEAD^)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual &&\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD^ >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n@@ -1006,9 +1064,13 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n \n \t\t${indent}14th\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1041,17 +1103,23 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '\n \tEOF\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (disabled)' '\n \ttest_config notes.rewrite.bar false &&\n-\techo $(git rev-parse HEAD~3) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=bar &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=bar <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1071,8 +1139,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n \tgit notes add -f -m\"a fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1080,8 +1150,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n test_expect_success 'git notes copy --for-rewrite (ignore)' '\n \ttest_config notes.rewriteMode ignore &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1103,8 +1175,10 @@ test_expect_success 'git notes copy --for-rewrite (append)' '\n \tgit notes add -f -m\"another fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1131,9 +1205,13 @@ test_expect_success 'git notes copy --for-rewrite (append two to one)' '\n \tgit notes add -f -m\"append 2\" HEAD^^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD^) $(git rev-parse HEAD) &&\n-\techo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD^^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1142,8 +1220,10 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '\n \tgit notes remove HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1163,8 +1243,10 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n \tgit notes add -f -m\"replacement note 1\" HEAD^ &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1184,9 +1266,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF works' '\n \tgit notes add -f -m\"replacement note 2\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_unconfig notes.rewriteRef &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1195,9 +1279,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '\n \tgit notes add -f -m\"replacement note 3\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef refs/notes/other &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \tgrep \"replacement note 3\" actual\n '\n@@ -1212,26 +1298,36 @@ test_expect_success 'git notes copy diagnoses too many or too few parameters' '\n test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes --ref=refs/heads/master get-ref)\" = \"refs/notes/refs/heads/master\"\n+\techo refs/notes/refs/heads/master >expect &&\n+\tgit notes --ref=refs/heads/master get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (no overrides)' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/commits\"\n+\techo refs/notes/commits >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (core.notesRef)' '\n \ttest_config core.notesRef refs/notes/foo &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/foo\"\n+\techo refs/notes/foo >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (GIT_NOTES_REF)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes get-ref)\" = \"refs/notes/bar\"\n+\techo refs/notes/bar >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (--ref)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref)\" = \"refs/notes/baz\"\n+\techo refs/notes/baz >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'setup testing of empty notes' '\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386676","messageId":"97ad3604dd9a84f20d4913e69bf2b16a6f7c5103.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 05/21] t3600: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:45:58Z","receivedAt":"2019-11-21T00:46:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have a helper function that can test the number of lines in a\nfile that gives better debugging information on failure, use\ntest_line_count() to test the number of lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 8c8cca5bfb..f6e659b7e9 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -113,9 +113,10 @@ test_expect_success '\"rm\" command printed' '\n \techo frotz >test-file &&\n \tgit add test-file &&\n \tgit commit -m \"add file for rm test\" &&\n-\tgit rm test-file >rm-output &&\n-\ttest $(grep \"^rm \" rm-output | wc -l) = 1 &&\n-\trm -f test-file rm-output &&\n+\tgit rm test-file >rm-output.raw &&\n+\tgrep \"^rm \" rm-output.raw >rm-output &&\n+\ttest_line_count = 1 rm-output &&\n+\trm -f test-file rm-output.raw rm-output &&\n \tgit commit -m \"remove file from rm test\"\n '\n \n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386677","messageId":"e0152ff3c1935969a97bc5bdb9831a277bc8f95d.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 06/21] t3600: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:00Z","receivedAt":"2019-11-21T00:46:06Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"When a command is in a non-assignment command substitution, the return\ncode will be lost in favour of the surrounding command's. As a result,\nif a git command fails, we won't know about it. Rewrite instances of\nthis so that git commands are either run in an assignment-only command\nsubstitution so that their return codes aren't lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex f6e659b7e9..0c3bf10edd 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -304,7 +304,8 @@ EOF\n \n test_expect_success 'rm removes empty submodules from work tree' '\n \tmkdir submod &&\n-\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) submod &&\n+\thash=$(git rev-parse HEAD) &&\n+\tgit update-index --add --cacheinfo 160000 \"$hash\" submod &&\n \tgit config -f .gitmodules submodule.sub.url ./. &&\n \tgit config -f .gitmodules submodule.sub.path submod &&\n \tgit submodule init &&\n@@ -623,7 +624,8 @@ test_expect_success 'setup subsubmodule' '\n \tgit submodule update &&\n \t(\n \t\tcd submod &&\n-\t\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) subsubmod &&\n+\t\thash=$(git rev-parse HEAD) &&\n+\t\tgit update-index --add --cacheinfo 160000 \"$hash\" subsubmod &&\n \t\tgit config -f .gitmodules submodule.sub.url ../. &&\n \t\tgit config -f .gitmodules submodule.sub.path subsubmod &&\n \t\tgit submodule init &&\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386678","messageId":"54e9e78e0323c7fad8ced40fbc7ba4236dd61056.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 07/21] t3600: comment on inducing SIGPIPE in `git rm`","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:03Z","receivedAt":"2019-11-21T00:46:07Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Add a comment about intentionally inducing SIGPIPE since this is unusual\nand future developers should be aware. Also, even though we are trying\nto refactor git commands out of the upstream of pipes, we cannot do it\nhere since we rely on it being upstream to induce SIGPIPE. Comment on\nthat as well so that future developers do not try to change it.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 0c3bf10edd..0ea858d652 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -251,6 +251,7 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\techo \"100644 $hash 0\tsome-file-$i\"\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n+\t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n \tgit rm -n \"some-file-*\" | : &&\n \ttest_path_is_missing .git/index.lock\n '\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386679","messageId":"7c9e9a4b814744b3d34230828c320931545affc9.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 08/21] t4015: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:05Z","receivedAt":"2019-11-21T00:46:10Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 119 ++++++++++++++++++++++---------------\n 1 file changed, 72 insertions(+), 47 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex eadaf57262..7fb83c8eff 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -16,7 +16,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t} while (0);\n \tEOF\n \tgit update-index --add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \tcat <<-\\EOF >x &&\n \tdo\n@@ -25,7 +26,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t}\n \twhile (0);\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -63,7 +65,8 @@ test_expect_success 'another test, without options' '\n \tEOF\n \n \tgit update-index x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \ttr \"_\" \" \" <<-\\EOF >x &&\n \t_\twhitespace at beginning\n@@ -73,7 +76,8 @@ test_expect_success 'another test, without options' '\n \tunchanged line\n \tCR at end\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \ttr \"Q_\" \"\\015 \" <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -526,13 +530,15 @@ test_expect_success 'ignore-blank-lines: mix changes and blank lines' '\n test_expect_success 'check mixed spaces and tabs in indent' '\n \t# This is indented with SP HT SP.\n \techo \" \t foo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check mixed tabs and spaces in indent' '\n \t# This is indented with HT SP HT.\n \techo \"\t \tfoo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check with no whitespace errors' '\n@@ -753,20 +759,23 @@ test_expect_success 'check tab-in-indent excluded from wildcard whitespace attri\n test_expect_success 'line numbers in --check output are correct' '\n \techo \"\" >x &&\n \techo \"foo(); \" >>x &&\n-\tgit diff --check | grep \"x:2:\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"x:2:\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n \techo \"foo();\" >x &&\n \techo \"\" >>x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n \t{ echo a; echo b; echo; echo; } >x &&\n \tgit add x &&\n \t{ echo a; echo; echo; echo; echo; } >x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff allows new blank lines' '\n@@ -794,14 +803,16 @@ test_expect_success 'whitespace-only changes reported across renames' '\n \tgit reset --hard &&\n \tfor i in 1 2 3 4 5 6 7 8 9; do echo \"$i$i$i$i$i$i\"; done >x &&\n \tgit add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\thash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$hash_x\") &&\n \tgit commit -m \"base\" &&\n \tsed -e \"5s/^/ /\" x >z &&\n \tgit rm x &&\n \tgit add z &&\n-\tafter=$(git rev-parse --short $(git hash-object z)) &&\n-\tgit diff -w -M --cached |\n-\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" >actual &&\n+\thash_z=$(git hash-object z) &&\n+\tafter=$(git rev-parse --short \"$hash_z\") &&\n+\tgit diff -w -M --cached >actual.raw &&\n+\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" actual.raw >actual &&\n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/z\n \tsimilarity index NUM%\n@@ -840,7 +851,8 @@ test_expect_success 'combined diff with autocrlf conversion' '\n \tgit config core.autocrlf true &&\n \ttest_must_fail git merge master &&\n \n-\tgit diff | sed -e \"1,/^@@@/d\" >actual &&\n+\tgit diff >actual.raw &&\n+\tsed -e \"1,/^@@@/d\" actual.raw >actual &&\n \t! grep \"^-\" actual\n \n '\n@@ -864,11 +876,14 @@ test_expect_success 'diff that introduces a line with only tabs' '\n \tgit config core.whitespace blank-at-eol &&\n \tgit reset --hard &&\n \techo \"test\" >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -m \"initial\" x &&\n \techo \"{NTN}\" | tr \"NT\" \"\\n\\t\" >>x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n-\tgit diff --color | test_decode_color >current &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -891,17 +906,19 @@ test_expect_success 'diff that introduces and removes ws breakages' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n-\tgit diff --color |\n-\ttest_decode_color >current &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -925,14 +942,16 @@ test_expect_success 'ws-error-highlight test setup' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat >expect.default-old <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -974,32 +993,32 @@ test_expect_success 'ws-error-highlight test setup' '\n \n test_expect_success 'test --ws-error-highlight option' '\n \n-\tgit diff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit diff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit diff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n \n test_expect_success 'test diff.wsErrorHighlight config' '\n \n-\tgit -c diff.wsErrorHighlight=default,old diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=default,old diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit -c diff.wsErrorHighlight=all diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=all diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit -c diff.wsErrorHighlight=none diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=none diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1007,18 +1026,18 @@ test_expect_success 'test diff.wsErrorHighlight config' '\n test_expect_success 'option overrides diff.wsErrorHighlight' '\n \n \tgit -c diff.wsErrorHighlight=none \\\n-\t\tdiff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n \tgit -c diff.wsErrorHighlight=default \\\n-\t\tdiff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n \tgit -c diff.wsErrorHighlight=all \\\n-\t\tdiff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1038,7 +1057,8 @@ test_expect_success 'detect moved code, complete file' '\n \tgit mv test.c main.c &&\n \ttest_config color.diff.oldMoved \"normal red\" &&\n \ttest_config color.diff.newMoved \"normal green\" &&\n-\tgit diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&\n+\tgit diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>new file mode 100644<RESET>\n@@ -1141,9 +1161,12 @@ test_expect_success 'detect malicious moved code, inside file' '\n \t\t\tbar();\n \t\t}\n \tEOF\n-\tafter_main=$(git rev-parse --short $(git hash-object main.c)) &&\n-\tafter_test=$(git rev-parse --short $(git hash-object test.c)) &&\n-\tgit diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&\n+\thash_main=$(git hash-object main.c) &&\n+\tafter_main=$(git rev-parse --short \"$hash_main\") &&\n+\thash_test=$(git hash-object test.c) &&\n+\tafter_test=$(git rev-parse --short \"$hash_test\") &&\n+\tgit diff HEAD --no-renames --color-moved=zebra --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1192,7 +1215,8 @@ test_expect_success 'plain moved code, inside file' '\n \ttest_config color.diff.oldMovedAlternative \"blue\" &&\n \ttest_config color.diff.newMovedAlternative \"yellow\" &&\n \t# needs previous test as setup\n-\tgit diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&\n+\tgit diff HEAD --no-renames --color-moved=plain --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1771,7 +1795,8 @@ test_expect_success 'move detection with submodules' '\n \t! grep BRED decoded_actual &&\n \n \t# nor did we mess with it another way\n-\tgit diff --submodule=diff --color | test_decode_color >expect &&\n+\tgit diff --submodule=diff --color >expect.raw &&\n+\ttest_decode_color <expect.raw >expect &&\n \ttest_cmp expect decoded_actual &&\n \trm -rf bananas &&\n \tgit submodule deinit bananas\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386680","messageId":"9fb33ea04eb291ea8de3968fef998435d2fd1cc9.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 09/21] t4015: use test_write_lines()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:07Z","receivedAt":"2019-11-21T00:46:12Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Instead of rolling our own method to write out some lines into a file,\nuse the existing test_write_lines().\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex 7fb83c8eff..4c540b1d70 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -771,9 +771,9 @@ test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n-\t{ echo a; echo b; echo; echo; } >x &&\n+\ttest_write_lines a b \"\" \"\" >x &&\n \tgit add x &&\n-\t{ echo a; echo; echo; echo; echo; } >x &&\n+\ttest_write_lines a \"\" \"\" \"\" \"\" >x &&\n \ttest_must_fail git diff --check >check &&\n \tgrep \"new blank line\" check\n '\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386681","messageId":"6c91594492e0be4b7ae7638e964f610534a170ca.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 10/21] t4138: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:10Z","receivedAt":"2019-11-21T00:46:14Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4138-apply-ws-expansion.sh | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh\nindex 3b636a63a3..b19faeb67a 100755\n--- a/t/t4138-apply-ws-expansion.sh\n+++ b/t/t4138-apply-ws-expansion.sh\n@@ -17,8 +17,8 @@ test_expect_success setup '\n \tprintf \"\\t%s\\n\" 1 2 3 >after &&\n \tprintf \"%64s\\n\" a b c >>after &&\n \tprintf \"\\t%s\\n\" 4 5 6 >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" >patch1.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch1.patch.raw &&\n+\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" patch1.patch.raw >patch1.patch &&\n \tprintf \"%64s\\n\" 1 2 3 4 5 6 >test-1 &&\n \tprintf \"%64s\\n\" 1 2 3 a b c 4 5 6 >expect-1 &&\n \n@@ -33,8 +33,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" >patch2.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch2.patch.raw &&\n+\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" patch2.patch.raw >patch2.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-2 &&\n \tprintf \"%64s\\n\" a b c >expect-2 &&\n \tx=1 &&\n@@ -56,8 +56,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" >patch3.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch3.patch.raw &&\n+\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" patch3.patch.raw >patch3.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-3 &&\n \tprintf \"%64s\\n\" a b c >expect-3 &&\n \tx=0 &&\n@@ -84,8 +84,8 @@ test_expect_success setup '\n \t\tprintf \"\\t%02d\\n\" $x >>after\n \t\tx=$(( $x + 1 ))\n \tdone &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" >patch4.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch4.patch.raw &&\n+\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" patch4.patch.raw >patch4.patch &&\n \t>test-4 &&\n \tx=0 &&\n \twhile test $x -lt 50\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386682","messageId":"04beafae8e4cec1cee3a82bef81e6010267ae1ff.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 11/21] t5317: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:12Z","receivedAt":"2019-11-21T00:46:17Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands output to a\nfile and surrounding commands only call command substitutions with\nnon-git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 13 +++++++------\n 1 file changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex 2d2f5d0229..a8bbad74e2 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -72,7 +72,8 @@ test_expect_success 'get an error for missing tree object' '\n \techo foo >r5/foo &&\n \tgit -C r5 add foo &&\n \tgit -C r5 commit -m \"foo\" &&\n-\tdel=$(git -C r5 rev-parse HEAD^{tree} | sed \"s|..|&/|\") &&\n+\tgit -C r5 rev-parse HEAD^{tree} >tree &&\n+\tdel=$(sed \"s|..|&/|\" tree) &&\n \trm r5/.git/objects/$del &&\n \ttest_must_fail git -C r5 pack-objects --revs --stdout 2>bad_tree <<-EOF &&\n \tHEAD\n@@ -230,10 +231,9 @@ test_expect_success 'verify explicitly specifying oversized blob in input' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&\n-\tHEAD\n-\t$(git -C r2 rev-parse HEAD:large.10000)\n-\tEOF\n+\techo HEAD >objects &&\n+\tgit -C r2 rev-parse HEAD:large.10000 >>objects &&\n+\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k <objects >filter.pack &&\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n@@ -377,7 +377,8 @@ test_expect_success 'verify sparse:oid=OID' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\toid=$(git -C r4 ls-files -s pattern | awk -f print_2.awk) &&\n+\tgit -C r4 ls-files -s pattern >staged &&\n+\toid=$(awk -f print_2.awk staged) &&\n \tgit -C r4 pack-objects --revs --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF &&\n \tHEAD\n \tEOF\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386683","messageId":"b24745bd6059017358bf47e96ad9ce33481f440f.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 12/21] t5317: use ! grep to check for no matching lines","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:14Z","receivedAt":"2019-11-21T00:46:19Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Several times in t5317, we would use `wc -l` to ensure that a grep\nresult is empty. However, grep already has a way to do that... Its\nreturn code! Use `! grep` in the cases where we are ensuring that there\nare no matching lines.\n\nIt turns out that these tests were simply born this way[1], doing all\nthis unnecessary work for no reason, probably due to copy/paste\nprogramming, and it seems no reviewer caught it. Likewise, the\nunnecessary work wasn't noticed even when the code was later touched\nfor various cleanups[2,3].\n\n[1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n[2]: bdbc17e86a (tests: standardize pipe placement, 2018-10-05)\n[3]: 61de0ff695 (tests: don't swallow Git errors upstream of pipes, 2018-10-05)\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n\nNotes:\n    Thanks for your help, Eric. I shamelessly stole your message text for\n    the commit message.\n\n t/t5317-pack-objects-filter-objects.sh | 21 +++------------------\n 1 file changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex a8bbad74e2..dc0446574b 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -45,12 +45,7 @@ test_expect_success 'verify blob:none packfile has no blobs' '\n \tgit -C r1 index-pack ../filter.pack &&\n \n \tgit -C r1 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify normal and blob:none packfiles have same commits/trees' '\n@@ -149,12 +144,7 @@ test_expect_success 'verify blob:limit=500 omits all blobs' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1000' '\n@@ -164,12 +154,7 @@ test_expect_success 'verify blob:limit=1000' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1001' '\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386684","messageId":"d5fb60be6bdd5e885c6f830c8c44ba250350538b.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 13/21] t5703: simplify one-time-sed generation logic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:17Z","receivedAt":"2019-11-21T00:46:21Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In inconsistency(), we had two `git rev-parse` invocations in the\nupstream of a pipe within a command substitution. In case this\ninvocation ever failed, its exit code would be swallowed up and we would\nnot know about it.\n\nPull the command substitutions out into variable assignments so that\ntheir return codes are not lost.\n\nDrop the pipe into tr because command substitutions should already strip\nleading and trailing whitespace, including newlines.\n\nFinally, convert the printf into an echo because it isn't necessary\nanymore.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 7 +++----\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 3a2c143c6d..88338c4e09 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -312,10 +312,9 @@ inconsistency () {\n \t# repository appears to change during negotiation, for example, when\n \t# different servers in a load-balancing arrangement serve (stateless)\n \t# RPCs during a single negotiation.\n-\tprintf \"s/%s/%s/\" \\\n-\t       $(git -C \"$REPO\" rev-parse $1 | tr -d \"\\n\") \\\n-\t       $(git -C \"$REPO\" rev-parse $2 | tr -d \"\\n\") \\\n-\t       >\"$HTTPD_ROOT_PATH/one-time-sed\"\n+\toid1=$(git -C \"$REPO\" rev-parse $1) &&\n+\toid2=$(git -C \"$REPO\" rev-parse $2) &&\n+\techo \"s/$oid1/$oid2/\" >\"$HTTPD_ROOT_PATH/one-time-sed\"\n }\n \n test_expect_success 'server is initially ahead - no ref in want' '\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386685","messageId":"4071168d8b50b7f976e81becfab30f4d0b27b81c.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 14/21] t5703: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:19Z","receivedAt":"2019-11-21T00:46:25Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands are in an\nassignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 46 +++++++++++++++++++-----------\n 1 file changed, 29 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 88338c4e09..1424fabd4a 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -18,14 +18,16 @@ get_actual_commits () {\n \t\tp\n \t\t}' <out | test-tool pkt-line unpack-sideband >o.pack &&\n \tgit index-pack o.pack &&\n-\tgit verify-pack -v o.idx | grep commit | cut -c-40 | sort >actual_commits\n+\tgit verify-pack -v o.idx >objs &&\n+\tgrep commit objs | cut -c-40 | sort >actual_commits\n }\n \n check_output () {\n \tget_actual_refs &&\n \ttest_cmp expected_refs actual_refs &&\n \tget_actual_commits &&\n-\ttest_cmp expected_commits actual_commits\n+\tsort expected_commits >sorted_commits &&\n+\ttest_cmp sorted_commits actual_commits\n }\n \n # c(o/foo) d(o/bar)\n@@ -75,17 +77,19 @@ test_expect_success 'invalid want-ref line' '\n '\n \n test_expect_success 'basic want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse f | sort >expected_commits &&\n+\tgit rev-parse f >expected_commits &&\n \n+\toid=$(git rev-parse a) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/master\n-\thave $(git rev-parse a)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -95,19 +99,22 @@ test_expect_success 'basic want-ref' '\n '\n \n test_expect_success 'multiple want-ref lines' '\n+\toid_c=$(git rev-parse c) &&\n+\toid_d=$(git rev-parse d) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n-\t$(git rev-parse d) refs/heads/o/bar\n+\t$oid_c refs/heads/o/foo\n+\t$oid_d refs/heads/o/bar\n \tEOF\n-\tgit rev-parse c d | sort >expected_commits &&\n+\tgit rev-parse c d >expected_commits &&\n \n+\toid=$(git rev-parse b) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n \twant-ref refs/heads/o/bar\n-\thave $(git rev-parse b)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -117,10 +124,11 @@ test_expect_success 'multiple want-ref lines' '\n '\n \n test_expect_success 'mix want and want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse e f | sort >expected_commits &&\n+\tgit rev-parse e f >expected_commits &&\n \n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n@@ -138,17 +146,19 @@ test_expect_success 'mix want and want-ref' '\n '\n \n test_expect_success 'want-ref with ref we already have commit for' '\n+\toid=$(git rev-parse c) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n+\t$oid refs/heads/o/foo\n \tEOF\n \t>expected_commits &&\n \n+\toid=$(git rev-parse c) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n-\thave $(git rev-parse c)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -211,13 +221,14 @@ test_expect_success 'fetching with exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse d) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\t$(git -C \"$REPO\" rev-parse d):refs/heads/actual &&\n+\t\t\"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"d\" >expected &&\n \tgit -C local rev-parse refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse d)\" log\n+\tgrep \"want $oid\" log\n '\n \n test_expect_success 'fetching multiple refs' '\n@@ -239,13 +250,14 @@ test_expect_success 'fetching ref and exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse b) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\tmaster $(git -C \"$REPO\" rev-parse b):refs/heads/actual &&\n+\t\tmaster \"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"master\" \"b\" >expected &&\n \tgit -C local rev-parse refs/remotes/origin/master refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse b)\" log &&\n+\tgrep \"want $oid\" log &&\n \tgrep \"want-ref refs/heads/master\" log\n '\n \n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386686","messageId":"63eebe1df6f7c0983cdbbf835ac2c42c84317158.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 15/21] t7501: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:22Z","receivedAt":"2019-11-21T00:46:26Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex f1349af56e..5765d33c53 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -150,7 +150,7 @@ test_expect_success 'setup: commit message from file' '\n test_expect_success 'amend commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/a file/an amend commit/g\" < \"$1\" > \"$1-\"\n+\tsed -e \"s/a file/an amend commit/g\" <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -263,7 +263,7 @@ test_expect_success 'using message from other commit' '\n test_expect_success 'editing message from other commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/amend/older/g\"  < \"$1\" > \"$1-\"\n+\tsed -e \"s/amend/older/g\"  <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -367,7 +367,7 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -382,7 +382,7 @@ test_expect_success 'amend commit to fix date' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --date=\"$newtick\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -448,7 +448,7 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -468,7 +468,7 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -489,7 +489,7 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +506,7 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -560,14 +560,14 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n \n test_expect_success 'git commit <file> with dirty index' '\n-\techo tacocat > elif &&\n-\techo tehlulz > chz &&\n+\techo tacocat >elif &&\n+\techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n \tgit show --stat | grep elif &&\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386687","messageId":"4675d3dbc4c066707218949154f51441c19d5ce0.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 16/21] t7501: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:24Z","receivedAt":"2019-11-21T00:46:30Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nIn the 'interactive add' test case, we prepend a `test_must_fail` to\n`git commit --interactive`. When there are no changes to commit,\n`git commit` will exit with status code 1. Following along with the rest\nof the file, we use `test_must_fail` to test for this case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 69 +++++++++++++++------------\n 1 file changed, 39 insertions(+), 30 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex 5765d33c53..110b4bf459 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -285,9 +285,8 @@ test_expect_success 'overriding author from command line' '\n '\n \n test_expect_success PERL 'interactive add' '\n-\techo 7 |\n-\tgit commit --interactive |\n-\tgrep \"What now\"\n+\techo 7 | test_must_fail git commit --interactive >out &&\n+\tgrep \"What now\" out\n '\n \n test_expect_success PERL \"commit --interactive doesn't change index if editor aborts\" '\n@@ -362,10 +361,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -377,10 +376,10 @@ test_expect_success 'amend commit to fix date' '\n \ttest_tick &&\n \tnewtick=$GIT_AUTHOR_DATE &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $newtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --date=\"$newtick\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -409,12 +408,13 @@ test_expect_success 'sign off (1)' '\n \techo 1 >positive &&\n \tgit add positive &&\n \tgit commit -s -m \"thank you\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -428,13 +428,14 @@ test_expect_success 'sign off (2)' '\n \tgit commit -s -m \"thank you\n \n $existing\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n \t\techo $existing &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -448,13 +449,14 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo $alt &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -468,15 +470,16 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo We have now &&\n \t\techo $alt &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -489,7 +492,8 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +510,8 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -538,7 +543,8 @@ test_expect_success 'multiple -m' '\n \t>negative &&\n \tgit add negative &&\n \tgit commit -m \"one\" -m \"two\" -m \"three\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo one &&\n \t\techo &&\n@@ -555,10 +561,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -570,8 +576,10 @@ test_expect_success 'git commit <file> with dirty index' '\n \techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n-\tgit show --stat | grep elif &&\n-\tgit diff --cached | grep chz\n+\tgit show --stat >stat &&\n+\tgrep elif stat &&\n+\tgit diff --cached >diff &&\n+\tgrep chz diff\n '\n \n test_expect_success 'same tree (single parent)' '\n@@ -584,7 +592,8 @@ test_expect_success 'same tree (single parent)' '\n test_expect_success 'same tree (single parent) --allow-empty' '\n \n \tgit commit --allow-empty -m \"forced empty\" &&\n-\tgit cat-file commit HEAD | grep forced\n+\tgit cat-file commit HEAD >commit &&\n+\tgrep forced commit\n \n '\n \n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386688","messageId":"3cc6e4455cd55ff5d03595f6c348ae80268497a6.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 17/21] t7700: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:26Z","receivedAt":"2019-11-21T00:46:31Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nIn one case where the output of stdout is consumed, redirect the output\nof test_commit to stderr.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 4e855bc21b..e1a689d6a9 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -5,7 +5,7 @@ test_description='git repack works correctly'\n . ./test-lib.sh\n \n commit_and_pack() {\n-\ttest_commit \"$@\" >/dev/null &&\n+\ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n@@ -19,7 +19,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n \tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack > /dev/null &&\n+\t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n \tpacksha1=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n@@ -235,7 +235,7 @@ test_expect_success 'incremental repack does not complain' '\n \n test_expect_success 'bitmaps can be disabled on bare repos' '\n \tgit -c repack.writeBitmaps=false -C bare.git repack -ad &&\n-\tbitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) &&\n+\tbitmap=$(ls bare.git/objects/pack/*.bitmap || :) &&\n \ttest -z \"$bitmap\"\n '\n \n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386689","messageId":"43f184dbd5f73c118aa2b6b3ecdfa84ae2249ff9.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 18/21] t7700: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:29Z","receivedAt":"2019-11-21T00:46:33Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 18 +++++++++---------\n 1 file changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex e1a689d6a9..8936928387 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -11,8 +11,8 @@ commit_and_pack() {\n }\n \n test_expect_success 'objects in packs marked .keep are not repacked' '\n-\techo content1 > file1 &&\n-\techo content2 > file2 &&\n+\techo content1 >file1 &&\n+\techo content2 >file2 &&\n \tgit add . &&\n \ttest_tick &&\n \tgit commit -m initial_commit &&\n@@ -75,8 +75,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n-\techo content3 > file3 &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n+\techo content3 >file3 &&\n \tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n@@ -111,7 +111,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n \trm -f .git/objects/pack/* &&\n-\techo new_content >> file1 &&\n+\techo new_content >>file1 &&\n \tgit add file1 &&\n \ttest_tick &&\n \tgit commit -m more_content &&\n@@ -169,12 +169,12 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n@@ -186,7 +186,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n@@ -196,7 +196,7 @@ test_expect_success 'objects made unreachable by grafts only are kept' '\n \tH0=$(git rev-parse HEAD) &&\n \tH1=$(git rev-parse HEAD^) &&\n \tH2=$(git rev-parse HEAD^^) &&\n-\techo \"$H0 $H2\" > .git/info/grafts &&\n+\techo \"$H0 $H2\" >.git/info/grafts &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n \tgit repack -a -d &&\n \tgit cat-file -t $H1\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386690","messageId":"9389a74fe01cbf1c599b2e4ef7830beeb93808c3.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 19/21] t7700: move keywords onto their own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:31Z","receivedAt":"2019-11-21T00:46:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move keywords onto their own line so that they conform with\nthe test style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 51 +++++++++++++++++++++++++++++++----------------\n 1 file changed, 34 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 8936928387..a96e876c4e 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -29,10 +29,12 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -45,10 +47,12 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -61,10 +65,12 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -83,8 +89,10 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -99,10 +107,13 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -119,10 +130,13 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -144,10 +158,13 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386691","messageId":"079a42c45b99417656f044d5359e19541dc449ed.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 20/21] t7700: s/test -f/test_path_is_file/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:34Z","receivedAt":"2019-11-21T00:46:38Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have debugging-friendly alternatives to `test -f`, replace\ninstances of `test -f` with `test_path_is_file` so that if a command\never fails, we get better debugging information.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex a96e876c4e..1d14ddcbdb 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -106,7 +106,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -129,7 +129,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -148,7 +148,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tfor p in alt_objects/pack/*.pack\n \tdo\n \t\tbase_name=$(basename $p .pack) &&\n-\t\tif test -f alt_objects/pack/$base_name.keep\n+\t\tif test_path_is_file alt_objects/pack/$base_name.keep\n \t\tthen\n \t\t\trm alt_objects/pack/$base_name.keep\n \t\telse\n@@ -157,7 +157,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tdone &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386692","messageId":"a455fbb625bf33111c67dd3bd7bb03d5d47d0c0a.1574296987.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v2 21/21] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T00:46:36Z","receivedAt":"2019-11-21T00:46:41Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 64 ++++++++++++++++++++++++++++-------------------\n 1 file changed, 38 insertions(+), 26 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 1d14ddcbdb..ff50722e26 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -18,14 +18,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit commit -m initial_commit &&\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n-\tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack &&\n+\tgit rev-list --objects --all >objs &&\n+\tgrep -v file2 objs | git pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpacksha1=$(git rev-list --objects --all | grep file2 |\n-\t\tgit pack-objects pack) &&\n+\tpacksha1=$(grep file2 objs | git pack-objects pack) &&\n \t>pack-$packsha1.keep &&\n-\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n-\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n+\tgit verify-pack -v pack-$packsha1.idx >packlist &&\n+\tobjsha1=$(head -n 1 packlist | sed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -33,7 +32,8 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -51,7 +51,8 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -69,7 +70,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -91,7 +93,8 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit prune-packed &&\n \tfor p in .git/objects/pack/*.idx\n \tdo\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -109,15 +112,18 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n@@ -132,15 +138,18 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n@@ -160,15 +169,18 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n@@ -184,8 +196,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! egrep \"^$csha1 \" packlist &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n@@ -201,8 +213,8 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! egrep \"^$csha1 \" &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n-- \n2.24.0.450.g7a9a4598a9\n\n"},{"id":"386717","messageId":"CAPig+cQviTjwLSZ+QkC62B58mq6z3yDA-XhPVJQYRq0inEo9nA@mail.gmail.com","threadId":"52269","inReplyTo":"b24745bd6059017358bf47e96ad9ce33481f440f.1574296987.git.liu.denton@gmail.com","subject":"Re: [PATCH v2 12/21] t5317: use ! grep to check for no matching lines","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-21T12:59:05Z","receivedAt":"2019-11-21T12:59:20Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Nov 20, 2019 at 7:46 PM Denton Liu <liu.denton@gmail.com> wrote:\n> Several times in t5317, we would use `wc -l` to ensure that a grep\n> result is empty. However, grep already has a way to do that... Its\n> return code! Use `! grep` in the cases where we are ensuring that there\n> are no matching lines.\n>\n> It turns out that these tests were simply born this way[1], doing all\n> this unnecessary work for no reason, probably due to copy/paste\n> programming, and it seems no reviewer caught it. Likewise, the\n> unnecessary work wasn't noticed even when the code was later touched\n> for various cleanups[2,3].\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n>     Thanks for your help, Eric. I shamelessly stole your message text for\n>     the commit message.\n\nThat's fine, but you ought to amend it a bit since it makes no sense\nwhen extracted verbatim from my longer review comment which provided\nneeded context. In particular, the bit:\n\n    ...doing all this unnecessary work for no reason...\n\nis confusing since the reader doesn't know what \"this unnecessary\nwork\" is. My review email had an entire preceding paragraph that\nprovided context. It should at least be amended to say something along\nthe lines of:\n\n    While at it, drop unnecessary invocations of 'awk' and 'sort' in\n    each affected test since those commands do not influence the\n    outcome. It's not clear why that extra work was being done in the\n    first place, and the code's history doesn't shed any light on the\n    matter since these tests were simply born this way[1], doing all\n    the unnecessary work for no reason, probably due to copy/paste\n    programming...\n"},{"id":"386719","messageId":"CAPig+cTQapDMZwtOPcSiyu-MSBKxSY2MJ+o9rh3=SC4tFu=u=w@mail.gmail.com","threadId":"52269","inReplyTo":"d5fb60be6bdd5e885c6f830c8c44ba250350538b.1574296987.git.liu.denton@gmail.com","subject":"Re: [PATCH v2 13/21] t5703: simplify one-time-sed generation logic","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-21T13:12:00Z","receivedAt":"2019-11-21T13:12:14Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Wed, Nov 20, 2019 at 7:46 PM Denton Liu <liu.denton@gmail.com> wrote:\n> In inconsistency(), we had two `git rev-parse` invocations in the\n> upstream of a pipe within a command substitution. In case this\n> invocation ever failed, its exit code would be swallowed up and we would\n> not know about it.\n>\n> Pull the command substitutions out into variable assignments so that\n> their return codes are not lost.\n>\n> Drop the pipe into tr because command substitutions should already strip\n> leading and trailing whitespace, including newlines.\n\nSaying that command substitution _should_ strip the whitespace leaves\nthe reader in doubt as to whether there are situations in which it\nmight or might not do so. More accurately, command substitution _does_\nstrip the whitespace, so please drop \"should\" from this sentence\naltogether.\n\n> Finally, convert the printf into an echo because it isn't necessary\n> anymore.\n\nThis is quite misleading. 'printf' was _never_ necessary; 'echo' was\nan appropriate alternative even before the other changes made by this\npatch. Worse, though, this sentence provides no context about _why_ it\nis safe to change 'printf' to 'echo', so the reader is left with even\nmore questions trying to understand the validity of this change than\nif you had merely omitted this sentence. My review email[1] provided\nexact reasoning about why this change is safe. Paraphrasing that\nexplanation for this patch's commit message would go a long way toward\nconvincing the reader that the change makes sense.\n\n[1]: https://lore.kernel.org/git/CAPig+cTj5qOCFRoD4cZOg7BjVvetQWTgdRHzSvAfgtX2YgUXPg@mail.gmail.com/\n"},{"id":"386780","messageId":"20191121232258.GA23376@generichostname","threadId":"52269","inReplyTo":"CAPig+cTQapDMZwtOPcSiyu-MSBKxSY2MJ+o9rh3=SC4tFu=u=w@mail.gmail.com","subject":"Re: [PATCH v2 13/21] t5703: simplify one-time-sed generation logic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-21T23:22:58Z","receivedAt":"2019-11-21T23:23:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Eric,\n\nOn Thu, Nov 21, 2019 at 08:12:00AM -0500, Eric Sunshine wrote:\n> On Wed, Nov 20, 2019 at 7:46 PM Denton Liu <liu.denton@gmail.com> wrote:\n> > In inconsistency(), we had two `git rev-parse` invocations in the\n> > upstream of a pipe within a command substitution. In case this\n> > invocation ever failed, its exit code would be swallowed up and we would\n> > not know about it.\n> >\n> > Pull the command substitutions out into variable assignments so that\n> > their return codes are not lost.\n> >\n> > Drop the pipe into tr because command substitutions should already strip\n> > leading and trailing whitespace, including newlines.\n> \n> Saying that command substitution _should_ strip the whitespace leaves\n> the reader in doubt as to whether there are situations in which it\n> might or might not do so. More accurately, command substitution _does_\n> strip the whitespace, so please drop \"should\" from this sentence\n> altogether.\n\nGood point. I think in general, I have a very passive writing style so\nI'll make a note to write my commit messages more assertively.\n\n> \n> > Finally, convert the printf into an echo because it isn't necessary\n> > anymore.\n> \n> This is quite misleading. 'printf' was _never_ necessary; 'echo' was\n> an appropriate alternative even before the other changes made by this\n> patch. Worse, though, this sentence provides no context about _why_ it\n> is safe to change 'printf' to 'echo', so the reader is left with even\n> more questions trying to understand the validity of this change than\n> if you had merely omitted this sentence. My review email[1] provided\n> exact reasoning about why this change is safe. Paraphrasing that\n> explanation for this patch's commit message would go a long way toward\n> convincing the reader that the change makes sense.\n\nWill do.\n\nThanks,\n\nDenton\n\n> \n> [1]: https://lore.kernel.org/git/CAPig+cTj5qOCFRoD4cZOg7BjVvetQWTgdRHzSvAfgtX2YgUXPg@mail.gmail.com/\n"},{"id":"386835","messageId":"cover.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574296987.git.liu.denton@gmail.com","subject":"[PATCH v3 00/22] t: test cleanup stemming from experimentally enabling pipefail","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:42Z","receivedAt":"2019-11-22T18:59:47Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"These patches perform some general test cleanup to modernise the style.\nThey should be relatively uncontroversial. The reason these tests were\nidentified for cleanup was because they failed under `set -o pipefail`.\n\nI've gotten rid of the RFC part that actually enables `set -o pipefail`\non supported platforms. As Peff pointed out, there are a lot of\nopportunities for racy SIGPIPE failures so that part still needs a lot\nof work to be ironed out.\n\nThose changes shouldn't hold back the first part of the series, however.\nLet's try to get this test cleanup merged in sooner than later so that\nany new test cases done by copy-paste will have their changes\nrepresented.\n\nChanges since v1:\n\n* Removed the `set -o pipefail` changes\n\n* Addressed Junio and Eric's comments on the first part of the series\n\nDenton Liu (22):\n  lib-bash.sh: move `then` onto its own line\n  apply-one-time-sed.sh: modernize style\n  t0014: remove git command upstream of pipe\n  t0090: stop losing return codes of git commands\n  t3301: stop losing return codes of git commands\n  t3600: use test_line_count() where possible\n  t3600: stop losing return codes of git commands\n  t3600: comment on inducing SIGPIPE in `git rm`\n  t4015: stop losing return codes of git commands\n  t4015: use test_write_lines()\n  t4138: stop losing return codes of git commands\n  t5317: stop losing return codes of git commands\n  t5317: use ! grep to check for no matching lines\n  t5703: simplify one-time-sed generation logic\n  t5703: stop losing return codes of git commands\n  t7501: remove spaces after redirect operators\n  t7501: stop losing return codes of git commands\n  t7700: drop redirections to /dev/null\n  t7700: remove spaces after redirect operators\n  t7700: move keywords onto their own line\n  t7700: s/test -f/test_path_is_file/\n  t7700: stop losing return codes of git commands\n\n t/lib-bash.sh                          |   6 +-\n t/lib-httpd/apply-one-time-sed.sh      |   8 +-\n t/t0014-alias.sh                       |   4 +-\n t/t0090-cache-tree.sh                  |   5 +-\n t/t3301-notes.sh                       | 230 ++++++++++++++++++-------\n t/t3600-rm.sh                          |  14 +-\n t/t4015-diff-whitespace.sh             | 123 +++++++------\n t/t4138-apply-ws-expansion.sh          |  16 +-\n t/t5317-pack-objects-filter-objects.sh |  34 ++--\n t/t5703-upload-pack-ref-in-want.sh     |  53 +++---\n t/t7501-commit-basic-functionality.sh  |  83 +++++----\n t/t7700-repack.sh                      | 125 ++++++++------\n 12 files changed, 433 insertions(+), 268 deletions(-)\n\nRange-diff against v2:\n 1:  9085cc00af =  1:  9085cc00af lib-bash.sh: move `then` onto its own line\n -:  ---------- >  2:  1fddaab701 apply-one-time-sed.sh: modernize style\n 2:  9ec5244905 =  3:  f69e5345ba t0014: remove git command upstream of pipe\n 3:  613a58491a =  4:  28ddc6c79d t0090: stop losing return codes of git commands\n 4:  ee40bc972f =  5:  4d5f868e50 t3301: stop losing return codes of git commands\n 5:  702a25f328 =  6:  658db8866e t3600: use test_line_count() where possible\n 6:  6ebfed9234 =  7:  a7d76f9cb9 t3600: stop losing return codes of git commands\n 7:  7ca9099fa7 =  8:  d35c054344 t3600: comment on inducing SIGPIPE in `git rm`\n 8:  64ecf82b94 =  9:  bd6f6487b9 t4015: stop losing return codes of git commands\n 9:  8d1f457d19 = 10:  6993316839 t4015: use test_write_lines()\n10:  0a843a25c8 = 11:  5e88c755ed t4138: stop losing return codes of git commands\n11:  4ace91a8b9 = 12:  56eebcc249 t5317: stop losing return codes of git commands\n12:  7a15dd95f8 ! 13:  85c2f8ca27 t5317: use ! grep to check for no matching lines\n    @@ Commit message\n         return code! Use `! grep` in the cases where we are ensuring that there\n         are no matching lines.\n     \n    -    It turns out that these tests were simply born this way[1], doing all\n    -    this unnecessary work for no reason, probably due to copy/paste\n    -    programming, and it seems no reviewer caught it. Likewise, the\n    -    unnecessary work wasn't noticed even when the code was later touched\n    -    for various cleanups[2,3].\n    +    While at it, drop unnecessary invocations of 'awk' and 'sort' in each\n    +    affected test since those commands do not influence the outcome. It's\n    +    not clear why that extra work was being done in the first place, and the\n    +    code's history doesn't shed any light on the matter since these tests\n    +    were simply born this way[1], doing all the unnecessary work for no\n    +    reason, probably due to copy/paste programming...\n     \n         [1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n    -    [2]: bdbc17e86a (tests: standardize pipe placement, 2018-10-05)\n    -    [3]: 61de0ff695 (tests: don't swallow Git errors upstream of pipes, 2018-10-05)\n     \n         Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n     \n13:  439994027d ! 14:  f7e8ae79fa t5703: simplify one-time-sed generation logic\n    @@ Commit message\n         Pull the command substitutions out into variable assignments so that\n         their return codes are not lost.\n     \n    -    Drop the pipe into tr because command substitutions should already strip\n    -    leading and trailing whitespace, including newlines.\n    +    Drop the pipe into `tr` because the $(...) substitution already takes\n    +    care of stripping out newlines, so the `tr` invocations in the code are\n    +    superfluous.\n     \n    -    Finally, convert the printf into an echo because it isn't necessary\n    -    anymore.\n    +    Finally, given the way the tests actually employ \"one-time-sed\" via\n    +    $(cat one-time-sed) in t/lib-httpd/apply-one-time-sed.sh, convert the\n    +    `printf` into an `echo`. This makes it consistent with the final \"server\n    +    loses a ref - ref in want\" test, which does use `echo` rather than\n    +    `printf`.\n    +\n    +    Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n     \n      ## t/t5703-upload-pack-ref-in-want.sh ##\n     @@ t/t5703-upload-pack-ref-in-want.sh: inconsistency () {\n14:  859328b168 = 15:  28ef8f3a59 t5703: stop losing return codes of git commands\n15:  d5e5be76c2 = 16:  0824965707 t7501: remove spaces after redirect operators\n16:  d4154e621d = 17:  5058d21880 t7501: stop losing return codes of git commands\n17:  2045c6e30e = 18:  297f383897 t7700: drop redirections to /dev/null\n18:  20563779ee = 19:  2521ade74d t7700: remove spaces after redirect operators\n19:  37a6d826bc = 20:  560f618334 t7700: move keywords onto their own line\n20:  ea4338a43a = 21:  bd27805e4b t7700: s/test -f/test_path_is_file/\n21:  98aec252fc = 22:  e9835b8542 t7700: stop losing return codes of git commands\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386836","messageId":"9085cc00af10408d9425cfdff5a8b2c49008ae7b.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 01/22] lib-bash.sh: move `then` onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:44Z","receivedAt":"2019-11-22T18:59:50Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move the `then` onto its own line so that it conforms with the\ntest style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-bash.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/lib-bash.sh b/t/lib-bash.sh\nindex 2be955fafb..b0b6060929 100644\n--- a/t/lib-bash.sh\n+++ b/t/lib-bash.sh\n@@ -2,10 +2,12 @@\n # to run under Bash; primarily intended for tests of the completion\n # script.\n \n-if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"; then\n+if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+then\n \t# we are in full-on bash mode\n \ttrue\n-elif type bash >/dev/null 2>&1; then\n+elif type bash >/dev/null 2>&1\n+then\n \t# execute in full-on bash mode\n \tunset POSIXLY_CORRECT\n \texec bash \"$0\" \"$@\"\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386837","messageId":"1fddaab7011dae7cdd15dee83a94b021085f6703.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 02/22] apply-one-time-sed.sh: modernize style","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:47Z","receivedAt":"2019-11-22T18:59:51Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Convert `[ ... ]` to use `test`.\n\nMove the `then`s onto their own lines so that it conforms with the\ngeneral test style.\n\nInstead of redirecting input into sed, allow it to open its own input.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-httpd/apply-one-time-sed.sh | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/t/lib-httpd/apply-one-time-sed.sh b/t/lib-httpd/apply-one-time-sed.sh\nindex fcef728925..3e9a615311 100644\n--- a/t/lib-httpd/apply-one-time-sed.sh\n+++ b/t/lib-httpd/apply-one-time-sed.sh\n@@ -7,11 +7,13 @@\n #\n # This can be used to simulate the effects of the repository changing in\n # between HTTP request-response pairs.\n-if [ -e one-time-sed ]; then\n+if test -e one-time-sed\n+then\n \t\"$GIT_EXEC_PATH/git-http-backend\" >out\n-\tsed \"$(cat one-time-sed)\" <out >out_modified\n+\tsed \"$(cat one-time-sed)\" out >out_modified\n \n-\tif diff out out_modified >/dev/null; then\n+\tif diff out out_modified >/dev/null\n+\tthen\n \t\tcat out\n \telse\n \t\tcat out_modified\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386838","messageId":"f69e5345ba1c1d7c3cc58fb14864b51e9db53030.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 03/22] t0014: remove git command upstream of pipe","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:49Z","receivedAt":"2019-11-22T18:59:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, the `git frotz` command would fail but its return code was\nhidden since it was in the upstream of a pipe. Break the pipeline into\ntwo commands so that the return code is no longer lost. Also, mark\n`git frotz` with test_must_fail since it's supposed to fail.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0014-alias.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0014-alias.sh b/t/t0014-alias.sh\nindex 2694c81afd..8d3d9144c0 100755\n--- a/t/t0014-alias.sh\n+++ b/t/t0014-alias.sh\n@@ -38,8 +38,8 @@ test_expect_success 'looping aliases - internal execution' '\n #'\n \n test_expect_success 'run-command formats empty args properly' '\n-    GIT_TRACE=1 git frotz a \"\" b \" \" c 2>&1 |\n-    sed -ne \"/run_command:/s/.*trace: run_command: //p\" >actual &&\n+    test_must_fail env GIT_TRACE=1 git frotz a \"\" b \" \" c 2>actual.raw &&\n+    sed -ne \"/run_command:/s/.*trace: run_command: //p\" actual.raw >actual &&\n     echo \"git-frotz a '\\'''\\'' b '\\'' '\\'' c\" >expect &&\n     test_cmp expect actual\n '\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386839","messageId":"28ddc6c79d21b91de4f5ef3185612e7bb1c53651.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 04/22] t0090: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:51Z","receivedAt":"2019-11-22T18:59:58Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In generate_expected_cache_tree_rec(), there are currently two instances\nof `git ls-files` in the upstream of a pipe. In the case where the\nupstream git command fails, its return code will be lost. Extract the\n`git ls-files` into its own call so that if it ever fails, its return\ncode is not lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0090-cache-tree.sh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex ce9a4a5f32..5a633690bf 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -21,9 +21,10 @@ generate_expected_cache_tree_rec () {\n \tparent=\"$2\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n-\tsubtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&\n+\tgit ls-files >files &&\n+\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n \tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n-\tentries=$(git ls-files|wc -l) &&\n+\tentries=$(wc -l <files) &&\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n \tfor subtree in $subtrees\n \tdo\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386840","messageId":"4d5f868e501735513e8b7922d644d8b7423387b2.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 05/22] t3301: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:54Z","receivedAt":"2019-11-22T19:00:00Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nThis patch fixes a real buggy test: in 'copy note with \"git notes\ncopy\"', `git notes` was mistyped as `git note`.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3301-notes.sh | 230 +++++++++++++++++++++++++++++++++--------------\n 1 file changed, 163 insertions(+), 67 deletions(-)\n\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex d66a5f6faa..8f43303007 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -54,7 +54,9 @@ test_expect_success 'create notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b4\" = \"$(git notes show)\" &&\n+\techo b4 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -79,14 +81,21 @@ test_expect_success 'edit existing notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n \n test_expect_success 'show notes from treeish' '\n-\ttest \"b3\" = \"$(git notes --ref commits^{tree} show)\" &&\n-\ttest \"b4\" = \"$(git notes --ref commits@{1} show)\"\n+\techo b3 >expect &&\n+\tgit notes --ref commits^{tree} show >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo b4 >expect &&\n+\tgit notes --ref commits@{1} show >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot edit notes from non-ref' '\n@@ -99,7 +108,9 @@ test_expect_success 'cannot \"git notes add -m\" where notes already exists' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -109,7 +120,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f -m\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -119,7 +132,9 @@ test_expect_success 'add w/no options on existing note morphs into edit' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b2\" = \"$(git notes show)\" &&\n+\techo b2 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -129,7 +144,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -146,7 +163,8 @@ test_expect_success 'show notes' '\n \t\tNotes:\n \t\t${indent}b1\n \tEOF\n-\t! (git cat-file commit HEAD | grep b1) &&\n+\tgit cat-file commit HEAD >commits &&\n+\t! grep b1 commits &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -472,9 +490,11 @@ test_expect_success 'removing with --stdin --ignore-missing' '\n test_expect_success 'list notes with \"git notes list\"' '\n \tcommit_2=$(git rev-parse 2nd) &&\n \tcommit_3=$(git rev-parse 3rd) &&\n+\tnote_2=$(git rev-parse refs/notes/commits:$commit_2) &&\n+\tnote_3=$(git rev-parse refs/notes/commits:$commit_3) &&\n \tsort -t\" \" -k2 >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect actual\n@@ -486,9 +506,7 @@ test_expect_success 'list notes with \"git notes\"' '\n '\n \n test_expect_success 'list specific note with \"git notes list <object>\"' '\n-\tcat >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_3)\n-\tEOF\n+\tgit rev-parse refs/notes/commits:$commit_3 >expect &&\n \tgit notes list HEAD^^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -512,10 +530,11 @@ test_expect_success 'append to existing note with \"git notes append\"' '\n \n test_expect_success '\"git notes list\" does not expand to \"git notes list HEAD\"' '\n \tcommit_5=$(git rev-parse 5th) &&\n+\tnote_5=$(git rev-parse refs/notes/commits:$commit_5) &&\n \tsort -t\" \" -k2 >expect_list <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n-\t\t$(git rev-parse refs/notes/commits:$commit_5) $commit_5\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n+\t\t$note_5 $commit_5\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect_list actual\n@@ -721,7 +740,8 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '\n \tgit notes show HEAD: >actual &&\n \ttest_cmp expect actual &&\n \techo \"Note on a blob\" >expect &&\n-\tfilename=$(git ls-tree --name-only HEAD | head -n1) &&\n+\tgit ls-tree --name-only HEAD >files &&\n+\tfilename=$(head -n1 files) &&\n \tgit notes add -m \"Note on a blob\" HEAD:$filename &&\n \tgit notes show HEAD:$filename >actual &&\n \ttest_cmp expect actual &&\n@@ -745,10 +765,13 @@ test_expect_success 'create note from other note with \"git notes add -C\"' '\n \t\tNotes:\n \t\t${indent}order test\n \tEOF\n-\tgit notes add -C $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes add -C $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'create note from non-existing note with \"git notes add -C\" fails' '\n@@ -777,11 +800,12 @@ test_expect_success 'create note from blob with \"git notes add -C\" reuses blob i\n \t\tNotes:\n \t\t${indent}This is a blob object\n \tEOF\n-\tblob=$(echo \"This is a blob object\" | git hash-object -w --stdin) &&\n-\tgit notes add -C $blob &&\n+\techo \"This is a blob object\" | git hash-object -w --stdin >blob &&\n+\tgit notes add -C $(cat blob) &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$blob\"\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp blob actual\n '\n \n test_expect_success 'create note from other note with \"git notes add -c\"' '\n@@ -797,7 +821,8 @@ test_expect_success 'create note from other note with \"git notes add -c\"' '\n \t\tNotes:\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes add -c $(git notes list HEAD^^) &&\n+\tnote=$(git notes list HEAD^^) &&\n+\tMSG=\"yet another note\" git notes add -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -822,7 +847,8 @@ test_expect_success 'append to note from other note with \"git notes append -C\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tgit notes append -C $(git notes list HEAD^) HEAD^ &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes append -C $note HEAD^ &&\n \tgit log -1 HEAD^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -839,7 +865,8 @@ test_expect_success 'create note from other note with \"git notes append -c\"' '\n \t\tNotes:\n \t\t${indent}other note\n \tEOF\n-\tMSG=\"other note\" git notes append -c $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tMSG=\"other note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -858,7 +885,8 @@ test_expect_success 'append to note from other note with \"git notes append -c\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes append -c $(git notes list HEAD) &&\n+\tnote=$(git notes list HEAD) &&\n+\tMSG=\"yet another note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -878,7 +906,9 @@ test_expect_success 'copy note with \"git notes copy\"' '\n \tgit notes copy 8th 4th &&\n \tgit log 3rd..4th >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git note list 4th)\" = \"$(git note list 8th)\"\n+\tgit notes list 4th >expect &&\n+\tgit notes list 8th >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'copy note with \"git notes copy\" with default' '\n@@ -899,14 +929,30 @@ test_expect_success 'copy note with \"git notes copy\" with default' '\n \tgit notes copy HEAD^ &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'prevent overwrite with \"git notes copy\"' '\n \ttest_must_fail git notes copy HEAD~2 HEAD &&\n+\tcat >expect <<-EOF &&\n+\t\tcommit $commit\n+\t\tAuthor: A U Thor <author@example.com>\n+\t\tDate:   Thu Apr 7 15:23:13 2005 -0700\n+\n+\t\t${indent}11th\n+\n+\t\tNotes:\n+\t\t${indent}other note\n+\t\t${indent}\n+\t\t${indent}yet another note\n+\tEOF\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n@@ -924,7 +970,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n \tgit notes copy -f HEAD~3 HEAD &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n@@ -944,7 +992,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n \tgit notes copy -f HEAD~2 &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot copy note from object without notes' '\n@@ -979,13 +1029,21 @@ test_expect_success 'git notes copy --stdin' '\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --stdin &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --stdin <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\" &&\n-\ttest \"$(git notes list HEAD^)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual &&\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD^ >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n@@ -1006,9 +1064,13 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n \n \t\t${indent}14th\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1041,17 +1103,23 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '\n \tEOF\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (disabled)' '\n \ttest_config notes.rewrite.bar false &&\n-\techo $(git rev-parse HEAD~3) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=bar &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=bar <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1071,8 +1139,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n \tgit notes add -f -m\"a fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1080,8 +1150,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n test_expect_success 'git notes copy --for-rewrite (ignore)' '\n \ttest_config notes.rewriteMode ignore &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1103,8 +1175,10 @@ test_expect_success 'git notes copy --for-rewrite (append)' '\n \tgit notes add -f -m\"another fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1131,9 +1205,13 @@ test_expect_success 'git notes copy --for-rewrite (append two to one)' '\n \tgit notes add -f -m\"append 2\" HEAD^^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD^) $(git rev-parse HEAD) &&\n-\techo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD^^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1142,8 +1220,10 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '\n \tgit notes remove HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1163,8 +1243,10 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n \tgit notes add -f -m\"replacement note 1\" HEAD^ &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1184,9 +1266,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF works' '\n \tgit notes add -f -m\"replacement note 2\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_unconfig notes.rewriteRef &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1195,9 +1279,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '\n \tgit notes add -f -m\"replacement note 3\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef refs/notes/other &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \tgrep \"replacement note 3\" actual\n '\n@@ -1212,26 +1298,36 @@ test_expect_success 'git notes copy diagnoses too many or too few parameters' '\n test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes --ref=refs/heads/master get-ref)\" = \"refs/notes/refs/heads/master\"\n+\techo refs/notes/refs/heads/master >expect &&\n+\tgit notes --ref=refs/heads/master get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (no overrides)' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/commits\"\n+\techo refs/notes/commits >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (core.notesRef)' '\n \ttest_config core.notesRef refs/notes/foo &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/foo\"\n+\techo refs/notes/foo >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (GIT_NOTES_REF)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes get-ref)\" = \"refs/notes/bar\"\n+\techo refs/notes/bar >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (--ref)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref)\" = \"refs/notes/baz\"\n+\techo refs/notes/baz >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'setup testing of empty notes' '\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386841","messageId":"658db8866e2bf8daf6cf8d75c785f10fd016bdfb.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 06/22] t3600: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:56Z","receivedAt":"2019-11-22T19:00:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have a helper function that can test the number of lines in a\nfile that gives better debugging information on failure, use\ntest_line_count() to test the number of lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 8c8cca5bfb..f6e659b7e9 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -113,9 +113,10 @@ test_expect_success '\"rm\" command printed' '\n \techo frotz >test-file &&\n \tgit add test-file &&\n \tgit commit -m \"add file for rm test\" &&\n-\tgit rm test-file >rm-output &&\n-\ttest $(grep \"^rm \" rm-output | wc -l) = 1 &&\n-\trm -f test-file rm-output &&\n+\tgit rm test-file >rm-output.raw &&\n+\tgrep \"^rm \" rm-output.raw >rm-output &&\n+\ttest_line_count = 1 rm-output &&\n+\trm -f test-file rm-output.raw rm-output &&\n \tgit commit -m \"remove file from rm test\"\n '\n \n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386842","messageId":"a7d76f9cb912bfcd0eb2fa413c6a5d8e104d7668.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 07/22] t3600: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T18:59:59Z","receivedAt":"2019-11-22T19:00:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"When a command is in a non-assignment command substitution, the return\ncode will be lost in favour of the surrounding command's. As a result,\nif a git command fails, we won't know about it. Rewrite instances of\nthis so that git commands are either run in an assignment-only command\nsubstitution so that their return codes aren't lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex f6e659b7e9..0c3bf10edd 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -304,7 +304,8 @@ EOF\n \n test_expect_success 'rm removes empty submodules from work tree' '\n \tmkdir submod &&\n-\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) submod &&\n+\thash=$(git rev-parse HEAD) &&\n+\tgit update-index --add --cacheinfo 160000 \"$hash\" submod &&\n \tgit config -f .gitmodules submodule.sub.url ./. &&\n \tgit config -f .gitmodules submodule.sub.path submod &&\n \tgit submodule init &&\n@@ -623,7 +624,8 @@ test_expect_success 'setup subsubmodule' '\n \tgit submodule update &&\n \t(\n \t\tcd submod &&\n-\t\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) subsubmod &&\n+\t\thash=$(git rev-parse HEAD) &&\n+\t\tgit update-index --add --cacheinfo 160000 \"$hash\" subsubmod &&\n \t\tgit config -f .gitmodules submodule.sub.url ../. &&\n \t\tgit config -f .gitmodules submodule.sub.path subsubmod &&\n \t\tgit submodule init &&\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386843","messageId":"d35c054344bee8c2b81532b384a49d9984b96471.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 08/22] t3600: comment on inducing SIGPIPE in `git rm`","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:01Z","receivedAt":"2019-11-22T19:00:05Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Add a comment about intentionally inducing SIGPIPE since this is unusual\nand future developers should be aware. Also, even though we are trying\nto refactor git commands out of the upstream of pipes, we cannot do it\nhere since we rely on it being upstream to induce SIGPIPE. Comment on\nthat as well so that future developers do not try to change it.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 0c3bf10edd..0ea858d652 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -251,6 +251,7 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\techo \"100644 $hash 0\tsome-file-$i\"\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n+\t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n \tgit rm -n \"some-file-*\" | : &&\n \ttest_path_is_missing .git/index.lock\n '\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386844","messageId":"bd6f6487b906030d6f9f2617ce45fe2a188af60a.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 09/22] t4015: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:03Z","receivedAt":"2019-11-22T19:00:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 119 ++++++++++++++++++++++---------------\n 1 file changed, 72 insertions(+), 47 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex eadaf57262..7fb83c8eff 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -16,7 +16,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t} while (0);\n \tEOF\n \tgit update-index --add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \tcat <<-\\EOF >x &&\n \tdo\n@@ -25,7 +26,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t}\n \twhile (0);\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -63,7 +65,8 @@ test_expect_success 'another test, without options' '\n \tEOF\n \n \tgit update-index x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \ttr \"_\" \" \" <<-\\EOF >x &&\n \t_\twhitespace at beginning\n@@ -73,7 +76,8 @@ test_expect_success 'another test, without options' '\n \tunchanged line\n \tCR at end\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \ttr \"Q_\" \"\\015 \" <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -526,13 +530,15 @@ test_expect_success 'ignore-blank-lines: mix changes and blank lines' '\n test_expect_success 'check mixed spaces and tabs in indent' '\n \t# This is indented with SP HT SP.\n \techo \" \t foo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check mixed tabs and spaces in indent' '\n \t# This is indented with HT SP HT.\n \techo \"\t \tfoo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check with no whitespace errors' '\n@@ -753,20 +759,23 @@ test_expect_success 'check tab-in-indent excluded from wildcard whitespace attri\n test_expect_success 'line numbers in --check output are correct' '\n \techo \"\" >x &&\n \techo \"foo(); \" >>x &&\n-\tgit diff --check | grep \"x:2:\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"x:2:\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n \techo \"foo();\" >x &&\n \techo \"\" >>x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n \t{ echo a; echo b; echo; echo; } >x &&\n \tgit add x &&\n \t{ echo a; echo; echo; echo; echo; } >x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff allows new blank lines' '\n@@ -794,14 +803,16 @@ test_expect_success 'whitespace-only changes reported across renames' '\n \tgit reset --hard &&\n \tfor i in 1 2 3 4 5 6 7 8 9; do echo \"$i$i$i$i$i$i\"; done >x &&\n \tgit add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\thash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$hash_x\") &&\n \tgit commit -m \"base\" &&\n \tsed -e \"5s/^/ /\" x >z &&\n \tgit rm x &&\n \tgit add z &&\n-\tafter=$(git rev-parse --short $(git hash-object z)) &&\n-\tgit diff -w -M --cached |\n-\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" >actual &&\n+\thash_z=$(git hash-object z) &&\n+\tafter=$(git rev-parse --short \"$hash_z\") &&\n+\tgit diff -w -M --cached >actual.raw &&\n+\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" actual.raw >actual &&\n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/z\n \tsimilarity index NUM%\n@@ -840,7 +851,8 @@ test_expect_success 'combined diff with autocrlf conversion' '\n \tgit config core.autocrlf true &&\n \ttest_must_fail git merge master &&\n \n-\tgit diff | sed -e \"1,/^@@@/d\" >actual &&\n+\tgit diff >actual.raw &&\n+\tsed -e \"1,/^@@@/d\" actual.raw >actual &&\n \t! grep \"^-\" actual\n \n '\n@@ -864,11 +876,14 @@ test_expect_success 'diff that introduces a line with only tabs' '\n \tgit config core.whitespace blank-at-eol &&\n \tgit reset --hard &&\n \techo \"test\" >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -m \"initial\" x &&\n \techo \"{NTN}\" | tr \"NT\" \"\\n\\t\" >>x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n-\tgit diff --color | test_decode_color >current &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -891,17 +906,19 @@ test_expect_success 'diff that introduces and removes ws breakages' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n-\tgit diff --color |\n-\ttest_decode_color >current &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -925,14 +942,16 @@ test_expect_success 'ws-error-highlight test setup' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat >expect.default-old <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -974,32 +993,32 @@ test_expect_success 'ws-error-highlight test setup' '\n \n test_expect_success 'test --ws-error-highlight option' '\n \n-\tgit diff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit diff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit diff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n \n test_expect_success 'test diff.wsErrorHighlight config' '\n \n-\tgit -c diff.wsErrorHighlight=default,old diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=default,old diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit -c diff.wsErrorHighlight=all diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=all diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit -c diff.wsErrorHighlight=none diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=none diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1007,18 +1026,18 @@ test_expect_success 'test diff.wsErrorHighlight config' '\n test_expect_success 'option overrides diff.wsErrorHighlight' '\n \n \tgit -c diff.wsErrorHighlight=none \\\n-\t\tdiff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n \tgit -c diff.wsErrorHighlight=default \\\n-\t\tdiff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n \tgit -c diff.wsErrorHighlight=all \\\n-\t\tdiff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1038,7 +1057,8 @@ test_expect_success 'detect moved code, complete file' '\n \tgit mv test.c main.c &&\n \ttest_config color.diff.oldMoved \"normal red\" &&\n \ttest_config color.diff.newMoved \"normal green\" &&\n-\tgit diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&\n+\tgit diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>new file mode 100644<RESET>\n@@ -1141,9 +1161,12 @@ test_expect_success 'detect malicious moved code, inside file' '\n \t\t\tbar();\n \t\t}\n \tEOF\n-\tafter_main=$(git rev-parse --short $(git hash-object main.c)) &&\n-\tafter_test=$(git rev-parse --short $(git hash-object test.c)) &&\n-\tgit diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&\n+\thash_main=$(git hash-object main.c) &&\n+\tafter_main=$(git rev-parse --short \"$hash_main\") &&\n+\thash_test=$(git hash-object test.c) &&\n+\tafter_test=$(git rev-parse --short \"$hash_test\") &&\n+\tgit diff HEAD --no-renames --color-moved=zebra --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1192,7 +1215,8 @@ test_expect_success 'plain moved code, inside file' '\n \ttest_config color.diff.oldMovedAlternative \"blue\" &&\n \ttest_config color.diff.newMovedAlternative \"yellow\" &&\n \t# needs previous test as setup\n-\tgit diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&\n+\tgit diff HEAD --no-renames --color-moved=plain --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1771,7 +1795,8 @@ test_expect_success 'move detection with submodules' '\n \t! grep BRED decoded_actual &&\n \n \t# nor did we mess with it another way\n-\tgit diff --submodule=diff --color | test_decode_color >expect &&\n+\tgit diff --submodule=diff --color >expect.raw &&\n+\ttest_decode_color <expect.raw >expect &&\n \ttest_cmp expect decoded_actual &&\n \trm -rf bananas &&\n \tgit submodule deinit bananas\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386845","messageId":"69933168398c7524c29945435edd26a8b0520c39.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 10/22] t4015: use test_write_lines()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:06Z","receivedAt":"2019-11-22T19:00:10Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Instead of rolling our own method to write out some lines into a file,\nuse the existing test_write_lines().\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex 7fb83c8eff..4c540b1d70 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -771,9 +771,9 @@ test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n-\t{ echo a; echo b; echo; echo; } >x &&\n+\ttest_write_lines a b \"\" \"\" >x &&\n \tgit add x &&\n-\t{ echo a; echo; echo; echo; echo; } >x &&\n+\ttest_write_lines a \"\" \"\" \"\" \"\" >x &&\n \ttest_must_fail git diff --check >check &&\n \tgrep \"new blank line\" check\n '\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386846","messageId":"5e88c755edd9648b2263ab3692dcd23856460f17.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 11/22] t4138: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:08Z","receivedAt":"2019-11-22T19:00:13Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4138-apply-ws-expansion.sh | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh\nindex 3b636a63a3..b19faeb67a 100755\n--- a/t/t4138-apply-ws-expansion.sh\n+++ b/t/t4138-apply-ws-expansion.sh\n@@ -17,8 +17,8 @@ test_expect_success setup '\n \tprintf \"\\t%s\\n\" 1 2 3 >after &&\n \tprintf \"%64s\\n\" a b c >>after &&\n \tprintf \"\\t%s\\n\" 4 5 6 >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" >patch1.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch1.patch.raw &&\n+\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" patch1.patch.raw >patch1.patch &&\n \tprintf \"%64s\\n\" 1 2 3 4 5 6 >test-1 &&\n \tprintf \"%64s\\n\" 1 2 3 a b c 4 5 6 >expect-1 &&\n \n@@ -33,8 +33,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" >patch2.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch2.patch.raw &&\n+\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" patch2.patch.raw >patch2.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-2 &&\n \tprintf \"%64s\\n\" a b c >expect-2 &&\n \tx=1 &&\n@@ -56,8 +56,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" >patch3.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch3.patch.raw &&\n+\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" patch3.patch.raw >patch3.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-3 &&\n \tprintf \"%64s\\n\" a b c >expect-3 &&\n \tx=0 &&\n@@ -84,8 +84,8 @@ test_expect_success setup '\n \t\tprintf \"\\t%02d\\n\" $x >>after\n \t\tx=$(( $x + 1 ))\n \tdone &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" >patch4.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch4.patch.raw &&\n+\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" patch4.patch.raw >patch4.patch &&\n \t>test-4 &&\n \tx=0 &&\n \twhile test $x -lt 50\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386847","messageId":"56eebcc249681233ea19b5d12400030aad9a259d.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 12/22] t5317: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:11Z","receivedAt":"2019-11-22T19:00:17Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands output to a\nfile and surrounding commands only call command substitutions with\nnon-git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 13 +++++++------\n 1 file changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex 2d2f5d0229..a8bbad74e2 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -72,7 +72,8 @@ test_expect_success 'get an error for missing tree object' '\n \techo foo >r5/foo &&\n \tgit -C r5 add foo &&\n \tgit -C r5 commit -m \"foo\" &&\n-\tdel=$(git -C r5 rev-parse HEAD^{tree} | sed \"s|..|&/|\") &&\n+\tgit -C r5 rev-parse HEAD^{tree} >tree &&\n+\tdel=$(sed \"s|..|&/|\" tree) &&\n \trm r5/.git/objects/$del &&\n \ttest_must_fail git -C r5 pack-objects --revs --stdout 2>bad_tree <<-EOF &&\n \tHEAD\n@@ -230,10 +231,9 @@ test_expect_success 'verify explicitly specifying oversized blob in input' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&\n-\tHEAD\n-\t$(git -C r2 rev-parse HEAD:large.10000)\n-\tEOF\n+\techo HEAD >objects &&\n+\tgit -C r2 rev-parse HEAD:large.10000 >>objects &&\n+\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k <objects >filter.pack &&\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n@@ -377,7 +377,8 @@ test_expect_success 'verify sparse:oid=OID' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\toid=$(git -C r4 ls-files -s pattern | awk -f print_2.awk) &&\n+\tgit -C r4 ls-files -s pattern >staged &&\n+\toid=$(awk -f print_2.awk staged) &&\n \tgit -C r4 pack-objects --revs --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF &&\n \tHEAD\n \tEOF\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386848","messageId":"85c2f8ca2704e54c2d0e6e65822a04d21e383f6a.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 13/22] t5317: use ! grep to check for no matching lines","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:13Z","receivedAt":"2019-11-22T19:00:19Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Several times in t5317, we would use `wc -l` to ensure that a grep\nresult is empty. However, grep already has a way to do that... Its\nreturn code! Use `! grep` in the cases where we are ensuring that there\nare no matching lines.\n\nWhile at it, drop unnecessary invocations of 'awk' and 'sort' in each\naffected test since those commands do not influence the outcome. It's\nnot clear why that extra work was being done in the first place, and the\ncode's history doesn't shed any light on the matter since these tests\nwere simply born this way[1], doing all the unnecessary work for no\nreason, probably due to copy/paste programming...\n\n[1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 21 +++------------------\n 1 file changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex a8bbad74e2..dc0446574b 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -45,12 +45,7 @@ test_expect_success 'verify blob:none packfile has no blobs' '\n \tgit -C r1 index-pack ../filter.pack &&\n \n \tgit -C r1 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify normal and blob:none packfiles have same commits/trees' '\n@@ -149,12 +144,7 @@ test_expect_success 'verify blob:limit=500 omits all blobs' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1000' '\n@@ -164,12 +154,7 @@ test_expect_success 'verify blob:limit=1000' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1001' '\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386849","messageId":"f7e8ae79fa4c0798e2419244756dc2465dcd0d28.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 14/22] t5703: simplify one-time-sed generation logic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:16Z","receivedAt":"2019-11-22T19:00:21Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In inconsistency(), we had two `git rev-parse` invocations in the\nupstream of a pipe within a command substitution. In case this\ninvocation ever failed, its exit code would be swallowed up and we would\nnot know about it.\n\nPull the command substitutions out into variable assignments so that\ntheir return codes are not lost.\n\nDrop the pipe into `tr` because the $(...) substitution already takes\ncare of stripping out newlines, so the `tr` invocations in the code are\nsuperfluous.\n\nFinally, given the way the tests actually employ \"one-time-sed\" via\n$(cat one-time-sed) in t/lib-httpd/apply-one-time-sed.sh, convert the\n`printf` into an `echo`. This makes it consistent with the final \"server\nloses a ref - ref in want\" test, which does use `echo` rather than\n`printf`.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 7 +++----\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 3a2c143c6d..88338c4e09 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -312,10 +312,9 @@ inconsistency () {\n \t# repository appears to change during negotiation, for example, when\n \t# different servers in a load-balancing arrangement serve (stateless)\n \t# RPCs during a single negotiation.\n-\tprintf \"s/%s/%s/\" \\\n-\t       $(git -C \"$REPO\" rev-parse $1 | tr -d \"\\n\") \\\n-\t       $(git -C \"$REPO\" rev-parse $2 | tr -d \"\\n\") \\\n-\t       >\"$HTTPD_ROOT_PATH/one-time-sed\"\n+\toid1=$(git -C \"$REPO\" rev-parse $1) &&\n+\toid2=$(git -C \"$REPO\" rev-parse $2) &&\n+\techo \"s/$oid1/$oid2/\" >\"$HTTPD_ROOT_PATH/one-time-sed\"\n }\n \n test_expect_success 'server is initially ahead - no ref in want' '\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386850","messageId":"28ef8f3a59d2b7647ee20ded55743e7dcb174919.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 15/22] t5703: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:18Z","receivedAt":"2019-11-22T19:00:23Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands are in an\nassignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 46 +++++++++++++++++++-----------\n 1 file changed, 29 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 88338c4e09..1424fabd4a 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -18,14 +18,16 @@ get_actual_commits () {\n \t\tp\n \t\t}' <out | test-tool pkt-line unpack-sideband >o.pack &&\n \tgit index-pack o.pack &&\n-\tgit verify-pack -v o.idx | grep commit | cut -c-40 | sort >actual_commits\n+\tgit verify-pack -v o.idx >objs &&\n+\tgrep commit objs | cut -c-40 | sort >actual_commits\n }\n \n check_output () {\n \tget_actual_refs &&\n \ttest_cmp expected_refs actual_refs &&\n \tget_actual_commits &&\n-\ttest_cmp expected_commits actual_commits\n+\tsort expected_commits >sorted_commits &&\n+\ttest_cmp sorted_commits actual_commits\n }\n \n # c(o/foo) d(o/bar)\n@@ -75,17 +77,19 @@ test_expect_success 'invalid want-ref line' '\n '\n \n test_expect_success 'basic want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse f | sort >expected_commits &&\n+\tgit rev-parse f >expected_commits &&\n \n+\toid=$(git rev-parse a) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/master\n-\thave $(git rev-parse a)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -95,19 +99,22 @@ test_expect_success 'basic want-ref' '\n '\n \n test_expect_success 'multiple want-ref lines' '\n+\toid_c=$(git rev-parse c) &&\n+\toid_d=$(git rev-parse d) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n-\t$(git rev-parse d) refs/heads/o/bar\n+\t$oid_c refs/heads/o/foo\n+\t$oid_d refs/heads/o/bar\n \tEOF\n-\tgit rev-parse c d | sort >expected_commits &&\n+\tgit rev-parse c d >expected_commits &&\n \n+\toid=$(git rev-parse b) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n \twant-ref refs/heads/o/bar\n-\thave $(git rev-parse b)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -117,10 +124,11 @@ test_expect_success 'multiple want-ref lines' '\n '\n \n test_expect_success 'mix want and want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse e f | sort >expected_commits &&\n+\tgit rev-parse e f >expected_commits &&\n \n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n@@ -138,17 +146,19 @@ test_expect_success 'mix want and want-ref' '\n '\n \n test_expect_success 'want-ref with ref we already have commit for' '\n+\toid=$(git rev-parse c) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n+\t$oid refs/heads/o/foo\n \tEOF\n \t>expected_commits &&\n \n+\toid=$(git rev-parse c) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n-\thave $(git rev-parse c)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -211,13 +221,14 @@ test_expect_success 'fetching with exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse d) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\t$(git -C \"$REPO\" rev-parse d):refs/heads/actual &&\n+\t\t\"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"d\" >expected &&\n \tgit -C local rev-parse refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse d)\" log\n+\tgrep \"want $oid\" log\n '\n \n test_expect_success 'fetching multiple refs' '\n@@ -239,13 +250,14 @@ test_expect_success 'fetching ref and exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse b) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\tmaster $(git -C \"$REPO\" rev-parse b):refs/heads/actual &&\n+\t\tmaster \"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"master\" \"b\" >expected &&\n \tgit -C local rev-parse refs/remotes/origin/master refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse b)\" log &&\n+\tgrep \"want $oid\" log &&\n \tgrep \"want-ref refs/heads/master\" log\n '\n \n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386851","messageId":"082496570716db89c79718171249975b26146518.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 16/22] t7501: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:21Z","receivedAt":"2019-11-22T19:00:27Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex f1349af56e..5765d33c53 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -150,7 +150,7 @@ test_expect_success 'setup: commit message from file' '\n test_expect_success 'amend commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/a file/an amend commit/g\" < \"$1\" > \"$1-\"\n+\tsed -e \"s/a file/an amend commit/g\" <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -263,7 +263,7 @@ test_expect_success 'using message from other commit' '\n test_expect_success 'editing message from other commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/amend/older/g\"  < \"$1\" > \"$1-\"\n+\tsed -e \"s/amend/older/g\"  <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -367,7 +367,7 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -382,7 +382,7 @@ test_expect_success 'amend commit to fix date' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --date=\"$newtick\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -448,7 +448,7 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -468,7 +468,7 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -489,7 +489,7 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +506,7 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -560,14 +560,14 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n \n test_expect_success 'git commit <file> with dirty index' '\n-\techo tacocat > elif &&\n-\techo tehlulz > chz &&\n+\techo tacocat >elif &&\n+\techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n \tgit show --stat | grep elif &&\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386852","messageId":"5058d218807c0d9560c1c923dc4ca95b341a07e2.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 17/22] t7501: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:23Z","receivedAt":"2019-11-22T19:00:29Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nIn the 'interactive add' test case, we prepend a `test_must_fail` to\n`git commit --interactive`. When there are no changes to commit,\n`git commit` will exit with status code 1. Following along with the rest\nof the file, we use `test_must_fail` to test for this case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 69 +++++++++++++++------------\n 1 file changed, 39 insertions(+), 30 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex 5765d33c53..110b4bf459 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -285,9 +285,8 @@ test_expect_success 'overriding author from command line' '\n '\n \n test_expect_success PERL 'interactive add' '\n-\techo 7 |\n-\tgit commit --interactive |\n-\tgrep \"What now\"\n+\techo 7 | test_must_fail git commit --interactive >out &&\n+\tgrep \"What now\" out\n '\n \n test_expect_success PERL \"commit --interactive doesn't change index if editor aborts\" '\n@@ -362,10 +361,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -377,10 +376,10 @@ test_expect_success 'amend commit to fix date' '\n \ttest_tick &&\n \tnewtick=$GIT_AUTHOR_DATE &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $newtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --date=\"$newtick\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -409,12 +408,13 @@ test_expect_success 'sign off (1)' '\n \techo 1 >positive &&\n \tgit add positive &&\n \tgit commit -s -m \"thank you\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -428,13 +428,14 @@ test_expect_success 'sign off (2)' '\n \tgit commit -s -m \"thank you\n \n $existing\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n \t\techo $existing &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -448,13 +449,14 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo $alt &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -468,15 +470,16 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo We have now &&\n \t\techo $alt &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -489,7 +492,8 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +510,8 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -538,7 +543,8 @@ test_expect_success 'multiple -m' '\n \t>negative &&\n \tgit add negative &&\n \tgit commit -m \"one\" -m \"two\" -m \"three\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo one &&\n \t\techo &&\n@@ -555,10 +561,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -570,8 +576,10 @@ test_expect_success 'git commit <file> with dirty index' '\n \techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n-\tgit show --stat | grep elif &&\n-\tgit diff --cached | grep chz\n+\tgit show --stat >stat &&\n+\tgrep elif stat &&\n+\tgit diff --cached >diff &&\n+\tgrep chz diff\n '\n \n test_expect_success 'same tree (single parent)' '\n@@ -584,7 +592,8 @@ test_expect_success 'same tree (single parent)' '\n test_expect_success 'same tree (single parent) --allow-empty' '\n \n \tgit commit --allow-empty -m \"forced empty\" &&\n-\tgit cat-file commit HEAD | grep forced\n+\tgit cat-file commit HEAD >commit &&\n+\tgrep forced commit\n \n '\n \n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386853","messageId":"297f38389760a5682198b8fa0a1e6ceea9b9deac.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 18/22] t7700: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:25Z","receivedAt":"2019-11-22T19:00:31Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nIn one case where the output of stdout is consumed, redirect the output\nof test_commit to stderr.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 4e855bc21b..e1a689d6a9 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -5,7 +5,7 @@ test_description='git repack works correctly'\n . ./test-lib.sh\n \n commit_and_pack() {\n-\ttest_commit \"$@\" >/dev/null &&\n+\ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n@@ -19,7 +19,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n \tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack > /dev/null &&\n+\t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n \tpacksha1=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n@@ -235,7 +235,7 @@ test_expect_success 'incremental repack does not complain' '\n \n test_expect_success 'bitmaps can be disabled on bare repos' '\n \tgit -c repack.writeBitmaps=false -C bare.git repack -ad &&\n-\tbitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) &&\n+\tbitmap=$(ls bare.git/objects/pack/*.bitmap || :) &&\n \ttest -z \"$bitmap\"\n '\n \n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386854","messageId":"2521ade74df0a0aebbb70abeff64d67ef8b00201.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 19/22] t7700: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:28Z","receivedAt":"2019-11-22T19:00:33Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 18 +++++++++---------\n 1 file changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex e1a689d6a9..8936928387 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -11,8 +11,8 @@ commit_and_pack() {\n }\n \n test_expect_success 'objects in packs marked .keep are not repacked' '\n-\techo content1 > file1 &&\n-\techo content2 > file2 &&\n+\techo content1 >file1 &&\n+\techo content2 >file2 &&\n \tgit add . &&\n \ttest_tick &&\n \tgit commit -m initial_commit &&\n@@ -75,8 +75,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n-\techo content3 > file3 &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n+\techo content3 >file3 &&\n \tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n@@ -111,7 +111,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n \trm -f .git/objects/pack/* &&\n-\techo new_content >> file1 &&\n+\techo new_content >>file1 &&\n \tgit add file1 &&\n \ttest_tick &&\n \tgit commit -m more_content &&\n@@ -169,12 +169,12 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n@@ -186,7 +186,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n@@ -196,7 +196,7 @@ test_expect_success 'objects made unreachable by grafts only are kept' '\n \tH0=$(git rev-parse HEAD) &&\n \tH1=$(git rev-parse HEAD^) &&\n \tH2=$(git rev-parse HEAD^^) &&\n-\techo \"$H0 $H2\" > .git/info/grafts &&\n+\techo \"$H0 $H2\" >.git/info/grafts &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n \tgit repack -a -d &&\n \tgit cat-file -t $H1\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386855","messageId":"560f6183345593558e7f8d9ca2064947b537d7a0.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 20/22] t7700: move keywords onto their own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:30Z","receivedAt":"2019-11-22T19:00:35Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move keywords onto their own line so that they conform with\nthe test style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 51 +++++++++++++++++++++++++++++++----------------\n 1 file changed, 34 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 8936928387..a96e876c4e 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -29,10 +29,12 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -45,10 +47,12 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -61,10 +65,12 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -83,8 +89,10 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -99,10 +107,13 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -119,10 +130,13 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -144,10 +158,13 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386856","messageId":"bd27805e4bbd7493be6abc6820213913b95107be.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 21/22] t7700: s/test -f/test_path_is_file/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:33Z","receivedAt":"2019-11-22T19:00:37Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have debugging-friendly alternatives to `test -f`, replace\ninstances of `test -f` with `test_path_is_file` so that if a command\never fails, we get better debugging information.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex a96e876c4e..1d14ddcbdb 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -106,7 +106,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -129,7 +129,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -148,7 +148,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tfor p in alt_objects/pack/*.pack\n \tdo\n \t\tbase_name=$(basename $p .pack) &&\n-\t\tif test -f alt_objects/pack/$base_name.keep\n+\t\tif test_path_is_file alt_objects/pack/$base_name.keep\n \t\tthen\n \t\t\trm alt_objects/pack/$base_name.keep\n \t\telse\n@@ -157,7 +157,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tdone &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386857","messageId":"e9835b85427a3486e2dba136bbf34506e521d355.1574449072.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v3 22/22] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-22T19:00:35Z","receivedAt":"2019-11-22T19:00:40Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 64 ++++++++++++++++++++++++++++-------------------\n 1 file changed, 38 insertions(+), 26 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 1d14ddcbdb..ff50722e26 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -18,14 +18,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit commit -m initial_commit &&\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n-\tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack &&\n+\tgit rev-list --objects --all >objs &&\n+\tgrep -v file2 objs | git pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpacksha1=$(git rev-list --objects --all | grep file2 |\n-\t\tgit pack-objects pack) &&\n+\tpacksha1=$(grep file2 objs | git pack-objects pack) &&\n \t>pack-$packsha1.keep &&\n-\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n-\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n+\tgit verify-pack -v pack-$packsha1.idx >packlist &&\n+\tobjsha1=$(head -n 1 packlist | sed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -33,7 +32,8 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -51,7 +51,8 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -69,7 +70,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -91,7 +93,8 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit prune-packed &&\n \tfor p in .git/objects/pack/*.idx\n \tdo\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -109,15 +112,18 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n@@ -132,15 +138,18 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n@@ -160,15 +169,18 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n+\tdone >packs &&\n+\tgit verify-pack -v $myidx >mypacklist &&\n+\twhile read sha1 rest\n \tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tif ! grep \"^$sha1\" mypacklist\n \t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-\tdone\n+\tdone <packs\n '\n \n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n@@ -184,8 +196,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! egrep \"^$csha1 \" packlist &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n@@ -201,8 +213,8 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! egrep \"^$csha1 \" &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n-- \n2.24.0.497.g17aadd8971\n\n"},{"id":"386888","messageId":"xmqqk17r2x8w.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"1fddaab7011dae7cdd15dee83a94b021085f6703.1574449072.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 02/22] apply-one-time-sed.sh: modernize style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-23T01:32:31Z","receivedAt":"2019-11-23T01:34:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Convert `[ ... ]` to use `test`.\n>\n> Move the `then`s onto their own lines so that it conforms with the\n> general test style.\n>\n> Instead of redirecting input into sed, allow it to open its own input.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n>  t/lib-httpd/apply-one-time-sed.sh | 8 +++++---\n>  1 file changed, 5 insertions(+), 3 deletions(-)\n\nThis one is new in this round.  As a conversion to match the style\nguidelines, it looks OK, but the original feels a bit substandard in\nother ways, e.g. I would have said \"if one-time-sed is a file\",\ninstead of \"if one-time-sed exists as any kind of filesystem\nentity\", and used \"cmp -s out out_modified\" instead of \"diff\", which\nis an overkill if you want to merely learn if two things are equal.\n\nWait.  If we are to see if A and B are the same, and show A when\nthey are the same and otherwise show B, wouldn't it be much simpler\nto do without comparison and always show B unconditionally instead?\n\nWhat am I missing?\n\nAh, there is one extra command in the \"else\" clause that we cannot\nsee in the post-context.  So, sorry for the noise---don't wait ;-)\n\nBut all the other things before the \"Wait\" still stands.\n\nThanks.\n\n> diff --git a/t/lib-httpd/apply-one-time-sed.sh b/t/lib-httpd/apply-one-time-sed.sh\n> index fcef728925..3e9a615311 100644\n> --- a/t/lib-httpd/apply-one-time-sed.sh\n> +++ b/t/lib-httpd/apply-one-time-sed.sh\n> @@ -7,11 +7,13 @@\n>  #\n>  # This can be used to simulate the effects of the repository changing in\n>  # between HTTP request-response pairs.\n> -if [ -e one-time-sed ]; then\n> +if test -e one-time-sed\n> +then\n>  \t\"$GIT_EXEC_PATH/git-http-backend\" >out\n> -\tsed \"$(cat one-time-sed)\" <out >out_modified\n> +\tsed \"$(cat one-time-sed)\" out >out_modified\n>  \n> -\tif diff out out_modified >/dev/null; then\n> +\tif diff out out_modified >/dev/null\n> +\tthen\n>  \t\tcat out\n>  \telse\n>  \t\tcat out_modified\n"},{"id":"386889","messageId":"xmqqftif2wg7.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"e9835b85427a3486e2dba136bbf34506e521d355.1574449072.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 22/22] t7700: stop losing return codes of git commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-23T01:49:44Z","receivedAt":"2019-11-23T01:52:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> -\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n> -\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n> +\tgit verify-pack -v pack-$packsha1.idx >packlist &&\n> +\tobjsha1=$(head -n 1 packlist | sed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n\nWe probably should lose reference to SHA-1 and use $OID_REGEX; this\nis obviously a #leftoverbits material that is outside the scope of\nthis series.\n\n> @@ -91,7 +93,8 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n>  \tgit prune-packed &&\n>  \tfor p in .git/objects/pack/*.idx\n>  \tdo\n> -\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n> +\t\tgit verify-pack -v $p >packlist || return $?\n> +\t\tif egrep \"^$objsha1\" packlist\n>  \t\tthen\n>  \t\t\tfound_duplicate_object=1\n>  \t\t\techo \"DUPLICATE OBJECT FOUND\"\n\nThese egrep that try to match lines that begin with an object name\ncan be a simple grep instead (again, outside the scope of this\nseries).\n\n> @@ -109,15 +112,18 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n>  \ttest_path_is_file \"$myidx\" &&\n>  \tfor p in alt_objects/pack/*.idx\n>  \tdo\n> -\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n> -\tdone | while read sha1 rest\n> +\t\tgit verify-pack -v $p >packlist || return $?\n> +\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n> +\tdone >packs &&\n\nA misleading filename?  The lines in this file are not pack files;\nrather the file has a list of objects in various packs.\n\n> +\tgit verify-pack -v $myidx >mypacklist &&\n> +\twhile read sha1 rest\n>  \tdo\n> -\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n> +\t\tif ! grep \"^$sha1\" mypacklist\n>  \t\tthen\n>  \t\t\techo \"Missing object in local pack: $sha1\"\n>  \t\t\treturn 1\n>  \t\tfi\n> -\tdone\n> +\tdone <packs\n>  '\n\nAgain outside the scope of this series, but this looks O(n^2)\nto me.\n\nIf I were writing this today, I would prepare a sorted list of all\nobject names (and nothing else on each line) in alt_objects/pack/ in\none file (call it 'orig'), and prepare another file with a sorted\nlist of all object names described in $myidx (call it 'dest'), and\nthen run \"comm -23 orig dest\" and see if there is anything that is\nunique in the 'orig' file (i.e. something in 'orig' is missing from\n'dest').\n\n> @@ -132,15 +138,18 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n>  \ttest_path_is_file \"$myidx\" &&\n>  \tfor p in alt_objects/pack/*.idx\n>  \tdo\n> -\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n> -\tdone | while read sha1 rest\n> +\t\tgit verify-pack -v $p >packlist || return $?\n> +\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n> +\tdone >packs &&\n> +\tgit verify-pack -v $myidx >mypacklist &&\n> +\twhile read sha1 rest\n>  \tdo\n> -\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n> +\t\tif ! grep \"^$sha1\" mypacklist\n>  \t\tthen\n>  \t\t\techo \"Missing object in local pack: $sha1\"\n>  \t\t\treturn 1\n>  \t\tfi\n> -\tdone\n> +\tdone <packs\n>  '\n\nLikewise.\n\n> @@ -160,15 +169,18 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n>  \ttest_path_is_file \"$myidx\" &&\n>  \tfor p in alt_objects/pack/*.idx\n>  \tdo\n> -\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n> -\tdone | while read sha1 rest\n> +\t\tgit verify-pack -v $p >packlist || return $?\n> +\t\tsed -n -e \"/^[0-9a-f]\\{40\\}/p\" packlist\n> +\tdone >packs &&\n> +\tgit verify-pack -v $myidx >mypacklist &&\n> +\twhile read sha1 rest\n>  \tdo\n> -\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n> +\t\tif ! grep \"^$sha1\" mypacklist\n>  \t\tthen\n>  \t\t\techo \"Missing object in local pack: $sha1\"\n>  \t\t\treturn 1\n>  \t\tfi\n> -\tdone\n> +\tdone <packs\n>  '\n\nLikewise.\n\n"},{"id":"386897","messageId":"CAPig+cTE_cYQi=Ys5tKYbs6bRXf9moNqO6zo1M_hn6w9HfL-bQ@mail.gmail.com","threadId":"52269","inReplyTo":"85c2f8ca2704e54c2d0e6e65822a04d21e383f6a.1574449072.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 13/22] t5317: use ! grep to check for no matching lines","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-23T06:21:29Z","receivedAt":"2019-11-23T06:21:44Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Nov 22, 2019 at 2:00 PM Denton Liu <liu.denton@gmail.com> wrote:\n> [...]\n> While at it, drop unnecessary invocations of 'awk' and 'sort' in each\n> affected test since those commands do not influence the outcome. It's\n> not clear why that extra work was being done in the first place, and the\n> code's history doesn't shed any light on the matter since these tests\n> were simply born this way[1], doing all the unnecessary work for no\n> reason, probably due to copy/paste programming...\n\nTaking this wording literally from my review comment[1] is (again)\nfine, but I ended the fragment intentionally with \"...\" with the\nexpectation that you would fill in the remainder, not expecting you to\ncopy/paste the fragment blindly. Without the remainder -- the part\nwhich is supposed to follow the \"...\" -- the reader if left hanging.\n\n[1]: https://lore.kernel.org/git/CAPig+cQviTjwLSZ+QkC62B58mq6z3yDA-XhPVJQYRq0inEo9nA@mail.gmail.com/\n"},{"id":"387019","messageId":"20191125214304.GA73230@generichostname","threadId":"52269","inReplyTo":"CAPig+cTE_cYQi=Ys5tKYbs6bRXf9moNqO6zo1M_hn6w9HfL-bQ@mail.gmail.com","subject":"Re: [PATCH v3 13/22] t5317: use ! grep to check for no matching lines","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-25T21:43:04Z","receivedAt":"2019-11-25T21:43:11Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Eric,\n\nOn Sat, Nov 23, 2019 at 01:21:29AM -0500, Eric Sunshine wrote:\n> On Fri, Nov 22, 2019 at 2:00 PM Denton Liu <liu.denton@gmail.com> wrote:\n> > [...]\n> > While at it, drop unnecessary invocations of 'awk' and 'sort' in each\n> > affected test since those commands do not influence the outcome. It's\n> > not clear why that extra work was being done in the first place, and the\n> > code's history doesn't shed any light on the matter since these tests\n> > were simply born this way[1], doing all the unnecessary work for no\n> > reason, probably due to copy/paste programming...\n> \n> Taking this wording literally from my review comment[1] is (again)\n> fine, but I ended the fragment intentionally with \"...\" with the\n> expectation that you would fill in the remainder, not expecting you to\n> copy/paste the fragment blindly. Without the remainder -- the part\n> which is supposed to follow the \"...\" -- the reader if left hanging.\n\nMy mistake, I interpreted the \"...\" as a stylistic writing choice as\nopposed to an indication for me to fill it in. I'll fix it up for the\nnext round.\n\nThanks,\n\nDenton\n\n> \n> [1]: https://lore.kernel.org/git/CAPig+cQviTjwLSZ+QkC62B58mq6z3yDA-XhPVJQYRq0inEo9nA@mail.gmail.com/\n"},{"id":"387023","messageId":"20191125235702.GA6250@generichostname","threadId":"52269","inReplyTo":"xmqqftif2wg7.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 22/22] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-25T23:57:02Z","receivedAt":"2019-11-25T23:57:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio,\n\nOn Sat, Nov 23, 2019 at 10:49:44AM +0900, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> > -\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n> > -\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n> > +\tgit verify-pack -v pack-$packsha1.idx >packlist &&\n> > +\tobjsha1=$(head -n 1 packlist | sed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n> \n> We probably should lose reference to SHA-1 and use $OID_REGEX; this\n> is obviously a #leftoverbits material that is outside the scope of\n> this series.\n\nSince the theme of this series is test cleanup, I believe that it's\nprobably appropriate to roll these changes (and the ones below that I\nomitted) into the current series. Since it isn't too much work, I'll\nsend them out in my next reroll.\n"},{"id":"387032","messageId":"CAPig+cQqK-HiDjmnBFo-qeE6cZ73EveWg6Ygb-4BX3X_iPSJZA@mail.gmail.com","threadId":"52269","inReplyTo":"20191125235702.GA6250@generichostname","subject":"Re: [PATCH v3 22/22] t7700: stop losing return codes of git commands","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-26T00:58:32Z","receivedAt":"2019-11-26T00:58:47Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Nov 25, 2019 at 6:57 PM Denton Liu <liu.denton@gmail.com> wrote:\n> On Sat, Nov 23, 2019 at 10:49:44AM +0900, Junio C Hamano wrote:\n> > Denton Liu <liu.denton@gmail.com> writes:\n> > > -   objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n> > > -           sed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n> > > +   git verify-pack -v pack-$packsha1.idx >packlist &&\n> > > +   objsha1=$(head -n 1 packlist | sed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n> >\n> > We probably should lose reference to SHA-1 and use $OID_REGEX; this\n> > is obviously a #leftoverbits material that is outside the scope of\n> > this series.\n>\n> Since the theme of this series is test cleanup, I believe that it's\n> probably appropriate to roll these changes (and the ones below that I\n> omitted) into the current series. Since it isn't too much work, I'll\n> send them out in my next reroll.\n\nIt may not be too much work for you to keep adding more (unrelated)\nchanges to a series, but doing so increases the burden on reviewers\nunnecessarily, especially for a long patch series such as this one.\nGenerally speaking, each iteration should help the series converge to\nthe point at which it can finally land (be merged to \"next\"). Thus,\nideally, each iteration should have fewer changes than the previous\none.\n\nWhen you add entirely new changes which are not directly related to\nthe changes which begat the series, that iteration diverges (not\nconverges). It creates extra work for reviewers (who are trying to\nhelp you land the series) and makes it less likely that people will\nwant to review each new iteration since a series which diverges with\neach iteration makes the goal of landing the series a moving target\n(thus, represents never-ending review work).\n"},{"id":"387037","messageId":"cover.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574449072.git.liu.denton@gmail.com","subject":"[PATCH v4 00/27] t: test cleanup stemming from experimentally enabling pipefail","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:17:44Z","receivedAt":"2019-11-26T01:17:49Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"These patches perform some general test cleanup to modernise the style.\nThey should be relatively uncontroversial. The reason these tests were\nidentified for cleanup was because they failed under `set -o pipefail`.\n\nI've gotten rid of the RFC part that actually enables `set -o pipefail`\non supported platforms. As Peff pointed out, there are a lot of\nopportunities for racy SIGPIPE failures so that part still needs a lot\nof work to be ironed out.\n\nThose changes shouldn't hold back the first part of the series, however.\nLet's try to get this test cleanup merged in sooner than later so that\nany new test cases done by copy-paste will have their changes\nrepresented.\n\nChanges since v3:\n\n* More commit message update\n\n* Clean up \"apply-one-time-sed.sh: modernize style\" more according to\n  Junio's suggestions\n\n* Clean up the t7700 leftover bits\n\nChanges since v2:\n\n* Update commit messages according to Eric's suggestions\n\n* Add \"apply-one-time-sed.sh: modernize style\"\n\nChanges since v1:\n\n* Removed the `set -o pipefail` changes\n\n* Addressed Junio and Eric's comments on the first part of the series\n\nDenton Liu (27):\n  lib-bash.sh: move `then` onto its own line\n  apply-one-time-sed.sh: modernize style\n  t0014: remove git command upstream of pipe\n  t0090: stop losing return codes of git commands\n  t3301: stop losing return codes of git commands\n  t3600: use test_line_count() where possible\n  t3600: stop losing return codes of git commands\n  t3600: comment on inducing SIGPIPE in `git rm`\n  t4015: stop losing return codes of git commands\n  t4015: use test_write_lines()\n  t4138: stop losing return codes of git commands\n  t5317: stop losing return codes of git commands\n  t5317: use ! grep to check for no matching lines\n  t5703: simplify one-time-sed generation logic\n  t5703: stop losing return codes of git commands\n  t7501: remove spaces after redirect operators\n  t7501: stop losing return codes of git commands\n  t7700: drop redirections to /dev/null\n  t7700: remove spaces after redirect operators\n  t7700: move keywords onto their own line\n  t7700: s/test -f/test_path_is_file/\n  t7700: consolidate code into test_no_missing_in_packs()\n  squash! t7700: consolidate code into test_no_missing_in_packs()\n  t7700: consolidate code into test_has_duplicate_object()\n  t7700: replace egrep with grep\n  t7700: make references to SHA-1 generic\n  t7700: stop losing return codes of git commands\n\n t/lib-bash.sh                          |   6 +-\n t/lib-httpd/apply-one-time-sed.sh      |   8 +-\n t/t0014-alias.sh                       |   4 +-\n t/t0090-cache-tree.sh                  |   5 +-\n t/t3301-notes.sh                       | 230 ++++++++++++++++++-------\n t/t3600-rm.sh                          |  14 +-\n t/t4015-diff-whitespace.sh             | 123 +++++++------\n t/t4138-apply-ws-expansion.sh          |  16 +-\n t/t5317-pack-objects-filter-objects.sh |  34 ++--\n t/t5703-upload-pack-ref-in-want.sh     |  53 +++---\n t/t7501-commit-basic-functionality.sh  |  83 +++++----\n t/t7700-repack.sh                      | 172 ++++++++----------\n 12 files changed, 425 insertions(+), 323 deletions(-)\n\nRange-diff against v3:\n 1:  9085cc00af =  1:  9085cc00af lib-bash.sh: move `then` onto its own line\n 2:  ac4164374d !  2:  86f625c65e apply-one-time-sed.sh: modernize style\n    @@ Metadata\n      ## Commit message ##\n         apply-one-time-sed.sh: modernize style\n     \n    -    Convert `[ ... ]` to use `test`.\n    +    Convert `[ ... ]` to use `test` and test for the existence of a regular\n    +    file (`-f`) instead of any file (`-e`).\n     \n         Move the `then`s onto their own lines so that it conforms with the\n         general test style.\n     \n         Instead of redirecting input into sed, allow it to open its own input.\n     \n    +    Use `cmp -s` instead of `diff` since we only care about whether the two\n    +    files are equal and `diff` is overkill for this.\n    +\n      ## t/lib-httpd/apply-one-time-sed.sh ##\n     @@\n      #\n      # This can be used to simulate the effects of the repository changing in\n      # between HTTP request-response pairs.\n     -if [ -e one-time-sed ]; then\n    -+if test -e one-time-sed\n    ++if test -f one-time-sed\n     +then\n      \t\"$GIT_EXEC_PATH/git-http-backend\" >out\n     -\tsed \"$(cat one-time-sed)\" <out >out_modified\n     +\tsed \"$(cat one-time-sed)\" out >out_modified\n      \n     -\tif diff out out_modified >/dev/null; then\n    -+\tif diff out out_modified >/dev/null\n    ++\tif cmp -s out out_modified\n     +\tthen\n      \t\tcat out\n      \telse\n 3:  b90d68829b =  3:  3844e00367 t0014: remove git command upstream of pipe\n 4:  51eaffb283 =  4:  7d33586b21 t0090: stop losing return codes of git commands\n 5:  3c6bb9b2f2 =  5:  df6b3393c4 t3301: stop losing return codes of git commands\n 6:  7925fa3e43 =  6:  d541a8d4d4 t3600: use test_line_count() where possible\n 7:  36be4d0ec1 =  7:  a8aeca6795 t3600: stop losing return codes of git commands\n 8:  01fc8518bf =  8:  e3db06578d t3600: comment on inducing SIGPIPE in `git rm`\n 9:  b6f6d47c00 =  9:  22ea5d736e t4015: stop losing return codes of git commands\n10:  58a1ae76c0 = 10:  a44dd28b4d t4015: use test_write_lines()\n11:  07822e3b4c = 11:  d512319be0 t4138: stop losing return codes of git commands\n12:  d892a7b181 = 12:  1e08c2b68b t5317: stop losing return codes of git commands\n13:  140de46f80 ! 13:  fa238be28b t5317: use ! grep to check for no matching lines\n    @@ Commit message\n         return code! Use `! grep` in the cases where we are ensuring that there\n         are no matching lines.\n     \n    -    While at it, drop unnecessary invocations of 'awk' and 'sort' in each\n    +    While at it, drop unnecessary invocations of `awk` and `sort` in each\n         affected test since those commands do not influence the outcome. It's\n         not clear why that extra work was being done in the first place, and the\n         code's history doesn't shed any light on the matter since these tests\n    -    were simply born this way[1], doing all the unnecessary work for no\n    -    reason, probably due to copy/paste programming...\n    +    were simply born this way[1], likely due to copy-paste programming. The\n    +    unnecessary work wasn't noticed even when the code was later touched for\n    +    various cleanups[2][3].\n     \n         [1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n    +    [2]: bdbc17e86a (tests: standardize pipe placement, 2018-10-05)\n    +    [3]: 61de0ff695 (tests: don't swallow Git errors upstream of pipes, 2018-10-05)\n     \n         Helped-by: Eric Sunshine <sunshine@sunshineco.com>\n     \n14:  6be0d0388d = 14:  291caf9bc1 t5703: simplify one-time-sed generation logic\n15:  3844e7372c = 15:  edf7af76ae t5703: stop losing return codes of git commands\n16:  d47bb4c9f6 = 16:  5eb7117fbe t7501: remove spaces after redirect operators\n17:  9e5ede8eac = 17:  bad732adc8 t7501: stop losing return codes of git commands\n18:  18031e67c7 = 18:  c50c192429 t7700: drop redirections to /dev/null\n19:  40cd07a57a = 19:  58ae066d12 t7700: remove spaces after redirect operators\n20:  049405b49d = 20:  82bf24d06a t7700: move keywords onto their own line\n21:  133171522d = 21:  251de77677 t7700: s/test -f/test_path_is_file/\n22:  d653869ead <  -:  ---------- t7700: stop losing return codes of git commands\n -:  ---------- > 22:  c98a2a1509 t7700: consolidate code into test_no_missing_in_packs()\n -:  ---------- > 23:  e4ba198483 squash! t7700: consolidate code into test_no_missing_in_packs()\n -:  ---------- > 24:  fa38d7e8f6 t7700: consolidate code into test_has_duplicate_object()\n -:  ---------- > 25:  4f02c00bd1 t7700: replace egrep with grep\n -:  ---------- > 26:  a747fbd08b t7700: make references to SHA-1 generic\n -:  ---------- > 27:  fb614f4385 t7700: stop losing return codes of git commands\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387038","messageId":"9085cc00af10408d9425cfdff5a8b2c49008ae7b.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 01/27] lib-bash.sh: move `then` onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:17:46Z","receivedAt":"2019-11-26T01:17:51Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move the `then` onto its own line so that it conforms with the\ntest style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-bash.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/lib-bash.sh b/t/lib-bash.sh\nindex 2be955fafb..b0b6060929 100644\n--- a/t/lib-bash.sh\n+++ b/t/lib-bash.sh\n@@ -2,10 +2,12 @@\n # to run under Bash; primarily intended for tests of the completion\n # script.\n \n-if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"; then\n+if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+then\n \t# we are in full-on bash mode\n \ttrue\n-elif type bash >/dev/null 2>&1; then\n+elif type bash >/dev/null 2>&1\n+then\n \t# execute in full-on bash mode\n \tunset POSIXLY_CORRECT\n \texec bash \"$0\" \"$@\"\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387039","messageId":"86f625c65e00b24d1de183c3a993e6acb7c8325e.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 02/27] apply-one-time-sed.sh: modernize style","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:17:48Z","receivedAt":"2019-11-26T01:17:53Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Convert `[ ... ]` to use `test` and test for the existence of a regular\nfile (`-f`) instead of any file (`-e`).\n\nMove the `then`s onto their own lines so that it conforms with the\ngeneral test style.\n\nInstead of redirecting input into sed, allow it to open its own input.\n\nUse `cmp -s` instead of `diff` since we only care about whether the two\nfiles are equal and `diff` is overkill for this.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-httpd/apply-one-time-sed.sh | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/t/lib-httpd/apply-one-time-sed.sh b/t/lib-httpd/apply-one-time-sed.sh\nindex fcef728925..bf7689d020 100644\n--- a/t/lib-httpd/apply-one-time-sed.sh\n+++ b/t/lib-httpd/apply-one-time-sed.sh\n@@ -7,11 +7,13 @@\n #\n # This can be used to simulate the effects of the repository changing in\n # between HTTP request-response pairs.\n-if [ -e one-time-sed ]; then\n+if test -f one-time-sed\n+then\n \t\"$GIT_EXEC_PATH/git-http-backend\" >out\n-\tsed \"$(cat one-time-sed)\" <out >out_modified\n+\tsed \"$(cat one-time-sed)\" out >out_modified\n \n-\tif diff out out_modified >/dev/null; then\n+\tif cmp -s out out_modified\n+\tthen\n \t\tcat out\n \telse\n \t\tcat out_modified\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387040","messageId":"3844e00367de57ec09b1e3282280fd20dd807c0b.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 03/27] t0014: remove git command upstream of pipe","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:17:51Z","receivedAt":"2019-11-26T01:17:55Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, the `git frotz` command would fail but its return code was\nhidden since it was in the upstream of a pipe. Break the pipeline into\ntwo commands so that the return code is no longer lost. Also, mark\n`git frotz` with test_must_fail since it's supposed to fail.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0014-alias.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0014-alias.sh b/t/t0014-alias.sh\nindex 2694c81afd..8d3d9144c0 100755\n--- a/t/t0014-alias.sh\n+++ b/t/t0014-alias.sh\n@@ -38,8 +38,8 @@ test_expect_success 'looping aliases - internal execution' '\n #'\n \n test_expect_success 'run-command formats empty args properly' '\n-    GIT_TRACE=1 git frotz a \"\" b \" \" c 2>&1 |\n-    sed -ne \"/run_command:/s/.*trace: run_command: //p\" >actual &&\n+    test_must_fail env GIT_TRACE=1 git frotz a \"\" b \" \" c 2>actual.raw &&\n+    sed -ne \"/run_command:/s/.*trace: run_command: //p\" actual.raw >actual &&\n     echo \"git-frotz a '\\'''\\'' b '\\'' '\\'' c\" >expect &&\n     test_cmp expect actual\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387041","messageId":"7d33586b214f8dfd8e027b3bc618ca908799b560.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 04/27] t0090: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:17:53Z","receivedAt":"2019-11-26T01:17:59Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In generate_expected_cache_tree_rec(), there are currently two instances\nof `git ls-files` in the upstream of a pipe. In the case where the\nupstream git command fails, its return code will be lost. Extract the\n`git ls-files` into its own call so that if it ever fails, its return\ncode is not lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0090-cache-tree.sh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex ce9a4a5f32..5a633690bf 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -21,9 +21,10 @@ generate_expected_cache_tree_rec () {\n \tparent=\"$2\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n-\tsubtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&\n+\tgit ls-files >files &&\n+\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n \tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n-\tentries=$(git ls-files|wc -l) &&\n+\tentries=$(wc -l <files) &&\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n \tfor subtree in $subtrees\n \tdo\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387042","messageId":"df6b3393c4b100fd1c490d4bfe0844a83368809a.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 05/27] t3301: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:17:55Z","receivedAt":"2019-11-26T01:18:01Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nThis patch fixes a real buggy test: in 'copy note with \"git notes\ncopy\"', `git notes` was mistyped as `git note`.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3301-notes.sh | 230 +++++++++++++++++++++++++++++++++--------------\n 1 file changed, 163 insertions(+), 67 deletions(-)\n\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex d66a5f6faa..8f43303007 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -54,7 +54,9 @@ test_expect_success 'create notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b4\" = \"$(git notes show)\" &&\n+\techo b4 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -79,14 +81,21 @@ test_expect_success 'edit existing notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n \n test_expect_success 'show notes from treeish' '\n-\ttest \"b3\" = \"$(git notes --ref commits^{tree} show)\" &&\n-\ttest \"b4\" = \"$(git notes --ref commits@{1} show)\"\n+\techo b3 >expect &&\n+\tgit notes --ref commits^{tree} show >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo b4 >expect &&\n+\tgit notes --ref commits@{1} show >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot edit notes from non-ref' '\n@@ -99,7 +108,9 @@ test_expect_success 'cannot \"git notes add -m\" where notes already exists' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -109,7 +120,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f -m\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -119,7 +132,9 @@ test_expect_success 'add w/no options on existing note morphs into edit' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b2\" = \"$(git notes show)\" &&\n+\techo b2 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -129,7 +144,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -146,7 +163,8 @@ test_expect_success 'show notes' '\n \t\tNotes:\n \t\t${indent}b1\n \tEOF\n-\t! (git cat-file commit HEAD | grep b1) &&\n+\tgit cat-file commit HEAD >commits &&\n+\t! grep b1 commits &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -472,9 +490,11 @@ test_expect_success 'removing with --stdin --ignore-missing' '\n test_expect_success 'list notes with \"git notes list\"' '\n \tcommit_2=$(git rev-parse 2nd) &&\n \tcommit_3=$(git rev-parse 3rd) &&\n+\tnote_2=$(git rev-parse refs/notes/commits:$commit_2) &&\n+\tnote_3=$(git rev-parse refs/notes/commits:$commit_3) &&\n \tsort -t\" \" -k2 >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect actual\n@@ -486,9 +506,7 @@ test_expect_success 'list notes with \"git notes\"' '\n '\n \n test_expect_success 'list specific note with \"git notes list <object>\"' '\n-\tcat >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_3)\n-\tEOF\n+\tgit rev-parse refs/notes/commits:$commit_3 >expect &&\n \tgit notes list HEAD^^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -512,10 +530,11 @@ test_expect_success 'append to existing note with \"git notes append\"' '\n \n test_expect_success '\"git notes list\" does not expand to \"git notes list HEAD\"' '\n \tcommit_5=$(git rev-parse 5th) &&\n+\tnote_5=$(git rev-parse refs/notes/commits:$commit_5) &&\n \tsort -t\" \" -k2 >expect_list <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n-\t\t$(git rev-parse refs/notes/commits:$commit_5) $commit_5\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n+\t\t$note_5 $commit_5\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect_list actual\n@@ -721,7 +740,8 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '\n \tgit notes show HEAD: >actual &&\n \ttest_cmp expect actual &&\n \techo \"Note on a blob\" >expect &&\n-\tfilename=$(git ls-tree --name-only HEAD | head -n1) &&\n+\tgit ls-tree --name-only HEAD >files &&\n+\tfilename=$(head -n1 files) &&\n \tgit notes add -m \"Note on a blob\" HEAD:$filename &&\n \tgit notes show HEAD:$filename >actual &&\n \ttest_cmp expect actual &&\n@@ -745,10 +765,13 @@ test_expect_success 'create note from other note with \"git notes add -C\"' '\n \t\tNotes:\n \t\t${indent}order test\n \tEOF\n-\tgit notes add -C $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes add -C $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'create note from non-existing note with \"git notes add -C\" fails' '\n@@ -777,11 +800,12 @@ test_expect_success 'create note from blob with \"git notes add -C\" reuses blob i\n \t\tNotes:\n \t\t${indent}This is a blob object\n \tEOF\n-\tblob=$(echo \"This is a blob object\" | git hash-object -w --stdin) &&\n-\tgit notes add -C $blob &&\n+\techo \"This is a blob object\" | git hash-object -w --stdin >blob &&\n+\tgit notes add -C $(cat blob) &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$blob\"\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp blob actual\n '\n \n test_expect_success 'create note from other note with \"git notes add -c\"' '\n@@ -797,7 +821,8 @@ test_expect_success 'create note from other note with \"git notes add -c\"' '\n \t\tNotes:\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes add -c $(git notes list HEAD^^) &&\n+\tnote=$(git notes list HEAD^^) &&\n+\tMSG=\"yet another note\" git notes add -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -822,7 +847,8 @@ test_expect_success 'append to note from other note with \"git notes append -C\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tgit notes append -C $(git notes list HEAD^) HEAD^ &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes append -C $note HEAD^ &&\n \tgit log -1 HEAD^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -839,7 +865,8 @@ test_expect_success 'create note from other note with \"git notes append -c\"' '\n \t\tNotes:\n \t\t${indent}other note\n \tEOF\n-\tMSG=\"other note\" git notes append -c $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tMSG=\"other note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -858,7 +885,8 @@ test_expect_success 'append to note from other note with \"git notes append -c\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes append -c $(git notes list HEAD) &&\n+\tnote=$(git notes list HEAD) &&\n+\tMSG=\"yet another note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -878,7 +906,9 @@ test_expect_success 'copy note with \"git notes copy\"' '\n \tgit notes copy 8th 4th &&\n \tgit log 3rd..4th >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git note list 4th)\" = \"$(git note list 8th)\"\n+\tgit notes list 4th >expect &&\n+\tgit notes list 8th >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'copy note with \"git notes copy\" with default' '\n@@ -899,14 +929,30 @@ test_expect_success 'copy note with \"git notes copy\" with default' '\n \tgit notes copy HEAD^ &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'prevent overwrite with \"git notes copy\"' '\n \ttest_must_fail git notes copy HEAD~2 HEAD &&\n+\tcat >expect <<-EOF &&\n+\t\tcommit $commit\n+\t\tAuthor: A U Thor <author@example.com>\n+\t\tDate:   Thu Apr 7 15:23:13 2005 -0700\n+\n+\t\t${indent}11th\n+\n+\t\tNotes:\n+\t\t${indent}other note\n+\t\t${indent}\n+\t\t${indent}yet another note\n+\tEOF\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n@@ -924,7 +970,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n \tgit notes copy -f HEAD~3 HEAD &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n@@ -944,7 +992,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n \tgit notes copy -f HEAD~2 &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot copy note from object without notes' '\n@@ -979,13 +1029,21 @@ test_expect_success 'git notes copy --stdin' '\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --stdin &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --stdin <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\" &&\n-\ttest \"$(git notes list HEAD^)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual &&\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD^ >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n@@ -1006,9 +1064,13 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n \n \t\t${indent}14th\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1041,17 +1103,23 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '\n \tEOF\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (disabled)' '\n \ttest_config notes.rewrite.bar false &&\n-\techo $(git rev-parse HEAD~3) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=bar &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=bar <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1071,8 +1139,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n \tgit notes add -f -m\"a fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1080,8 +1150,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n test_expect_success 'git notes copy --for-rewrite (ignore)' '\n \ttest_config notes.rewriteMode ignore &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1103,8 +1175,10 @@ test_expect_success 'git notes copy --for-rewrite (append)' '\n \tgit notes add -f -m\"another fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1131,9 +1205,13 @@ test_expect_success 'git notes copy --for-rewrite (append two to one)' '\n \tgit notes add -f -m\"append 2\" HEAD^^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD^) $(git rev-parse HEAD) &&\n-\techo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD^^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1142,8 +1220,10 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '\n \tgit notes remove HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1163,8 +1243,10 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n \tgit notes add -f -m\"replacement note 1\" HEAD^ &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1184,9 +1266,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF works' '\n \tgit notes add -f -m\"replacement note 2\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_unconfig notes.rewriteRef &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1195,9 +1279,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '\n \tgit notes add -f -m\"replacement note 3\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef refs/notes/other &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \tgrep \"replacement note 3\" actual\n '\n@@ -1212,26 +1298,36 @@ test_expect_success 'git notes copy diagnoses too many or too few parameters' '\n test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes --ref=refs/heads/master get-ref)\" = \"refs/notes/refs/heads/master\"\n+\techo refs/notes/refs/heads/master >expect &&\n+\tgit notes --ref=refs/heads/master get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (no overrides)' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/commits\"\n+\techo refs/notes/commits >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (core.notesRef)' '\n \ttest_config core.notesRef refs/notes/foo &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/foo\"\n+\techo refs/notes/foo >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (GIT_NOTES_REF)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes get-ref)\" = \"refs/notes/bar\"\n+\techo refs/notes/bar >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (--ref)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref)\" = \"refs/notes/baz\"\n+\techo refs/notes/baz >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'setup testing of empty notes' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387043","messageId":"d541a8d4d4b8fc224fe1967ce5717d70c0f2b55f.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 06/27] t3600: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:17:58Z","receivedAt":"2019-11-26T01:18:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have a helper function that can test the number of lines in a\nfile that gives better debugging information on failure, use\ntest_line_count() to test the number of lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 8c8cca5bfb..f6e659b7e9 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -113,9 +113,10 @@ test_expect_success '\"rm\" command printed' '\n \techo frotz >test-file &&\n \tgit add test-file &&\n \tgit commit -m \"add file for rm test\" &&\n-\tgit rm test-file >rm-output &&\n-\ttest $(grep \"^rm \" rm-output | wc -l) = 1 &&\n-\trm -f test-file rm-output &&\n+\tgit rm test-file >rm-output.raw &&\n+\tgrep \"^rm \" rm-output.raw >rm-output &&\n+\ttest_line_count = 1 rm-output &&\n+\trm -f test-file rm-output.raw rm-output &&\n \tgit commit -m \"remove file from rm test\"\n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387044","messageId":"a8aeca67956f503829ac1f16072782ae5a906dd8.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 07/27] t3600: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:01Z","receivedAt":"2019-11-26T01:18:05Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"When a command is in a non-assignment command substitution, the return\ncode will be lost in favour of the surrounding command's. As a result,\nif a git command fails, we won't know about it. Rewrite instances of\nthis so that git commands are either run in an assignment-only command\nsubstitution so that their return codes aren't lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex f6e659b7e9..0c3bf10edd 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -304,7 +304,8 @@ EOF\n \n test_expect_success 'rm removes empty submodules from work tree' '\n \tmkdir submod &&\n-\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) submod &&\n+\thash=$(git rev-parse HEAD) &&\n+\tgit update-index --add --cacheinfo 160000 \"$hash\" submod &&\n \tgit config -f .gitmodules submodule.sub.url ./. &&\n \tgit config -f .gitmodules submodule.sub.path submod &&\n \tgit submodule init &&\n@@ -623,7 +624,8 @@ test_expect_success 'setup subsubmodule' '\n \tgit submodule update &&\n \t(\n \t\tcd submod &&\n-\t\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) subsubmod &&\n+\t\thash=$(git rev-parse HEAD) &&\n+\t\tgit update-index --add --cacheinfo 160000 \"$hash\" subsubmod &&\n \t\tgit config -f .gitmodules submodule.sub.url ../. &&\n \t\tgit config -f .gitmodules submodule.sub.path subsubmod &&\n \t\tgit submodule init &&\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387045","messageId":"e3db06578df23ee6e2036c18a25e79ae6c4d46e3.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 08/27] t3600: comment on inducing SIGPIPE in `git rm`","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:03Z","receivedAt":"2019-11-26T01:18:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Add a comment about intentionally inducing SIGPIPE since this is unusual\nand future developers should be aware. Also, even though we are trying\nto refactor git commands out of the upstream of pipes, we cannot do it\nhere since we rely on it being upstream to induce SIGPIPE. Comment on\nthat as well so that future developers do not try to change it.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 0c3bf10edd..0ea858d652 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -251,6 +251,7 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\techo \"100644 $hash 0\tsome-file-$i\"\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n+\t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n \tgit rm -n \"some-file-*\" | : &&\n \ttest_path_is_missing .git/index.lock\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387046","messageId":"22ea5d736e98205c08716c0d898d280be7f6cbef.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 09/27] t4015: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:05Z","receivedAt":"2019-11-26T01:18:12Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 119 ++++++++++++++++++++++---------------\n 1 file changed, 72 insertions(+), 47 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex eadaf57262..7fb83c8eff 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -16,7 +16,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t} while (0);\n \tEOF\n \tgit update-index --add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \tcat <<-\\EOF >x &&\n \tdo\n@@ -25,7 +26,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t}\n \twhile (0);\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -63,7 +65,8 @@ test_expect_success 'another test, without options' '\n \tEOF\n \n \tgit update-index x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \ttr \"_\" \" \" <<-\\EOF >x &&\n \t_\twhitespace at beginning\n@@ -73,7 +76,8 @@ test_expect_success 'another test, without options' '\n \tunchanged line\n \tCR at end\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \ttr \"Q_\" \"\\015 \" <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -526,13 +530,15 @@ test_expect_success 'ignore-blank-lines: mix changes and blank lines' '\n test_expect_success 'check mixed spaces and tabs in indent' '\n \t# This is indented with SP HT SP.\n \techo \" \t foo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check mixed tabs and spaces in indent' '\n \t# This is indented with HT SP HT.\n \techo \"\t \tfoo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check with no whitespace errors' '\n@@ -753,20 +759,23 @@ test_expect_success 'check tab-in-indent excluded from wildcard whitespace attri\n test_expect_success 'line numbers in --check output are correct' '\n \techo \"\" >x &&\n \techo \"foo(); \" >>x &&\n-\tgit diff --check | grep \"x:2:\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"x:2:\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n \techo \"foo();\" >x &&\n \techo \"\" >>x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n \t{ echo a; echo b; echo; echo; } >x &&\n \tgit add x &&\n \t{ echo a; echo; echo; echo; echo; } >x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff allows new blank lines' '\n@@ -794,14 +803,16 @@ test_expect_success 'whitespace-only changes reported across renames' '\n \tgit reset --hard &&\n \tfor i in 1 2 3 4 5 6 7 8 9; do echo \"$i$i$i$i$i$i\"; done >x &&\n \tgit add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\thash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$hash_x\") &&\n \tgit commit -m \"base\" &&\n \tsed -e \"5s/^/ /\" x >z &&\n \tgit rm x &&\n \tgit add z &&\n-\tafter=$(git rev-parse --short $(git hash-object z)) &&\n-\tgit diff -w -M --cached |\n-\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" >actual &&\n+\thash_z=$(git hash-object z) &&\n+\tafter=$(git rev-parse --short \"$hash_z\") &&\n+\tgit diff -w -M --cached >actual.raw &&\n+\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" actual.raw >actual &&\n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/z\n \tsimilarity index NUM%\n@@ -840,7 +851,8 @@ test_expect_success 'combined diff with autocrlf conversion' '\n \tgit config core.autocrlf true &&\n \ttest_must_fail git merge master &&\n \n-\tgit diff | sed -e \"1,/^@@@/d\" >actual &&\n+\tgit diff >actual.raw &&\n+\tsed -e \"1,/^@@@/d\" actual.raw >actual &&\n \t! grep \"^-\" actual\n \n '\n@@ -864,11 +876,14 @@ test_expect_success 'diff that introduces a line with only tabs' '\n \tgit config core.whitespace blank-at-eol &&\n \tgit reset --hard &&\n \techo \"test\" >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -m \"initial\" x &&\n \techo \"{NTN}\" | tr \"NT\" \"\\n\\t\" >>x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n-\tgit diff --color | test_decode_color >current &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -891,17 +906,19 @@ test_expect_success 'diff that introduces and removes ws breakages' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n-\tgit diff --color |\n-\ttest_decode_color >current &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -925,14 +942,16 @@ test_expect_success 'ws-error-highlight test setup' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat >expect.default-old <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -974,32 +993,32 @@ test_expect_success 'ws-error-highlight test setup' '\n \n test_expect_success 'test --ws-error-highlight option' '\n \n-\tgit diff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit diff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit diff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n \n test_expect_success 'test diff.wsErrorHighlight config' '\n \n-\tgit -c diff.wsErrorHighlight=default,old diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=default,old diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit -c diff.wsErrorHighlight=all diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=all diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit -c diff.wsErrorHighlight=none diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=none diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1007,18 +1026,18 @@ test_expect_success 'test diff.wsErrorHighlight config' '\n test_expect_success 'option overrides diff.wsErrorHighlight' '\n \n \tgit -c diff.wsErrorHighlight=none \\\n-\t\tdiff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n \tgit -c diff.wsErrorHighlight=default \\\n-\t\tdiff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n \tgit -c diff.wsErrorHighlight=all \\\n-\t\tdiff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1038,7 +1057,8 @@ test_expect_success 'detect moved code, complete file' '\n \tgit mv test.c main.c &&\n \ttest_config color.diff.oldMoved \"normal red\" &&\n \ttest_config color.diff.newMoved \"normal green\" &&\n-\tgit diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&\n+\tgit diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>new file mode 100644<RESET>\n@@ -1141,9 +1161,12 @@ test_expect_success 'detect malicious moved code, inside file' '\n \t\t\tbar();\n \t\t}\n \tEOF\n-\tafter_main=$(git rev-parse --short $(git hash-object main.c)) &&\n-\tafter_test=$(git rev-parse --short $(git hash-object test.c)) &&\n-\tgit diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&\n+\thash_main=$(git hash-object main.c) &&\n+\tafter_main=$(git rev-parse --short \"$hash_main\") &&\n+\thash_test=$(git hash-object test.c) &&\n+\tafter_test=$(git rev-parse --short \"$hash_test\") &&\n+\tgit diff HEAD --no-renames --color-moved=zebra --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1192,7 +1215,8 @@ test_expect_success 'plain moved code, inside file' '\n \ttest_config color.diff.oldMovedAlternative \"blue\" &&\n \ttest_config color.diff.newMovedAlternative \"yellow\" &&\n \t# needs previous test as setup\n-\tgit diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&\n+\tgit diff HEAD --no-renames --color-moved=plain --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1771,7 +1795,8 @@ test_expect_success 'move detection with submodules' '\n \t! grep BRED decoded_actual &&\n \n \t# nor did we mess with it another way\n-\tgit diff --submodule=diff --color | test_decode_color >expect &&\n+\tgit diff --submodule=diff --color >expect.raw &&\n+\ttest_decode_color <expect.raw >expect &&\n \ttest_cmp expect decoded_actual &&\n \trm -rf bananas &&\n \tgit submodule deinit bananas\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387047","messageId":"a44dd28b4d22cf9dfbb9344d3184d5d0bd4ac1da.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 10/27] t4015: use test_write_lines()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:08Z","receivedAt":"2019-11-26T01:18:13Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Instead of rolling our own method to write out some lines into a file,\nuse the existing test_write_lines().\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex 7fb83c8eff..4c540b1d70 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -771,9 +771,9 @@ test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n-\t{ echo a; echo b; echo; echo; } >x &&\n+\ttest_write_lines a b \"\" \"\" >x &&\n \tgit add x &&\n-\t{ echo a; echo; echo; echo; echo; } >x &&\n+\ttest_write_lines a \"\" \"\" \"\" \"\" >x &&\n \ttest_must_fail git diff --check >check &&\n \tgrep \"new blank line\" check\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387048","messageId":"d512319be0f3a19cafb696ca9f6f2ccb7d0b8e85.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 11/27] t4138: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:11Z","receivedAt":"2019-11-26T01:18:15Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4138-apply-ws-expansion.sh | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh\nindex 3b636a63a3..b19faeb67a 100755\n--- a/t/t4138-apply-ws-expansion.sh\n+++ b/t/t4138-apply-ws-expansion.sh\n@@ -17,8 +17,8 @@ test_expect_success setup '\n \tprintf \"\\t%s\\n\" 1 2 3 >after &&\n \tprintf \"%64s\\n\" a b c >>after &&\n \tprintf \"\\t%s\\n\" 4 5 6 >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" >patch1.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch1.patch.raw &&\n+\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" patch1.patch.raw >patch1.patch &&\n \tprintf \"%64s\\n\" 1 2 3 4 5 6 >test-1 &&\n \tprintf \"%64s\\n\" 1 2 3 a b c 4 5 6 >expect-1 &&\n \n@@ -33,8 +33,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" >patch2.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch2.patch.raw &&\n+\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" patch2.patch.raw >patch2.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-2 &&\n \tprintf \"%64s\\n\" a b c >expect-2 &&\n \tx=1 &&\n@@ -56,8 +56,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" >patch3.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch3.patch.raw &&\n+\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" patch3.patch.raw >patch3.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-3 &&\n \tprintf \"%64s\\n\" a b c >expect-3 &&\n \tx=0 &&\n@@ -84,8 +84,8 @@ test_expect_success setup '\n \t\tprintf \"\\t%02d\\n\" $x >>after\n \t\tx=$(( $x + 1 ))\n \tdone &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" >patch4.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch4.patch.raw &&\n+\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" patch4.patch.raw >patch4.patch &&\n \t>test-4 &&\n \tx=0 &&\n \twhile test $x -lt 50\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387049","messageId":"1e08c2b68ba041f5bc94695481ddbd106e9bb4f4.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 12/27] t5317: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:13Z","receivedAt":"2019-11-26T01:18:17Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands output to a\nfile and surrounding commands only call command substitutions with\nnon-git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 13 +++++++------\n 1 file changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex 2d2f5d0229..a8bbad74e2 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -72,7 +72,8 @@ test_expect_success 'get an error for missing tree object' '\n \techo foo >r5/foo &&\n \tgit -C r5 add foo &&\n \tgit -C r5 commit -m \"foo\" &&\n-\tdel=$(git -C r5 rev-parse HEAD^{tree} | sed \"s|..|&/|\") &&\n+\tgit -C r5 rev-parse HEAD^{tree} >tree &&\n+\tdel=$(sed \"s|..|&/|\" tree) &&\n \trm r5/.git/objects/$del &&\n \ttest_must_fail git -C r5 pack-objects --revs --stdout 2>bad_tree <<-EOF &&\n \tHEAD\n@@ -230,10 +231,9 @@ test_expect_success 'verify explicitly specifying oversized blob in input' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&\n-\tHEAD\n-\t$(git -C r2 rev-parse HEAD:large.10000)\n-\tEOF\n+\techo HEAD >objects &&\n+\tgit -C r2 rev-parse HEAD:large.10000 >>objects &&\n+\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k <objects >filter.pack &&\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n@@ -377,7 +377,8 @@ test_expect_success 'verify sparse:oid=OID' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\toid=$(git -C r4 ls-files -s pattern | awk -f print_2.awk) &&\n+\tgit -C r4 ls-files -s pattern >staged &&\n+\toid=$(awk -f print_2.awk staged) &&\n \tgit -C r4 pack-objects --revs --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF &&\n \tHEAD\n \tEOF\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387050","messageId":"fa238be28b5f4e1281d310eab0a6f90c15196d88.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 13/27] t5317: use ! grep to check for no matching lines","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:15Z","receivedAt":"2019-11-26T01:18:22Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Several times in t5317, we would use `wc -l` to ensure that a grep\nresult is empty. However, grep already has a way to do that... Its\nreturn code! Use `! grep` in the cases where we are ensuring that there\nare no matching lines.\n\nWhile at it, drop unnecessary invocations of `awk` and `sort` in each\naffected test since those commands do not influence the outcome. It's\nnot clear why that extra work was being done in the first place, and the\ncode's history doesn't shed any light on the matter since these tests\nwere simply born this way[1], likely due to copy-paste programming. The\nunnecessary work wasn't noticed even when the code was later touched for\nvarious cleanups[2][3].\n\n[1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n[2]: bdbc17e86a (tests: standardize pipe placement, 2018-10-05)\n[3]: 61de0ff695 (tests: don't swallow Git errors upstream of pipes, 2018-10-05)\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 21 +++------------------\n 1 file changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex a8bbad74e2..dc0446574b 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -45,12 +45,7 @@ test_expect_success 'verify blob:none packfile has no blobs' '\n \tgit -C r1 index-pack ../filter.pack &&\n \n \tgit -C r1 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify normal and blob:none packfiles have same commits/trees' '\n@@ -149,12 +144,7 @@ test_expect_success 'verify blob:limit=500 omits all blobs' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1000' '\n@@ -164,12 +154,7 @@ test_expect_success 'verify blob:limit=1000' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1001' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387051","messageId":"291caf9bc11574b8f2ce8dcbaeb5d369c597a8c8.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 14/27] t5703: simplify one-time-sed generation logic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:18Z","receivedAt":"2019-11-26T01:18:24Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In inconsistency(), we had two `git rev-parse` invocations in the\nupstream of a pipe within a command substitution. In case this\ninvocation ever failed, its exit code would be swallowed up and we would\nnot know about it.\n\nPull the command substitutions out into variable assignments so that\ntheir return codes are not lost.\n\nDrop the pipe into `tr` because the $(...) substitution already takes\ncare of stripping out newlines, so the `tr` invocations in the code are\nsuperfluous.\n\nFinally, given the way the tests actually employ \"one-time-sed\" via\n$(cat one-time-sed) in t/lib-httpd/apply-one-time-sed.sh, convert the\n`printf` into an `echo`. This makes it consistent with the final \"server\nloses a ref - ref in want\" test, which does use `echo` rather than\n`printf`.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 7 +++----\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 3a2c143c6d..88338c4e09 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -312,10 +312,9 @@ inconsistency () {\n \t# repository appears to change during negotiation, for example, when\n \t# different servers in a load-balancing arrangement serve (stateless)\n \t# RPCs during a single negotiation.\n-\tprintf \"s/%s/%s/\" \\\n-\t       $(git -C \"$REPO\" rev-parse $1 | tr -d \"\\n\") \\\n-\t       $(git -C \"$REPO\" rev-parse $2 | tr -d \"\\n\") \\\n-\t       >\"$HTTPD_ROOT_PATH/one-time-sed\"\n+\toid1=$(git -C \"$REPO\" rev-parse $1) &&\n+\toid2=$(git -C \"$REPO\" rev-parse $2) &&\n+\techo \"s/$oid1/$oid2/\" >\"$HTTPD_ROOT_PATH/one-time-sed\"\n }\n \n test_expect_success 'server is initially ahead - no ref in want' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387052","messageId":"edf7af76aed1ed33dcdebb45a0d031b9bf4838f3.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 15/27] t5703: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:20Z","receivedAt":"2019-11-26T01:18:27Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands are in an\nassignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 46 +++++++++++++++++++-----------\n 1 file changed, 29 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 88338c4e09..1424fabd4a 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -18,14 +18,16 @@ get_actual_commits () {\n \t\tp\n \t\t}' <out | test-tool pkt-line unpack-sideband >o.pack &&\n \tgit index-pack o.pack &&\n-\tgit verify-pack -v o.idx | grep commit | cut -c-40 | sort >actual_commits\n+\tgit verify-pack -v o.idx >objs &&\n+\tgrep commit objs | cut -c-40 | sort >actual_commits\n }\n \n check_output () {\n \tget_actual_refs &&\n \ttest_cmp expected_refs actual_refs &&\n \tget_actual_commits &&\n-\ttest_cmp expected_commits actual_commits\n+\tsort expected_commits >sorted_commits &&\n+\ttest_cmp sorted_commits actual_commits\n }\n \n # c(o/foo) d(o/bar)\n@@ -75,17 +77,19 @@ test_expect_success 'invalid want-ref line' '\n '\n \n test_expect_success 'basic want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse f | sort >expected_commits &&\n+\tgit rev-parse f >expected_commits &&\n \n+\toid=$(git rev-parse a) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/master\n-\thave $(git rev-parse a)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -95,19 +99,22 @@ test_expect_success 'basic want-ref' '\n '\n \n test_expect_success 'multiple want-ref lines' '\n+\toid_c=$(git rev-parse c) &&\n+\toid_d=$(git rev-parse d) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n-\t$(git rev-parse d) refs/heads/o/bar\n+\t$oid_c refs/heads/o/foo\n+\t$oid_d refs/heads/o/bar\n \tEOF\n-\tgit rev-parse c d | sort >expected_commits &&\n+\tgit rev-parse c d >expected_commits &&\n \n+\toid=$(git rev-parse b) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n \twant-ref refs/heads/o/bar\n-\thave $(git rev-parse b)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -117,10 +124,11 @@ test_expect_success 'multiple want-ref lines' '\n '\n \n test_expect_success 'mix want and want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse e f | sort >expected_commits &&\n+\tgit rev-parse e f >expected_commits &&\n \n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n@@ -138,17 +146,19 @@ test_expect_success 'mix want and want-ref' '\n '\n \n test_expect_success 'want-ref with ref we already have commit for' '\n+\toid=$(git rev-parse c) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n+\t$oid refs/heads/o/foo\n \tEOF\n \t>expected_commits &&\n \n+\toid=$(git rev-parse c) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n-\thave $(git rev-parse c)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -211,13 +221,14 @@ test_expect_success 'fetching with exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse d) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\t$(git -C \"$REPO\" rev-parse d):refs/heads/actual &&\n+\t\t\"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"d\" >expected &&\n \tgit -C local rev-parse refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse d)\" log\n+\tgrep \"want $oid\" log\n '\n \n test_expect_success 'fetching multiple refs' '\n@@ -239,13 +250,14 @@ test_expect_success 'fetching ref and exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse b) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\tmaster $(git -C \"$REPO\" rev-parse b):refs/heads/actual &&\n+\t\tmaster \"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"master\" \"b\" >expected &&\n \tgit -C local rev-parse refs/remotes/origin/master refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse b)\" log &&\n+\tgrep \"want $oid\" log &&\n \tgrep \"want-ref refs/heads/master\" log\n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387053","messageId":"5eb7117fbef4c39aecbdbd25c9e1f0a637c4b0de.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 16/27] t7501: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:23Z","receivedAt":"2019-11-26T01:18:27Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex f1349af56e..5765d33c53 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -150,7 +150,7 @@ test_expect_success 'setup: commit message from file' '\n test_expect_success 'amend commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/a file/an amend commit/g\" < \"$1\" > \"$1-\"\n+\tsed -e \"s/a file/an amend commit/g\" <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -263,7 +263,7 @@ test_expect_success 'using message from other commit' '\n test_expect_success 'editing message from other commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/amend/older/g\"  < \"$1\" > \"$1-\"\n+\tsed -e \"s/amend/older/g\"  <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -367,7 +367,7 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -382,7 +382,7 @@ test_expect_success 'amend commit to fix date' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --date=\"$newtick\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -448,7 +448,7 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -468,7 +468,7 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -489,7 +489,7 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +506,7 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -560,14 +560,14 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n \n test_expect_success 'git commit <file> with dirty index' '\n-\techo tacocat > elif &&\n-\techo tehlulz > chz &&\n+\techo tacocat >elif &&\n+\techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n \tgit show --stat | grep elif &&\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387054","messageId":"bad732adc8067804bb35e46026ddcf736c4eb2ce.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 17/27] t7501: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:25Z","receivedAt":"2019-11-26T01:18:30Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nIn the 'interactive add' test case, we prepend a `test_must_fail` to\n`git commit --interactive`. When there are no changes to commit,\n`git commit` will exit with status code 1. Following along with the rest\nof the file, we use `test_must_fail` to test for this case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 69 +++++++++++++++------------\n 1 file changed, 39 insertions(+), 30 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex 5765d33c53..110b4bf459 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -285,9 +285,8 @@ test_expect_success 'overriding author from command line' '\n '\n \n test_expect_success PERL 'interactive add' '\n-\techo 7 |\n-\tgit commit --interactive |\n-\tgrep \"What now\"\n+\techo 7 | test_must_fail git commit --interactive >out &&\n+\tgrep \"What now\" out\n '\n \n test_expect_success PERL \"commit --interactive doesn't change index if editor aborts\" '\n@@ -362,10 +361,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -377,10 +376,10 @@ test_expect_success 'amend commit to fix date' '\n \ttest_tick &&\n \tnewtick=$GIT_AUTHOR_DATE &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $newtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --date=\"$newtick\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -409,12 +408,13 @@ test_expect_success 'sign off (1)' '\n \techo 1 >positive &&\n \tgit add positive &&\n \tgit commit -s -m \"thank you\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -428,13 +428,14 @@ test_expect_success 'sign off (2)' '\n \tgit commit -s -m \"thank you\n \n $existing\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n \t\techo $existing &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -448,13 +449,14 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo $alt &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -468,15 +470,16 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo We have now &&\n \t\techo $alt &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -489,7 +492,8 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +510,8 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -538,7 +543,8 @@ test_expect_success 'multiple -m' '\n \t>negative &&\n \tgit add negative &&\n \tgit commit -m \"one\" -m \"two\" -m \"three\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo one &&\n \t\techo &&\n@@ -555,10 +561,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -570,8 +576,10 @@ test_expect_success 'git commit <file> with dirty index' '\n \techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n-\tgit show --stat | grep elif &&\n-\tgit diff --cached | grep chz\n+\tgit show --stat >stat &&\n+\tgrep elif stat &&\n+\tgit diff --cached >diff &&\n+\tgrep chz diff\n '\n \n test_expect_success 'same tree (single parent)' '\n@@ -584,7 +592,8 @@ test_expect_success 'same tree (single parent)' '\n test_expect_success 'same tree (single parent) --allow-empty' '\n \n \tgit commit --allow-empty -m \"forced empty\" &&\n-\tgit cat-file commit HEAD | grep forced\n+\tgit cat-file commit HEAD >commit &&\n+\tgrep forced commit\n \n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387055","messageId":"c50c192429c73146b64a8c7637e89554fee4e24d.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 18/27] t7700: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:27Z","receivedAt":"2019-11-26T01:18:32Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nIn one case where the output of stdout is consumed, redirect the output\nof test_commit to stderr.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 4e855bc21b..e1a689d6a9 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -5,7 +5,7 @@ test_description='git repack works correctly'\n . ./test-lib.sh\n \n commit_and_pack() {\n-\ttest_commit \"$@\" >/dev/null &&\n+\ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n@@ -19,7 +19,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n \tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack > /dev/null &&\n+\t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n \tpacksha1=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n@@ -235,7 +235,7 @@ test_expect_success 'incremental repack does not complain' '\n \n test_expect_success 'bitmaps can be disabled on bare repos' '\n \tgit -c repack.writeBitmaps=false -C bare.git repack -ad &&\n-\tbitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) &&\n+\tbitmap=$(ls bare.git/objects/pack/*.bitmap || :) &&\n \ttest -z \"$bitmap\"\n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387056","messageId":"58ae066d12144a226ceb7617a3597c5799a2cd58.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 19/27] t7700: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:30Z","receivedAt":"2019-11-26T01:18:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 18 +++++++++---------\n 1 file changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex e1a689d6a9..8936928387 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -11,8 +11,8 @@ commit_and_pack() {\n }\n \n test_expect_success 'objects in packs marked .keep are not repacked' '\n-\techo content1 > file1 &&\n-\techo content2 > file2 &&\n+\techo content1 >file1 &&\n+\techo content2 >file2 &&\n \tgit add . &&\n \ttest_tick &&\n \tgit commit -m initial_commit &&\n@@ -75,8 +75,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n-\techo content3 > file3 &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n+\techo content3 >file3 &&\n \tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n@@ -111,7 +111,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n \trm -f .git/objects/pack/* &&\n-\techo new_content >> file1 &&\n+\techo new_content >>file1 &&\n \tgit add file1 &&\n \ttest_tick &&\n \tgit commit -m more_content &&\n@@ -169,12 +169,12 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n@@ -186,7 +186,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n@@ -196,7 +196,7 @@ test_expect_success 'objects made unreachable by grafts only are kept' '\n \tH0=$(git rev-parse HEAD) &&\n \tH1=$(git rev-parse HEAD^) &&\n \tH2=$(git rev-parse HEAD^^) &&\n-\techo \"$H0 $H2\" > .git/info/grafts &&\n+\techo \"$H0 $H2\" >.git/info/grafts &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n \tgit repack -a -d &&\n \tgit cat-file -t $H1\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387057","messageId":"82bf24d06ab663d404a717ae9091dd272d1c3396.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 20/27] t7700: move keywords onto their own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:32Z","receivedAt":"2019-11-26T01:18:38Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move keywords onto their own line so that they conform with\nthe test style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 51 +++++++++++++++++++++++++++++++----------------\n 1 file changed, 34 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 8936928387..a96e876c4e 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -29,10 +29,12 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -45,10 +47,12 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -61,10 +65,12 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -83,8 +89,10 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -99,10 +107,13 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -119,10 +130,13 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -144,10 +158,13 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387058","messageId":"251de77677a9eda0d13c3f5668fa456ad4a52902.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 21/27] t7700: s/test -f/test_path_is_file/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:34Z","receivedAt":"2019-11-26T01:18:41Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have debugging-friendly alternatives to `test -f`, replace\ninstances of `test -f` with `test_path_is_file` so that if a command\never fails, we get better debugging information.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex a96e876c4e..1d14ddcbdb 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -106,7 +106,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -129,7 +129,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -148,7 +148,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tfor p in alt_objects/pack/*.pack\n \tdo\n \t\tbase_name=$(basename $p .pack) &&\n-\t\tif test -f alt_objects/pack/$base_name.keep\n+\t\tif test_path_is_file alt_objects/pack/$base_name.keep\n \t\tthen\n \t\t\trm alt_objects/pack/$base_name.keep\n \t\telse\n@@ -157,7 +157,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tdone &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387059","messageId":"c98a2a15090ac3d23757d1d4317d6a1bdcf5b115.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 22/27] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:37Z","receivedAt":"2019-11-26T01:18:42Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code to test that objects were not missing from the packfile was\nduplicated many times. Extract the duplicated code into\ntest_no_missing_in_packs() and use that instead.\n\nRefactor the resulting extraction so that if any git commands fail,\ntheir return codes are not silently lost.\n\nWe were using sed to filter lines. Although not incorrect, this is\nexactly what grep is built for. Replace this invocation of sed with grep\nso that we use the correct tool for the job.\n\nThe original testing construct was O(n^2): it used a grep in a loop to\ntest whether any objects were missing in the packfile. Rewrite this to\nuse sort the files then use `comm -23` so that finding missing lines\nfrom the original file is done more efficiently.\n\nWhile we're at it, add a space to `commit_and_pack ()` for style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 59 +++++++++++++++--------------------------------\n 1 file changed, 19 insertions(+), 40 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 1d14ddcbdb..a6c3d34277 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -4,12 +4,27 @@ test_description='git repack works correctly'\n \n . ./test-lib.sh\n \n-commit_and_pack() {\n+commit_and_pack () {\n \ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n \n+test_no_missing_in_packs () {\n+\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n+\ttest_path_is_file \"$myidx\" &&\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tgrep \"^[0-9a-f]\\{40\\}\" packlist\n+\tdone >orig.raw &&\n+\tcut -d\" \" -f1 orig.raw | sort >orig &&\n+\tgit verify-pack -v $myidx >dest.raw &&\n+\tcut -d\" \" -f1 dest.raw | sort >dest &&\n+\tcomm -23 orig dest >missing &&\n+\ttest_must_be_empty missing\n+}\n+\n test_expect_success 'objects in packs marked .keep are not repacked' '\n \techo content1 >file1 &&\n \techo content2 >file2 &&\n@@ -105,19 +120,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmkdir alt_objects/pack &&\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n@@ -128,19 +131,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit commit -m more_content &&\n \tgit repack &&\n \tgit repack -a -d &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n@@ -156,19 +147,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \t\tfi\n \tdone &&\n \tgit repack -a -d &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387060","messageId":"e4ba198483b5501bdc719843470cf685ca4079f1.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 23/27] squash! t7700: consolidate code into test_no_missing_in_packs()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:39Z","receivedAt":"2019-11-26T01:18:44Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Instead of verifying each file of `alt_objects/pack/*.idx` individually\nin a for-loop, batch them together into one verification step.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n\nNotes:\n    We should probably squash this in but before we do this, I'd like some\n    confirmation that doing this doesn't have any negative impacts.\n\n t/t7700-repack.sh | 8 ++------\n 1 file changed, 2 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex a6c3d34277..4bcd9fcc80 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -13,12 +13,8 @@ commit_and_pack () {\n test_no_missing_in_packs () {\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p >packlist || return $?\n-\t\tgrep \"^[0-9a-f]\\{40\\}\" packlist\n-\tdone >orig.raw &&\n-\tcut -d\" \" -f1 orig.raw | sort >orig &&\n+\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n+\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n \tgit verify-pack -v $myidx >dest.raw &&\n \tcut -d\" \" -f1 dest.raw | sort >dest &&\n \tcomm -23 orig dest >missing &&\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387061","messageId":"fa38d7e8f667e9d0773aa8b846a94a747097c394.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 24/27] t7700: consolidate code into test_has_duplicate_object()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:41Z","receivedAt":"2019-11-26T01:18:46Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code to test that objects were not duplicated from the packfile was\nduplicated many times. Extract the duplicated code into\ntest_has_duplicate_object() and use that instead.\n\nRefactor the resulting extraction so that if the git command fails,\nthe return code is not silently lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 71 +++++++++++++++--------------------------------\n 1 file changed, 23 insertions(+), 48 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 4bcd9fcc80..5bbed02fe5 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -21,6 +21,25 @@ test_no_missing_in_packs () {\n \ttest_must_be_empty missing\n }\n \n+# we expect $packsha1 and $objsha1 to be defined\n+test_has_duplicate_object () {\n+\twant_duplicate_object=\"$1\"\n+\tfound_duplicate_object=false\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tidx=$(basename $p)\n+\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n+\t\tthen\n+\t\t\tfound_duplicate_object=true\n+\t\t\techo \"DUPLICATE OBJECT FOUND\"\n+\t\t\tbreak\n+\t\tfi\n+\tdone &&\n+\ttest \"$want_duplicate_object\" = \"$found_duplicate_object\"\n+}\n+\n test_expect_success 'objects in packs marked .keep are not repacked' '\n \techo content1 >file1 &&\n \techo content2 >file2 &&\n@@ -40,54 +59,19 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest -z \"$found_duplicate_object\"\n+\ttest_has_duplicate_object false\n '\n \n test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n-\ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest \"$found_duplicate_object\" = 1\n+\ttest_has_duplicate_object true\n '\n \n test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n-\ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest \"$found_duplicate_object\" = 1\n+\ttest_has_duplicate_object true\n '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n@@ -100,16 +84,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest -z \"$found_duplicate_object\"\n+\ttest_has_duplicate_object false\n '\n \n test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387062","messageId":"4f02c00bd1cb2e23e5ab7d84dcd42c76e9b076ac.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 25/27] t7700: replace egrep with grep","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:43Z","receivedAt":"2019-11-26T01:18:48Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The egrep expressions in this test suite were of the form `^$variable`.\nAlthough egrep works just fine, it's overkill since we're not using any\nextended regex. Replace egrep invocations with grep so that we aren't\nswatting flies with a sledgehammer.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 5bbed02fe5..2493cc4e9b 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -30,7 +30,7 @@ test_has_duplicate_object () {\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n \t\tgit verify-pack -v $p >packlist || return $?\n-\t\tif egrep \"^$objsha1\" packlist\n+\t\tif grep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=true\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -135,7 +135,7 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n@@ -152,7 +152,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387063","messageId":"a747fbd08b46f394c4dc1e9f9b8399d13d294273.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 26/27] t7700: make references to SHA-1 generic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:46Z","receivedAt":"2019-11-26T01:18:52Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Make the test more hash-agnostic by renaming variables from \"sha1\" to\n\"oid\" (case-insensitively). Also, replace the regex, `[0-9a-f]\\{40\\}`\nwith `$OID_REGEX`.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 38 +++++++++++++++++++-------------------\n 1 file changed, 19 insertions(+), 19 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 2493cc4e9b..d96b1a5949 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -6,31 +6,31 @@ test_description='git repack works correctly'\n \n commit_and_pack () {\n \ttest_commit \"$@\" 1>&2 &&\n-\tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n-\techo pack-${SHA1}.pack\n+\tOID=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n+\techo pack-${OID}.pack\n }\n \n test_no_missing_in_packs () {\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest_path_is_file \"$myidx\" &&\n \tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n-\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n+\tgrep \"^$OID_REGEX\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n \tgit verify-pack -v $myidx >dest.raw &&\n \tcut -d\" \" -f1 dest.raw | sort >dest &&\n \tcomm -23 orig dest >missing &&\n \ttest_must_be_empty missing\n }\n \n-# we expect $packsha1 and $objsha1 to be defined\n+# we expect $packoid and $objoid to be defined\n test_has_duplicate_object () {\n \twant_duplicate_object=\"$1\"\n \tfound_duplicate_object=false\n \tfor p in .git/objects/pack/*.idx\n \tdo\n \t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n+\t\ttest \"pack-$packoid.idx\" = \"$idx\" && continue\n \t\tgit verify-pack -v $p >packlist || return $?\n-\t\tif grep \"^$objsha1\" packlist\n+\t\tif grep \"^$objoid\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=true\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -51,11 +51,11 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit rev-list --objects --all | grep -v file2 |\n \t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpacksha1=$(git rev-list --objects --all | grep file2 |\n+\tpackoid=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n-\t>pack-$packsha1.keep &&\n-\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n-\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n+\t>pack-$packoid.keep &&\n+\tobjoid=$(git verify-pack -v pack-$packoid.idx | head -n 1 |\n+\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -63,13 +63,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n '\n \n test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '\n-\t# build on $objsha1, $packsha1, and .keep state from previous\n+\t# build on $objoid, $packoid, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_has_duplicate_object true\n '\n \n test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n-\t# build on $objsha1, $packsha1, and .keep state from previous\n+\t# build on $objoid, $packoid, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_has_duplicate_object true\n '\n@@ -78,7 +78,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n \techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo content3 >file3 &&\n-\tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n+\tobjoid=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n \tgit commit -m commit_file3 &&\n@@ -124,7 +124,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f alt_objects/pack/*.keep &&\n \tmv .git/objects/pack/* alt_objects/pack/ &&\n-\tcsha1=$(git rev-parse HEAD^{commit}) &&\n+\tcoid=$(git rev-parse HEAD^{commit}) &&\n \tgit reset --hard HEAD^ &&\n \ttest_tick &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n@@ -135,14 +135,14 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n-\ttest_must_fail git show $csha1\n+\ttest_must_fail git show $coid\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n \techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n-\techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n+\techo \"$coid\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \t# The pack-objects call on the next line is equivalent to\n@@ -152,9 +152,9 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n-\ttest_must_fail git show $csha1\n+\ttest_must_fail git show $coid\n '\n \n test_expect_success 'objects made unreachable by grafts only are kept' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387064","messageId":"fb614f4385745c804aea36e0471dfc96c0b97cb9.1574731022.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v4 27/27] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T01:18:48Z","receivedAt":"2019-11-26T01:18:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 19 +++++++++----------\n 1 file changed, 9 insertions(+), 10 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex d96b1a5949..93b20bb7a8 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -48,14 +48,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit commit -m initial_commit &&\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n-\tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack &&\n+\tgit rev-list --objects --all >objs &&\n+\tgrep -v file2 objs | git pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpackoid=$(git rev-list --objects --all | grep file2 |\n-\t\tgit pack-objects pack) &&\n+\tpackoid=$(grep file2 objs | git pack-objects pack) &&\n \t>pack-$packoid.keep &&\n-\tobjoid=$(git verify-pack -v pack-$packoid.idx | head -n 1 |\n-\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n+\tgit verify-pack -v pack-$packoid.idx >packlist &&\n+\tobjoid=$(head -n 1 packlist | sed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -134,8 +133,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! grep \"^$coid \" packlist &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $coid\n '\n@@ -151,8 +150,8 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! grep \"^$coid \" &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $coid\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387068","messageId":"xmqqlfs3whc7.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"CAPig+cQqK-HiDjmnBFo-qeE6cZ73EveWg6Ygb-4BX3X_iPSJZA@mail.gmail.com","subject":"Re: [PATCH v3 22/22] t7700: stop losing return codes of git commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-26T01:34:48Z","receivedAt":"2019-11-26T01:34:52Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> It may not be too much work for you to keep adding more (unrelated)\n> changes to a series, but doing so increases the burden on reviewers\n> unnecessarily, especially for a long patch series such as this one.\n> Generally speaking, each iteration should help the series converge to\n> the point at which it can finally land (be merged to \"next\"). Thus,\n> ideally, each iteration should have fewer changes than the previous\n> one.\n\nYup.  It is too easy to paint an ongoing series with a brush that is\nbroader than necessary and say \"this is to clean up\", and fall into\na never-ending run of scope expansion, as there always is yet\nanother thing to clean up.  The focus of the series has been to\nensure that we catch error exit from \"git\" and that script conforms\nto the style guidelines, and does not include hash migration.  \n\nLet's resist the urge to expand the scope.\n\nThanks.\n\n\n"},{"id":"387070","messageId":"CAPig+cS13ohg7UJv3b-D4h4MPn5yHmH3joQRtdn592SN+XUeUQ@mail.gmail.com","threadId":"52269","inReplyTo":"c98a2a15090ac3d23757d1d4317d6a1bdcf5b115.1574731022.git.liu.denton@gmail.com","subject":"Re: [PATCH v4 22/27] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-26T02:35:33Z","receivedAt":"2019-11-26T02:35:48Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Nov 25, 2019 at 8:21 PM Denton Liu <liu.denton@gmail.com> wrote:\n> The code to test that objects were not missing from the packfile was\n> duplicated many times. Extract the duplicated code into\n> test_no_missing_in_packs() and use that instead.\n>\n> Refactor the resulting extraction so that if any git commands fail,\n> their return codes are not silently lost.\n>\n> We were using sed to filter lines. Although not incorrect, this is\n> exactly what grep is built for. Replace this invocation of sed with grep\n> so that we use the correct tool for the job.\n>\n> The original testing construct was O(n^2): it used a grep in a loop to\n> test whether any objects were missing in the packfile. Rewrite this to\n> use sort the files then use `comm -23` so that finding missing lines\n\ns/use sort/sort/\n\n> from the original file is done more efficiently.\n>\n> While we're at it, add a space to `commit_and_pack ()` for style.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n"},{"id":"387072","messageId":"CAPig+cRDVndrWajFzZDShyo2cV2MechUF1bZFqkRTk87moN3rA@mail.gmail.com","threadId":"52269","inReplyTo":"a747fbd08b46f394c4dc1e9f9b8399d13d294273.1574731022.git.liu.denton@gmail.com","subject":"Re: [PATCH v4 26/27] t7700: make references to SHA-1 generic","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-26T03:15:55Z","receivedAt":"2019-11-26T03:16:09Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Mon, Nov 25, 2019 at 8:22 PM Denton Liu <liu.denton@gmail.com> wrote:\n> Make the test more hash-agnostic by renaming variables from \"sha1\" to\n> \"oid\" (case-insensitively). Also, replace the regex, `[0-9a-f]\\{40\\}`\n> with `$OID_REGEX`.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n> diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\n> @@ -6,31 +6,31 @@ test_description='git repack works correctly'\n>  commit_and_pack () {\n>         test_commit \"$@\" 1>&2 &&\n> -       SHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n> -       echo pack-${SHA1}.pack\n> +       OID=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n> +       echo pack-${OID}.pack\n>  }\n\nMeh. OID stands for \"object ID\". However, in this context, SHA1 is a\ncomputed hash value -- a checksum -- not the ID of an object. So,\ncalling this an OID is confusing (IMHO). By the way, the uppercase\n\"SHA1\" gives the impression that this value is global to the script,\nbut it is, in fact, used only in this function, so it would be clearer\nto downcase the entire name, implying by convention that it is a local\nvariable. Taking both observations into consideration, a better name\nmight be \"packid\".\n\n> -# we expect $packsha1 and $objsha1 to be defined\n> +# we expect $packoid and $objoid to be defined\n\nLikewise. By using \"oid\" in these names, you're calling these values\n\"pack object ID\" and \"object object ID\", respectively, which doesn't\nmake much sense. Perhaps \"packid\" and simply \"oid\" would be better\nnames.\n\nSame comment applies to remaining changes in this patch.\n\n> @@ -124,7 +124,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n>  test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n>         rm -f alt_objects/pack/*.keep &&\n>         mv .git/objects/pack/* alt_objects/pack/ &&\n> -       csha1=$(git rev-parse HEAD^{commit}) &&\n> +       coid=$(git rev-parse HEAD^{commit}) &&\n\nThis is indeed an object ID, so replacing literal \"sha1\" with \"oid\" makes sense.\n"},{"id":"387073","messageId":"20191126044703.GA3579@generichostname","threadId":"52269","inReplyTo":"xmqqlfs3whc7.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 22/22] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-26T04:47:03Z","receivedAt":"2019-11-26T04:47:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio and Eric,\n\nOn Tue, Nov 26, 2019 at 10:34:48AM +0900, Junio C Hamano wrote:\n> Eric Sunshine <sunshine@sunshineco.com> writes:\n> \n> > It may not be too much work for you to keep adding more (unrelated)\n> > changes to a series, but doing so increases the burden on reviewers\n> > unnecessarily, especially for a long patch series such as this one.\n> > Generally speaking, each iteration should help the series converge to\n> > the point at which it can finally land (be merged to \"next\"). Thus,\n> > ideally, each iteration should have fewer changes than the previous\n> > one.\n\nSorry for expanding the burden I've been putting on you. I really\nappreciate the effort both of you have been putting in reviewing my work\nand I'll make sure to not make it any harder than necessary for any\nreviewers in the future.\n\n> \n> Yup.  It is too easy to paint an ongoing series with a brush that is\n> broader than necessary and say \"this is to clean up\", and fall into\n> a never-ending run of scope expansion, as there always is yet\n> another thing to clean up.  The focus of the series has been to\n> ensure that we catch error exit from \"git\" and that script conforms\n> to the style guidelines, and does not include hash migration.  \n> \n> Let's resist the urge to expand the scope.\n\nI see that Eric's already reviewed the changes from this round (thanks,\nEric) so I don't want his work to go to waste. But I won't change the\nscope from this point forward.\n\nSorry again for the extra burden,\n\nDenton\n\n> \n> Thanks.\n> \n> \n"},{"id":"387212","messageId":"cover.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574731022.git.liu.denton@gmail.com","subject":"[PATCH v5 00/26] t: test cleanup stemming from experimentally enabling pipefail","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:00Z","receivedAt":"2019-11-27T19:53:06Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"These patches perform some general test cleanup to modernise the style.\nThey should be relatively uncontroversial. The reason these tests were\nidentified for cleanup was because they failed under `set -o pipefail`.\n\nI've gotten rid of the RFC part that actually enables `set -o pipefail`\non supported platforms. As Peff pointed out, there are a lot of\nopportunities for racy SIGPIPE failures so that part still needs a lot\nof work to be ironed out.\n\nThose changes shouldn't hold back the first part of the series, however.\nLet's try to get this test cleanup merged in sooner than later so that\nany new test cases done by copy-paste will have their changes\nrepresented.\n\nChanges since v4:\n\n* Squash in \"squash! t7700: consolidate code into test_no_missing_in_packs()\"\n\n* Fix typo in \"t7700: consolidate code into test_no_missing_in_packs()\"\n\n* Use \"oid\" and \"packid\" instead of \"objoid\" and \"packoid\" in \"t7700:\n  make references to SHA-1 generic\"\n\nChanges since v3:\n\n* More commit message update\n\n* Clean up \"apply-one-time-sed.sh: modernize style\" more according to\n  Junio's suggestions\n\n* Clean up the t7700 leftover bits\n\nChanges since v2:\n\n* Update commit messages according to Eric's suggestions\n\n* Add \"apply-one-time-sed.sh: modernize style\"\n\nChanges since v1:\n\n* Removed the `set -o pipefail` changes\n\n* Addressed Junio and Eric's comments on the first part of the series\n\nDenton Liu (26):\n  lib-bash.sh: move `then` onto its own line\n  apply-one-time-sed.sh: modernize style\n  t0014: remove git command upstream of pipe\n  t0090: stop losing return codes of git commands\n  t3301: stop losing return codes of git commands\n  t3600: use test_line_count() where possible\n  t3600: stop losing return codes of git commands\n  t3600: comment on inducing SIGPIPE in `git rm`\n  t4015: stop losing return codes of git commands\n  t4015: use test_write_lines()\n  t4138: stop losing return codes of git commands\n  t5317: stop losing return codes of git commands\n  t5317: use ! grep to check for no matching lines\n  t5703: simplify one-time-sed generation logic\n  t5703: stop losing return codes of git commands\n  t7501: remove spaces after redirect operators\n  t7501: stop losing return codes of git commands\n  t7700: drop redirections to /dev/null\n  t7700: remove spaces after redirect operators\n  t7700: move keywords onto their own line\n  t7700: s/test -f/test_path_is_file/\n  t7700: consolidate code into test_no_missing_in_packs()\n  t7700: consolidate code into test_has_duplicate_object()\n  t7700: replace egrep with grep\n  t7700: make references to SHA-1 generic\n  t7700: stop losing return codes of git commands\n\n t/lib-bash.sh                          |   6 +-\n t/lib-httpd/apply-one-time-sed.sh      |   8 +-\n t/t0014-alias.sh                       |   4 +-\n t/t0090-cache-tree.sh                  |   5 +-\n t/t3301-notes.sh                       | 230 ++++++++++++++++++-------\n t/t3600-rm.sh                          |  14 +-\n t/t4015-diff-whitespace.sh             | 123 +++++++------\n t/t4138-apply-ws-expansion.sh          |  16 +-\n t/t5317-pack-objects-filter-objects.sh |  34 ++--\n t/t5703-upload-pack-ref-in-want.sh     |  53 +++---\n t/t7501-commit-basic-functionality.sh  |  83 +++++----\n t/t7700-repack.sh                      | 172 ++++++++----------\n 12 files changed, 425 insertions(+), 323 deletions(-)\n\nRange-diff against v4:\n 1:  d5e769af39 =  1:  9085cc00af lib-bash.sh: move `then` onto its own line\n 2:  31434dfb4b =  2:  86f625c65e apply-one-time-sed.sh: modernize style\n 3:  e4443a6358 =  3:  3844e00367 t0014: remove git command upstream of pipe\n 4:  712354f90c =  4:  7d33586b21 t0090: stop losing return codes of git commands\n 5:  adef902872 =  5:  df6b3393c4 t3301: stop losing return codes of git commands\n 6:  a79cfe261a =  6:  d541a8d4d4 t3600: use test_line_count() where possible\n 7:  bfbb8bde3a =  7:  a8aeca6795 t3600: stop losing return codes of git commands\n 8:  714da9e618 =  8:  e3db06578d t3600: comment on inducing SIGPIPE in `git rm`\n 9:  4d5f40f3b0 =  9:  22ea5d736e t4015: stop losing return codes of git commands\n10:  68ed9ba7b6 = 10:  a44dd28b4d t4015: use test_write_lines()\n11:  c1ce767a98 = 11:  d512319be0 t4138: stop losing return codes of git commands\n12:  b5fa2ddb87 = 12:  1e08c2b68b t5317: stop losing return codes of git commands\n13:  000126915e = 13:  fa238be28b t5317: use ! grep to check for no matching lines\n14:  e18ab06152 = 14:  291caf9bc1 t5703: simplify one-time-sed generation logic\n15:  42b63b4735 = 15:  edf7af76ae t5703: stop losing return codes of git commands\n16:  e816d6e18d = 16:  5eb7117fbe t7501: remove spaces after redirect operators\n17:  6147ec6e8f = 17:  bad732adc8 t7501: stop losing return codes of git commands\n18:  7013c3a3c7 = 18:  c50c192429 t7700: drop redirections to /dev/null\n19:  f421b35adb = 19:  58ae066d12 t7700: remove spaces after redirect operators\n20:  7b8d5767fb = 20:  82bf24d06a t7700: move keywords onto their own line\n21:  dafc8da2d2 = 21:  251de77677 t7700: s/test -f/test_path_is_file/\n22:  1e8f239080 ! 22:  a99a45cb6f t7700: consolidate code into test_no_missing_in_packs()\n    @@ Commit message\n         exactly what grep is built for. Replace this invocation of sed with grep\n         so that we use the correct tool for the job.\n     \n    +    Instead of verifying each file of `alt_objects/pack/*.idx` individually\n    +    in a for-loop, batch them together into one verification step.\n    +\n         The original testing construct was O(n^2): it used a grep in a loop to\n         test whether any objects were missing in the packfile. Rewrite this to\n    -    use sort the files then use `comm -23` so that finding missing lines\n    -    from the original file is done more efficiently.\n    +    sort the files then use `comm -23` so that finding missing lines from\n    +    the original file is done more efficiently.\n     \n         While we're at it, add a space to `commit_and_pack ()` for style.\n     \n    @@ t/t7700-repack.sh: test_description='git repack works correctly'\n     +test_no_missing_in_packs () {\n     +\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n     +\ttest_path_is_file \"$myidx\" &&\n    -+\tfor p in alt_objects/pack/*.idx\n    -+\tdo\n    -+\t\tgit verify-pack -v $p >packlist || return $?\n    -+\t\tgrep \"^[0-9a-f]\\{40\\}\" packlist\n    -+\tdone >orig.raw &&\n    -+\tcut -d\" \" -f1 orig.raw | sort >orig &&\n    ++\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n    ++\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n     +\tgit verify-pack -v $myidx >dest.raw &&\n     +\tcut -d\" \" -f1 dest.raw | sort >dest &&\n     +\tcomm -23 orig dest >missing &&\n23:  4b70b92e1d <  -:  ---------- squash! t7700: consolidate code into test_no_missing_in_packs()\n24:  b0e58908d9 = 23:  f79240e937 t7700: consolidate code into test_has_duplicate_object()\n25:  6bd266035f = 24:  632a62f6e9 t7700: replace egrep with grep\n26:  8193fee859 ! 25:  bf70cc5a0d t7700: make references to SHA-1 generic\n    @@ Commit message\n         t7700: make references to SHA-1 generic\n     \n         Make the test more hash-agnostic by renaming variables from \"sha1\" to\n    -    \"oid\" (case-insensitively). Also, replace the regex, `[0-9a-f]\\{40\\}`\n    -    with `$OID_REGEX`.\n    +    some variation of \"oid\" or \"packid\". Also, replace the regex,\n    +    `[0-9a-f]\\{40\\}` with `$OID_REGEX`.\n    +\n    +    A better name for \"incrpackid\" (incremental pack-id) might have been\n    +    just \"packid\". However, later in the test suite, we have other uses of\n    +    \"packid\". Although the scopes of these variables don't conflict, a\n    +    future developer may think that commit_and_pack() and\n    +    test_has_duplicate_object() are semantically related somehow since they\n    +    share the same variable name. Give them distinct names so that it's\n    +    clear these uses are unrelated.\n     \n      ## t/t7700-repack.sh ##\n     @@ t/t7700-repack.sh: test_description='git repack works correctly'\n    @@ t/t7700-repack.sh: test_description='git repack works correctly'\n      \ttest_commit \"$@\" 1>&2 &&\n     -\tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n     -\techo pack-${SHA1}.pack\n    -+\tOID=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n    -+\techo pack-${OID}.pack\n    ++\tincrpackid=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n    ++\techo pack-${incrpackid}.pack\n      }\n      \n      test_no_missing_in_packs () {\n    @@ t/t7700-repack.sh: test_description='git repack works correctly'\n      }\n      \n     -# we expect $packsha1 and $objsha1 to be defined\n    -+# we expect $packoid and $objoid to be defined\n    ++# we expect $packid and $oid to be defined\n      test_has_duplicate_object () {\n      \twant_duplicate_object=\"$1\"\n      \tfound_duplicate_object=false\n    @@ t/t7700-repack.sh: test_description='git repack works correctly'\n      \tdo\n      \t\tidx=$(basename $p)\n     -\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n    -+\t\ttest \"pack-$packoid.idx\" = \"$idx\" && continue\n    ++\t\ttest \"pack-$packid.idx\" = \"$idx\" && continue\n      \t\tgit verify-pack -v $p >packlist || return $?\n     -\t\tif grep \"^$objsha1\" packlist\n    -+\t\tif grep \"^$objoid\" packlist\n    ++\t\tif grep \"^$oid\" packlist\n      \t\tthen\n      \t\t\tfound_duplicate_object=true\n      \t\t\techo \"DUPLICATE OBJECT FOUND\"\n    @@ t/t7700-repack.sh: test_expect_success 'objects in packs marked .keep are not re\n      \t\tgit pack-objects pack &&\n      \t# The second pack will contain the excluded object\n     -\tpacksha1=$(git rev-list --objects --all | grep file2 |\n    -+\tpackoid=$(git rev-list --objects --all | grep file2 |\n    ++\tpackid=$(git rev-list --objects --all | grep file2 |\n      \t\tgit pack-objects pack) &&\n     -\t>pack-$packsha1.keep &&\n     -\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n     -\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n    -+\t>pack-$packoid.keep &&\n    -+\tobjoid=$(git verify-pack -v pack-$packoid.idx | head -n 1 |\n    ++\t>pack-$packid.keep &&\n    ++\toid=$(git verify-pack -v pack-$packid.idx | head -n 1 |\n     +\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n      \tmv pack-* .git/objects/pack/ &&\n      \tgit repack -A -d -l &&\n    @@ t/t7700-repack.sh: test_expect_success 'objects in packs marked .keep are not re\n      \n      test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '\n     -\t# build on $objsha1, $packsha1, and .keep state from previous\n    -+\t# build on $objoid, $packoid, and .keep state from previous\n    ++\t# build on $oid, $packid, and .keep state from previous\n      \tgit repack -Adbl &&\n      \ttest_has_duplicate_object true\n      '\n      \n      test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n     -\t# build on $objsha1, $packsha1, and .keep state from previous\n    -+\t# build on $objoid, $packoid, and .keep state from previous\n    ++\t# build on $oid, $packid, and .keep state from previous\n      \tgit -c repack.writebitmaps=true repack -Adl &&\n      \ttest_has_duplicate_object true\n      '\n    @@ t/t7700-repack.sh: test_expect_success 'loose objects in alternate ODB are not r\n      \techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n      \techo content3 >file3 &&\n     -\tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n    -+\tobjoid=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n    ++\toid=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n      \tgit add file3 &&\n      \ttest_tick &&\n      \tgit commit -m commit_file3 &&\n27:  456aeaa506 ! 26:  1f6d9a80ad t7700: stop losing return codes of git commands\n    @@ t/t7700-repack.sh: test_expect_success 'objects in packs marked .keep are not re\n     +\tgit rev-list --objects --all >objs &&\n     +\tgrep -v file2 objs | git pack-objects pack &&\n      \t# The second pack will contain the excluded object\n    --\tpackoid=$(git rev-list --objects --all | grep file2 |\n    +-\tpackid=$(git rev-list --objects --all | grep file2 |\n     -\t\tgit pack-objects pack) &&\n    -+\tpackoid=$(grep file2 objs | git pack-objects pack) &&\n    - \t>pack-$packoid.keep &&\n    --\tobjoid=$(git verify-pack -v pack-$packoid.idx | head -n 1 |\n    ++\tpackid=$(grep file2 objs | git pack-objects pack) &&\n    + \t>pack-$packid.keep &&\n    +-\toid=$(git verify-pack -v pack-$packid.idx | head -n 1 |\n     -\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n    -+\tgit verify-pack -v pack-$packoid.idx >packlist &&\n    -+\tobjoid=$(head -n 1 packlist | sed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n    ++\tgit verify-pack -v pack-$packid.idx >packlist &&\n    ++\toid=$(head -n 1 packlist | sed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n      \tmv pack-* .git/objects/pack/ &&\n      \tgit repack -A -d -l &&\n      \tgit prune-packed &&\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387213","messageId":"9085cc00af10408d9425cfdff5a8b2c49008ae7b.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 01/26] lib-bash.sh: move `then` onto its own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:03Z","receivedAt":"2019-11-27T19:53:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move the `then` onto its own line so that it conforms with the\ntest style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-bash.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/lib-bash.sh b/t/lib-bash.sh\nindex 2be955fafb..b0b6060929 100644\n--- a/t/lib-bash.sh\n+++ b/t/lib-bash.sh\n@@ -2,10 +2,12 @@\n # to run under Bash; primarily intended for tests of the completion\n # script.\n \n-if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"; then\n+if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+then\n \t# we are in full-on bash mode\n \ttrue\n-elif type bash >/dev/null 2>&1; then\n+elif type bash >/dev/null 2>&1\n+then\n \t# execute in full-on bash mode\n \tunset POSIXLY_CORRECT\n \texec bash \"$0\" \"$@\"\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387214","messageId":"86f625c65e00b24d1de183c3a993e6acb7c8325e.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 02/26] apply-one-time-sed.sh: modernize style","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:06Z","receivedAt":"2019-11-27T19:53:11Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Convert `[ ... ]` to use `test` and test for the existence of a regular\nfile (`-f`) instead of any file (`-e`).\n\nMove the `then`s onto their own lines so that it conforms with the\ngeneral test style.\n\nInstead of redirecting input into sed, allow it to open its own input.\n\nUse `cmp -s` instead of `diff` since we only care about whether the two\nfiles are equal and `diff` is overkill for this.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/lib-httpd/apply-one-time-sed.sh | 8 +++++---\n 1 file changed, 5 insertions(+), 3 deletions(-)\n\ndiff --git a/t/lib-httpd/apply-one-time-sed.sh b/t/lib-httpd/apply-one-time-sed.sh\nindex fcef728925..bf7689d020 100644\n--- a/t/lib-httpd/apply-one-time-sed.sh\n+++ b/t/lib-httpd/apply-one-time-sed.sh\n@@ -7,11 +7,13 @@\n #\n # This can be used to simulate the effects of the repository changing in\n # between HTTP request-response pairs.\n-if [ -e one-time-sed ]; then\n+if test -f one-time-sed\n+then\n \t\"$GIT_EXEC_PATH/git-http-backend\" >out\n-\tsed \"$(cat one-time-sed)\" <out >out_modified\n+\tsed \"$(cat one-time-sed)\" out >out_modified\n \n-\tif diff out out_modified >/dev/null; then\n+\tif cmp -s out out_modified\n+\tthen\n \t\tcat out\n \telse\n \t\tcat out_modified\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387215","messageId":"3844e00367de57ec09b1e3282280fd20dd807c0b.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 03/26] t0014: remove git command upstream of pipe","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:08Z","receivedAt":"2019-11-27T19:53:14Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Before, the `git frotz` command would fail but its return code was\nhidden since it was in the upstream of a pipe. Break the pipeline into\ntwo commands so that the return code is no longer lost. Also, mark\n`git frotz` with test_must_fail since it's supposed to fail.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0014-alias.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0014-alias.sh b/t/t0014-alias.sh\nindex 2694c81afd..8d3d9144c0 100755\n--- a/t/t0014-alias.sh\n+++ b/t/t0014-alias.sh\n@@ -38,8 +38,8 @@ test_expect_success 'looping aliases - internal execution' '\n #'\n \n test_expect_success 'run-command formats empty args properly' '\n-    GIT_TRACE=1 git frotz a \"\" b \" \" c 2>&1 |\n-    sed -ne \"/run_command:/s/.*trace: run_command: //p\" >actual &&\n+    test_must_fail env GIT_TRACE=1 git frotz a \"\" b \" \" c 2>actual.raw &&\n+    sed -ne \"/run_command:/s/.*trace: run_command: //p\" actual.raw >actual &&\n     echo \"git-frotz a '\\'''\\'' b '\\'' '\\'' c\" >expect &&\n     test_cmp expect actual\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387216","messageId":"7d33586b214f8dfd8e027b3bc618ca908799b560.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 04/26] t0090: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:11Z","receivedAt":"2019-11-27T19:53:16Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In generate_expected_cache_tree_rec(), there are currently two instances\nof `git ls-files` in the upstream of a pipe. In the case where the\nupstream git command fails, its return code will be lost. Extract the\n`git ls-files` into its own call so that if it ever fails, its return\ncode is not lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t0090-cache-tree.sh | 5 +++--\n 1 file changed, 3 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex ce9a4a5f32..5a633690bf 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -21,9 +21,10 @@ generate_expected_cache_tree_rec () {\n \tparent=\"$2\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n-\tsubtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&\n+\tgit ls-files >files &&\n+\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n \tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n-\tentries=$(git ls-files|wc -l) &&\n+\tentries=$(wc -l <files) &&\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n \tfor subtree in $subtrees\n \tdo\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387217","messageId":"df6b3393c4b100fd1c490d4bfe0844a83368809a.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 05/26] t3301: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:13Z","receivedAt":"2019-11-27T19:53:18Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nThis patch fixes a real buggy test: in 'copy note with \"git notes\ncopy\"', `git notes` was mistyped as `git note`.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3301-notes.sh | 230 +++++++++++++++++++++++++++++++++--------------\n 1 file changed, 163 insertions(+), 67 deletions(-)\n\ndiff --git a/t/t3301-notes.sh b/t/t3301-notes.sh\nindex d66a5f6faa..8f43303007 100755\n--- a/t/t3301-notes.sh\n+++ b/t/t3301-notes.sh\n@@ -54,7 +54,9 @@ test_expect_success 'create notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b4\" = \"$(git notes show)\" &&\n+\techo b4 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -79,14 +81,21 @@ test_expect_success 'edit existing notes' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n \n test_expect_success 'show notes from treeish' '\n-\ttest \"b3\" = \"$(git notes --ref commits^{tree} show)\" &&\n-\ttest \"b4\" = \"$(git notes --ref commits@{1} show)\"\n+\techo b3 >expect &&\n+\tgit notes --ref commits^{tree} show >actual &&\n+\ttest_cmp expect actual &&\n+\n+\techo b4 >expect &&\n+\tgit notes --ref commits@{1} show >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot edit notes from non-ref' '\n@@ -99,7 +108,9 @@ test_expect_success 'cannot \"git notes add -m\" where notes already exists' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b3\" = \"$(git notes show)\" &&\n+\techo b3 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -109,7 +120,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f -m\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -119,7 +132,9 @@ test_expect_success 'add w/no options on existing note morphs into edit' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b2\" = \"$(git notes show)\" &&\n+\techo b2 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -129,7 +144,9 @@ test_expect_success 'can overwrite existing note with \"git notes add -f\"' '\n \ttest_path_is_missing .git/NOTES_EDITMSG &&\n \tgit ls-tree -r refs/notes/commits >actual &&\n \ttest_line_count = 1 actual &&\n-\ttest \"b1\" = \"$(git notes show)\" &&\n+\techo b1 >expect &&\n+\tgit notes show >actual &&\n+\ttest_cmp expect actual &&\n \tgit show HEAD^ &&\n \ttest_must_fail git notes show HEAD^\n '\n@@ -146,7 +163,8 @@ test_expect_success 'show notes' '\n \t\tNotes:\n \t\t${indent}b1\n \tEOF\n-\t! (git cat-file commit HEAD | grep b1) &&\n+\tgit cat-file commit HEAD >commits &&\n+\t! grep b1 commits &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -472,9 +490,11 @@ test_expect_success 'removing with --stdin --ignore-missing' '\n test_expect_success 'list notes with \"git notes list\"' '\n \tcommit_2=$(git rev-parse 2nd) &&\n \tcommit_3=$(git rev-parse 3rd) &&\n+\tnote_2=$(git rev-parse refs/notes/commits:$commit_2) &&\n+\tnote_3=$(git rev-parse refs/notes/commits:$commit_3) &&\n \tsort -t\" \" -k2 >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect actual\n@@ -486,9 +506,7 @@ test_expect_success 'list notes with \"git notes\"' '\n '\n \n test_expect_success 'list specific note with \"git notes list <object>\"' '\n-\tcat >expect <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_3)\n-\tEOF\n+\tgit rev-parse refs/notes/commits:$commit_3 >expect &&\n \tgit notes list HEAD^^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -512,10 +530,11 @@ test_expect_success 'append to existing note with \"git notes append\"' '\n \n test_expect_success '\"git notes list\" does not expand to \"git notes list HEAD\"' '\n \tcommit_5=$(git rev-parse 5th) &&\n+\tnote_5=$(git rev-parse refs/notes/commits:$commit_5) &&\n \tsort -t\" \" -k2 >expect_list <<-EOF &&\n-\t\t$(git rev-parse refs/notes/commits:$commit_2) $commit_2\n-\t\t$(git rev-parse refs/notes/commits:$commit_3) $commit_3\n-\t\t$(git rev-parse refs/notes/commits:$commit_5) $commit_5\n+\t\t$note_2 $commit_2\n+\t\t$note_3 $commit_3\n+\t\t$note_5 $commit_5\n \tEOF\n \tgit notes list >actual &&\n \ttest_cmp expect_list actual\n@@ -721,7 +740,8 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '\n \tgit notes show HEAD: >actual &&\n \ttest_cmp expect actual &&\n \techo \"Note on a blob\" >expect &&\n-\tfilename=$(git ls-tree --name-only HEAD | head -n1) &&\n+\tgit ls-tree --name-only HEAD >files &&\n+\tfilename=$(head -n1 files) &&\n \tgit notes add -m \"Note on a blob\" HEAD:$filename &&\n \tgit notes show HEAD:$filename >actual &&\n \ttest_cmp expect actual &&\n@@ -745,10 +765,13 @@ test_expect_success 'create note from other note with \"git notes add -C\"' '\n \t\tNotes:\n \t\t${indent}order test\n \tEOF\n-\tgit notes add -C $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes add -C $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'create note from non-existing note with \"git notes add -C\" fails' '\n@@ -777,11 +800,12 @@ test_expect_success 'create note from blob with \"git notes add -C\" reuses blob i\n \t\tNotes:\n \t\t${indent}This is a blob object\n \tEOF\n-\tblob=$(echo \"This is a blob object\" | git hash-object -w --stdin) &&\n-\tgit notes add -C $blob &&\n+\techo \"This is a blob object\" | git hash-object -w --stdin >blob &&\n+\tgit notes add -C $(cat blob) &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$blob\"\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp blob actual\n '\n \n test_expect_success 'create note from other note with \"git notes add -c\"' '\n@@ -797,7 +821,8 @@ test_expect_success 'create note from other note with \"git notes add -c\"' '\n \t\tNotes:\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes add -c $(git notes list HEAD^^) &&\n+\tnote=$(git notes list HEAD^^) &&\n+\tMSG=\"yet another note\" git notes add -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -822,7 +847,8 @@ test_expect_success 'append to note from other note with \"git notes append -C\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tgit notes append -C $(git notes list HEAD^) HEAD^ &&\n+\tnote=$(git notes list HEAD^) &&\n+\tgit notes append -C $note HEAD^ &&\n \tgit log -1 HEAD^ >actual &&\n \ttest_cmp expect actual\n '\n@@ -839,7 +865,8 @@ test_expect_success 'create note from other note with \"git notes append -c\"' '\n \t\tNotes:\n \t\t${indent}other note\n \tEOF\n-\tMSG=\"other note\" git notes append -c $(git notes list HEAD^) &&\n+\tnote=$(git notes list HEAD^) &&\n+\tMSG=\"other note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -858,7 +885,8 @@ test_expect_success 'append to note from other note with \"git notes append -c\"'\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\tMSG=\"yet another note\" git notes append -c $(git notes list HEAD) &&\n+\tnote=$(git notes list HEAD) &&\n+\tMSG=\"yet another note\" git notes append -c $note &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -878,7 +906,9 @@ test_expect_success 'copy note with \"git notes copy\"' '\n \tgit notes copy 8th 4th &&\n \tgit log 3rd..4th >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git note list 4th)\" = \"$(git note list 8th)\"\n+\tgit notes list 4th >expect &&\n+\tgit notes list 8th >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'copy note with \"git notes copy\" with default' '\n@@ -899,14 +929,30 @@ test_expect_success 'copy note with \"git notes copy\" with default' '\n \tgit notes copy HEAD^ &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'prevent overwrite with \"git notes copy\"' '\n \ttest_must_fail git notes copy HEAD~2 HEAD &&\n+\tcat >expect <<-EOF &&\n+\t\tcommit $commit\n+\t\tAuthor: A U Thor <author@example.com>\n+\t\tDate:   Thu Apr 7 15:23:13 2005 -0700\n+\n+\t\t${indent}11th\n+\n+\t\tNotes:\n+\t\t${indent}other note\n+\t\t${indent}\n+\t\t${indent}yet another note\n+\tEOF\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD^)\"\n+\tgit notes list HEAD^ >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n@@ -924,7 +970,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\"' '\n \tgit notes copy -f HEAD~3 HEAD &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n@@ -944,7 +992,9 @@ test_expect_success 'allow overwrite with \"git notes copy -f\" with default' '\n \tgit notes copy -f HEAD~2 &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'cannot copy note from object without notes' '\n@@ -979,13 +1029,21 @@ test_expect_success 'git notes copy --stdin' '\n \t\t${indent}\n \t\t${indent}yet another note\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --stdin &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --stdin <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual &&\n-\ttest \"$(git notes list HEAD)\" = \"$(git notes list HEAD~2)\" &&\n-\ttest \"$(git notes list HEAD^)\" = \"$(git notes list HEAD~3)\"\n+\tgit notes list HEAD~2 >expect &&\n+\tgit notes list HEAD >actual &&\n+\ttest_cmp expect actual &&\n+\tgit notes list HEAD~3 >expect &&\n+\tgit notes list HEAD^ >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n@@ -1006,9 +1064,13 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' '\n \n \t\t${indent}14th\n \tEOF\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1041,17 +1103,23 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' '\n \tEOF\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) &&\n-\techo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD^) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD~2) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n \n test_expect_success 'git notes copy --for-rewrite (disabled)' '\n \ttest_config notes.rewrite.bar false &&\n-\techo $(git rev-parse HEAD~3) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=bar &&\n+\tfrom=$(git rev-parse HEAD~3) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=bar <copy &&\n \tgit log -2 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1071,8 +1139,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n \tgit notes add -f -m\"a fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1080,8 +1150,10 @@ test_expect_success 'git notes copy --for-rewrite (overwrite)' '\n test_expect_success 'git notes copy --for-rewrite (ignore)' '\n \ttest_config notes.rewriteMode ignore &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1103,8 +1175,10 @@ test_expect_success 'git notes copy --for-rewrite (append)' '\n \tgit notes add -f -m\"another fresh note\" HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1131,9 +1205,13 @@ test_expect_success 'git notes copy --for-rewrite (append two to one)' '\n \tgit notes add -f -m\"append 2\" HEAD^^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\t(echo $(git rev-parse HEAD^) $(git rev-parse HEAD) &&\n-\techo $(git rev-parse HEAD^^) $(git rev-parse HEAD)) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tfrom=$(git rev-parse HEAD^^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >>copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1142,8 +1220,10 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' '\n \tgit notes remove HEAD^ &&\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tgit notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1163,8 +1243,10 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' '\n \ttest_config notes.rewriteMode concatenate &&\n \ttest_config notes.rewriteRef \"refs/notes/*\" &&\n \tgit notes add -f -m\"replacement note 1\" HEAD^ &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n-\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo &&\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n+\tGIT_NOTES_REWRITE_MODE=overwrite git notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1184,9 +1266,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF works' '\n \tgit notes add -f -m\"replacement note 2\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_unconfig notes.rewriteRef &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits:refs/notes/other \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \ttest_cmp expect actual\n '\n@@ -1195,9 +1279,11 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' '\n \tgit notes add -f -m\"replacement note 3\" HEAD^ &&\n \ttest_config notes.rewriteMode overwrite &&\n \ttest_config notes.rewriteRef refs/notes/other &&\n-\techo $(git rev-parse HEAD^) $(git rev-parse HEAD) |\n+\tfrom=$(git rev-parse HEAD^) &&\n+\tto=$(git rev-parse HEAD) &&\n+\techo \"$from\" \"$to\" >copy &&\n \tGIT_NOTES_REWRITE_REF=refs/notes/commits \\\n-\t\tgit notes copy --for-rewrite=foo &&\n+\t\tgit notes copy --for-rewrite=foo <copy &&\n \tgit log -1 >actual &&\n \tgrep \"replacement note 3\" actual\n '\n@@ -1212,26 +1298,36 @@ test_expect_success 'git notes copy diagnoses too many or too few parameters' '\n test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes --ref=refs/heads/master get-ref)\" = \"refs/notes/refs/heads/master\"\n+\techo refs/notes/refs/heads/master >expect &&\n+\tgit notes --ref=refs/heads/master get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (no overrides)' '\n \ttest_unconfig core.notesRef &&\n \tsane_unset GIT_NOTES_REF &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/commits\"\n+\techo refs/notes/commits >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (core.notesRef)' '\n \ttest_config core.notesRef refs/notes/foo &&\n-\ttest \"$(git notes get-ref)\" = \"refs/notes/foo\"\n+\techo refs/notes/foo >expect &&\n+\tgit notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (GIT_NOTES_REF)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes get-ref)\" = \"refs/notes/bar\"\n+\techo refs/notes/bar >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'git notes get-ref (--ref)' '\n-\ttest \"$(GIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref)\" = \"refs/notes/baz\"\n+\techo refs/notes/baz >expect &&\n+\tGIT_NOTES_REF=refs/notes/bar git notes --ref=baz get-ref >actual &&\n+\ttest_cmp expect actual\n '\n \n test_expect_success 'setup testing of empty notes' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387218","messageId":"d541a8d4d4b8fc224fe1967ce5717d70c0f2b55f.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 06/26] t3600: use test_line_count() where possible","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:16Z","receivedAt":"2019-11-27T19:53:20Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have a helper function that can test the number of lines in a\nfile that gives better debugging information on failure, use\ntest_line_count() to test the number of lines.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 8c8cca5bfb..f6e659b7e9 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -113,9 +113,10 @@ test_expect_success '\"rm\" command printed' '\n \techo frotz >test-file &&\n \tgit add test-file &&\n \tgit commit -m \"add file for rm test\" &&\n-\tgit rm test-file >rm-output &&\n-\ttest $(grep \"^rm \" rm-output | wc -l) = 1 &&\n-\trm -f test-file rm-output &&\n+\tgit rm test-file >rm-output.raw &&\n+\tgrep \"^rm \" rm-output.raw >rm-output &&\n+\ttest_line_count = 1 rm-output &&\n+\trm -f test-file rm-output.raw rm-output &&\n \tgit commit -m \"remove file from rm test\"\n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387219","messageId":"a8aeca67956f503829ac1f16072782ae5a906dd8.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 07/26] t3600: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:18Z","receivedAt":"2019-11-27T19:53:24Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"When a command is in a non-assignment command substitution, the return\ncode will be lost in favour of the surrounding command's. As a result,\nif a git command fails, we won't know about it. Rewrite instances of\nthis so that git commands are either run in an assignment-only command\nsubstitution so that their return codes aren't lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex f6e659b7e9..0c3bf10edd 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -304,7 +304,8 @@ EOF\n \n test_expect_success 'rm removes empty submodules from work tree' '\n \tmkdir submod &&\n-\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) submod &&\n+\thash=$(git rev-parse HEAD) &&\n+\tgit update-index --add --cacheinfo 160000 \"$hash\" submod &&\n \tgit config -f .gitmodules submodule.sub.url ./. &&\n \tgit config -f .gitmodules submodule.sub.path submod &&\n \tgit submodule init &&\n@@ -623,7 +624,8 @@ test_expect_success 'setup subsubmodule' '\n \tgit submodule update &&\n \t(\n \t\tcd submod &&\n-\t\tgit update-index --add --cacheinfo 160000 $(git rev-parse HEAD) subsubmod &&\n+\t\thash=$(git rev-parse HEAD) &&\n+\t\tgit update-index --add --cacheinfo 160000 \"$hash\" subsubmod &&\n \t\tgit config -f .gitmodules submodule.sub.url ../. &&\n \t\tgit config -f .gitmodules submodule.sub.path subsubmod &&\n \t\tgit submodule init &&\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387220","messageId":"e3db06578df23ee6e2036c18a25e79ae6c4d46e3.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 08/26] t3600: comment on inducing SIGPIPE in `git rm`","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:20Z","receivedAt":"2019-11-27T19:53:28Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Add a comment about intentionally inducing SIGPIPE since this is unusual\nand future developers should be aware. Also, even though we are trying\nto refactor git commands out of the upstream of pipes, we cannot do it\nhere since we rely on it being upstream to induce SIGPIPE. Comment on\nthat as well so that future developers do not try to change it.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t3600-rm.sh | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 0c3bf10edd..0ea858d652 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -251,6 +251,7 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\techo \"100644 $hash 0\tsome-file-$i\"\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n+\t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n \tgit rm -n \"some-file-*\" | : &&\n \ttest_path_is_missing .git/index.lock\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387221","messageId":"22ea5d736e98205c08716c0d898d280be7f6cbef.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 09/26] t4015: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:24Z","receivedAt":"2019-11-27T19:53:29Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this so that git commands are either run\non their own or in an assignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 119 ++++++++++++++++++++++---------------\n 1 file changed, 72 insertions(+), 47 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex eadaf57262..7fb83c8eff 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -16,7 +16,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t} while (0);\n \tEOF\n \tgit update-index --add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \tcat <<-\\EOF >x &&\n \tdo\n@@ -25,7 +26,8 @@ test_expect_success \"Ray Lehtiniemi's example\" '\n \t}\n \twhile (0);\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -63,7 +65,8 @@ test_expect_success 'another test, without options' '\n \tEOF\n \n \tgit update-index x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \n \ttr \"_\" \" \" <<-\\EOF >x &&\n \t_\twhitespace at beginning\n@@ -73,7 +76,8 @@ test_expect_success 'another test, without options' '\n \tunchanged line\n \tCR at end\n \tEOF\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \ttr \"Q_\" \"\\015 \" <<-EOF >expect &&\n \tdiff --git a/x b/x\n@@ -526,13 +530,15 @@ test_expect_success 'ignore-blank-lines: mix changes and blank lines' '\n test_expect_success 'check mixed spaces and tabs in indent' '\n \t# This is indented with SP HT SP.\n \techo \" \t foo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check mixed tabs and spaces in indent' '\n \t# This is indented with HT SP HT.\n \techo \"\t \tfoo();\" >x &&\n-\tgit diff --check | grep \"space before tab in indent\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"space before tab in indent\" check\n '\n \n test_expect_success 'check with no whitespace errors' '\n@@ -753,20 +759,23 @@ test_expect_success 'check tab-in-indent excluded from wildcard whitespace attri\n test_expect_success 'line numbers in --check output are correct' '\n \techo \"\" >x &&\n \techo \"foo(); \" >>x &&\n-\tgit diff --check | grep \"x:2:\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"x:2:\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n \techo \"foo();\" >x &&\n \techo \"\" >>x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n \t{ echo a; echo b; echo; echo; } >x &&\n \tgit add x &&\n \t{ echo a; echo; echo; echo; echo; } >x &&\n-\tgit diff --check | grep \"new blank line\"\n+\ttest_must_fail git diff --check >check &&\n+\tgrep \"new blank line\" check\n '\n \n test_expect_success 'checkdiff allows new blank lines' '\n@@ -794,14 +803,16 @@ test_expect_success 'whitespace-only changes reported across renames' '\n \tgit reset --hard &&\n \tfor i in 1 2 3 4 5 6 7 8 9; do echo \"$i$i$i$i$i$i\"; done >x &&\n \tgit add x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\thash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$hash_x\") &&\n \tgit commit -m \"base\" &&\n \tsed -e \"5s/^/ /\" x >z &&\n \tgit rm x &&\n \tgit add z &&\n-\tafter=$(git rev-parse --short $(git hash-object z)) &&\n-\tgit diff -w -M --cached |\n-\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" >actual &&\n+\thash_z=$(git hash-object z) &&\n+\tafter=$(git rev-parse --short \"$hash_z\") &&\n+\tgit diff -w -M --cached >actual.raw &&\n+\tsed -e \"/^similarity index /s/[0-9][0-9]*/NUM/\" actual.raw >actual &&\n \tcat <<-EOF >expect &&\n \tdiff --git a/x b/z\n \tsimilarity index NUM%\n@@ -840,7 +851,8 @@ test_expect_success 'combined diff with autocrlf conversion' '\n \tgit config core.autocrlf true &&\n \ttest_must_fail git merge master &&\n \n-\tgit diff | sed -e \"1,/^@@@/d\" >actual &&\n+\tgit diff >actual.raw &&\n+\tsed -e \"1,/^@@@/d\" actual.raw >actual &&\n \t! grep \"^-\" actual\n \n '\n@@ -864,11 +876,14 @@ test_expect_success 'diff that introduces a line with only tabs' '\n \tgit config core.whitespace blank-at-eol &&\n \tgit reset --hard &&\n \techo \"test\" >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -m \"initial\" x &&\n \techo \"{NTN}\" | tr \"NT\" \"\\n\\t\" >>x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n-\tgit diff --color | test_decode_color >current &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -891,17 +906,19 @@ test_expect_success 'diff that introduces and removes ws breakages' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n-\tgit diff --color |\n-\ttest_decode_color >current &&\n+\tgit diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -925,14 +942,16 @@ test_expect_success 'ws-error-highlight test setup' '\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. blank-at-eol \"\n \t} >x &&\n-\tbefore=$(git rev-parse --short $(git hash-object x)) &&\n+\told_hash_x=$(git hash-object x) &&\n+\tbefore=$(git rev-parse --short \"$old_hash_x\") &&\n \tgit commit -a --allow-empty -m preimage &&\n \t{\n \t\techo \"0. blank-at-eol \" &&\n \t\techo \"1. still-blank-at-eol \" &&\n \t\techo \"2. and a new line \"\n \t} >x &&\n-\tafter=$(git rev-parse --short $(git hash-object x)) &&\n+\tnew_hash_x=$(git hash-object x) &&\n+\tafter=$(git rev-parse --short \"$new_hash_x\") &&\n \n \tcat >expect.default-old <<-EOF &&\n \t<BOLD>diff --git a/x b/x<RESET>\n@@ -974,32 +993,32 @@ test_expect_success 'ws-error-highlight test setup' '\n \n test_expect_success 'test --ws-error-highlight option' '\n \n-\tgit diff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit diff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit diff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\tgit diff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n \n test_expect_success 'test diff.wsErrorHighlight config' '\n \n-\tgit -c diff.wsErrorHighlight=default,old diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=default,old diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n-\tgit -c diff.wsErrorHighlight=all diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=all diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n-\tgit -c diff.wsErrorHighlight=none diff --color |\n-\ttest_decode_color >current &&\n+\tgit -c diff.wsErrorHighlight=none diff --color >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1007,18 +1026,18 @@ test_expect_success 'test diff.wsErrorHighlight config' '\n test_expect_success 'option overrides diff.wsErrorHighlight' '\n \n \tgit -c diff.wsErrorHighlight=none \\\n-\t\tdiff --color --ws-error-highlight=default,old |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=default,old >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.default-old current &&\n \n \tgit -c diff.wsErrorHighlight=default \\\n-\t\tdiff --color --ws-error-highlight=all |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=all >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.all current &&\n \n \tgit -c diff.wsErrorHighlight=all \\\n-\t\tdiff --color --ws-error-highlight=none |\n-\ttest_decode_color >current &&\n+\t\tdiff --color --ws-error-highlight=none >current.raw &&\n+\ttest_decode_color <current.raw >current &&\n \ttest_cmp expect.none current\n \n '\n@@ -1038,7 +1057,8 @@ test_expect_success 'detect moved code, complete file' '\n \tgit mv test.c main.c &&\n \ttest_config color.diff.oldMoved \"normal red\" &&\n \ttest_config color.diff.newMoved \"normal green\" &&\n-\tgit diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual &&\n+\tgit diff HEAD --color-moved=zebra --color --no-renames >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat >expected <<-EOF &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>new file mode 100644<RESET>\n@@ -1141,9 +1161,12 @@ test_expect_success 'detect malicious moved code, inside file' '\n \t\t\tbar();\n \t\t}\n \tEOF\n-\tafter_main=$(git rev-parse --short $(git hash-object main.c)) &&\n-\tafter_test=$(git rev-parse --short $(git hash-object test.c)) &&\n-\tgit diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual &&\n+\thash_main=$(git hash-object main.c) &&\n+\tafter_main=$(git rev-parse --short \"$hash_main\") &&\n+\thash_test=$(git hash-object test.c) &&\n+\tafter_test=$(git rev-parse --short \"$hash_test\") &&\n+\tgit diff HEAD --no-renames --color-moved=zebra --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1192,7 +1215,8 @@ test_expect_success 'plain moved code, inside file' '\n \ttest_config color.diff.oldMovedAlternative \"blue\" &&\n \ttest_config color.diff.newMovedAlternative \"yellow\" &&\n \t# needs previous test as setup\n-\tgit diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual &&\n+\tgit diff HEAD --no-renames --color-moved=plain --color >actual.raw &&\n+\ttest_decode_color <actual.raw >actual &&\n \tcat <<-EOF >expected &&\n \t<BOLD>diff --git a/main.c b/main.c<RESET>\n \t<BOLD>index $before_main..$after_main 100644<RESET>\n@@ -1771,7 +1795,8 @@ test_expect_success 'move detection with submodules' '\n \t! grep BRED decoded_actual &&\n \n \t# nor did we mess with it another way\n-\tgit diff --submodule=diff --color | test_decode_color >expect &&\n+\tgit diff --submodule=diff --color >expect.raw &&\n+\ttest_decode_color <expect.raw >expect &&\n \ttest_cmp expect decoded_actual &&\n \trm -rf bananas &&\n \tgit submodule deinit bananas\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387222","messageId":"d512319be0f3a19cafb696ca9f6f2ccb7d0b8e85.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 11/26] t4138: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:29Z","receivedAt":"2019-11-27T19:53:33Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4138-apply-ws-expansion.sh | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t4138-apply-ws-expansion.sh b/t/t4138-apply-ws-expansion.sh\nindex 3b636a63a3..b19faeb67a 100755\n--- a/t/t4138-apply-ws-expansion.sh\n+++ b/t/t4138-apply-ws-expansion.sh\n@@ -17,8 +17,8 @@ test_expect_success setup '\n \tprintf \"\\t%s\\n\" 1 2 3 >after &&\n \tprintf \"%64s\\n\" a b c >>after &&\n \tprintf \"\\t%s\\n\" 4 5 6 >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" >patch1.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch1.patch.raw &&\n+\tsed -e \"s/before/test-1/\" -e \"s/after/test-1/\" patch1.patch.raw >patch1.patch &&\n \tprintf \"%64s\\n\" 1 2 3 4 5 6 >test-1 &&\n \tprintf \"%64s\\n\" 1 2 3 a b c 4 5 6 >expect-1 &&\n \n@@ -33,8 +33,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\t\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" >patch2.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch2.patch.raw &&\n+\tsed -e \"s/before/test-2/\" -e \"s/after/test-2/\" patch2.patch.raw >patch2.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-2 &&\n \tprintf \"%64s\\n\" a b c >expect-2 &&\n \tx=1 &&\n@@ -56,8 +56,8 @@ test_expect_success setup '\n \t\tx=$(( $x + 1 ))\n \tdone &&\n \tprintf \"\\t%s\\n\" d e f >>after &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" >patch3.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch3.patch.raw &&\n+\tsed -e \"s/before/test-3/\" -e \"s/after/test-3/\" patch3.patch.raw >patch3.patch &&\n \tprintf \"%64s\\n\" a b c d e f >test-3 &&\n \tprintf \"%64s\\n\" a b c >expect-3 &&\n \tx=0 &&\n@@ -84,8 +84,8 @@ test_expect_success setup '\n \t\tprintf \"\\t%02d\\n\" $x >>after\n \t\tx=$(( $x + 1 ))\n \tdone &&\n-\tgit diff --no-index before after |\n-\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" >patch4.patch &&\n+\ttest_expect_code 1 git diff --no-index before after >patch4.patch.raw &&\n+\tsed -e \"s/before/test-4/\" -e \"s/after/test-4/\" patch4.patch.raw >patch4.patch &&\n \t>test-4 &&\n \tx=0 &&\n \twhile test $x -lt 50\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387223","messageId":"a44dd28b4d22cf9dfbb9344d3184d5d0bd4ac1da.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 10/26] t4015: use test_write_lines()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:26Z","receivedAt":"2019-11-27T19:53:34Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Instead of rolling our own method to write out some lines into a file,\nuse the existing test_write_lines().\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t4015-diff-whitespace.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh\nindex 7fb83c8eff..4c540b1d70 100755\n--- a/t/t4015-diff-whitespace.sh\n+++ b/t/t4015-diff-whitespace.sh\n@@ -771,9 +771,9 @@ test_expect_success 'checkdiff detects new trailing blank lines (1)' '\n '\n \n test_expect_success 'checkdiff detects new trailing blank lines (2)' '\n-\t{ echo a; echo b; echo; echo; } >x &&\n+\ttest_write_lines a b \"\" \"\" >x &&\n \tgit add x &&\n-\t{ echo a; echo; echo; echo; echo; } >x &&\n+\ttest_write_lines a \"\" \"\" \"\" \"\" >x &&\n \ttest_must_fail git diff --check >check &&\n \tgrep \"new blank line\" check\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387224","messageId":"1e08c2b68ba041f5bc94695481ddbd106e9bb4f4.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 12/26] t5317: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:31Z","receivedAt":"2019-11-27T19:53:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands output to a\nfile and surrounding commands only call command substitutions with\nnon-git commands.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 13 +++++++------\n 1 file changed, 7 insertions(+), 6 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex 2d2f5d0229..a8bbad74e2 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -72,7 +72,8 @@ test_expect_success 'get an error for missing tree object' '\n \techo foo >r5/foo &&\n \tgit -C r5 add foo &&\n \tgit -C r5 commit -m \"foo\" &&\n-\tdel=$(git -C r5 rev-parse HEAD^{tree} | sed \"s|..|&/|\") &&\n+\tgit -C r5 rev-parse HEAD^{tree} >tree &&\n+\tdel=$(sed \"s|..|&/|\" tree) &&\n \trm r5/.git/objects/$del &&\n \ttest_must_fail git -C r5 pack-objects --revs --stdout 2>bad_tree <<-EOF &&\n \tHEAD\n@@ -230,10 +231,9 @@ test_expect_success 'verify explicitly specifying oversized blob in input' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF &&\n-\tHEAD\n-\t$(git -C r2 rev-parse HEAD:large.10000)\n-\tEOF\n+\techo HEAD >objects &&\n+\tgit -C r2 rev-parse HEAD:large.10000 >>objects &&\n+\tgit -C r2 pack-objects --revs --stdout --filter=blob:limit=1k <objects >filter.pack &&\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n@@ -377,7 +377,8 @@ test_expect_success 'verify sparse:oid=OID' '\n \tawk -f print_2.awk ls_files_result |\n \tsort >expected &&\n \n-\toid=$(git -C r4 ls-files -s pattern | awk -f print_2.awk) &&\n+\tgit -C r4 ls-files -s pattern >staged &&\n+\toid=$(awk -f print_2.awk staged) &&\n \tgit -C r4 pack-objects --revs --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF &&\n \tHEAD\n \tEOF\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387225","messageId":"fa238be28b5f4e1281d310eab0a6f90c15196d88.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 13/26] t5317: use ! grep to check for no matching lines","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:33Z","receivedAt":"2019-11-27T19:53:38Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Several times in t5317, we would use `wc -l` to ensure that a grep\nresult is empty. However, grep already has a way to do that... Its\nreturn code! Use `! grep` in the cases where we are ensuring that there\nare no matching lines.\n\nWhile at it, drop unnecessary invocations of `awk` and `sort` in each\naffected test since those commands do not influence the outcome. It's\nnot clear why that extra work was being done in the first place, and the\ncode's history doesn't shed any light on the matter since these tests\nwere simply born this way[1], likely due to copy-paste programming. The\nunnecessary work wasn't noticed even when the code was later touched for\nvarious cleanups[2][3].\n\n[1]: 9535ce7337 (pack-objects: add list-objects filtering, 2017-11-21)\n[2]: bdbc17e86a (tests: standardize pipe placement, 2018-10-05)\n[3]: 61de0ff695 (tests: don't swallow Git errors upstream of pipes, 2018-10-05)\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5317-pack-objects-filter-objects.sh | 21 +++------------------\n 1 file changed, 3 insertions(+), 18 deletions(-)\n\ndiff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh\nindex a8bbad74e2..dc0446574b 100755\n--- a/t/t5317-pack-objects-filter-objects.sh\n+++ b/t/t5317-pack-objects-filter-objects.sh\n@@ -45,12 +45,7 @@ test_expect_success 'verify blob:none packfile has no blobs' '\n \tgit -C r1 index-pack ../filter.pack &&\n \n \tgit -C r1 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify normal and blob:none packfiles have same commits/trees' '\n@@ -149,12 +144,7 @@ test_expect_success 'verify blob:limit=500 omits all blobs' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1000' '\n@@ -164,12 +154,7 @@ test_expect_success 'verify blob:limit=1000' '\n \tgit -C r2 index-pack ../filter.pack &&\n \n \tgit -C r2 verify-pack -v ../filter.pack >verify_result &&\n-\tgrep blob verify_result |\n-\tawk -f print_1.awk |\n-\tsort >observed &&\n-\n-\tnr=$(wc -l <observed) &&\n-\ttest 0 -eq $nr\n+\t! grep blob verify_result\n '\n \n test_expect_success 'verify blob:limit=1001' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387226","messageId":"291caf9bc11574b8f2ce8dcbaeb5d369c597a8c8.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 14/26] t5703: simplify one-time-sed generation logic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:36Z","receivedAt":"2019-11-27T19:53:41Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In inconsistency(), we had two `git rev-parse` invocations in the\nupstream of a pipe within a command substitution. In case this\ninvocation ever failed, its exit code would be swallowed up and we would\nnot know about it.\n\nPull the command substitutions out into variable assignments so that\ntheir return codes are not lost.\n\nDrop the pipe into `tr` because the $(...) substitution already takes\ncare of stripping out newlines, so the `tr` invocations in the code are\nsuperfluous.\n\nFinally, given the way the tests actually employ \"one-time-sed\" via\n$(cat one-time-sed) in t/lib-httpd/apply-one-time-sed.sh, convert the\n`printf` into an `echo`. This makes it consistent with the final \"server\nloses a ref - ref in want\" test, which does use `echo` rather than\n`printf`.\n\nHelped-by: Eric Sunshine <sunshine@sunshineco.com>\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 7 +++----\n 1 file changed, 3 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 3a2c143c6d..88338c4e09 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -312,10 +312,9 @@ inconsistency () {\n \t# repository appears to change during negotiation, for example, when\n \t# different servers in a load-balancing arrangement serve (stateless)\n \t# RPCs during a single negotiation.\n-\tprintf \"s/%s/%s/\" \\\n-\t       $(git -C \"$REPO\" rev-parse $1 | tr -d \"\\n\") \\\n-\t       $(git -C \"$REPO\" rev-parse $2 | tr -d \"\\n\") \\\n-\t       >\"$HTTPD_ROOT_PATH/one-time-sed\"\n+\toid1=$(git -C \"$REPO\" rev-parse $1) &&\n+\toid2=$(git -C \"$REPO\" rev-parse $2) &&\n+\techo \"s/$oid1/$oid2/\" >\"$HTTPD_ROOT_PATH/one-time-sed\"\n }\n \n test_expect_success 'server is initially ahead - no ref in want' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387227","messageId":"edf7af76aed1ed33dcdebb45a0d031b9bf4838f3.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 15/26] t5703: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:38Z","receivedAt":"2019-11-27T19:53:43Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there are two ways where the return codes of git commands are\nlost. The first way is when a command is in the upstream of a pipe. In a\npipe, only the return code of the last command is used. Thus, all other\ncommands will have their return codes masked. Rewrite pipes so that\nthere are no git commands upstream.\n\nThe other way is when a command is in a non-assignment command\nsubstitution. The return code will be lost in favour of the surrounding\ncommand's. Rewrite instances of this such that git commands are in an\nassignment-only command substitution.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 46 +++++++++++++++++++-----------\n 1 file changed, 29 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex 88338c4e09..1424fabd4a 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -18,14 +18,16 @@ get_actual_commits () {\n \t\tp\n \t\t}' <out | test-tool pkt-line unpack-sideband >o.pack &&\n \tgit index-pack o.pack &&\n-\tgit verify-pack -v o.idx | grep commit | cut -c-40 | sort >actual_commits\n+\tgit verify-pack -v o.idx >objs &&\n+\tgrep commit objs | cut -c-40 | sort >actual_commits\n }\n \n check_output () {\n \tget_actual_refs &&\n \ttest_cmp expected_refs actual_refs &&\n \tget_actual_commits &&\n-\ttest_cmp expected_commits actual_commits\n+\tsort expected_commits >sorted_commits &&\n+\ttest_cmp sorted_commits actual_commits\n }\n \n # c(o/foo) d(o/bar)\n@@ -75,17 +77,19 @@ test_expect_success 'invalid want-ref line' '\n '\n \n test_expect_success 'basic want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse f | sort >expected_commits &&\n+\tgit rev-parse f >expected_commits &&\n \n+\toid=$(git rev-parse a) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/master\n-\thave $(git rev-parse a)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -95,19 +99,22 @@ test_expect_success 'basic want-ref' '\n '\n \n test_expect_success 'multiple want-ref lines' '\n+\toid_c=$(git rev-parse c) &&\n+\toid_d=$(git rev-parse d) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n-\t$(git rev-parse d) refs/heads/o/bar\n+\t$oid_c refs/heads/o/foo\n+\t$oid_d refs/heads/o/bar\n \tEOF\n-\tgit rev-parse c d | sort >expected_commits &&\n+\tgit rev-parse c d >expected_commits &&\n \n+\toid=$(git rev-parse b) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n \twant-ref refs/heads/o/bar\n-\thave $(git rev-parse b)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -117,10 +124,11 @@ test_expect_success 'multiple want-ref lines' '\n '\n \n test_expect_success 'mix want and want-ref' '\n+\toid=$(git rev-parse f) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse f) refs/heads/master\n+\t$oid refs/heads/master\n \tEOF\n-\tgit rev-parse e f | sort >expected_commits &&\n+\tgit rev-parse e f >expected_commits &&\n \n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n@@ -138,17 +146,19 @@ test_expect_success 'mix want and want-ref' '\n '\n \n test_expect_success 'want-ref with ref we already have commit for' '\n+\toid=$(git rev-parse c) &&\n \tcat >expected_refs <<-EOF &&\n-\t$(git rev-parse c) refs/heads/o/foo\n+\t$oid refs/heads/o/foo\n \tEOF\n \t>expected_commits &&\n \n+\toid=$(git rev-parse c) &&\n \ttest-tool pkt-line pack >in <<-EOF &&\n \tcommand=fetch\n \t0001\n \tno-progress\n \twant-ref refs/heads/o/foo\n-\thave $(git rev-parse c)\n+\thave $oid\n \tdone\n \t0000\n \tEOF\n@@ -211,13 +221,14 @@ test_expect_success 'fetching with exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse d) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\t$(git -C \"$REPO\" rev-parse d):refs/heads/actual &&\n+\t\t\"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"d\" >expected &&\n \tgit -C local rev-parse refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse d)\" log\n+\tgrep \"want $oid\" log\n '\n \n test_expect_success 'fetching multiple refs' '\n@@ -239,13 +250,14 @@ test_expect_success 'fetching ref and exact OID' '\n \n \trm -rf local &&\n \tcp -r \"$LOCAL_PRISTINE\" local &&\n+\toid=$(git -C \"$REPO\" rev-parse b) &&\n \tGIT_TRACE_PACKET=\"$(pwd)/log\" git -C local fetch origin \\\n-\t\tmaster $(git -C \"$REPO\" rev-parse b):refs/heads/actual &&\n+\t\tmaster \"$oid\":refs/heads/actual &&\n \n \tgit -C \"$REPO\" rev-parse \"master\" \"b\" >expected &&\n \tgit -C local rev-parse refs/remotes/origin/master refs/heads/actual >actual &&\n \ttest_cmp expected actual &&\n-\tgrep \"want $(git -C \"$REPO\" rev-parse b)\" log &&\n+\tgrep \"want $oid\" log &&\n \tgrep \"want-ref refs/heads/master\" log\n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387228","messageId":"5eb7117fbef4c39aecbdbd25c9e1f0a637c4b0de.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 16/26] t7501: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:40Z","receivedAt":"2019-11-27T19:53:45Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 22 +++++++++++-----------\n 1 file changed, 11 insertions(+), 11 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex f1349af56e..5765d33c53 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -150,7 +150,7 @@ test_expect_success 'setup: commit message from file' '\n test_expect_success 'amend commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/a file/an amend commit/g\" < \"$1\" > \"$1-\"\n+\tsed -e \"s/a file/an amend commit/g\" <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -263,7 +263,7 @@ test_expect_success 'using message from other commit' '\n test_expect_success 'editing message from other commit' '\n \tcat >editor <<-\\EOF &&\n \t#!/bin/sh\n-\tsed -e \"s/amend/older/g\"  < \"$1\" > \"$1-\"\n+\tsed -e \"s/amend/older/g\"  <\"$1\" >\"$1-\"\n \tmv \"$1-\" \"$1\"\n \tEOF\n \tchmod 755 editor &&\n@@ -367,7 +367,7 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -382,7 +382,7 @@ test_expect_success 'amend commit to fix date' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --date=\"$newtick\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n@@ -448,7 +448,7 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -468,7 +468,7 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n@@ -489,7 +489,7 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +506,7 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" > actual &&\n+\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -560,14 +560,14 @@ test_expect_success 'amend commit to fix author' '\n \t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n \t\texpected &&\n \tgit commit --amend --author=\"$author\" &&\n-\tgit cat-file -p HEAD > current &&\n+\tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n \n '\n \n test_expect_success 'git commit <file> with dirty index' '\n-\techo tacocat > elif &&\n-\techo tehlulz > chz &&\n+\techo tacocat >elif &&\n+\techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n \tgit show --stat | grep elif &&\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387229","messageId":"bad732adc8067804bb35e46026ddcf736c4eb2ce.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 17/26] t7501: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:43Z","receivedAt":"2019-11-27T19:53:48Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nIn the 'interactive add' test case, we prepend a `test_must_fail` to\n`git commit --interactive`. When there are no changes to commit,\n`git commit` will exit with status code 1. Following along with the rest\nof the file, we use `test_must_fail` to test for this case.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7501-commit-basic-functionality.sh | 69 +++++++++++++++------------\n 1 file changed, 39 insertions(+), 30 deletions(-)\n\ndiff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh\nindex 5765d33c53..110b4bf459 100755\n--- a/t/t7501-commit-basic-functionality.sh\n+++ b/t/t7501-commit-basic-functionality.sh\n@@ -285,9 +285,8 @@ test_expect_success 'overriding author from command line' '\n '\n \n test_expect_success PERL 'interactive add' '\n-\techo 7 |\n-\tgit commit --interactive |\n-\tgrep \"What now\"\n+\techo 7 | test_must_fail git commit --interactive >out &&\n+\tgrep \"What now\" out\n '\n \n test_expect_success PERL \"commit --interactive doesn't change index if editor aborts\" '\n@@ -362,10 +361,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -377,10 +376,10 @@ test_expect_success 'amend commit to fix date' '\n \ttest_tick &&\n \tnewtick=$GIT_AUTHOR_DATE &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $newtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --date=\"$newtick\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -409,12 +408,13 @@ test_expect_success 'sign off (1)' '\n \techo 1 >positive &&\n \tgit add positive &&\n \tgit commit -s -m \"thank you\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -428,13 +428,14 @@ test_expect_success 'sign off (2)' '\n \tgit commit -s -m \"thank you\n \n $existing\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo thank you &&\n \t\techo &&\n \t\techo $existing &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n \n@@ -448,13 +449,14 @@ test_expect_success 'signoff gap' '\n \tgit commit -s -m \"welcome\n \n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo $alt &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -468,15 +470,16 @@ test_expect_success 'signoff gap 2' '\n \n We have now\n $alt\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo welcome &&\n \t\techo &&\n \t\techo We have now &&\n \t\techo $alt &&\n \t\techo &&\n-\t\tgit var GIT_COMMITTER_IDENT |\n-\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\"\n+\t\tgit var GIT_COMMITTER_IDENT >ident &&\n+\t\tsed -e \"s/>.*/>/\" -e \"s/^/Signed-off-by: /\" ident\n \t) >expected &&\n \ttest_cmp expected actual\n '\n@@ -489,7 +492,8 @@ test_expect_success 'signoff respects trailer config' '\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -506,7 +510,8 @@ Myfooter: x\" &&\n \n non-trailer line\n Myfooter: x\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo subject &&\n \t\techo &&\n@@ -538,7 +543,8 @@ test_expect_success 'multiple -m' '\n \t>negative &&\n \tgit add negative &&\n \tgit commit -m \"one\" -m \"two\" -m \"three\" &&\n-\tgit cat-file commit HEAD | sed -e \"1,/^\\$/d\" >actual &&\n+\tgit cat-file commit HEAD >commit &&\n+\tsed -e \"1,/^\\$/d\" commit >actual &&\n \t(\n \t\techo one &&\n \t\techo &&\n@@ -555,10 +561,10 @@ test_expect_success 'amend commit to fix author' '\n \toldtick=$GIT_AUTHOR_DATE &&\n \ttest_tick &&\n \tgit reset --hard &&\n-\tgit cat-file -p HEAD |\n+\tgit cat-file -p HEAD >commit &&\n \tsed -e \"s/author.*/author $author $oldtick/\" \\\n-\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" > \\\n-\t\texpected &&\n+\t\t-e \"s/^\\(committer.*> \\).*$/\\1$GIT_COMMITTER_DATE/\" \\\n+\t\tcommit >expected &&\n \tgit commit --amend --author=\"$author\" &&\n \tgit cat-file -p HEAD >current &&\n \ttest_cmp expected current\n@@ -570,8 +576,10 @@ test_expect_success 'git commit <file> with dirty index' '\n \techo tehlulz >chz &&\n \tgit add chz &&\n \tgit commit elif -m \"tacocat is a palindrome\" &&\n-\tgit show --stat | grep elif &&\n-\tgit diff --cached | grep chz\n+\tgit show --stat >stat &&\n+\tgrep elif stat &&\n+\tgit diff --cached >diff &&\n+\tgrep chz diff\n '\n \n test_expect_success 'same tree (single parent)' '\n@@ -584,7 +592,8 @@ test_expect_success 'same tree (single parent)' '\n test_expect_success 'same tree (single parent) --allow-empty' '\n \n \tgit commit --allow-empty -m \"forced empty\" &&\n-\tgit cat-file commit HEAD | grep forced\n+\tgit cat-file commit HEAD >commit &&\n+\tgrep forced commit\n \n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387230","messageId":"c50c192429c73146b64a8c7637e89554fee4e24d.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 18/26] t7700: drop redirections to /dev/null","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:45Z","receivedAt":"2019-11-27T19:53:50Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since output is silenced when running without `-v` and debugging output\nis useful with `-v`, remove redirections to /dev/null as it is not\nuseful.\n\nIn one case where the output of stdout is consumed, redirect the output\nof test_commit to stderr.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 4e855bc21b..e1a689d6a9 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -5,7 +5,7 @@ test_description='git repack works correctly'\n . ./test-lib.sh\n \n commit_and_pack() {\n-\ttest_commit \"$@\" >/dev/null &&\n+\ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n@@ -19,7 +19,7 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n \tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack > /dev/null &&\n+\t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n \tpacksha1=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n@@ -235,7 +235,7 @@ test_expect_success 'incremental repack does not complain' '\n \n test_expect_success 'bitmaps can be disabled on bare repos' '\n \tgit -c repack.writeBitmaps=false -C bare.git repack -ad &&\n-\tbitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) &&\n+\tbitmap=$(ls bare.git/objects/pack/*.bitmap || :) &&\n \ttest -z \"$bitmap\"\n '\n \n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387231","messageId":"58ae066d12144a226ceb7617a3597c5799a2cd58.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 19/26] t7700: remove spaces after redirect operators","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:47Z","receivedAt":"2019-11-27T19:53:53Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"For shell scripts, the usual convention is for there to be no space\nafter redirection operators, (e.g. `>file`, not `> file`). Remove these\nspaces wherever they appear.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 18 +++++++++---------\n 1 file changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex e1a689d6a9..8936928387 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -11,8 +11,8 @@ commit_and_pack() {\n }\n \n test_expect_success 'objects in packs marked .keep are not repacked' '\n-\techo content1 > file1 &&\n-\techo content2 > file2 &&\n+\techo content1 >file1 &&\n+\techo content2 >file2 &&\n \tgit add . &&\n \ttest_tick &&\n \tgit commit -m initial_commit &&\n@@ -75,8 +75,8 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n-\techo content3 > file3 &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n+\techo content3 >file3 &&\n \tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n@@ -111,7 +111,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n \trm -f .git/objects/pack/* &&\n-\techo new_content >> file1 &&\n+\techo new_content >>file1 &&\n \tgit add file1 &&\n \ttest_tick &&\n \tgit commit -m more_content &&\n@@ -169,12 +169,12 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n-\techo $(pwd)/alt_objects > .git/objects/info/alternates &&\n+\techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n@@ -186,7 +186,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n \t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n-\techo > .git/objects/info/alternates &&\n+\techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n \n@@ -196,7 +196,7 @@ test_expect_success 'objects made unreachable by grafts only are kept' '\n \tH0=$(git rev-parse HEAD) &&\n \tH1=$(git rev-parse HEAD^) &&\n \tH2=$(git rev-parse HEAD^^) &&\n-\techo \"$H0 $H2\" > .git/info/grafts &&\n+\techo \"$H0 $H2\" >.git/info/grafts &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n \tgit repack -a -d &&\n \tgit cat-file -t $H1\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387232","messageId":"82bf24d06ab663d404a717ae9091dd272d1c3396.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 20/26] t7700: move keywords onto their own line","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:49Z","receivedAt":"2019-11-27T19:53:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code style for tests is to have statements on their own line if\npossible. Move keywords onto their own line so that they conform with\nthe test style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 51 +++++++++++++++++++++++++++++++----------------\n 1 file changed, 34 insertions(+), 17 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 8936928387..a96e876c4e 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -29,10 +29,12 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -45,10 +47,12 @@ test_expect_success 'writing bitmaps via command-line can duplicate .keep object\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -61,10 +65,12 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx; do\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -83,8 +89,10 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx; do\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"; then\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n+\t\tthen\n \t\t\tfound_duplicate_object=1\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n \t\t\tbreak\n@@ -99,10 +107,13 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -119,10 +130,13 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n@@ -144,10 +158,13 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest -f \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx; do\n+\tfor p in alt_objects/pack/*.idx\n+\tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest; do\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" ); then\n+\tdone | while read sha1 rest\n+\tdo\n+\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n+\t\tthen\n \t\t\techo \"Missing object in local pack: $sha1\"\n \t\t\treturn 1\n \t\tfi\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387233","messageId":"251de77677a9eda0d13c3f5668fa456ad4a52902.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 21/26] t7700: s/test -f/test_path_is_file/","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:52Z","receivedAt":"2019-11-27T19:53:57Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Since we have debugging-friendly alternatives to `test -f`, replace\ninstances of `test -f` with `test_path_is_file` so that if a command\never fails, we get better debugging information.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 8 ++++----\n 1 file changed, 4 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex a96e876c4e..1d14ddcbdb 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -106,7 +106,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -129,7 +129,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit repack &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n@@ -148,7 +148,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tfor p in alt_objects/pack/*.pack\n \tdo\n \t\tbase_name=$(basename $p .pack) &&\n-\t\tif test -f alt_objects/pack/$base_name.keep\n+\t\tif test_path_is_file alt_objects/pack/$base_name.keep\n \t\tthen\n \t\t\trm alt_objects/pack/$base_name.keep\n \t\telse\n@@ -157,7 +157,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \tdone &&\n \tgit repack -a -d &&\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest -f \"$myidx\" &&\n+\ttest_path_is_file \"$myidx\" &&\n \tfor p in alt_objects/pack/*.idx\n \tdo\n \t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387234","messageId":"a99a45cb6f2cc7328ef0e52fc2ea8fec537bfba9.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:54Z","receivedAt":"2019-11-27T19:53:59Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code to test that objects were not missing from the packfile was\nduplicated many times. Extract the duplicated code into\ntest_no_missing_in_packs() and use that instead.\n\nRefactor the resulting extraction so that if any git commands fail,\ntheir return codes are not silently lost.\n\nWe were using sed to filter lines. Although not incorrect, this is\nexactly what grep is built for. Replace this invocation of sed with grep\nso that we use the correct tool for the job.\n\nInstead of verifying each file of `alt_objects/pack/*.idx` individually\nin a for-loop, batch them together into one verification step.\n\nThe original testing construct was O(n^2): it used a grep in a loop to\ntest whether any objects were missing in the packfile. Rewrite this to\nsort the files then use `comm -23` so that finding missing lines from\nthe original file is done more efficiently.\n\nWhile we're at it, add a space to `commit_and_pack ()` for style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 55 +++++++++++++----------------------------------\n 1 file changed, 15 insertions(+), 40 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 1d14ddcbdb..4bcd9fcc80 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -4,12 +4,23 @@ test_description='git repack works correctly'\n \n . ./test-lib.sh\n \n-commit_and_pack() {\n+commit_and_pack () {\n \ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n \n+test_no_missing_in_packs () {\n+\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n+\ttest_path_is_file \"$myidx\" &&\n+\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n+\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n+\tgit verify-pack -v $myidx >dest.raw &&\n+\tcut -d\" \" -f1 dest.raw | sort >dest &&\n+\tcomm -23 orig dest >missing &&\n+\ttest_must_be_empty missing\n+}\n+\n test_expect_success 'objects in packs marked .keep are not repacked' '\n \techo content1 >file1 &&\n \techo content2 >file2 &&\n@@ -105,19 +116,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmkdir alt_objects/pack &&\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n@@ -128,19 +127,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit commit -m more_content &&\n \tgit repack &&\n \tgit repack -a -d &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n@@ -156,19 +143,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \t\tfi\n \tdone &&\n \tgit repack -a -d &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387235","messageId":"f79240e937300febc468363bb8e96160e7683b7f.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 23/26] t7700: consolidate code into test_has_duplicate_object()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:56Z","receivedAt":"2019-11-27T19:54:02Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code to test that objects were not duplicated from the packfile was\nduplicated many times. Extract the duplicated code into\ntest_has_duplicate_object() and use that instead.\n\nRefactor the resulting extraction so that if the git command fails,\nthe return code is not silently lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 71 +++++++++++++++--------------------------------\n 1 file changed, 23 insertions(+), 48 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 4bcd9fcc80..5bbed02fe5 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -21,6 +21,25 @@ test_no_missing_in_packs () {\n \ttest_must_be_empty missing\n }\n \n+# we expect $packsha1 and $objsha1 to be defined\n+test_has_duplicate_object () {\n+\twant_duplicate_object=\"$1\"\n+\tfound_duplicate_object=false\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tidx=$(basename $p)\n+\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n+\t\tthen\n+\t\t\tfound_duplicate_object=true\n+\t\t\techo \"DUPLICATE OBJECT FOUND\"\n+\t\t\tbreak\n+\t\tfi\n+\tdone &&\n+\ttest \"$want_duplicate_object\" = \"$found_duplicate_object\"\n+}\n+\n test_expect_success 'objects in packs marked .keep are not repacked' '\n \techo content1 >file1 &&\n \techo content2 >file2 &&\n@@ -40,54 +59,19 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest -z \"$found_duplicate_object\"\n+\ttest_has_duplicate_object false\n '\n \n test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n-\ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest \"$found_duplicate_object\" = 1\n+\ttest_has_duplicate_object true\n '\n \n test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n-\ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest \"$found_duplicate_object\" = 1\n+\ttest_has_duplicate_object true\n '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n@@ -100,16 +84,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest -z \"$found_duplicate_object\"\n+\ttest_has_duplicate_object false\n '\n \n test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387236","messageId":"632a62f6e9cdd58bebe7203ded8bbb9aea7c4c62.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 24/26] t7700: replace egrep with grep","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:53:59Z","receivedAt":"2019-11-27T19:54:04Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The egrep expressions in this test suite were of the form `^$variable`.\nAlthough egrep works just fine, it's overkill since we're not using any\nextended regex. Replace egrep invocations with grep so that we aren't\nswatting flies with a sledgehammer.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 5bbed02fe5..2493cc4e9b 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -30,7 +30,7 @@ test_has_duplicate_object () {\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n \t\tgit verify-pack -v $p >packlist || return $?\n-\t\tif egrep \"^$objsha1\" packlist\n+\t\tif grep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=true\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -135,7 +135,7 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n@@ -152,7 +152,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387237","messageId":"bf70cc5a0d1766b9e9ef43013fc476ec76a7d70f.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 25/26] t7700: make references to SHA-1 generic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:54:01Z","receivedAt":"2019-11-27T19:54:06Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Make the test more hash-agnostic by renaming variables from \"sha1\" to\nsome variation of \"oid\" or \"packid\". Also, replace the regex,\n`[0-9a-f]\\{40\\}` with `$OID_REGEX`.\n\nA better name for \"incrpackid\" (incremental pack-id) might have been\njust \"packid\". However, later in the test suite, we have other uses of\n\"packid\". Although the scopes of these variables don't conflict, a\nfuture developer may think that commit_and_pack() and\ntest_has_duplicate_object() are semantically related somehow since they\nshare the same variable name. Give them distinct names so that it's\nclear these uses are unrelated.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 38 +++++++++++++++++++-------------------\n 1 file changed, 19 insertions(+), 19 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 2493cc4e9b..1edb21bf93 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -6,31 +6,31 @@ test_description='git repack works correctly'\n \n commit_and_pack () {\n \ttest_commit \"$@\" 1>&2 &&\n-\tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n-\techo pack-${SHA1}.pack\n+\tincrpackid=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n+\techo pack-${incrpackid}.pack\n }\n \n test_no_missing_in_packs () {\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest_path_is_file \"$myidx\" &&\n \tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n-\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n+\tgrep \"^$OID_REGEX\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n \tgit verify-pack -v $myidx >dest.raw &&\n \tcut -d\" \" -f1 dest.raw | sort >dest &&\n \tcomm -23 orig dest >missing &&\n \ttest_must_be_empty missing\n }\n \n-# we expect $packsha1 and $objsha1 to be defined\n+# we expect $packid and $oid to be defined\n test_has_duplicate_object () {\n \twant_duplicate_object=\"$1\"\n \tfound_duplicate_object=false\n \tfor p in .git/objects/pack/*.idx\n \tdo\n \t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n+\t\ttest \"pack-$packid.idx\" = \"$idx\" && continue\n \t\tgit verify-pack -v $p >packlist || return $?\n-\t\tif grep \"^$objsha1\" packlist\n+\t\tif grep \"^$oid\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=true\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -51,11 +51,11 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit rev-list --objects --all | grep -v file2 |\n \t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpacksha1=$(git rev-list --objects --all | grep file2 |\n+\tpackid=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n-\t>pack-$packsha1.keep &&\n-\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n-\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n+\t>pack-$packid.keep &&\n+\toid=$(git verify-pack -v pack-$packid.idx | head -n 1 |\n+\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -63,13 +63,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n '\n \n test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '\n-\t# build on $objsha1, $packsha1, and .keep state from previous\n+\t# build on $oid, $packid, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_has_duplicate_object true\n '\n \n test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n-\t# build on $objsha1, $packsha1, and .keep state from previous\n+\t# build on $oid, $packid, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_has_duplicate_object true\n '\n@@ -78,7 +78,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n \techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo content3 >file3 &&\n-\tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n+\toid=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n \tgit commit -m commit_file3 &&\n@@ -124,7 +124,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f alt_objects/pack/*.keep &&\n \tmv .git/objects/pack/* alt_objects/pack/ &&\n-\tcsha1=$(git rev-parse HEAD^{commit}) &&\n+\tcoid=$(git rev-parse HEAD^{commit}) &&\n \tgit reset --hard HEAD^ &&\n \ttest_tick &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n@@ -135,14 +135,14 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n-\ttest_must_fail git show $csha1\n+\ttest_must_fail git show $coid\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n \techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n-\techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n+\techo \"$coid\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \t# The pack-objects call on the next line is equivalent to\n@@ -152,9 +152,9 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n-\ttest_must_fail git show $csha1\n+\ttest_must_fail git show $coid\n '\n \n test_expect_success 'objects made unreachable by grafts only are kept' '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387238","messageId":"1f6d9a80ad45fd9f51c8cffe9ce3721fce9b80c0.1574884302.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1574884302.git.liu.denton@gmail.com","subject":"[PATCH v5 26/26] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-11-27T19:54:04Z","receivedAt":"2019-11-27T19:54:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 19 +++++++++----------\n 1 file changed, 9 insertions(+), 10 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 1edb21bf93..d5cce7c06f 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -48,14 +48,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit commit -m initial_commit &&\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n-\tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack &&\n+\tgit rev-list --objects --all >objs &&\n+\tgrep -v file2 objs | git pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpackid=$(git rev-list --objects --all | grep file2 |\n-\t\tgit pack-objects pack) &&\n+\tpackid=$(grep file2 objs | git pack-objects pack) &&\n \t>pack-$packid.keep &&\n-\toid=$(git verify-pack -v pack-$packid.idx | head -n 1 |\n-\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n+\tgit verify-pack -v pack-$packid.idx >packlist &&\n+\toid=$(head -n 1 packlist | sed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -134,8 +133,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! grep \"^$coid \" packlist &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $coid\n '\n@@ -151,8 +150,8 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! grep \"^$coid \" &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $coid\n '\n-- \n2.24.0.504.g3cd56eb17d\n\n"},{"id":"387319","messageId":"xmqq7e3i4b1p.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"a99a45cb6f2cc7328ef0e52fc2ea8fec537bfba9.1574884302.git.liu.denton@gmail.com","subject":"Re: [PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-29T21:39:30Z","receivedAt":"2019-11-29T21:39:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> The code to test that objects were not missing from the packfile was\n> duplicated many times. Extract the duplicated code into\n> test_no_missing_in_packs() and use that instead.\n>\n> Refactor the resulting extraction so that if any git commands fail,\n> their return codes are not silently lost.\n>\n> We were using sed to filter lines. Although not incorrect, this is\n> exactly what grep is built for. Replace this invocation of sed with grep\n> so that we use the correct tool for the job.\n\nWell, \n\n    $ sed -n -e 's/required match/desired part of the line/p'\n\nis much much more approirate than \n\n    $ grep -e \"requred match\" |\n      extract desired part of the line\n\n\"grep\" is better only if the original were\n\n    $ sed -n -e '/required match/p'\n\nbut everybody would write it with grep to begin with ;-)\n\nSo, I dunno about this part of the conversion.\n\n> Instead of verifying each file of `alt_objects/pack/*.idx` individually\n> in a for-loop, batch them together into one verification step.\n\nDo you mean this one?\n\n\tgit verify-pack -v alt_objects/pack/*.idx\n\nwhere we may pass 1 or more .idx file to the command?  At first my\nreading was interrupted by a \"Huh?\", but that does look good.  We'd\nneed to be a bit careful to make sure that we have at least 1 .idx\nfile, as the shell will happily feed a file whose name is \"*.idx\",\nwhich verify-pack would be unhappy about.\n\n> The original testing construct was O(n^2): it used a grep in a loop to\n> test whether any objects were missing in the packfile. Rewrite this to\n> sort the files then use `comm -23` so that finding missing lines from\n> the original file is done more efficiently.\n\nOK.  If we an show measurable speedups, it would be great, but the\nloop structure does look O(n^2) and unnecessary costly.\n\n> +test_no_missing_in_packs () {\n> +\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n> +\ttest_path_is_file \"$myidx\" &&\n\nIf there are 2 or more .idx files, or if there is none, $myidx would\nhopefully be a concatenation of these filenames or a string that\nends with asterisk-dot-idx and would fail path_is_file.  Sounds OK.\n\nAh, I do not have to review this part---these are repeated patterns\nin the original.\n\n> +\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n> +\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n\nIf output from 'grep' can be used as-is, it is worth doing, but if\nyou have to pipe it to cut, the original that used sed to filter and\nedit the line would probably be a better way to write it.\n\n> +\tgit verify-pack -v $myidx >dest.raw &&\n\nThis part does not quote $myidx\" (inherited from the original); it\nprobably is OK, as any potentially problematic value in $myidx would\nhave been caught as an error much earlier in this test.\n\n"},{"id":"387332","messageId":"20191130104812.GA18401@danh.dev","threadId":"52269","inReplyTo":"1f6d9a80ad45fd9f51c8cffe9ce3721fce9b80c0.1574884302.git.liu.denton@gmail.com","subject":"Re: [PATCH v5 26/26] t7700: stop losing return codes of git commands","fromName":"Danh Doan","fromEmail":"congdanhqx@gmail.com","sentAt":"2019-11-30T10:48:12Z","receivedAt":"2019-11-30T10:48:17Z","isPatch":true,"sender":{"key":"congdanhqx@gmail.com","avatar":"https://avatars.githubusercontent.com/u/42673067?v=4"},"body":"\nHi Denton,\n\nOn 2019-11-27 11:54:04-0800, Denton Liu <liu.denton@gmail.com> wrote:\n> -\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n> -\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n> +\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n> +\t! grep \"^$coid \" packlist &&\n\nI think we want to use test_must_fail instead of !\n\n>  \techo >.git/objects/info/alternates &&\n>  \ttest_must_fail git show $coid\n>  '\n> @@ -151,8 +150,8 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n>  \t    --unpack-unreachable </dev/null pack &&\n>  \trm -f .git/objects/pack/* &&\n>  \tmv pack-* .git/objects/pack/ &&\n> -\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n> -\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n> +\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n> +\t! grep \"^$coid \" &&\n\nditto\n\n-- \nDanh\n"},{"id":"387333","messageId":"CAPig+cQ38J_0wHLw0CuhSdWBBEP-RuAchgG014GPHiSp6QOpsQ@mail.gmail.com","threadId":"52269","inReplyTo":"20191130104812.GA18401@danh.dev","subject":"Re: [PATCH v5 26/26] t7700: stop losing return codes of git commands","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2019-11-30T11:31:04Z","receivedAt":"2019-11-30T11:31:20Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Nov 30, 2019 at 5:48 AM Danh Doan <congdanhqx@gmail.com> wrote:\n> On 2019-11-27 11:54:04-0800, Denton Liu <liu.denton@gmail.com> wrote:\n> > +   ! grep \"^$coid \" packlist &&\n>\n> I think we want to use test_must_fail instead of !\n\ntest_must_fail() is intended only for use with 'git' commands; \"!\"\nshould be used otherwise. Quoting from t/README:\n\n    Don't use '! git cmd' when you want to make sure the git command\n    exits with failure in a controlled way by calling \"die()\".  Instead,\n    use 'test_must_fail git cmd'.  This will signal a failure if git\n    dies in an unexpected way (e.g. segfault).\n\n    On the other hand, don't use test_must_fail for running regular\n    platform commands; just use '! cmd'.  We are not in the business\n    of verifying that the world given to us sanely works.\n\nSo, Denton's use of \"!\" here is correct.\n"},{"id":"387336","messageId":"xmqqv9r12tbb.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"CAPig+cQ38J_0wHLw0CuhSdWBBEP-RuAchgG014GPHiSp6QOpsQ@mail.gmail.com","subject":"Re: [PATCH v5 26/26] t7700: stop losing return codes of git commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-11-30T17:00:08Z","receivedAt":"2019-11-30T17:00:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n> On Sat, Nov 30, 2019 at 5:48 AM Danh Doan <congdanhqx@gmail.com> wrote:\n>> On 2019-11-27 11:54:04-0800, Denton Liu <liu.denton@gmail.com> wrote:\n>> > +   ! grep \"^$coid \" packlist &&\n>>\n>> I think we want to use test_must_fail instead of !\n>\n> test_must_fail() is intended only for use with 'git' commands; \"!\"\n> should be used otherwise. Quoting from t/README:\n>\n>     Don't use '! git cmd' when you want to make sure the git command\n>     exits with failure in a controlled way by calling \"die()\".  Instead,\n>     use 'test_must_fail git cmd'.  This will signal a failure if git\n>     dies in an unexpected way (e.g. segfault).\n>\n>     On the other hand, don't use test_must_fail for running regular\n>     platform commands; just use '! cmd'.  We are not in the business\n>     of verifying that the world given to us sanely works.\n>\n> So, Denton's use of \"!\" here is correct.\n\nI wonder we can make the framework a bit more self-documenting to\navoid having to waste time on discovering potential issues and\nexplaining why it is not an issue, like this exchange.\n\nSome ideas:\n\n * Perhaps test_must_fail is not descriptive enough that it should\n   apply only to git command invocation.  Would it make it more\n   obvious to rename it to say git_must_fail?  That would also make\n   it unnecessary to give this rather unfortunate comment in\n   test-lib-functions.sh:\n\n   # This is not among top-level (test_expect_success | test_expect_failure)\n   # but is a prefix that can be used in the test script, like:\n   #\n   #\ttest_expect_success 'complain and die' '\n   #           do something &&\n   #           do something else &&\n   #\t    test_must_fail git checkout ../outerspace\n   #\t'\n   #\n\n * If it is too much trouble to rename it, perhaps test_must_fail\n   can be documented better up there?\n\n   diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\n   index b299ecc326..052d88c5da 100644\n   --- a/t/test-lib-functions.sh\n   +++ b/t/test-lib-functions.sh\n   @@ -817,6 +817,13 @@ list_contains () {\n    #     Multiple signals can be specified as a comma separated list.\n    #     Currently recognized signal names are: sigpipe, success.\n    #     (Don't use 'success', use 'test_might_fail' instead.)\n   +#\n   +# Do not use this to run anything but \"git\".  We are not in the business\n   +# of vetting system supplied commands---IOW this is wrong:\n   +#\n   +#    test_must_fail grep pattern output\n   +#\n   +# Just use '!' instead.\n\n    test_must_fail () {\n           case \"$1\" in\n\n * Or perhaps we can detect its use on anything that is not \"git\"\n   automatically?  This is merely to illustrate the idea (the\n   exemption of \"env\" shown here is too broad for production use)\n\n   diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\n   index b299ecc326..7ab113cd50 100644\n   --- a/t/test-lib-functions.sh\n   +++ b/t/test-lib-functions.sh\n   @@ -828,6 +828,10 @@ test_must_fail () {\n                   _test_ok=\n                   ;;\n           esac\n   +\tcase \"$1\" in\n   +\tgit|test-tool|env) ;;\n   +\t*) echo >&7 \"warning: test_must_fail $*???\" ;;\n   +\tesac\n           \"$@\" 2>&7\n           exit_code=$?\n           if test $exit_code -eq 0 && ! list_contains \"$_test_ok\" success\n\nHmm?\n"},{"id":"387419","messageId":"20191202205037.GA43606@generichostname","threadId":"52269","inReplyTo":"xmqq7e3i4b1p.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-02T20:50:37Z","receivedAt":"2019-12-02T20:50:43Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio,\n\nOn Fri, Nov 29, 2019 at 01:39:30PM -0800, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> > The code to test that objects were not missing from the packfile was\n> > duplicated many times. Extract the duplicated code into\n> > test_no_missing_in_packs() and use that instead.\n> >\n> > Refactor the resulting extraction so that if any git commands fail,\n> > their return codes are not silently lost.\n> >\n> > We were using sed to filter lines. Although not incorrect, this is\n> > exactly what grep is built for. Replace this invocation of sed with grep\n> > so that we use the correct tool for the job.\n> \n> Well, \n> \n>     $ sed -n -e 's/required match/desired part of the line/p'\n> \n> is much much more approirate than \n> \n>     $ grep -e \"requred match\" |\n>       extract desired part of the line\n> \n> \"grep\" is better only if the original were\n> \n>     $ sed -n -e '/required match/p'\n> \n> but everybody would write it with grep to begin with ;-)\n\nThis was what I was intending. It was originally written like the above\nand it made sense to convert it to use grep. I guess \"filter lines\" in\nmy commit message is a little bit vague. Could we change this to \"filter\nmatching lines\" perhaps?\n\n> \n> So, I dunno about this part of the conversion.\n> \n> > Instead of verifying each file of `alt_objects/pack/*.idx` individually\n> > in a for-loop, batch them together into one verification step.\n> \n> Do you mean this one?\n> \n> \tgit verify-pack -v alt_objects/pack/*.idx\n> \n> where we may pass 1 or more .idx file to the command?  At first my\n> reading was interrupted by a \"Huh?\", but that does look good.  We'd\n> need to be a bit careful to make sure that we have at least 1 .idx\n> file, as the shell will happily feed a file whose name is \"*.idx\",\n> which verify-pack would be unhappy about.\n> \n> > The original testing construct was O(n^2): it used a grep in a loop to\n> > test whether any objects were missing in the packfile. Rewrite this to\n> > sort the files then use `comm -23` so that finding missing lines from\n> > the original file is done more efficiently.\n> \n> OK.  If we an show measurable speedups, it would be great, but the\n> loop structure does look O(n^2) and unnecessary costly.\n> \n> > +test_no_missing_in_packs () {\n> > +\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n> > +\ttest_path_is_file \"$myidx\" &&\n> \n> If there are 2 or more .idx files, or if there is none, $myidx would\n> hopefully be a concatenation of these filenames or a string that\n> ends with asterisk-dot-idx and would fail path_is_file.  Sounds OK.\n> \n> Ah, I do not have to review this part---these are repeated patterns\n> in the original.\n> \n> > +\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n> > +\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n> \n> If output from 'grep' can be used as-is, it is worth doing, but if\n> you have to pipe it to cut, the original that used sed to filter and\n> edit the line would probably be a better way to write it.\n\nThe original sed actually only filtered the line; no editing done. The\ncut invocation was a consequence of using comm. Previously, in the while\nloop, we would separate the line into `sha1` and `rest` components and\nonly match using the `sha1`. Since we use comm now, we have to use cut\nto grab the sha1 and omit the rest of the line.\n\nWe could rewrite it with sed like this:\n\n\tsed -n -e \"/^[0-9a-f]\\{40\\}/s/^\\($[0-9a-f]\\{40\\}\\).*/\\1/\" orig.raw\n\nbut I believe that breaking it into grep and cut makes the intent much\nmore clear. \n\nWhat do you think?\n\n(By the way, if I were to reroll this series, should I keep sending out\nthe entire patchset? It feels very noisy to send out 20-something emails\nevery reroll when I'm just making a small one or two line change.)\n\nThanks,\n\nDenton\n\n> \n> > +\tgit verify-pack -v $myidx >dest.raw &&\n> \n> This part does not quote $myidx\" (inherited from the original); it\n> probably is OK, as any potentially problematic value in $myidx would\n> have been caught as an error much earlier in this test.\n> \n"},{"id":"387421","messageId":"xmqqo8wqwd9m.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"20191202205037.GA43606@generichostname","subject":"Re: [PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-02T22:53:09Z","receivedAt":"2019-12-02T22:53:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> Hi Junio,\n> ...\n>> \"grep\" is better only if the original were\n>> \n>>     $ sed -n -e '/required match/p'\n>> \n>> but everybody would write it with grep to begin with ;-)\n>\n> This was what I was intending. It was originally written like the above\n> and it made sense to convert it to use grep. I guess \"filter lines\" in\n> my commit message is a little bit vague. Could we change this to \"filter\n> matching lines\" perhaps?\n\nAh, I see.  I somehow thought that some of the \"sed\" invocation in\nthe original version were doing \"find lines and filter its\ncontents\" (i.e. \"-n -e 's/find/munge/p'\"), but all three of them are\njust \"find lines\" (i.e. \"-n -e '/find/p'\").  So I think the change\nmade by the patch is OK.\n\nI think I was reacting to the output of \"grep\" being piped to \"cut\".\nIOW, the original\n\n\t... | sed -n -e '/find/p' |\n\twhile read sha1 garbage\n\tdo\n\t\t... use sha1 ...\n\nwere rewritten to\n\n\t... >raw &&\n\tgrep -e 'find' raw | cut -d\" \" -f1 >orig\n\t... use orig as a list of sha1s ...\n\nBut the \"grep piped to cut\" can be a single process\n\n\t... >raw &&\n\tsed -n -e 's/\\(find\\).*/\\1/p' raw >orig\n\t... use orig as a list of sha1s ...\n\nSo in the tiniest picture, turning \"sed -n -e /find/p\" into \"grep\"\nis not wrong per-se, but if you step back a bit and see a larger\npicture, using \"sed\" a bit more effectively turns out to be still a\nbetter rewrite.\n\n... and I wrote the above before I read the remainder of your\nresponse, where you considered which one is easier to read between\n\"grep piped to cut\" and \"sed\" ;-)\n\n\n> (By the way, if I were to reroll this series, should I keep sending out\n> the entire patchset? It feels very noisy to send out 20-something emails\n> every reroll when I'm just making a small one or two line change.)\n\nEspecially if it is near the end of the series, just a single step\nis OK.  But is there anything that is glaringly wrong that needs a\nreroll?  Or would it be \"this is good enough, so let's have them\ncook in 'next' and graduate to 'master'---further clean-up can be\ndone after all the dust settles\"?  I have an impression that we\nreached the latter by now.\n\nThanks.\n"},{"id":"387422","messageId":"20191202232816.GA26892@generichostname","threadId":"52269","inReplyTo":"xmqqo8wqwd9m.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-02T23:28:16Z","receivedAt":"2019-12-02T23:28:21Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio,\n\nOn Mon, Dec 02, 2019 at 02:53:09PM -0800, Junio C Hamano wrote:\n> > (By the way, if I were to reroll this series, should I keep sending out\n> > the entire patchset? It feels very noisy to send out 20-something emails\n> > every reroll when I'm just making a small one or two line change.)\n> \n> Especially if it is near the end of the series, just a single step\n> is OK.  But is there anything that is glaringly wrong that needs a\n> reroll?  Or would it be \"this is good enough, so let's have them\n> cook in 'next' and graduate to 'master'---further clean-up can be\n> done after all the dust settles\"?  I have an impression that we\n> reached the latter by now.\n\nPerhaps the log message could use some improvement to document the\ndiscussion we had? I don't know if that's worth a reroll, though. Aside\nfrom that, I agree that it's ready for 'next'.\n\n> \n> Thanks.\n"},{"id":"387455","messageId":"xmqqblsp76xs.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"20191202232816.GA26892@generichostname","subject":"Re: [PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-03T15:41:19Z","receivedAt":"2019-12-03T15:41:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n>> Especially if it is near the end of the series, just a single step\n>> is OK.  But is there anything that is glaringly wrong that needs a\n>> reroll?  Or would it be \"this is good enough, so let's have them\n>> cook in 'next' and graduate to 'master'---further clean-up can be\n>> done after all the dust settles\"?  I have an impression that we\n>> reached the latter by now.\n>\n> Perhaps the log message could use some improvement to document the\n> discussion we had? I don't know if that's worth a reroll, though. Aside\n> from that, I agree that it's ready for 'next'.\n\nSure, let's see what you have in mind.\n\nThanks for working on this.\n"},{"id":"387479","messageId":"20191204072437.GA3395833@generichostname","threadId":"52269","inReplyTo":"xmqqblsp76xs.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T07:24:37Z","receivedAt":"2019-12-04T07:40:53Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio,\n\nOn Tue, Dec 03, 2019 at 07:41:19AM -0800, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> >> Especially if it is near the end of the series, just a single step\n> >> is OK.  But is there anything that is glaringly wrong that needs a\n> >> reroll?  Or would it be \"this is good enough, so let's have them\n> >> cook in 'next' and graduate to 'master'---further clean-up can be\n> >> done after all the dust settles\"?  I have an impression that we\n> >> reached the latter by now.\n> >\n> > Perhaps the log message could use some improvement to document the\n> > discussion we had? I don't know if that's worth a reroll, though. Aside\n> > from that, I agree that it's ready for 'next'.\n> \n> Sure, let's see what you have in mind.\n\nHere's a complete replacement for the commit message:\n\n\tt7700: consolidate code into test_no_missing_in_packs()\n\n\tThe code to test that objects were not missing from the packfile was\n\tduplicated many times. Extract the duplicated code into\n\ttest_no_missing_in_packs() and use that instead.\n\n\tRefactor the resulting extraction so that if any git commands fail,\n\ttheir return codes are not silently lost.\n\n\tWe were using sed to filter lines. Although not incorrect, this is\n\texactly what grep is built for. Replace this invocation of sed with grep\n\tso that we use the correct tool for the job.\n\n\tInstead of verifying each file of `alt_objects/pack/*.idx` individually\n\tin a for-loop, batch them together into one verification step.\n\n\tThe original testing construct was O(n^2): it used a grep in a loop to\n\ttest whether any objects were missing in the packfile. Rewrite this to\n\tsort the files then use `comm -23` so that finding missing lines from\n\tthe original file is done more efficiently.\n\n\tThe result of this is that we end up with a `grep | cut | sort`\n\tpipeline. Previously, we were extracting the `sha1` as part of the\n\t`while read sha1 rest` loop. Since we removed the while-loop, we need to\n\tuse `cut` to extract the `sha1` field. Note that we could have chosen to\n\tcombine the `grep | cut` into a single `sed` invocation but we\n\tconsciously leave it separate as it makes the intent more clear.\n\n\tWhile we're at it, add a space to `commit_and_pack ()` for style.\n\n\tSigned-off-by: Denton Liu <liu.denton@gmail.com>\n\nThe only change between this and the old commit message is the addition\nof the \"The result of this...\" paragraph.\n\nThanks,\n\nDenton\n\n> \n> Thanks for working on this.\n"},{"id":"387487","messageId":"20191204125937.GA798672@generichostname","threadId":"52269","inReplyTo":"xmqqv9r12tbb.fsf@gitster-ct.c.googlers.com","subject":"t: remove inappropriate uses of test_must_fail(), was Re: [PATCH v5 26/26] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T12:59:37Z","receivedAt":"2019-12-04T12:59:42Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi all,\n\nOn Sat, Nov 30, 2019 at 09:00:08AM -0800, Junio C Hamano wrote:\n>  * Or perhaps we can detect its use on anything that is not \"git\"\n>    automatically?  This is merely to illustrate the idea (the\n>    exemption of \"env\" shown here is too broad for production use)\n> \n>    diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\n>    index b299ecc326..7ab113cd50 100644\n>    --- a/t/test-lib-functions.sh\n>    +++ b/t/test-lib-functions.sh\n>    @@ -828,6 +828,10 @@ test_must_fail () {\n>                    _test_ok=\n>                    ;;\n>            esac\n>    +\tcase \"$1\" in\n>    +\tgit|test-tool|env) ;;\n>    +\t*) echo >&7 \"warning: test_must_fail $*???\" ;;\n>    +\tesac\n>            \"$@\" 2>&7\n>            exit_code=$?\n>            if test $exit_code -eq 0 && ! list_contains \"$_test_ok\" success\n\nI've been cooking a series that gets rid of inappropriate uses\ntest_must_fail() for a while now. As a finishing touch, I implemented\nthe idea Junio suggested above and it seems to be working well.\n\nIt's a pretty hefty series, weighing in at 46 patches. After the dust\nsettles on 'dl/test-cleanup' (once it gets merged to master), I'll\nprobably start sending out this test_must_fail() series around 10\npatches at a time.\n\nAn advanced preview can be found here[1]. Or, if you'd like me to\nprivately mail you the series, I can do that too. Early comments would\nbe very appreciated.\n\nThanks,\n\nDenton\n\n[1]: https://github.com/Denton-L/git/commits/ready/cleanup-test-must-fail\n"},{"id":"387497","messageId":"xmqq1rtk557e.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"20191204072437.GA3395833@generichostname","subject":"Re: [PATCH v5 22/26] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-04T18:13:57Z","receivedAt":"2019-12-04T18:14:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n>> Sure, let's see what you have in mind.\n>\n> Here's a complete replacement for the commit message:\n>\n> \tt7700: consolidate code into test_no_missing_in_packs()\n>\n> \tThe code to test that objects were not missing from the packfile was\n> \tduplicated many times. Extract the duplicated code into\n> \ttest_no_missing_in_packs() and use that instead.\n>\n> \tRefactor the resulting extraction so that if any git commands fail,\n> \ttheir return codes are not silently lost.\n>\n> \tWe were using sed to filter lines. Although not incorrect, this is\n> \texactly what grep is built for. Replace this invocation of sed with grep\n> \tso that we use the correct tool for the job.\n>\n> \tInstead of verifying each file of `alt_objects/pack/*.idx` individually\n> \tin a for-loop, batch them together into one verification step.\n>\n> \tThe original testing construct was O(n^2): it used a grep in a loop to\n> \ttest whether any objects were missing in the packfile. Rewrite this to\n> \tsort the files then use `comm -23` so that finding missing lines from\n> \tthe original file is done more efficiently.\n>\n> \tThe result of this is that we end up with a `grep | cut | sort`\n> \tpipeline. Previously, we were extracting the `sha1` as part of the\n> \t`while read sha1 rest` loop. Since we removed the while-loop, we need to\n> \tuse `cut` to extract the `sha1` field. Note that we could have chosen to\n> \tcombine the `grep | cut` into a single `sed` invocation but we\n> \tconsciously leave it separate as it makes the intent more clear.\n>\n> \tWhile we're at it, add a space to `commit_and_pack ()` for style.\n>\n> \tSigned-off-by: Denton Liu <liu.denton@gmail.com>\n>\n> The only change between this and the old commit message is the addition\n> of the \"The result of this...\" paragraph.\n\nAh, you were planning to only update the log message?  Then let's\nnot bother.  I do not think we would want to encourage \"grep piped\nto cut\" as a good pattern for others to follow and a single sed that\nfinds the relevant lines and munges the content of these lines into\nwhat is desired conveys the intent clearly and more concisely (I\nwas hoping that that was what you had in mind for a reroll).\n\n\n\n\n\n\n"},{"id":"387522","messageId":"cover.1575496683.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"xmqq1rtk557e.fsf@gitster-ct.c.googlers.com","subject":"[PATCH v6 0/5] t: test cleanup stemming from experimentally enabling pipefail","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T22:03:03Z","receivedAt":"2019-12-04T22:03:11Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Junio,\n\nSorry for the confusion. Looking it over, I see that the sed expression\nyou proposed indeed makes the intent a lot clearer. Here's a replacement\nseries for the last five commits of the branch.\n\nI would've opted to send out a single replacement patch but this change\ncauses some minor textual conflicts in 4/5 so this should make your life\na little easier ;)\n\nDenton Liu (5):\n  t7700: consolidate code into test_no_missing_in_packs()\n  t7700: consolidate code into test_has_duplicate_object()\n  t7700: replace egrep with grep\n  t7700: make references to SHA-1 generic\n  t7700: stop losing return codes of git commands\n\n t/t7700-repack.sh | 165 ++++++++++++++++------------------------------\n 1 file changed, 57 insertions(+), 108 deletions(-)\n\nRange-diff against v5:\n1:  a99a45cb6f ! 1:  3008ce8deb t7700: consolidate code into test_no_missing_in_packs()\n    @@ Commit message\n         Refactor the resulting extraction so that if any git commands fail,\n         their return codes are not silently lost.\n     \n    -    We were using sed to filter lines. Although not incorrect, this is\n    -    exactly what grep is built for. Replace this invocation of sed with grep\n    -    so that we use the correct tool for the job.\n    -\n         Instead of verifying each file of `alt_objects/pack/*.idx` individually\n         in a for-loop, batch them together into one verification step.\n     \n         The original testing construct was O(n^2): it used a grep in a loop to\n         test whether any objects were missing in the packfile. Rewrite this to\n    -    sort the files then use `comm -23` so that finding missing lines from\n    -    the original file is done more efficiently.\n    +    extract the hash using sed or cut, sort the files, then use `comm -23`\n    +    so that finding missing lines from the original file is done more\n    +    efficiently.\n     \n         While we're at it, add a space to `commit_and_pack ()` for style.\n     \n    @@ t/t7700-repack.sh: test_description='git repack works correctly'\n     +\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n     +\ttest_path_is_file \"$myidx\" &&\n     +\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n    -+\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n    ++\tsed -n -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/p\" orig.raw | sort >orig &&\n     +\tgit verify-pack -v $myidx >dest.raw &&\n     +\tcut -d\" \" -f1 dest.raw | sort >dest &&\n     +\tcomm -23 orig dest >missing &&\n2:  f79240e937 = 2:  f3a0470edc t7700: consolidate code into test_has_duplicate_object()\n3:  632a62f6e9 = 3:  c34477a5a9 t7700: replace egrep with grep\n4:  bf70cc5a0d ! 4:  113f375192 t7700: make references to SHA-1 generic\n    @@ t/t7700-repack.sh: test_description='git repack works correctly'\n      \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n      \ttest_path_is_file \"$myidx\" &&\n      \tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n    --\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n    -+\tgrep \"^$OID_REGEX\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n    +-\tsed -n -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/p\" orig.raw | sort >orig &&\n    ++\tsed -n -e \"s/^\\($OID_REGEX\\).*/\\1/p\" orig.raw | sort >orig &&\n      \tgit verify-pack -v $myidx >dest.raw &&\n      \tcut -d\" \" -f1 dest.raw | sort >dest &&\n      \tcomm -23 orig dest >missing &&\n5:  1f6d9a80ad = 5:  ab653bd76f t7700: stop losing return codes of git commands\n-- \n2.24.0.578.g4820254054\n\n"},{"id":"387523","messageId":"3008ce8deb4055f39fd4e1331b30666b40b26eaa.1575496684.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1575496683.git.liu.denton@gmail.com","subject":"[PATCH v6 1/5] t7700: consolidate code into test_no_missing_in_packs()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T22:03:09Z","receivedAt":"2019-12-04T22:03:16Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code to test that objects were not missing from the packfile was\nduplicated many times. Extract the duplicated code into\ntest_no_missing_in_packs() and use that instead.\n\nRefactor the resulting extraction so that if any git commands fail,\ntheir return codes are not silently lost.\n\nInstead of verifying each file of `alt_objects/pack/*.idx` individually\nin a for-loop, batch them together into one verification step.\n\nThe original testing construct was O(n^2): it used a grep in a loop to\ntest whether any objects were missing in the packfile. Rewrite this to\nextract the hash using sed or cut, sort the files, then use `comm -23`\nso that finding missing lines from the original file is done more\nefficiently.\n\nWhile we're at it, add a space to `commit_and_pack ()` for style.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 55 +++++++++++++----------------------------------\n 1 file changed, 15 insertions(+), 40 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 1d14ddcbdb..5fb9e99f34 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -4,12 +4,23 @@ test_description='git repack works correctly'\n \n . ./test-lib.sh\n \n-commit_and_pack() {\n+commit_and_pack () {\n \ttest_commit \"$@\" 1>&2 &&\n \tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n \techo pack-${SHA1}.pack\n }\n \n+test_no_missing_in_packs () {\n+\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n+\ttest_path_is_file \"$myidx\" &&\n+\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n+\tsed -n -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/p\" orig.raw | sort >orig &&\n+\tgit verify-pack -v $myidx >dest.raw &&\n+\tcut -d\" \" -f1 dest.raw | sort >dest &&\n+\tcomm -23 orig dest >missing &&\n+\ttest_must_be_empty missing\n+}\n+\n test_expect_success 'objects in packs marked .keep are not repacked' '\n \techo content1 >file1 &&\n \techo content2 >file2 &&\n@@ -105,19 +116,7 @@ test_expect_success 'packed obs in alt ODB are repacked even when local repo is\n \tmkdir alt_objects/pack &&\n \tmv .git/objects/pack/* alt_objects/pack &&\n \tgit repack -a &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed obs in alt ODB are repacked when local repo has packs' '\n@@ -128,19 +127,7 @@ test_expect_success 'packed obs in alt ODB are repacked when local repo has pack\n \tgit commit -m more_content &&\n \tgit repack &&\n \tgit repack -a -d &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n@@ -156,19 +143,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n \t\tfi\n \tdone &&\n \tgit repack -a -d &&\n-\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n-\ttest_path_is_file \"$myidx\" &&\n-\tfor p in alt_objects/pack/*.idx\n-\tdo\n-\t\tgit verify-pack -v $p | sed -n -e \"/^[0-9a-f]\\{40\\}/p\"\n-\tdone | while read sha1 rest\n-\tdo\n-\t\tif ! ( git verify-pack -v $myidx | grep \"^$sha1\" )\n-\t\tthen\n-\t\t\techo \"Missing object in local pack: $sha1\"\n-\t\t\treturn 1\n-\t\tfi\n-\tdone\n+\ttest_no_missing_in_packs\n '\n \n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n-- \n2.24.0.578.g4820254054\n\n"},{"id":"387524","messageId":"f3a0470edc7816bda151b0d11ddff8657b56cdfa.1575496684.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1575496683.git.liu.denton@gmail.com","subject":"[PATCH v6 2/5] t7700: consolidate code into test_has_duplicate_object()","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T22:03:14Z","receivedAt":"2019-12-04T22:03:21Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The code to test that objects were not duplicated from the packfile was\nduplicated many times. Extract the duplicated code into\ntest_has_duplicate_object() and use that instead.\n\nRefactor the resulting extraction so that if the git command fails,\nthe return code is not silently lost.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 71 +++++++++++++++--------------------------------\n 1 file changed, 23 insertions(+), 48 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 5fb9e99f34..80ded48088 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -21,6 +21,25 @@ test_no_missing_in_packs () {\n \ttest_must_be_empty missing\n }\n \n+# we expect $packsha1 and $objsha1 to be defined\n+test_has_duplicate_object () {\n+\twant_duplicate_object=\"$1\"\n+\tfound_duplicate_object=false\n+\tfor p in .git/objects/pack/*.idx\n+\tdo\n+\t\tidx=$(basename $p)\n+\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n+\t\tgit verify-pack -v $p >packlist || return $?\n+\t\tif egrep \"^$objsha1\" packlist\n+\t\tthen\n+\t\t\tfound_duplicate_object=true\n+\t\t\techo \"DUPLICATE OBJECT FOUND\"\n+\t\t\tbreak\n+\t\tfi\n+\tdone &&\n+\ttest \"$want_duplicate_object\" = \"$found_duplicate_object\"\n+}\n+\n test_expect_success 'objects in packs marked .keep are not repacked' '\n \techo content1 >file1 &&\n \techo content2 >file2 &&\n@@ -40,54 +59,19 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest -z \"$found_duplicate_object\"\n+\ttest_has_duplicate_object false\n '\n \n test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit repack -Adbl &&\n-\ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest \"$found_duplicate_object\" = 1\n+\ttest_has_duplicate_object true\n '\n \n test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n \t# build on $objsha1, $packsha1, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n-\ttest_when_finished \"found_duplicate_object=\" &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest \"$found_duplicate_object\" = 1\n+\ttest_has_duplicate_object true\n '\n \n test_expect_success 'loose objects in alternate ODB are not repacked' '\n@@ -100,16 +84,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tgit commit -m commit_file3 &&\n \tgit repack -a -d -l &&\n \tgit prune-packed &&\n-\tfor p in .git/objects/pack/*.idx\n-\tdo\n-\t\tif git verify-pack -v $p | egrep \"^$objsha1\"\n-\t\tthen\n-\t\t\tfound_duplicate_object=1\n-\t\t\techo \"DUPLICATE OBJECT FOUND\"\n-\t\t\tbreak\n-\t\tfi\n-\tdone &&\n-\ttest -z \"$found_duplicate_object\"\n+\ttest_has_duplicate_object false\n '\n \n test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '\n-- \n2.24.0.578.g4820254054\n\n"},{"id":"387525","messageId":"c34477a5a9f5c48c20046abd6ebee2064095bbe5.1575496684.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1575496683.git.liu.denton@gmail.com","subject":"[PATCH v6 3/5] t7700: replace egrep with grep","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T22:03:19Z","receivedAt":"2019-12-04T22:03:27Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"The egrep expressions in this test suite were of the form `^$variable`.\nAlthough egrep works just fine, it's overkill since we're not using any\nextended regex. Replace egrep invocations with grep so that we aren't\nswatting flies with a sledgehammer.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 80ded48088..bfef5888a2 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -30,7 +30,7 @@ test_has_duplicate_object () {\n \t\tidx=$(basename $p)\n \t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n \t\tgit verify-pack -v $p >packlist || return $?\n-\t\tif egrep \"^$objsha1\" packlist\n+\t\tif grep \"^$objsha1\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=true\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -135,7 +135,7 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n@@ -152,7 +152,7 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tegrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $csha1\n '\n-- \n2.24.0.578.g4820254054\n\n"},{"id":"387526","messageId":"113f375192655c3cb566770cb7f1c4f993e51b47.1575496684.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1575496683.git.liu.denton@gmail.com","subject":"[PATCH v6 4/5] t7700: make references to SHA-1 generic","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T22:03:24Z","receivedAt":"2019-12-04T22:03:32Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Make the test more hash-agnostic by renaming variables from \"sha1\" to\nsome variation of \"oid\" or \"packid\". Also, replace the regex,\n`[0-9a-f]\\{40\\}` with `$OID_REGEX`.\n\nA better name for \"incrpackid\" (incremental pack-id) might have been\njust \"packid\". However, later in the test suite, we have other uses of\n\"packid\". Although the scopes of these variables don't conflict, a\nfuture developer may think that commit_and_pack() and\ntest_has_duplicate_object() are semantically related somehow since they\nshare the same variable name. Give them distinct names so that it's\nclear these uses are unrelated.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 38 +++++++++++++++++++-------------------\n 1 file changed, 19 insertions(+), 19 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex bfef5888a2..5229999d77 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -6,31 +6,31 @@ test_description='git repack works correctly'\n \n commit_and_pack () {\n \ttest_commit \"$@\" 1>&2 &&\n-\tSHA1=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n-\techo pack-${SHA1}.pack\n+\tincrpackid=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) &&\n+\techo pack-${incrpackid}.pack\n }\n \n test_no_missing_in_packs () {\n \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n \ttest_path_is_file \"$myidx\" &&\n \tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n-\tsed -n -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/p\" orig.raw | sort >orig &&\n+\tsed -n -e \"s/^\\($OID_REGEX\\).*/\\1/p\" orig.raw | sort >orig &&\n \tgit verify-pack -v $myidx >dest.raw &&\n \tcut -d\" \" -f1 dest.raw | sort >dest &&\n \tcomm -23 orig dest >missing &&\n \ttest_must_be_empty missing\n }\n \n-# we expect $packsha1 and $objsha1 to be defined\n+# we expect $packid and $oid to be defined\n test_has_duplicate_object () {\n \twant_duplicate_object=\"$1\"\n \tfound_duplicate_object=false\n \tfor p in .git/objects/pack/*.idx\n \tdo\n \t\tidx=$(basename $p)\n-\t\ttest \"pack-$packsha1.idx\" = \"$idx\" && continue\n+\t\ttest \"pack-$packid.idx\" = \"$idx\" && continue\n \t\tgit verify-pack -v $p >packlist || return $?\n-\t\tif grep \"^$objsha1\" packlist\n+\t\tif grep \"^$oid\" packlist\n \t\tthen\n \t\t\tfound_duplicate_object=true\n \t\t\techo \"DUPLICATE OBJECT FOUND\"\n@@ -51,11 +51,11 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit rev-list --objects --all | grep -v file2 |\n \t\tgit pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpacksha1=$(git rev-list --objects --all | grep file2 |\n+\tpackid=$(git rev-list --objects --all | grep file2 |\n \t\tgit pack-objects pack) &&\n-\t>pack-$packsha1.keep &&\n-\tobjsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |\n-\t\tsed -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/\") &&\n+\t>pack-$packid.keep &&\n+\toid=$(git verify-pack -v pack-$packid.idx | head -n 1 |\n+\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -63,13 +63,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n '\n \n test_expect_success 'writing bitmaps via command-line can duplicate .keep objects' '\n-\t# build on $objsha1, $packsha1, and .keep state from previous\n+\t# build on $oid, $packid, and .keep state from previous\n \tgit repack -Adbl &&\n \ttest_has_duplicate_object true\n '\n \n test_expect_success 'writing bitmaps via config can duplicate .keep objects' '\n-\t# build on $objsha1, $packsha1, and .keep state from previous\n+\t# build on $oid, $packid, and .keep state from previous\n \tgit -c repack.writebitmaps=true repack -Adl &&\n \ttest_has_duplicate_object true\n '\n@@ -78,7 +78,7 @@ test_expect_success 'loose objects in alternate ODB are not repacked' '\n \tmkdir alt_objects &&\n \techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n \techo content3 >file3 &&\n-\tobjsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n+\toid=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&\n \tgit add file3 &&\n \ttest_tick &&\n \tgit commit -m commit_file3 &&\n@@ -124,7 +124,7 @@ test_expect_success 'packed obs in alternate ODB kept pack are repacked' '\n test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f alt_objects/pack/*.keep &&\n \tmv .git/objects/pack/* alt_objects/pack/ &&\n-\tcsha1=$(git rev-parse HEAD^{commit}) &&\n+\tcoid=$(git rev-parse HEAD^{commit}) &&\n \tgit reset --hard HEAD^ &&\n \ttest_tick &&\n \tgit reflog expire --expire=$test_tick --expire-unreachable=$test_tick --all &&\n@@ -135,14 +135,14 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n-\ttest_must_fail git show $csha1\n+\ttest_must_fail git show $coid\n '\n \n test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '\n \techo $(pwd)/alt_objects >.git/objects/info/alternates &&\n-\techo \"$csha1\" | git pack-objects --non-empty --all --reflog pack &&\n+\techo \"$coid\" | git pack-objects --non-empty --all --reflog pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \t# The pack-objects call on the next line is equivalent to\n@@ -152,9 +152,9 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n \ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$csha1 \" | sort | uniq | wc -l) &&\n+\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n \techo >.git/objects/info/alternates &&\n-\ttest_must_fail git show $csha1\n+\ttest_must_fail git show $coid\n '\n \n test_expect_success 'objects made unreachable by grafts only are kept' '\n-- \n2.24.0.578.g4820254054\n\n"},{"id":"387527","messageId":"ab653bd76fd3a20c2831ed8af6aa69c6d3abb47d.1575496684.git.liu.denton@gmail.com","threadId":"52269","inReplyTo":"cover.1575496683.git.liu.denton@gmail.com","subject":"[PATCH v6 5/5] t7700: stop losing return codes of git commands","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-12-04T22:03:30Z","receivedAt":"2019-12-04T22:03:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"In a pipe, only the return code of the last command is used. Thus, all\nother commands will have their return codes masked. Rewrite pipes so\nthat there are no git commands upstream so that we will know if a\ncommand fails.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n t/t7700-repack.sh | 19 +++++++++----------\n 1 file changed, 9 insertions(+), 10 deletions(-)\n\ndiff --git a/t/t7700-repack.sh b/t/t7700-repack.sh\nindex 5229999d77..25b235c063 100755\n--- a/t/t7700-repack.sh\n+++ b/t/t7700-repack.sh\n@@ -48,14 +48,13 @@ test_expect_success 'objects in packs marked .keep are not repacked' '\n \tgit commit -m initial_commit &&\n \t# Create two packs\n \t# The first pack will contain all of the objects except one\n-\tgit rev-list --objects --all | grep -v file2 |\n-\t\tgit pack-objects pack &&\n+\tgit rev-list --objects --all >objs &&\n+\tgrep -v file2 objs | git pack-objects pack &&\n \t# The second pack will contain the excluded object\n-\tpackid=$(git rev-list --objects --all | grep file2 |\n-\t\tgit pack-objects pack) &&\n+\tpackid=$(grep file2 objs | git pack-objects pack) &&\n \t>pack-$packid.keep &&\n-\toid=$(git verify-pack -v pack-$packid.idx | head -n 1 |\n-\t\tsed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n+\tgit verify-pack -v pack-$packid.idx >packlist &&\n+\toid=$(head -n 1 packlist | sed -e \"s/^\\($OID_REGEX\\).*/\\1/\") &&\n \tmv pack-* .git/objects/pack/ &&\n \tgit repack -A -d -l &&\n \tgit prune-packed &&\n@@ -134,8 +133,8 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! grep \"^$coid \" packlist &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $coid\n '\n@@ -151,8 +150,8 @@ test_expect_success 'local packed unreachable obs that exist in alternate ODB ar\n \t    --unpack-unreachable </dev/null pack &&\n \trm -f .git/objects/pack/* &&\n \tmv pack-* .git/objects/pack/ &&\n-\ttest 0 = $(git verify-pack -v -- .git/objects/pack/*.idx |\n-\t\tgrep \"^$coid \" | sort | uniq | wc -l) &&\n+\tgit verify-pack -v -- .git/objects/pack/*.idx >packlist &&\n+\t! grep \"^$coid \" &&\n \techo >.git/objects/info/alternates &&\n \ttest_must_fail git show $coid\n '\n-- \n2.24.0.578.g4820254054\n\n"},{"id":"387528","messageId":"xmqqfthz3fu6.fsf@gitster-ct.c.googlers.com","threadId":"52269","inReplyTo":"cover.1575496683.git.liu.denton@gmail.com","subject":"Re: [PATCH v6 0/5] t: test cleanup stemming from experimentally enabling pipefail","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-12-04T22:07:13Z","receivedAt":"2019-12-04T22:07:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n>\n> Range-diff against v5:\n> 1:  a99a45cb6f ! 1:  3008ce8deb t7700: consolidate code into test_no_missing_in_packs()\n>     @@ Commit message\n>          Refactor the resulting extraction so that if any git commands fail,\n>          their return codes are not silently lost.\n>      \n>     -    We were using sed to filter lines. Although not incorrect, this is\n>     -    exactly what grep is built for. Replace this invocation of sed with grep\n>     -    so that we use the correct tool for the job.\n>     -\n>          Instead of verifying each file of `alt_objects/pack/*.idx` individually\n>          in a for-loop, batch them together into one verification step.\n>      \n>          The original testing construct was O(n^2): it used a grep in a loop to\n>          test whether any objects were missing in the packfile. Rewrite this to\n>     -    sort the files then use `comm -23` so that finding missing lines from\n>     -    the original file is done more efficiently.\n>     +    extract the hash using sed or cut, sort the files, then use `comm -23`\n>     +    so that finding missing lines from the original file is done more\n>     +    efficiently.\n>      \n>          While we're at it, add a space to `commit_and_pack ()` for style.\n>      \n>     @@ t/t7700-repack.sh: test_description='git repack works correctly'\n>      +\tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n>      +\ttest_path_is_file \"$myidx\" &&\n>      +\tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n>     -+\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n>     ++\tsed -n -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/p\" orig.raw | sort >orig &&\n>      +\tgit verify-pack -v $myidx >dest.raw &&\n>      +\tcut -d\" \" -f1 dest.raw | sort >dest &&\n>      +\tcomm -23 orig dest >missing &&\n\nOK.\n\n> 2:  f79240e937 = 2:  f3a0470edc t7700: consolidate code into test_has_duplicate_object()\n> 3:  632a62f6e9 = 3:  c34477a5a9 t7700: replace egrep with grep\n> 4:  bf70cc5a0d ! 4:  113f375192 t7700: make references to SHA-1 generic\n>     @@ t/t7700-repack.sh: test_description='git repack works correctly'\n>       \tmyidx=$(ls -1 .git/objects/pack/*.idx) &&\n>       \ttest_path_is_file \"$myidx\" &&\n>       \tgit verify-pack -v alt_objects/pack/*.idx >orig.raw &&\n>     --\tgrep \"^[0-9a-f]\\{40\\}\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n>     -+\tgrep \"^$OID_REGEX\" orig.raw | cut -d\" \" -f1 | sort >orig &&\n>     +-\tsed -n -e \"s/^\\([0-9a-f]\\{40\\}\\).*/\\1/p\" orig.raw | sort >orig &&\n>     ++\tsed -n -e \"s/^\\($OID_REGEX\\).*/\\1/p\" orig.raw | sort >orig &&\n\nLooking really good.\n\nThanks for following through.  Will replace and queue.\n\nHopefully this round is now ready for 'next'.  Knock knock...\n"},{"id":"414399","messageId":"20210114233515.31298-1-avarab@gmail.com","threadId":"52269","inReplyTo":"20191115040909.GA21654@sigill.intra.peff.net","subject":"[PATCH 0/6] tests: add a bash \"set -o pipefail\" test mode","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-14T23:35:09Z","receivedAt":"2021-01-14T23:36:03Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"There's been past attempts to add a \"set -o pipefail\" test mode. I\nsuspect it can't be done in any sane way the way it works in bash\nnow. See 6/6 for details.\n\nThis series makes it work because I patched it to work sanely in bash\nitself when it comes to SIGPIPE. I'm partially submitting this so I\ncan prod the bash maintainer with a link to this thread.\n\nBut also because even though you need to patch your bash to benefit\nfrom this new test mode, it doesn't break anything for anyone who\ndoesn't have the patch (we guard it with a detection for the sane\nbehavior), and at the very least 4/6 (or maybe just to 2/6) are\ngenerally sane fixes even without the rest.\n\n1. https://lore.kernel.org/git/cover.1573779465.git.liu.denton@gmail.com/\n\nÆvar Arnfjörð Bjarmason (6):\n  test-lib: add tests for test_might_fail\n  test-lib: add ok=* support to test_might_fail\n  test_lib: allow test_{must,might}_fail to accept non-git on \"sigpipe\"\n  tests: use \"test_might_fail ok=sigpipe grep\" when appropriate\n  tests: split up bash detection library\n  tests: add a \"set -o pipefail\" for a patched bash\n\n t/README                           |  6 +++++\n t/lib-bash-detection.sh            |  8 +++++++\n t/lib-bash.sh                      |  4 +++-\n t/t0000-basic.sh                   | 38 ++++++++++++++++++++++++++++++\n t/t0005-signals.sh                 |  4 ++--\n t/t0090-cache-tree.sh              |  2 +-\n t/t5000-tar-tree.sh                |  2 +-\n t/t5703-upload-pack-ref-in-want.sh |  2 +-\n t/t9151-svn-mergeinfo.sh           |  6 ++---\n t/t9902-completion.sh              |  5 ++++\n t/test-lib-functions.sh            | 24 ++++++++++++++++++-\n t/test-lib.sh                      | 29 +++++++++++++++++++++++\n 12 files changed, 120 insertions(+), 10 deletions(-)\n create mode 100644 t/lib-bash-detection.sh\n\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414400","messageId":"20210114233515.31298-3-avarab@gmail.com","threadId":"52269","inReplyTo":"20191115040909.GA21654@sigill.intra.peff.net","subject":"[PATCH 2/6] test-lib: add ok=* support to test_might_fail","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-14T23:35:11Z","receivedAt":"2021-01-14T23:36:22Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add the same ok=* support to test_might_fail as its test_must_fail\nsibling. This will be used to make it accept \"sigpipe\" failures.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0000-basic.sh        |  5 +++++\n t/test-lib-functions.sh | 12 +++++++++++-\n 2 files changed, 16 insertions(+), 1 deletion(-)\n\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex f90c375fe9..fd6cb8d5d3 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -1332,4 +1332,9 @@ test_expect_success 'test_might_fail is like test_must_fail ok=' '\n \ttest_might_fail git version\n '\n \n+test_expect_success 'test_might_fail supports an ok=* option like test_must_fail' '\n+\ttest_might_fail git version &&\n+\ttest_might_fail ok=success git version\n+'\n+\n test_done\ndiff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\nindex 999982fe4a..e01761f7ba 100644\n--- a/t/test-lib-functions.sh\n+++ b/t/test-lib-functions.sh\n@@ -918,7 +918,17 @@ test_must_fail () {\n # Accepts the same options as test_must_fail.\n \n test_might_fail () {\n-\ttest_must_fail ok=success \"$@\" 2>&7\n+\tcase \"$1\" in\n+\tok=*)\n+\t\t_test_ok=success,${1#ok=}\n+\t\tshift\n+\t\t;;\n+\t*)\n+\t\t_test_ok=success\n+\t\t;;\n+\tesac\n+\n+\ttest_must_fail ok=$_test_ok \"$@\" 2>&7\n } 7>&2 2>&4\n \n # Similar to test_must_fail and test_might_fail, but check that a\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414401","messageId":"20210114233515.31298-2-avarab@gmail.com","threadId":"52269","inReplyTo":"20191115040909.GA21654@sigill.intra.peff.net","subject":"[PATCH 1/6] test-lib: add tests for test_might_fail","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-14T23:35:10Z","receivedAt":"2021-01-14T23:36:22Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"This trivial sibling command of test_must_fail added in\nfdf1bc48ca (t7006: guard cleanup with test_expect_success, 2010-04-14)\ndidn't have any tests. Let's add at least a basic one.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0000-basic.sh | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex f4ba2e8c85..f90c375fe9 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -1326,4 +1326,10 @@ test_expect_success 'test_must_fail rejects a non-git command with env' '\n \tgrep -F \"test_must_fail: only '\"'\"'git'\"'\"' is allowed\" err\n '\n \n+test_expect_success 'test_might_fail is like test_must_fail ok=' '\n+\t! test_must_fail git version &&\n+\t! test_must_fail ok= git version &&\n+\ttest_might_fail git version\n+'\n+\n test_done\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414402","messageId":"20210114233515.31298-5-avarab@gmail.com","threadId":"52269","inReplyTo":"20191115040909.GA21654@sigill.intra.peff.net","subject":"[PATCH 4/6] tests: use \"test_might_fail ok=sigpipe grep\" when appropriate","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-14T23:35:13Z","receivedAt":"2021-01-14T23:36:22Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change tests where the \"grep\" might exit with non-zero to use our new\n\"test_might_fail ok=sigpipe\" wrapper. A subsequent commit will show\nhow useful this is in combination with \"set -o pipefail\".\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh              | 2 +-\n t/t5703-upload-pack-ref-in-want.sh | 2 +-\n t/t9151-svn-mergeinfo.sh           | 6 +++---\n 3 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 5a633690bf..2e69ab138b 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -22,7 +22,7 @@ generate_expected_cache_tree_rec () {\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n \tgit ls-files >files &&\n-\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n+\tsubtrees=$(test_might_fail ok=sigpipe grep / files |cut -d / -f 1|uniq) &&\n \tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n \tentries=$(wc -l <files) &&\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex eab966985b..44238b7409 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -16,7 +16,7 @@ get_actual_commits () {\n \ttest-tool pkt-line unpack-sideband <out >o.pack &&\n \tgit index-pack o.pack &&\n \tgit verify-pack -v o.idx >objs &&\n-\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n+\ttest_might_fail ok=sigpipe grep commit objs | cut -d\" \" -f1 | sort >actual_commits\n }\n \n check_output () {\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 4f6c06ecb2..dc8491c14a 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -18,19 +18,19 @@ test_expect_success 'load svn dump' \"\n \n test_expect_success 'all svn merges became git merge commits' '\n \tunmarked=$(git rev-list --parents --all --grep=Merge |\n-\t\tgrep -v \" .* \" | cut -f1 -d\" \") &&\n+\t\ttest_might_fail ok=sigpipe grep -v \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$unmarked\" ]\n \t'\n \n test_expect_success 'cherry picks did not become git merge commits' '\n \tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n+\t\ttest_might_fail ok=sigpipe grep grep \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$bad_cherries\" ]\n \t'\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n \tbad_non_merges=$(git rev-list --parents --all --grep=non-merge |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n+\t\ttest_might_fail ok=sigpipe grep grep \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$bad_non_merges\" ]\n \t'\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414403","messageId":"20210114233515.31298-4-avarab@gmail.com","threadId":"52269","inReplyTo":"20191115040909.GA21654@sigill.intra.peff.net","subject":"[PATCH 3/6] test_lib: allow test_{must,might}_fail to accept non-git on \"sigpipe\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-14T23:35:12Z","receivedAt":"2021-01-14T23:36:22Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"As the documentation here notes you usually do not want to do:\n\n    test_might_fail grep ...\n\nBut instead:\n\n    ! grep ...\n\nHowever, as a future commit will show it's handy to be able to do:\n\n    some | test_might_fail ok=sigpipe grep | commands | here\n\nTo allow \"grep\" to fail in the middle of a pipe, if we're in a mode\nsuch as a \"set -o pipefail\" that knows how to accept check intra-pipe\nfailures.\n\nTo test this in t0000-basic.sh we don't actually need to have\ntest_{might,must}_fail in the middle of a pipe, it'll just that it\naccepts e.g. \"grep\" when we provide ok=sigpipe.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0000-basic.sh        | 13 +++++++++++++\n t/test-lib-functions.sh | 12 ++++++++++++\n 2 files changed, 25 insertions(+)\n\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex fd6cb8d5d3..930cf9d1b7 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -1337,4 +1337,17 @@ test_expect_success 'test_might_fail supports an ok=* option like test_must_fail\n \ttest_might_fail ok=success git version\n '\n \n+test_expect_success 'test_{must,might}_fail accept non-git on \"sigpipe\"' '\n+\t! test_must_fail grep blob <badobjects 2>err &&\n+\tgrep \"only.*git.*is allowed\" err &&\n+\t! test_might_fail grep blob <badobjects &&\n+\tgrep \"only.*git.*is allowed\" err &&\n+\n+\t! test_must_fail ok=sigpipe grep . badobjects 2>err &&\n+\ttest_must_be_empty err &&\n+\ttest_might_fail ok=sigpipe grep . badobjects >out 2>err &&\n+\ttest_must_be_empty err &&\n+\ttest_cmp badobjects out\n+'\n+\n test_done\ndiff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh\nindex e01761f7ba..f10bd6170a 100644\n--- a/t/test-lib-functions.sh\n+++ b/t/test-lib-functions.sh\n@@ -828,6 +828,7 @@ test_must_fail_acceptable () {\n \t\treturn 0\n \t\t;;\n \t*)\n+\t\tlist_contains \"$_test_ok\" sigpipe && return 0\n \t\treturn 1\n \t\t;;\n \tesac\n@@ -863,6 +864,17 @@ test_must_fail_acceptable () {\n # Instead use '!':\n #\n #    ! grep pattern output\n+#\n+# An exception to this is if ok=* contains \"sigpipe\". Then you might\n+# want to use this in a test to ignore e.g. \"grep\" failing due to not\n+# finding anything in a multi-pipe command:\n+#\n+#    test_must_fail ok=success,sigpipe grep [...] | [...]\n+#\n+# Or, more succinctly with the test_might_fail wrapper function:\n+#\n+#    test_might_fail ok=sigpipe grep [...] | [...]\n+#\n \n test_must_fail () {\n \tcase \"$1\" in\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414404","messageId":"20210114233515.31298-6-avarab@gmail.com","threadId":"52269","inReplyTo":"20191115040909.GA21654@sigill.intra.peff.net","subject":"[PATCH 5/6] tests: split up bash detection library","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-14T23:35:14Z","receivedAt":"2021-01-14T23:36:59Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split up the detection for whether we're running under bash, and\nwhether it's the /bin/sh POSIX-y mode or the /bin/bash bash-y mode\ninto its own library.\n\nThis will soon be used very early in test-lib.sh itself to check for\nthe /bin/bash, so let's make this new file as small as possible.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/lib-bash-detection.sh | 8 ++++++++\n t/lib-bash.sh           | 4 +++-\n 2 files changed, 11 insertions(+), 1 deletion(-)\n create mode 100644 t/lib-bash-detection.sh\n\ndiff --git a/t/lib-bash-detection.sh b/t/lib-bash-detection.sh\nnew file mode 100644\nindex 0000000000..8fbdae1d52\n--- /dev/null\n+++ b/t/lib-bash-detection.sh\n@@ -0,0 +1,8 @@\n+#!/bin/sh\n+\n+TEST_SH_IS_BIN_BASH=\n+if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+then\n+\tTEST_SH_IS_BIN_BASH=true\n+\texport TEST_SH_IS_BIN_BASH\n+fi\ndiff --git a/t/lib-bash.sh b/t/lib-bash.sh\nindex b0b6060929..8fd06d2e58 100644\n--- a/t/lib-bash.sh\n+++ b/t/lib-bash.sh\n@@ -2,7 +2,9 @@\n # to run under Bash; primarily intended for tests of the completion\n # script.\n \n-if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+. ./lib-bash-detection.sh\n+\n+if test -n \"$TEST_SH_IS_BIN_BASH\"\n then\n \t# we are in full-on bash mode\n \ttrue\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414405","messageId":"20210114233515.31298-7-avarab@gmail.com","threadId":"52269","inReplyTo":"20191115040909.GA21654@sigill.intra.peff.net","subject":"[PATCH 6/6] tests: add a \"set -o pipefail\" for a patched bash","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-14T23:35:15Z","receivedAt":"2021-01-14T23:36:59Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a \"set -o pipefail\" test mode to the test suite to detect failures\nin \"git\" its output is fed directly to a pipe. Doing so is a pattern\nwe discourage[1] in the test suite, but we've got plenty of tests like\nthat. Now we can reliably detect those failures.\n\nThere was a previous attempt in [2] to add such a test mode, but as\nnoted by Jeff King in [3] adding it is a matter of peeing against the\nwind with current bash semantics of failing on SIGPIPE.\n\nThis series relies on a patch of mine to bash, which I'm submitting\nupstream. Vanilla bash ignores SIGPIPE under \"set -e\" since version\n3.1. It's only under \"set -o pipefail\" (added in 3.2) that it doesn't\ntake account of SIGPIPE, in a seeming omission nobody bothered to fix\nyet.\n\nPatching bash[4] with:\n\n    diff --git a/jobs.c b/jobs.c\n    index a581f305..fa5de82a 100644\n    --- a/jobs.c\n    +++ b/jobs.c\n    @@ -2851,8 +2851,14 @@ raw_job_exit_status (job)\n           p = jobs[job]->pipe;\n           do\n     \t{\n    -\t  if (WSTATUS (p->status) != EXECUTION_SUCCESS)\n    -\t    fail = WSTATUS(p->status);\n    +\t  if (WSTATUS (p->status) != EXECUTION_SUCCESS\n    +#if defined (DONT_REPORT_SIGPIPE)\n    +              && WTERMSIG (p->status) != SIGPIPE\n    +#endif\n    +              )\n    +            {\n    +              fail = WSTATUS(p->status);\n    +            }\n     \t  p = p->next;\n     \t}\n           while (p != jobs[job]->pipe);\n\nMakes it useful for something like the git test suite. With vanilla\nbash and GIT_TEST_PIPEFAIL=true we'll fail 4 tests in my one-off test.\n\nWith my patched bash the only tests we need to skip are those that are\nexplicitly testing that a piped command returned SIGPIPE.\n\nAs Jeff noted in [3] that count isn't reliable, as more will fail in a\nway that's hard to reproduce due to the racy nature of vanilla \"set -o\npipefail\"\n\n1. a378fee5b0 (Documentation: add shell guidelines, 2018-10-05)\n2. https://lore.kernel.org/git/cover.1573779465.git.liu.denton@gmail.com/\n3. https://lore.kernel.org/git/20191115040909.GA21654@sigill.intra.peff.net/\n4. https://github.com/bminor/bash/compare/master...avar:avar/ignore-sigterm-and-sigpipe-on-pipe-fail\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/README              |  6 ++++++\n t/t0000-basic.sh      | 14 ++++++++++++++\n t/t0005-signals.sh    |  4 ++--\n t/t5000-tar-tree.sh   |  2 +-\n t/t9902-completion.sh |  5 +++++\n t/test-lib.sh         | 29 +++++++++++++++++++++++++++++\n 6 files changed, 57 insertions(+), 3 deletions(-)\n\ndiff --git a/t/README b/t/README\nindex c730a70770..d9f65bfa6b 100644\n--- a/t/README\n+++ b/t/README\n@@ -439,6 +439,12 @@ GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to\n use in the test scripts. Recognized values for <hash-algo> are \"sha1\"\n and \"sha256\".\n \n+GIT_TEST_PIPEFAIL=<boolean>, when true, run 'set -o pipefail' to catch\n+failures in commands that aren't the last in a pipe. Defaults to true\n+on bash versions which know how to ignore SIGPIPE failures under the\n+'set -o pipefail' mode (as of 2021-01-14 only in an out-of-tree patch\n+to bash).\n+\n Naming Tests\n ------------\n \ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex 930cf9d1b7..e70cc37139 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -1350,4 +1350,18 @@ test_expect_success 'test_{must,might}_fail accept non-git on \"sigpipe\"' '\n \ttest_cmp badobjects out\n '\n \n+test_expect_failure BASH_SET_O_PIPEFAIL 'test_{must,might}_fail ok=sigpipe under bash \"set -o pipefail\"' '\n+\tgrep string </dev/null | true\n+'\n+\n+test_expect_failure BASH_SET_O_PIPEFAIL 'test_{must,might}_fail ok=sigpipe under bash \"set -o pipefail\"' '\n+\ttest_must_fail grep string </dev/null | true &&\n+\ttest_might_fail grep string </dev/null | true\n+'\n+\n+test_expect_success BASH_SET_O_PIPEFAIL 'test_{must,might}_fail ok=sigpipe under bash \"set -o pipefail\"' '\n+\ttest_must_fail ok=sigpipe grep string </dev/null | true &&\n+\ttest_might_fail ok=sigpipe grep string </dev/null | true\n+'\n+\n test_done\ndiff --git a/t/t0005-signals.sh b/t/t0005-signals.sh\nindex 4c214bd11c..cc5784a274 100755\n--- a/t/t0005-signals.sh\n+++ b/t/t0005-signals.sh\n@@ -40,12 +40,12 @@ test_expect_success 'create blob' '\n \tgit add file\n '\n \n-test_expect_success !MINGW 'a constipated git dies with SIGPIPE' '\n+test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE' '\n \tOUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&\n \ttest_match_signal 13 \"$OUT\"\n '\n \n-test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' '\n+test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE even if parent ignores it' '\n \tOUT=$( ((trap \"\" PIPE; large_git; echo $? 1>&3) | :) 3>&1 ) &&\n \ttest_match_signal 13 \"$OUT\"\n '\ndiff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh\nindex 3ebb0d3b65..3adcbce84c 100755\n--- a/t/t5000-tar-tree.sh\n+++ b/t/t5000-tar-tree.sh\n@@ -416,7 +416,7 @@ test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '\n \n # We expect git to die with SIGPIPE here (otherwise we\n # would generate the whole 64GB).\n-test_expect_success LONG_IS_64BIT 'generate tar with huge size' '\n+test_expect_success LONG_IS_64BIT,!BASH_SET_O_PIPEFAIL 'generate tar with huge size' '\n \t{\n \t\tgit archive HEAD\n \t\techo $? >exit-code\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex a1c4f1f6d4..3414ac56f4 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -7,6 +7,11 @@ test_description='test bash completion'\n \n . ./lib-bash.sh\n \n+if test -n \"$GIT_TEST_PIPEFAIL_TRUE\"\n+then\n+\tset +o pipefail\n+fi\n+\n complete ()\n {\n \t# do nothing\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 9fa7c1d0f6..118dc80ffc 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -36,6 +36,31 @@ then\n fi\n GIT_BUILD_DIR=\"$TEST_DIRECTORY\"/..\n \n+# Does \"set -o pipefail\" on this bash version handle SIGPIPE? Use it!\n+. \"$TEST_DIRECTORY/lib-bash-detection.sh\"\n+GIT_TEST_PIPEFAIL_TRUE=\n+GIT_TEST_PIPEFAIL_DEFAULT=false\n+if test -n \"$TEST_SH_IS_BIN_BASH\" &&\n+       $BASH -c 'set -eo pipefail; yes | head -n 1 >/dev/null'\n+then\n+\tGIT_TEST_PIPEFAIL_DEFAULT=true\n+fi\n+# We're too early for test_bool_env\n+if git env--helper --type=bool --default=\"$GIT_TEST_PIPEFAIL_DEFAULT\" \\\n+       --exit-code GIT_TEST_PIPEFAIL\n+then\n+\tset -o pipefail\n+\n+\t# Only \"set -o pipefail\" in the main test scripts, not any\n+\t# sub-programs we spawn.\n+\tGIT_TEST_PIPEFAIL=\n+\texport GIT_TEST_PIPEFAIL\n+\n+\t# For the convenience of the prereq for it.\n+\tGIT_TEST_PIPEFAIL_TRUE=true\n+\texport GIT_TEST_PIPEFAIL_TRUE\n+fi\n+\n # If we were built with ASAN, it may complain about leaks\n # of program-lifetime variables. Disable it by default to lower\n # the noise level. This needs to happen at the start of the script,\n@@ -1552,6 +1577,10 @@ test_lazy_prereq PIPE '\n \trm -f testfifo && mkfifo testfifo\n '\n \n+test_lazy_prereq BASH_SET_O_PIPEFAIL '\n+\ttest -n \"$GIT_TEST_PIPEFAIL_TRUE\"\n+'\n+\n test_lazy_prereq SYMLINKS '\n \t# test whether the filesystem supports symbolic links\n \tln -s x y && test -h y\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414434","messageId":"YAFPDJHH7ChvnVSD@generichostname","threadId":"52269","inReplyTo":"20210114233515.31298-4-avarab@gmail.com","subject":"Re: [PATCH 3/6] test_lib: allow test_{must,might}_fail to accept non-git on \"sigpipe\"","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2021-01-15T08:15:08Z","receivedAt":"2021-01-15T08:16:09Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Ævar,\n\nFirst of all, thanks for reviving this series! I hope that Bash accepts\nyour proposed patch because it would definitely be helpful.\n\nOn Fri, Jan 15, 2021 at 12:35:12AM +0100, Ævar Arnfjörð Bjarmason wrote:\n> As the documentation here notes you usually do not want to do:\n> \n>     test_might_fail grep ...\n> \n> But instead:\n> \n>     ! grep ...\n> \n> However, as a future commit will show it's handy to be able to do:\n> \n>     some | test_might_fail ok=sigpipe grep | commands | here\n> \n> To allow \"grep\" to fail in the middle of a pipe, if we're in a mode\n> such as a \"set -o pipefail\" that knows how to accept check intra-pipe\n> failures.\n\nFrom what I can see, there presently aren't any other use cases here\nexcept for with grep. I propose writing a wrapper around\ngrep, à la [0]:\n\n\ttest_filter () {\n\t\tgrep \"$@\" || :\n\t}\n\nThis has two main advantanges: the first would be that we could avoid\ncomplicating the test_must_fail_acceptable() code. The second is that\nit would be much less of a mouthful to write and it would be more\nreadable.\n\nCompare\n\n\tsome | test_might_fail ok=sigpipe grep | commands | here\n\nto\n\n\tsome | test_filter | commands | here\n\n\nThanks,\nDenton\n\n[0]: https://lore.kernel.org/git/3f79d23b40c0586d0351f4d721097be4f7ba26b8.1573779465.git.liu.denton@gmail.com/\n\n> To test this in t0000-basic.sh we don't actually need to have\n> test_{might,must}_fail in the middle of a pipe, it'll just that it\n> accepts e.g. \"grep\" when we provide ok=sigpipe.\n> \n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n"},{"id":"414439","messageId":"87r1mm4l4v.fsf@evledraar.gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-5-avarab@gmail.com","subject":"Re: [PATCH 4/6] tests: use \"test_might_fail ok=sigpipe grep\" when appropriate","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-15T09:14:40Z","receivedAt":"2021-01-15T09:15:29Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Jan 15 2021, Ævar Arnfjörð Bjarmason wrote:\n\n>  test_expect_success 'cherry picks did not become git merge commits' '\n>  \tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n> -\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n> +\t\ttest_might_fail ok=sigpipe grep grep \" .* \" | cut -f1 -d\" \") &&\n> [...]\n> -\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n> +\t\ttest_might_fail ok=sigpipe grep grep \" .* \" | cut -f1 -d\" \") &&\n\nSo, \"grep grep\" is an obvious typo there. Oops. The test still passes\nbecause it's fragile to begin with, we're just checking that we get no\noutput, so \"grep this string is not here\" would also pass.\n"},{"id":"414442","messageId":"YAFiFW7D1qD7ZJ8I@coredump.intra.peff.net","threadId":"52269","inReplyTo":"20210114233515.31298-2-avarab@gmail.com","subject":"Re: [PATCH 1/6] test-lib: add tests for test_might_fail","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-15T09:36:21Z","receivedAt":"2021-01-15T09:37:05Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 15, 2021 at 12:35:10AM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> +test_expect_success 'test_might_fail is like test_must_fail ok=' '\n> +\t! test_must_fail git version &&\n> +\t! test_must_fail ok= git version &&\n> +\ttest_might_fail git version\n> +'\n\nThe title confuses me. Isn't might_fail like \"must_fail ok=success\"?\n\nAnd certainly the code here shows us expecting the _opposite_ of what\n\"Must_fail ok=\" does.\n\n-Peff\n"},{"id":"414443","messageId":"87o8hq4jzu.fsf@evledraar.gmail.com","threadId":"52269","inReplyTo":"YAFPDJHH7ChvnVSD@generichostname","subject":"Re: [PATCH 3/6] test_lib: allow test_{must,might}_fail to accept non-git on \"sigpipe\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-15T09:39:17Z","receivedAt":"2021-01-15T09:40:03Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Jan 15 2021, Denton Liu wrote:\n\n> Hi Ævar,\n>\n> First of all, thanks for reviving this series! I hope that Bash accepts\n> your proposed patch because it would definitely be helpful.\n\n*nod*\n\n> On Fri, Jan 15, 2021 at 12:35:12AM +0100, Ævar Arnfjörð Bjarmason wrote:\n>> As the documentation here notes you usually do not want to do:\n>> \n>>     test_might_fail grep ...\n>> \n>> But instead:\n>> \n>>     ! grep ...\n>> \n>> However, as a future commit will show it's handy to be able to do:\n>> \n>>     some | test_might_fail ok=sigpipe grep | commands | here\n>> \n>> To allow \"grep\" to fail in the middle of a pipe, if we're in a mode\n>> such as a \"set -o pipefail\" that knows how to accept check intra-pipe\n>> failures.\n>\n> From what I can see, there presently aren't any other use cases here\n> except for with grep. I propose writing a wrapper around\n> grep, à la [0]:\n>\n> \ttest_filter () {\n> \t\tgrep \"$@\" || :\n> \t}\n>\n> This has two main advantanges: the first would be that we could avoid\n> complicating the test_must_fail_acceptable() code. The second is that\n> it would be much less of a mouthful to write and it would be more\n> readable.\n>\n> Compare\n>\n> \tsome | test_might_fail ok=sigpipe grep | commands | here\n>\n> to\n>\n> \tsome | test_filter | commands | here\n\nI saw your original series/patch. including Junio's suggestion that\ntest_grep_return_success was a bit too verbose & the suggestion for\n\"test_filter\".\n\nI think the \"test_might_fail\" in this case is more readable, readable !=\nshort. I.e. imagine you haven't just been looking at this code & open\nthat test file. If it's using \"test_{might,must}_fail ok=*\" you're more\nlikely to immediately understand it since you've seen those functions in\nlots of places before.\n\nIf not, then \"test might fail ok=sigpipe\" is almost so self-documenting\nthat you don't need to look at the function.\n\nWhereas a \"test_filter\" for me at least would prompt an immediate \"hrm?\nwhat's that?\", followed by grepping it and the side-quest of reading the\nsource for that function we use in a grand total of <10 places.\n\nAnyway, just my 0.02. I also think it makes conceptual sense to just\nhave a limited whitelist in \"test_{might,must}_fail\", since in this case\nthe reason we recommend against its use for non-git doesn't\napply. I.e. we're normally not in the business of testing the OS, but in\nthis case it's got the useful behavior of knowing how to handle the exit\ncode & signal special-case, so we might as well use it.\n\n\n> [0]: https://lore.kernel.org/git/3f79d23b40c0586d0351f4d721097be4f7ba26b8.1573779465.git.liu.denton@gmail.com/\n>\n>> To test this in t0000-basic.sh we don't actually need to have\n>> test_{might,must}_fail in the middle of a pipe, it'll just that it\n>> accepts e.g. \"grep\" when we provide ok=sigpipe.\n>> \n>> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\n"},{"id":"414444","messageId":"87lfcu4jv4.fsf@evledraar.gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-6-avarab@gmail.com","subject":"Re: [PATCH 5/6] tests: split up bash detection library","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-15T09:42:07Z","receivedAt":"2021-01-15T09:43:00Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Jan 15 2021, Ævar Arnfjörð Bjarmason wrote:\n\n> +TEST_SH_IS_BIN_BASH=\n> +if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n> +then\n> +\tTEST_SH_IS_BIN_BASH=true\n> +\texport TEST_SH_IS_BIN_BASH\n> +fi\n\nI haven't been able to find from bash's documentation & sources whether\nthis really is the right thing here. I.e. in test-lib.sh we've got an\nexisting test for checking $BASH_VERSION. As far as I can tell it's not\ndocumented, but that variable doesn't appear in bash's /bin/sh mode,\njust in /bin/bash mode.\n\nAnd then there's $POSIXLY_CORRECT, does that make it 2 modes in total,\nor 4 (or 3)? I didn't look too carefully, and in any case this worked\nfor all the cases I threw at it of running the tests with /bin/sh or\n/bin/bash, but it would be a nice follow-up patch to unify this & the\nother $BASH_VERSION check in test-lib.sh if we could...\n"},{"id":"414445","messageId":"YAFk/evY0GLr62dt@coredump.intra.peff.net","threadId":"52269","inReplyTo":"87r1mm4l4v.fsf@evledraar.gmail.com","subject":"Re: [PATCH 4/6] tests: use \"test_might_fail ok=sigpipe grep\" when appropriate","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-15T09:48:45Z","receivedAt":"2021-01-15T09:49:29Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 15, 2021 at 10:14:40AM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> \n> On Fri, Jan 15 2021, Ævar Arnfjörð Bjarmason wrote:\n> \n> >  test_expect_success 'cherry picks did not become git merge commits' '\n> >  \tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n> > -\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n> > +\t\ttest_might_fail ok=sigpipe grep grep \" .* \" | cut -f1 -d\" \") &&\n> > [...]\n> > -\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n> > +\t\ttest_might_fail ok=sigpipe grep grep \" .* \" | cut -f1 -d\" \") &&\n> \n> So, \"grep grep\" is an obvious typo there. Oops. The test still passes\n> because it's fragile to begin with, we're just checking that we get no\n> output, so \"grep this string is not here\" would also pass.\n\nThis is a good example of why tests are often better written to check\nfor an expected outcome, rather than lack of an unexpected one.\n\nThat does often make tests more verbose and brittle, though (in this\ncase, I guess we'd presumably have to validate the whole \"rev-list\"\noutput. So it may not be practical.\n\nI do wonder if this test needs these pipes at all. It looks like we are\nlooking for merge commits. Maybe \"rev-list --merges\" would be a bit\nsimpler these days? I.e.:\n\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 4f6c06ecb2..20dd62c5c4 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -17,22 +17,19 @@ test_expect_success 'load svn dump' \"\n \t\"\n \n test_expect_success 'all svn merges became git merge commits' '\n-\tunmarked=$(git rev-list --parents --all --grep=Merge |\n-\t\tgrep -v \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$unmarked\" ]\n-\t'\n+\tgit rev-list --all --no-merges --grep=Merge >actual &&\n+\ttest_must_be_empty actual\n+'\n \n test_expect_success 'cherry picks did not become git merge commits' '\n-\tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$bad_cherries\" ]\n-\t'\n+\tgit rev-list --all --merges --grep=Cherry >actual &&\n+\ttest_must_be_empty actual\n+'\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n-\tbad_non_merges=$(git rev-list --parents --all --grep=non-merge |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$bad_non_merges\" ]\n-\t'\n+\tgit rev-list --all --merges --grep=non-merge >actual &&\n+\ttest_must_be_empty actual\n+'\n \n test_expect_success 'commit made to merged branch is reachable from the merge' '\n \tbefore_commit=$(git rev-list --all --grep=\"trunk commit before merging trunk to b2\") &&\n\n-Peff\n"},{"id":"414446","messageId":"YAFntgQE3NZ3yQx5@coredump.intra.peff.net","threadId":"52269","inReplyTo":"87o8hq4jzu.fsf@evledraar.gmail.com","subject":"Re: [PATCH 3/6] test_lib: allow test_{must,might}_fail to accept non-git on \"sigpipe\"","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-15T10:00:22Z","receivedAt":"2021-01-15T10:01:21Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 15, 2021 at 10:39:17AM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> > Compare\n> >\n> > \tsome | test_might_fail ok=sigpipe grep | commands | here\n> >\n> > to\n> >\n> > \tsome | test_filter | commands | here\n> \n> I saw your original series/patch. including Junio's suggestion that\n> test_grep_return_success was a bit too verbose & the suggestion for\n> \"test_filter\".\n> \n> I think the \"test_might_fail\" in this case is more readable, readable !=\n> short. I.e. imagine you haven't just been looking at this code & open\n> that test file. If it's using \"test_{might,must}_fail ok=*\" you're more\n> likely to immediately understand it since you've seen those functions in\n> lots of places before.\n> \n> If not, then \"test might fail ok=sigpipe\" is almost so self-documenting\n> that you don't need to look at the function.\n\nBut I'm left confused...do we expect grep to get sigpipe here? I don't\nthink so. The problem is that grep will return 0 for \"I did not match\nanything\". We would get sigpipe if \"commands | here\" exited without\nreading all of the input.\n\nSo the \"ok=sigpipe\" seems very misleading to me (and likewise, the whole\n\"test_might_fail ok=sigpipe\" exception seems weird; sigpipe is not the\nreason we want to use it with grep here; it is because grep might\nactually fail).\n\nWhereas the test-filter approach is expressing what we actually are\ninterested in (ignoring the exit code of grep, no matter what).\n\n> Whereas a \"test_filter\" for me at least would prompt an immediate \"hrm?\n> what's that?\", followed by grepping it and the side-quest of reading the\n> source for that function we use in a grand total of <10 places.\n\nI agree this is sometimes a problem. But if we want to inline it, it\nseems like the correct spelling here is:\n\n  some | { grep ... || true; } | commands | here\n\n> Anyway, just my 0.02. I also think it makes conceptual sense to just\n> have a limited whitelist in \"test_{might,must}_fail\", since in this case\n> the reason we recommend against its use for non-git doesn't\n> apply. I.e. we're normally not in the business of testing the OS, but in\n> this case it's got the useful behavior of knowing how to handle the exit\n> code & signal special-case, so we might as well use it.\n\nI'm somewhat lukewarm on the whitelist already, as I got bit recently by\na (not yet published) test doing:\n\n  foo() {\n\tgit --with --some --options \"$@\"\n  }\n  test_expect_success '...' '\n\t# this one is expected to succeed\n\tfoo ok &&\n\t# this one is not\n\ttest_must_fail foo bad\n  '\n\n-Peff\n"},{"id":"414447","messageId":"YAFokKRE6KDd6avN@coredump.intra.peff.net","threadId":"52269","inReplyTo":"20210114233515.31298-7-avarab@gmail.com","subject":"Re: [PATCH 6/6] tests: add a \"set -o pipefail\" for a patched bash","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-15T10:04:00Z","receivedAt":"2021-01-15T10:04:44Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Jan 15, 2021 at 12:35:15AM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> Makes it useful for something like the git test suite. With vanilla\n> bash and GIT_TEST_PIPEFAIL=true we'll fail 4 tests in my one-off test.\n> \n> With my patched bash the only tests we need to skip are those that are\n> explicitly testing that a piped command returned SIGPIPE.\n> \n> As Jeff noted in [3] that count isn't reliable, as more will fail in a\n> way that's hard to reproduce due to the racy nature of vanilla \"set -o\n> pipefail\"\n\nYeah, the count is IMHO not important. Without a way to globally ignore\nsigpipe for pipefail, we're left with annotating callers. Which means it\nhas now become much easier for people to introduce tests which racily\nfail. That is much worse than the problem you are trying to solve here. ;)\n\nSo it does not matter much how many cases we have. The fact that it\nwould be easy to introduce new ones makes it unworkable IMHO (without\nthe bash patch, I mean).\n\n-Peff\n"},{"id":"414496","messageId":"20210116153554.12604-10-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 09/11] archive tests: use a cheaper \"zipinfo -h\" invocation to get header","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:52Z","receivedAt":"2021-01-16T17:06:28Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change an invocation of zipinfo added in 19ee29401d (t5004: test ZIP\narchives with many entries, 2015-08-22) to simply ask zipinfo for the\nheader info, rather than spewing out info about the entire archive and\nrace to kill it with SIGPIPE due to the downstream \"head -2\".\n\nI ran across this because I'm adding a \"set -o pipefail\" test\nmode. This won't be needed for the version of the mode that I'm\nintroducing (which currently relies on a patch to GNU bash), but I\nthink this is a good idea anyway.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t5004-archive-corner-cases.sh | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh\nindex 3e7b23cb32..2d32d0ed12 100755\n--- a/t/t5004-archive-corner-cases.sh\n+++ b/t/t5004-archive-corner-cases.sh\n@@ -153,7 +153,8 @@ test_expect_success ZIPINFO 'zip archive with many entries' '\n \n \t# check the number of entries in the ZIP file directory\n \texpr 65536 + 256 >expect &&\n-\t\"$ZIPINFO\" many.zip | head -2 | sed -n \"2s/.* //p\" >actual &&\n+\t\"$ZIPINFO\" -h many.zip >zipinfo &&\n+\tsed -n \"2s/.* //p\" <zipinfo >actual &&\n \ttest_cmp expect actual\n '\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414497","messageId":"20210116153554.12604-9-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 08/11] upload-pack tests: avoid a non-zero \"grep\" exit status","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:51Z","receivedAt":"2021-01-16T17:08:45Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Continue changing a test that 763b47bafa (t5703: stop losing return\ncodes of git commands, 2019-11-27) already refactored. A follow-up\ncommit will add support for testing under bash's \"set -o pipefail\",\nunder that mode this test will fail because sometimes there's no\ncommits in the \"objs\" output.\n\nIt's easier to just fix this than to exempt these tests under a\nsoon-to-be added \"set -o pipefail\" test mode. So let's do that.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 6 +++++-\n 1 file changed, 5 insertions(+), 1 deletion(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex eab966985b..420cf2bbde 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -16,7 +16,11 @@ get_actual_commits () {\n \ttest-tool pkt-line unpack-sideband <out >o.pack &&\n \tgit index-pack o.pack &&\n \tgit verify-pack -v o.idx >objs &&\n-\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n+\t>actual_commits &&\n+\tif grep -q commit objs\n+\tthen\n+\t\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n+\tfi\n }\n \n check_output () {\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414498","messageId":"20210116153554.12604-11-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 10/11] tests: split up bash detection library","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:53Z","receivedAt":"2021-01-16T17:09:57Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Split up the detection for whether we're running under bash, and\nwhether it's the /bin/sh POSIX-y mode or the /bin/bash bash-y mode\ninto its own library.\n\nThis will soon be used very early in test-lib.sh itself to check for\nthe /bin/bash, so let's make this new file as small as possible.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/lib-bash-detection.sh | 8 ++++++++\n t/lib-bash.sh           | 4 +++-\n 2 files changed, 11 insertions(+), 1 deletion(-)\n create mode 100644 t/lib-bash-detection.sh\n\ndiff --git a/t/lib-bash-detection.sh b/t/lib-bash-detection.sh\nnew file mode 100644\nindex 0000000000..8fbdae1d52\n--- /dev/null\n+++ b/t/lib-bash-detection.sh\n@@ -0,0 +1,8 @@\n+#!/bin/sh\n+\n+TEST_SH_IS_BIN_BASH=\n+if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+then\n+\tTEST_SH_IS_BIN_BASH=true\n+\texport TEST_SH_IS_BIN_BASH\n+fi\ndiff --git a/t/lib-bash.sh b/t/lib-bash.sh\nindex b0b6060929..8fd06d2e58 100644\n--- a/t/lib-bash.sh\n+++ b/t/lib-bash.sh\n@@ -2,7 +2,9 @@\n # to run under Bash; primarily intended for tests of the completion\n # script.\n \n-if test -n \"$BASH\" && test -z \"$POSIXLY_CORRECT\"\n+. ./lib-bash-detection.sh\n+\n+if test -n \"$TEST_SH_IS_BIN_BASH\"\n then\n \t# we are in full-on bash mode\n \ttrue\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414500","messageId":"20210116153554.12604-6-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 05/11] git svn mergeinfo tests: refactor \"test -z\" to use test_must_be_empty","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:48Z","receivedAt":"2021-01-16T17:10:35Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Refactor some old-style test code to use test_must_be_empty instead of\n\"test -z\". This makes a follow-up commit easier to read.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t9151-svn-mergeinfo.sh | 31 ++++++++++++++++---------------\n 1 file changed, 16 insertions(+), 15 deletions(-)\n\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 59c5847c5f..806eff4023 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -17,41 +17,42 @@ test_expect_success 'load svn dump' \"\n \"\n \n test_expect_success 'all svn merges became git merge commits' '\n-\tunmarked=$(git rev-list --parents --all --grep=Merge |\n-\t\tgrep -v \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$unmarked\" ]\n+\tgit rev-list --parents --all --grep=Merge |\n+\t\tgrep -v \" .* \" | cut -f1 -d\" \" >unmarked &&\n+\ttest_must_be_empty unmarked\n '\n \n+\n test_expect_success 'cherry picks did not become git merge commits' '\n-\tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$bad_cherries\" ]\n+\tgit rev-list --parents --all --grep=Cherry |\n+\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-cherries &&\n+\ttest_must_be_empty bad-cherries\n '\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n-\tbad_non_merges=$(git rev-list --parents --all --grep=non-merge |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$bad_non_merges\" ]\n+\tgit rev-list --parents --all --grep=non-merge |\n+\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-non-merges &&\n+\ttest_must_be_empty bad-non-merges\n '\n \n test_expect_success 'commit made to merged branch is reachable from the merge' '\n \tbefore_commit=$(git rev-list --all --grep=\"trunk commit before merging trunk to b2\") &&\n \tmerge_commit=$(git rev-list --all --grep=\"Merge trunk to b2\") &&\n-\tnot_reachable=$(git rev-list -1 $before_commit --not $merge_commit) &&\n-\t[ -z \"$not_reachable\" ]\n+\tgit rev-list -1 $before_commit --not $merge_commit >not-reachable &&\n+\ttest_must_be_empty not-reachable\n '\n \n test_expect_success 'merging two branches in one commit is detected correctly' '\n \tf1_commit=$(git rev-list --all --grep=\"make f1 branch from trunk\") &&\n \tf2_commit=$(git rev-list --all --grep=\"make f2 branch from trunk\") &&\n \tmerge_commit=$(git rev-list --all --grep=\"Merge f1 and f2 to trunk\") &&\n-\tnot_reachable=$(git rev-list -1 $f1_commit $f2_commit --not $merge_commit) &&\n-\t[ -z \"$not_reachable\" ]\n+\tgit rev-list -1 $f1_commit $f2_commit --not $merge_commit >not-reachable &&\n+\ttest_must_be_empty not-reachable\n '\n \n test_expect_failure 'everything got merged in the end' '\n-\tunmerged=$(git rev-list --all --not master) &&\n-\t[ -z \"$unmerged\" ]\n+\tgit rev-list --all --not master >unmerged &&\n+\ttest_must_be_empty unmerged\n '\n \n test_done\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414501","messageId":"20210116153554.12604-12-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 11/11] tests: add a \"set -o pipefail\" for a patched bash","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:54Z","receivedAt":"2021-01-16T17:12:17Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Add a \"set -o pipefail\" test mode to the test suite to detect failures\nin \"git\" its output is fed directly to a pipe. Doing so is a pattern\nwe discourage[1] in the test suite, but we've got plenty of tests like\nthat. Now we can reliably detect those failures.\n\nThere was a previous attempt in [2] to add such a test mode, but as\nnoted by Jeff King in [3] adding it is a matter of peeing against the\nwind with current bash semantics of failing on SIGPIPE.\n\nThis series relies on a patch of mine to bash, which I'm submitting\nupstream, while not breaking anything for vanilla bash users. They\nwon't have GIT_TEST_PIPEFAIL turned on for them, and will only get\nbreakages if they turn it on explicitly with \"GIT_TEST_PIPEFAIL=true\".\n\nVanilla bash ignores SIGPIPE under \"set -e\" since version 3.1. It's\nonly under \"set -o pipefail\" (added in 3.2) that it doesn't take\naccount of SIGPIPE, in a seeming omission nobody bothered to fix yet.\n\nPatching bash[4] with:\n\n    diff --git a/jobs.c b/jobs.c\n    index a581f305..fa5de82a 100644\n    --- a/jobs.c\n    +++ b/jobs.c\n    @@ -2851,8 +2851,14 @@ raw_job_exit_status (job)\n           p = jobs[job]->pipe;\n           do\n     \t{\n    -\t  if (WSTATUS (p->status) != EXECUTION_SUCCESS)\n    -\t    fail = WSTATUS(p->status);\n    +\t  if (WSTATUS (p->status) != EXECUTION_SUCCESS\n    +#if defined (DONT_REPORT_SIGPIPE)\n    +              && WTERMSIG (p->status) != SIGPIPE\n    +#endif\n    +              )\n    +            {\n    +              fail = WSTATUS(p->status);\n    +            }\n     \t  p = p->next;\n     \t}\n           while (p != jobs[job]->pipe);\n\nMakes it useful for something like the git test suite.\n\nUnder this test mode we only tests we need to skip those tests which\nare explicitly testing that a piped command returned SIGPIPE. Those\ntests will now return 0 instead of an exit code indicating SIGPIPE.\n\nForcing the mode to run under vanilla bash with\n\"GIT_TEST_PIPEFAIL=true\" doesn't fail any tests for me, except the\ntest in t0000-basic.sh which explicitly checks for the desired\npipefail semantics. However, as Jeff noted in [3] that absence of\nfailure isn't reliable. I might not see some of the failures due to\nthe racy nature of how vanilla \"set -o pipefail\" interacts with *nix\npipe semantics.\n\n1. a378fee5b0 (Documentation: add shell guidelines, 2018-10-05)\n2. https://lore.kernel.org/git/cover.1573779465.git.liu.denton@gmail.com/\n3. https://lore.kernel.org/git/20191115040909.GA21654@sigill.intra.peff.net/\n4. https://github.com/bminor/bash/compare/master...avar:avar/ignore-sigterm-and-sigpipe-on-pipe-fail\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/README              |  5 +++++\n t/t0000-basic.sh      |  4 ++++\n t/t0005-signals.sh    |  4 ++--\n t/t3600-rm.sh         |  5 ++++-\n t/t5000-tar-tree.sh   |  2 +-\n t/t9902-completion.sh |  5 +++++\n t/test-lib.sh         | 29 +++++++++++++++++++++++++++++\n 7 files changed, 50 insertions(+), 4 deletions(-)\n\ndiff --git a/t/README b/t/README\nindex c730a70770..cecc00442d 100644\n--- a/t/README\n+++ b/t/README\n@@ -439,6 +439,11 @@ GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to\n use in the test scripts. Recognized values for <hash-algo> are \"sha1\"\n and \"sha256\".\n \n+GIT_TEST_PIPEFAIL=<boolean>, when true, run 'set -o pipefail' to catch\n+failures in commands that aren't the last in a pipe. Defaults to true\n+on bash versions which know how to ignore SIGPIPE failures under the\n+'set -o pipefail' mode.\n+\n Naming Tests\n ------------\n \ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex f4ba2e8c85..38e04b9ce0 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -1326,4 +1326,8 @@ test_expect_success 'test_must_fail rejects a non-git command with env' '\n \tgrep -F \"test_must_fail: only '\"'\"'git'\"'\"' is allowed\" err\n '\n \n+test_expect_success BASH_SET_O_PIPEFAIL 'our bash under \"set -o pipefail\" mode ignores SIGPIPE failures' '\n+\tyes | head -n 1 | true\n+'\n+\n test_done\ndiff --git a/t/t0005-signals.sh b/t/t0005-signals.sh\nindex 4c214bd11c..cc5784a274 100755\n--- a/t/t0005-signals.sh\n+++ b/t/t0005-signals.sh\n@@ -40,12 +40,12 @@ test_expect_success 'create blob' '\n \tgit add file\n '\n \n-test_expect_success !MINGW 'a constipated git dies with SIGPIPE' '\n+test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE' '\n \tOUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&\n \ttest_match_signal 13 \"$OUT\"\n '\n \n-test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' '\n+test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE even if parent ignores it' '\n \tOUT=$( ((trap \"\" PIPE; large_git; echo $? 1>&3) | :) 3>&1 ) &&\n \ttest_match_signal 13 \"$OUT\"\n '\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex 4f7e62d05c..7b5d92add5 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -251,7 +251,10 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n \tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n-\ttest_match_signal 13 \"$OUT\" &&\n+\tif ! test_have_prereq BASH_SET_O_PIPEFAIL\n+\tthen\n+\t\ttest_match_signal 13 \"$OUT\"\n+\tfi &&\n \ttest_path_is_missing .git/index.lock\n '\n \ndiff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh\nindex 3ebb0d3b65..3adcbce84c 100755\n--- a/t/t5000-tar-tree.sh\n+++ b/t/t5000-tar-tree.sh\n@@ -416,7 +416,7 @@ test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '\n \n # We expect git to die with SIGPIPE here (otherwise we\n # would generate the whole 64GB).\n-test_expect_success LONG_IS_64BIT 'generate tar with huge size' '\n+test_expect_success LONG_IS_64BIT,!BASH_SET_O_PIPEFAIL 'generate tar with huge size' '\n \t{\n \t\tgit archive HEAD\n \t\techo $? >exit-code\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex c4a7758409..947294bebb 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -7,6 +7,11 @@ test_description='test bash completion'\n \n . ./lib-bash.sh\n \n+if test -n \"$GIT_TEST_PIPEFAIL_TRUE\"\n+then\n+\tset +o pipefail\n+fi\n+\n complete ()\n {\n \t# do nothing\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 9fa7c1d0f6..118dc80ffc 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -36,6 +36,31 @@ then\n fi\n GIT_BUILD_DIR=\"$TEST_DIRECTORY\"/..\n \n+# Does \"set -o pipefail\" on this bash version handle SIGPIPE? Use it!\n+. \"$TEST_DIRECTORY/lib-bash-detection.sh\"\n+GIT_TEST_PIPEFAIL_TRUE=\n+GIT_TEST_PIPEFAIL_DEFAULT=false\n+if test -n \"$TEST_SH_IS_BIN_BASH\" &&\n+       $BASH -c 'set -eo pipefail; yes | head -n 1 >/dev/null'\n+then\n+\tGIT_TEST_PIPEFAIL_DEFAULT=true\n+fi\n+# We're too early for test_bool_env\n+if git env--helper --type=bool --default=\"$GIT_TEST_PIPEFAIL_DEFAULT\" \\\n+       --exit-code GIT_TEST_PIPEFAIL\n+then\n+\tset -o pipefail\n+\n+\t# Only \"set -o pipefail\" in the main test scripts, not any\n+\t# sub-programs we spawn.\n+\tGIT_TEST_PIPEFAIL=\n+\texport GIT_TEST_PIPEFAIL\n+\n+\t# For the convenience of the prereq for it.\n+\tGIT_TEST_PIPEFAIL_TRUE=true\n+\texport GIT_TEST_PIPEFAIL_TRUE\n+fi\n+\n # If we were built with ASAN, it may complain about leaks\n # of program-lifetime variables. Disable it by default to lower\n # the noise level. This needs to happen at the start of the script,\n@@ -1552,6 +1577,10 @@ test_lazy_prereq PIPE '\n \trm -f testfifo && mkfifo testfifo\n '\n \n+test_lazy_prereq BASH_SET_O_PIPEFAIL '\n+\ttest -n \"$GIT_TEST_PIPEFAIL_TRUE\"\n+'\n+\n test_lazy_prereq SYMLINKS '\n \t# test whether the filesystem supports symbolic links\n \tln -s x y && test -h y\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414502","messageId":"20210116153554.12604-3-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 02/11] cache-tree tests: use a sub-shell with less indirection","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:45Z","receivedAt":"2021-01-16T17:13:01Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change a \"cd xyz && work && cd ..\" pattern introduced in\n9c4d6c0297 (cache-tree: Write updated cache-tree after commit,\n2014-07-13) to use a sub-shell instead with less indirection.\n\nWe did actually recover correctly if we failed in this function since\nwe were wrapped in a subshell one function call up. Let's just use the\nsub-shell at the point where we want to change the directory\ninstead. This also allows us to get rid of the wrapper function.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh | 15 +++++----------\n 1 file changed, 5 insertions(+), 10 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 354b7f15f7..2e3efeb80e 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -27,20 +27,15 @@ generate_expected_cache_tree_rec () {\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n \tfor subtree in $subtrees\n \tdo\n-\t\tcd \"$subtree\"\n-\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n-\t\tcd ..\n+\t\t(\n+\t\t\tcd \"$subtree\"\n+\t\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n+\t\t)\n \tdone\n }\n \n-generate_expected_cache_tree () {\n-\t(\n-\t\tgenerate_expected_cache_tree_rec\n-\t)\n-}\n-\n test_cache_tree () {\n-\tgenerate_expected_cache_tree >expect &&\n+\tgenerate_expected_cache_tree_rec >expect &&\n \tcmp_cache_tree expect\n }\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414504","messageId":"20210116153554.12604-8-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 07/11] rm tests: actually test for SIGPIPE in SIGPIPE test","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:50Z","receivedAt":"2021-01-16T17:14:48Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change a test initially added in 50cd31c652 (t3600: comment on\ninducing SIGPIPE in `git rm`, 2019-11-27) to explicitly test for\nSIGPIPE using a pattern initially established in 7559a1be8a (unblock\nand unignore SIGPIPE, 2014-09-18).\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t3600-rm.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex efec8d13b6..4f7e62d05c 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -250,8 +250,8 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \t\techo \"100644 $hash 0\tsome-file-$i\"\n \t\ti=$(( $i + 1 ))\n \tdone | git update-index --index-info &&\n-\t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n-\tgit rm -n \"some-file-*\" | : &&\n+\tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n+\ttest_match_signal 13 \"$OUT\" &&\n \ttest_path_is_missing .git/index.lock\n '\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414505","messageId":"20210116144147.14036-1-avarab@gmail.com","threadId":"52269","inReplyTo":"YAFiFW7D1qD7ZJ8I@coredump.intra.peff.net","subject":"[PATCH] test-lib: add tests for test_might_fail","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T14:41:47Z","receivedAt":"2021-01-16T17:14:49Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"This trivial sibling command of test_must_fail added in\nfdf1bc48ca (t7006: guard cleanup with test_expect_success, 2010-04-14)\ndidn't have any tests. Let's add at least a basic one.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n\nOn Fri, Jan 15 2021, Jeff King wrote:\n\n> On Fri, Jan 15, 2021 at 12:35:10AM +0100, Ævar Arnfjörð Bjarmason wrote:\n>\n>> +test_expect_success 'test_might_fail is like test_must_fail ok=' '\n>> +    ! test_must_fail git version &&\n>> +    ! test_must_fail ok= git version &&\n>> +    test_might_fail git version\n>> +'\n>\n> The title confuses me. Isn't might_fail like \"must_fail ok=success\"?\n>\n> And certainly the code here shows us expecting the _opposite_ of what\n> \"Must_fail ok=\" does.\n\nYes, this made no sense. Here's a sensibe test.\n\nJunio: This is a stand-alone patch now. I'm splitting this off from my\nWIP v2 of the \"set -o pipefail\" series.\n\n t/t0000-basic.sh | 5 +++++\n 1 file changed, 5 insertions(+)\n\ndiff --git a/t/t0000-basic.sh b/t/t0000-basic.sh\nindex f4ba2e8c85..efaf7ec4d9 100755\n--- a/t/t0000-basic.sh\n+++ b/t/t0000-basic.sh\n@@ -1326,4 +1326,9 @@ test_expect_success 'test_must_fail rejects a non-git command with env' '\n \tgrep -F \"test_must_fail: only '\"'\"'git'\"'\"' is allowed\" err\n '\n \n+test_expect_success 'test_might_fail is like test_must_fail ok=success' '\n+\ttest_must_fail ok=success git version &&\n+\ttest_might_fail git version\n+'\n+\n test_done\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414506","messageId":"20210116153554.12604-4-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 03/11] cache-tree tests: refactor overly complex function","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:46Z","receivedAt":"2021-01-16T17:14:49Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Refactor overly complex code added in 9c4d6c0297 (cache-tree: Write\nupdated cache-tree after commit, 2014-07-13).\n\nInterestingly, in the numerous commits[1][2][3] who fixed commits bugs\nin this code since its introduction it seems not to have been noticed\nthat we didn't need to be doing some dance with grep/cut/uniq/awk to\nextract this information. It can be done in a much simpler way with\njust \"ls-tree\" and \"wc -l\".\n\nI'm also removing the comment, because I think now that this code is\ntrivial to understand it's not needed anymore.\n\n1. c8db708d5d (t0090: avoid passing empty string to printf %d,\n   2014-09-30)\n2. d69360c6b1 (t0090: tweak awk statement for Solaris\n   /usr/xpg4/bin/awk, 2014-12-22)\n3. 9b5a9fa60a (t0090: stop losing return codes of git commands,\n   2019-11-27)\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh | 16 ++++++----------\n 1 file changed, 6 insertions(+), 10 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 2e3efeb80e..f1b0a6a679 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -18,20 +18,16 @@ cmp_cache_tree () {\n # correct.\n generate_expected_cache_tree_rec () {\n \tdir=\"$1${1:+/}\" &&\n-\t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n-\t# We want to count only foo because it's the only direct child\n-\tgit ls-files >files &&\n-\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n-\tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n-\tentries=$(wc -l <files) &&\n-\tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n-\tfor subtree in $subtrees\n+\tgit ls-tree --name-only HEAD >files &&\n+\tgit ls-tree --name-only -d HEAD >subtrees &&\n+\tprintf \"SHA %s (%d entries, %d subtrees)\\n\" \"$dir\" $(wc -l <files) $(wc -l <subtrees) &&\n+\twhile read subtree\n \tdo\n \t\t(\n \t\t\tcd \"$subtree\"\n-\t\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n+\t\t\tgenerate_expected_cache_tree_rec \"$subtree\" || return 1\n \t\t)\n-\tdone\n+\tdone <subtrees\n }\n \n test_cache_tree () {\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414507","messageId":"20210116153554.12604-2-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 01/11] cache-tree tests: remove unused $2 parameter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:44Z","receivedAt":"2021-01-16T17:14:49Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Remove the $2 paramater. This appears to have been some\nwork-in-progress code from an earlier version of\n9c4d6c0297 (cache-tree: Write updated cache-tree after commit,\n2014-07-13) which was left in the final version.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh | 6 ++----\n 1 file changed, 2 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 5a633690bf..354b7f15f7 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -18,7 +18,6 @@ cmp_cache_tree () {\n # correct.\n generate_expected_cache_tree_rec () {\n \tdir=\"$1${1:+/}\" &&\n-\tparent=\"$2\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n \tgit ls-files >files &&\n@@ -29,10 +28,9 @@ generate_expected_cache_tree_rec () {\n \tfor subtree in $subtrees\n \tdo\n \t\tcd \"$subtree\"\n-\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" \"$dir\" || return 1\n+\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n \t\tcd ..\n-\tdone &&\n-\tdir=$parent\n+\tdone\n }\n \n generate_expected_cache_tree () {\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414508","messageId":"20210116153554.12604-7-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 06/11] git-svn tests: rewrite brittle tests to use \"--[no-]merges\".","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:49Z","receivedAt":"2021-01-16T17:15:39Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"From: Jeff King <peff@peff.net>\n\nRewrite a brittle tests which used \"rev-list\" without \"--[no-]merges\"\nto figure out if a set of commits turned into merge commits or not.\n\nSigned-off-by: Jeff King <peff@peff.net>\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\nCommit-message-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t9151-svn-mergeinfo.sh | 10 +++-------\n 1 file changed, 3 insertions(+), 7 deletions(-)\n\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 806eff4023..c33bae91fb 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -17,21 +17,17 @@ test_expect_success 'load svn dump' \"\n \"\n \n test_expect_success 'all svn merges became git merge commits' '\n-\tgit rev-list --parents --all --grep=Merge |\n-\t\tgrep -v \" .* \" | cut -f1 -d\" \" >unmarked &&\n+\tgit rev-list --all --no-merges --grep=Merge >unmarked &&\n \ttest_must_be_empty unmarked\n '\n \n-\n test_expect_success 'cherry picks did not become git merge commits' '\n-\tgit rev-list --parents --all --grep=Cherry |\n-\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-cherries &&\n+\tgit rev-list --all --merges --grep=Cherry >bad-cherries &&\n \ttest_must_be_empty bad-cherries\n '\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n-\tgit rev-list --parents --all --grep=non-merge |\n-\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-non-merges &&\n+\tgit rev-list --all --merges --grep=non-merge >bad-non-merges &&\n \ttest_must_be_empty bad-non-merges\n '\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414509","messageId":"20210116153554.12604-5-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 04/11] git svn mergeinfo tests: modernize redirection & quoting style","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:47Z","receivedAt":"2021-01-16T17:15:39Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Use \"<file\" instead of \"< file\", and don't put the closing quote for\nstrings on an indented line. This makes a follow-up refactoring commit\neasier to read.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t9151-svn-mergeinfo.sh | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 4f6c06ecb2..59c5847c5f 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -9,37 +9,37 @@ test_description='git-svn svn mergeinfo properties'\n \n test_expect_success 'load svn dump' \"\n \tsvnadmin load -q '$rawsvnrepo' \\\n-\t  < '$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&\n+\t  <'$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&\n \tgit svn init --minimize-url -R svnmerge \\\n \t  --rewrite-root=http://svn.example.org \\\n \t  -T trunk -b branches '$svnrepo' &&\n \tgit svn fetch --all\n-\t\"\n+\"\n \n test_expect_success 'all svn merges became git merge commits' '\n \tunmarked=$(git rev-list --parents --all --grep=Merge |\n \t\tgrep -v \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$unmarked\" ]\n-\t'\n+'\n \n test_expect_success 'cherry picks did not become git merge commits' '\n \tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n \t\tgrep \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$bad_cherries\" ]\n-\t'\n+'\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n \tbad_non_merges=$(git rev-list --parents --all --grep=non-merge |\n \t\tgrep \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$bad_non_merges\" ]\n-\t'\n+'\n \n test_expect_success 'commit made to merged branch is reachable from the merge' '\n \tbefore_commit=$(git rev-list --all --grep=\"trunk commit before merging trunk to b2\") &&\n \tmerge_commit=$(git rev-list --all --grep=\"Merge trunk to b2\") &&\n \tnot_reachable=$(git rev-list -1 $before_commit --not $merge_commit) &&\n \t[ -z \"$not_reachable\" ]\n-\t'\n+'\n \n test_expect_success 'merging two branches in one commit is detected correctly' '\n \tf1_commit=$(git rev-list --all --grep=\"make f1 branch from trunk\") &&\n@@ -47,11 +47,11 @@ test_expect_success 'merging two branches in one commit is detected correctly' '\n \tmerge_commit=$(git rev-list --all --grep=\"Merge f1 and f2 to trunk\") &&\n \tnot_reachable=$(git rev-list -1 $f1_commit $f2_commit --not $merge_commit) &&\n \t[ -z \"$not_reachable\" ]\n-\t'\n+'\n \n test_expect_failure 'everything got merged in the end' '\n \tunmerged=$(git rev-list --all --not master) &&\n \t[ -z \"$unmerged\" ]\n-\t'\n+'\n \n test_done\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414510","messageId":"20210116153554.12604-1-avarab@gmail.com","threadId":"52269","inReplyTo":"20210114233515.31298-1-avarab@gmail.com","subject":"[PATCH v2 00/11] tests: add a bash \"set -o pipefail\" test mode","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-16T15:35:43Z","receivedAt":"2021-01-16T17:15:39Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"An unstated aim of v1 of this series was to fix up the tests on\nvanilla bash's \"set -o pipefail\" enough that the test suite would have\nsome failures, but wouldn't look like a complete dumpster fire.\n\nBut this was confusing and relied on a side-quest to change the\ntest_{must,might}_fail helpers. See\nhttps://lore.kernel.org/git/YAFntgQE3NZ3yQx5@coredump.intra.peff.net/\n\nI've now ejected all of that, in favor of just fixing some of the\ntests instead as Jeff suggested. Jeff, I added your Signed-off-by to\n06/11 which you're mostly the author of. Please Ack that you're OK\nwith that (the original diff-for-discussin didn't have a SOB).\n\nJeff King (1):\n  git-svn tests: rewrite brittle tests to use \"--[no-]merges\".\n\nÆvar Arnfjörð Bjarmason (10):\n  cache-tree tests: remove unused $2 parameter\n  cache-tree tests: use a sub-shell with less indirection\n  cache-tree tests: refactor overly complex function\n  git svn mergeinfo tests: modernize redirection & quoting style\n  git svn mergeinfo tests: refactor \"test -z\" to use test_must_be_empty\n  rm tests: actually test for SIGPIPE in SIGPIPE test\n  upload-pack tests: avoid a non-zero \"grep\" exit status\n  archive tests: use a cheaper \"zipinfo -h\" invocation to get header\n  tests: split up bash detection library\n  tests: add a \"set -o pipefail\" for a patched bash\n\n t/README                           |  5 ++++\n t/lib-bash-detection.sh            |  8 ++++++\n t/lib-bash.sh                      |  4 ++-\n t/t0000-basic.sh                   |  4 +++\n t/t0005-signals.sh                 |  4 +--\n t/t0090-cache-tree.sh              | 31 +++++++--------------\n t/t3600-rm.sh                      |  7 +++--\n t/t5000-tar-tree.sh                |  2 +-\n t/t5004-archive-corner-cases.sh    |  3 ++-\n t/t5703-upload-pack-ref-in-want.sh |  6 ++++-\n t/t9151-svn-mergeinfo.sh           | 43 ++++++++++++++----------------\n t/t9902-completion.sh              |  5 ++++\n t/test-lib.sh                      | 29 ++++++++++++++++++++\n 13 files changed, 99 insertions(+), 52 deletions(-)\n create mode 100644 t/lib-bash-detection.sh\n\nRange-diff:\n 1:  d950fbb967 <  -:  ---------- test-lib: add tests for test_might_fail\n 2:  1a0ffb1159 <  -:  ---------- test-lib: add ok=* support to test_might_fail\n 3:  f7eaceeb3e <  -:  ---------- test_lib: allow test_{must,might}_fail to accept non-git on \"sigpipe\"\n 4:  0e77779947 <  -:  ---------- tests: use \"test_might_fail ok=sigpipe grep\" when appropriate\n -:  ---------- >  1:  8e8e03fa3d cache-tree tests: remove unused $2 parameter\n -:  ---------- >  2:  828d25533c cache-tree tests: use a sub-shell with less indirection\n -:  ---------- >  3:  fefdc570a5 cache-tree tests: refactor overly complex function\n -:  ---------- >  4:  a16938e58d git svn mergeinfo tests: modernize redirection & quoting style\n -:  ---------- >  5:  b520656240 git svn mergeinfo tests: refactor \"test -z\" to use test_must_be_empty\n -:  ---------- >  6:  f2e70ac911 git-svn tests: rewrite brittle tests to use \"--[no-]merges\".\n -:  ---------- >  7:  dcf001e165 rm tests: actually test for SIGPIPE in SIGPIPE test\n -:  ---------- >  8:  2212fa65eb upload-pack tests: avoid a non-zero \"grep\" exit status\n -:  ---------- >  9:  8167c2e346 archive tests: use a cheaper \"zipinfo -h\" invocation to get header\n 5:  c3916b8e7b = 10:  30c454ae7c tests: split up bash detection library\n 6:  4a988d1c73 ! 11:  6f290f850c tests: add a \"set -o pipefail\" for a patched bash\n    @@ Commit message\n         wind with current bash semantics of failing on SIGPIPE.\n     \n         This series relies on a patch of mine to bash, which I'm submitting\n    -    upstream. Vanilla bash ignores SIGPIPE under \"set -e\" since version\n    -    3.1. It's only under \"set -o pipefail\" (added in 3.2) that it doesn't\n    -    take account of SIGPIPE, in a seeming omission nobody bothered to fix\n    -    yet.\n    +    upstream, while not breaking anything for vanilla bash users. They\n    +    won't have GIT_TEST_PIPEFAIL turned on for them, and will only get\n    +    breakages if they turn it on explicitly with \"GIT_TEST_PIPEFAIL=true\".\n    +\n    +    Vanilla bash ignores SIGPIPE under \"set -e\" since version 3.1. It's\n    +    only under \"set -o pipefail\" (added in 3.2) that it doesn't take\n    +    account of SIGPIPE, in a seeming omission nobody bothered to fix yet.\n     \n         Patching bash[4] with:\n     \n    @@ Commit message\n                 }\n                    while (p != jobs[job]->pipe);\n     \n    -    Makes it useful for something like the git test suite. With vanilla\n    -    bash and GIT_TEST_PIPEFAIL=true we'll fail 4 tests in my one-off test.\n    +    Makes it useful for something like the git test suite.\n     \n    -    With my patched bash the only tests we need to skip are those that are\n    -    explicitly testing that a piped command returned SIGPIPE.\n    +    Under this test mode we only tests we need to skip those tests which\n    +    are explicitly testing that a piped command returned SIGPIPE. Those\n    +    tests will now return 0 instead of an exit code indicating SIGPIPE.\n     \n    -    As Jeff noted in [3] that count isn't reliable, as more will fail in a\n    -    way that's hard to reproduce due to the racy nature of vanilla \"set -o\n    -    pipefail\"\n    +    Forcing the mode to run under vanilla bash with\n    +    \"GIT_TEST_PIPEFAIL=true\" doesn't fail any tests for me, except the\n    +    test in t0000-basic.sh which explicitly checks for the desired\n    +    pipefail semantics. However, as Jeff noted in [3] that absence of\n    +    failure isn't reliable. I might not see some of the failures due to\n    +    the racy nature of how vanilla \"set -o pipefail\" interacts with *nix\n    +    pipe semantics.\n     \n         1. a378fee5b0 (Documentation: add shell guidelines, 2018-10-05)\n         2. https://lore.kernel.org/git/cover.1573779465.git.liu.denton@gmail.com/\n    @@ t/README: GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to\n     +GIT_TEST_PIPEFAIL=<boolean>, when true, run 'set -o pipefail' to catch\n     +failures in commands that aren't the last in a pipe. Defaults to true\n     +on bash versions which know how to ignore SIGPIPE failures under the\n    -+'set -o pipefail' mode (as of 2021-01-14 only in an out-of-tree patch\n    -+to bash).\n    ++'set -o pipefail' mode.\n     +\n      Naming Tests\n      ------------\n      \n     \n      ## t/t0000-basic.sh ##\n    -@@ t/t0000-basic.sh: test_expect_success 'test_{must,might}_fail accept non-git on \"sigpipe\"' '\n    - \ttest_cmp badobjects out\n    +@@ t/t0000-basic.sh: test_expect_success 'test_must_fail rejects a non-git command with env' '\n    + \tgrep -F \"test_must_fail: only '\"'\"'git'\"'\"' is allowed\" err\n      '\n      \n    -+test_expect_failure BASH_SET_O_PIPEFAIL 'test_{must,might}_fail ok=sigpipe under bash \"set -o pipefail\"' '\n    -+\tgrep string </dev/null | true\n    -+'\n    -+\n    -+test_expect_failure BASH_SET_O_PIPEFAIL 'test_{must,might}_fail ok=sigpipe under bash \"set -o pipefail\"' '\n    -+\ttest_must_fail grep string </dev/null | true &&\n    -+\ttest_might_fail grep string </dev/null | true\n    -+'\n    -+\n    -+test_expect_success BASH_SET_O_PIPEFAIL 'test_{must,might}_fail ok=sigpipe under bash \"set -o pipefail\"' '\n    -+\ttest_must_fail ok=sigpipe grep string </dev/null | true &&\n    -+\ttest_might_fail ok=sigpipe grep string </dev/null | true\n    ++test_expect_success BASH_SET_O_PIPEFAIL 'our bash under \"set -o pipefail\" mode ignores SIGPIPE failures' '\n    ++\tyes | head -n 1 | true\n     +'\n     +\n      test_done\n    @@ t/t0005-signals.sh: test_expect_success 'create blob' '\n      \ttest_match_signal 13 \"$OUT\"\n      '\n     \n    + ## t/t3600-rm.sh ##\n    +@@ t/t3600-rm.sh: test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n    + \t\ti=$(( $i + 1 ))\n    + \tdone | git update-index --index-info &&\n    + \tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n    +-\ttest_match_signal 13 \"$OUT\" &&\n    ++\tif ! test_have_prereq BASH_SET_O_PIPEFAIL\n    ++\tthen\n    ++\t\ttest_match_signal 13 \"$OUT\"\n    ++\tfi &&\n    + \ttest_path_is_missing .git/index.lock\n    + '\n    + \n    +\n      ## t/t5000-tar-tree.sh ##\n     @@ t/t5000-tar-tree.sh: test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '\n      \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"414526","messageId":"xmqqzh18o8o6.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210116153554.12604-9-avarab@gmail.com","subject":"Re: [PATCH v2 08/11] upload-pack tests: avoid a non-zero \"grep\" exit status","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-16T21:48:09Z","receivedAt":"2021-01-16T21:49:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Continue changing a test that 763b47bafa (t5703: stop losing return\n> codes of git commands, 2019-11-27) already refactored. A follow-up\n> commit will add support for testing under bash's \"set -o pipefail\",\n> under that mode this test will fail because sometimes there's no\n> commits in the \"objs\" output.\n>\n> It's easier to just fix this than to exempt these tests under a\n> soon-to-be added \"set -o pipefail\" test mode. So let's do that.\n\nHmph, if you do not like the fact that grep indicates hits vs no\nhits via its exit codes and you are purely interested in its text\nmunging utility, why not use a more appropriate tool than grep piped\nto cut?  Running the same grep twice just to work around its exit\ncode looks doubly suboptimal.\n\n\tsed -n -e 's/\\([0-9a-f][0-9a-f]*\\) commit .*/\\1/p' objs |\n\tsort >actual_commits\n\nperhaps?\n\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n>  t/t5703-upload-pack-ref-in-want.sh | 6 +++++-\n>  1 file changed, 5 insertions(+), 1 deletion(-)\n>\n> diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\n> index eab966985b..420cf2bbde 100755\n> --- a/t/t5703-upload-pack-ref-in-want.sh\n> +++ b/t/t5703-upload-pack-ref-in-want.sh\n> @@ -16,7 +16,11 @@ get_actual_commits () {\n>  \ttest-tool pkt-line unpack-sideband <out >o.pack &&\n>  \tgit index-pack o.pack &&\n>  \tgit verify-pack -v o.idx >objs &&\n> -\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n> +\t>actual_commits &&\n> +\tif grep -q commit objs\n> +\tthen\n> +\t\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n> +\tfi\n>  }\n>  \n>  check_output () {\n"},{"id":"414527","messageId":"xmqqturgo8js.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210116153554.12604-1-avarab@gmail.com","subject":"Re: [PATCH v2 00/11] tests: add a bash \"set -o pipefail\" test mode","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-16T21:50:47Z","receivedAt":"2021-01-16T21:51:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> An unstated aim of v1 of this series was to fix up the tests on\n> vanilla bash's \"set -o pipefail\" enough that the test suite would have\n> some failures, but wouldn't look like a complete dumpster fire.\n>\n> But this was confusing and relied on a side-quest to change the\n> test_{must,might}_fail helpers. See\n> https://lore.kernel.org/git/YAFntgQE3NZ3yQx5@coredump.intra.peff.net/\n>\n> I've now ejected all of that, in favor of just fixing some of the\n> tests instead as Jeff suggested. Jeff, I added your Signed-off-by to\n> 06/11 which you're mostly the author of. Please Ack that you're OK\n> with that (the original diff-for-discussin didn't have a SOB).\n\nI didn't read the last two pieces that are bash specific, but\neverything else was a pleasant read.  I did have a few comments,\nthough.\n\nThanks.\n"},{"id":"414528","messageId":"xmqqo8hoo8j5.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210116153554.12604-7-avarab@gmail.com","subject":"Re: [PATCH v2 06/11] git-svn tests: rewrite brittle tests to use \"--[no-]merges\".","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-16T21:51:10Z","receivedAt":"2021-01-16T21:51:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> From: Jeff King <peff@peff.net>\n>\n> Rewrite a brittle tests which used \"rev-list\" without \"--[no-]merges\"\n> to figure out if a set of commits turned into merge commits or not.\n>\n> Signed-off-by: Jeff King <peff@peff.net>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> Commit-message-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\nThe last two entries are not chronological, but when you relay a\npatch by others with tweaks, we typically do it more like this:\n\n    From: Jeff King <peff@peff.net>\n\n    Rewrite a brittle ...\n\n    Signed-off-by: Jeff King <peff@peff.net>\n    [ÆAB: wrote commit message]\n    Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\ne.g. cf. 155067ab4f, a9ecaa06a723, 567ad2c0f9\n\nThanks.\n"},{"id":"414529","messageId":"xmqqim7wo8j4.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210116153554.12604-5-avarab@gmail.com","subject":"Re: [PATCH v2 04/11] git svn mergeinfo tests: modernize redirection & quoting style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-16T21:51:11Z","receivedAt":"2021-01-16T21:52:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Use \"<file\" instead of \"< file\", and don't put the closing quote for\n> strings on an indented line. This makes a follow-up refactoring commit\n> easier to read.\n>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n>  t/t9151-svn-mergeinfo.sh | 16 ++++++++--------\n>  1 file changed, 8 insertions(+), 8 deletions(-)\n>\n> diff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\n> index 4f6c06ecb2..59c5847c5f 100755\n> --- a/t/t9151-svn-mergeinfo.sh\n> +++ b/t/t9151-svn-mergeinfo.sh\n> @@ -9,37 +9,37 @@ test_description='git-svn svn mergeinfo properties'\n>  \n>  test_expect_success 'load svn dump' \"\n>  \tsvnadmin load -q '$rawsvnrepo' \\\n> -\t  < '$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&\n> +\t  <'$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&\n\nThis is not a new issue, but if $TEST_DIRECTORY or $rawsvnrepo have\na funny character (like \"'\") in them, the above does not do the\nright thing.  Everything would work much better, if swap dq and sq\nfor the body, because these $variables _are_ visible in the body\nthat is eval'ed.\n\nBut you mentioned \"a follow-up refactoring\", so let's expect that\nthings will get better in a later step.\n\nThanks.\n"},{"id":"414530","messageId":"xmqqczy4o8j0.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210116153554.12604-4-avarab@gmail.com","subject":"Re: [PATCH v2 03/11] cache-tree tests: refactor overly complex function","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-16T21:51:15Z","receivedAt":"2021-01-16T21:52:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Refactor overly complex code added in 9c4d6c0297 (cache-tree: Write\n> updated cache-tree after commit, 2014-07-13).\n\nOK.\n\n> Interestingly, in the numerous commits[1][2][3] who fixed commits bugs\n> in this code since its introduction it seems not to have been noticed\n\nSorry but -ECANNOTPARSE.\n\n> that we didn't need to be doing some dance with grep/cut/uniq/awk to\n> extract this information. It can be done in a much simpler way with\n> just \"ls-tree\" and \"wc -l\".\n\nThe new code seems to take advantage of the fact that the index and\nHEAD are always in sync when test_cache_tree is called; it is worth\nmentioning in the log message around here.\n\n> I'm also removing the comment, because I think now that this code is\n> trivial to understand it's not needed anymore.\n\nOK.\n\nThanks.\n\n> 1. c8db708d5d (t0090: avoid passing empty string to printf %d,\n>    2014-09-30)\n> 2. d69360c6b1 (t0090: tweak awk statement for Solaris\n>    /usr/xpg4/bin/awk, 2014-12-22)\n> 3. 9b5a9fa60a (t0090: stop losing return codes of git commands,\n>    2019-11-27)\n>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> ---\n>  t/t0090-cache-tree.sh | 16 ++++++----------\n>  1 file changed, 6 insertions(+), 10 deletions(-)\n>\n> diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\n> index 2e3efeb80e..f1b0a6a679 100755\n> --- a/t/t0090-cache-tree.sh\n> +++ b/t/t0090-cache-tree.sh\n> @@ -18,20 +18,16 @@ cmp_cache_tree () {\n>  # correct.\n>  generate_expected_cache_tree_rec () {\n>  \tdir=\"$1${1:+/}\" &&\n> -\t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n> -\t# We want to count only foo because it's the only direct child\n> -\tgit ls-files >files &&\n> -\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n> -\tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n> -\tentries=$(wc -l <files) &&\n> -\tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n> -\tfor subtree in $subtrees\n> +\tgit ls-tree --name-only HEAD >files &&\n> +\tgit ls-tree --name-only -d HEAD >subtrees &&\n> +\tprintf \"SHA %s (%d entries, %d subtrees)\\n\" \"$dir\" $(wc -l <files) $(wc -l <subtrees) &&\n> +\twhile read subtree\n>  \tdo\n>  \t\t(\n>  \t\t\tcd \"$subtree\"\n> -\t\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n> +\t\t\tgenerate_expected_cache_tree_rec \"$subtree\" || return 1\n>  \t\t)\n> -\tdone\n> +\tdone <subtrees\n>  }\n>  \n>  test_cache_tree () {\n"},{"id":"414550","messageId":"YARqLXG4diPxBKC0@coredump.intra.peff.net","threadId":"52269","inReplyTo":"20210116153554.12604-7-avarab@gmail.com","subject":"Re: [PATCH v2 06/11] git-svn tests: rewrite brittle tests to use \"--[no-]merges\".","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-17T16:47:41Z","receivedAt":"2021-01-17T16:49:02Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jan 16, 2021 at 04:35:49PM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> From: Jeff King <peff@peff.net>\n> \n> Rewrite a brittle tests which used \"rev-list\" without \"--[no-]merges\"\n> to figure out if a set of commits turned into merge commits or not.\n> \n> Signed-off-by: Jeff King <peff@peff.net>\n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n> Commit-message-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\nThanks for picking this up. I think it's a cleanup worth doing.\n\nI didn't actually sign-off the original I sent, though. I'm quite happy\nto do so now, and in general everything I send to the list as a\n\"something like this\" patch will be done with the intent that it could\nbe contributed under the DCO. But I think in such a case, we should stop\nshort of forging the signoff. And ideally get an explicit signoff, or\nlacking that just add your own to assert DCO's paragraph (b).\n\nAnyway, this is most definitely:\n\n  Signed-off-by: Jeff King <peff@peff.net>\n\n-Peff\n"},{"id":"414551","messageId":"YARqdkrxJEW79PYQ@coredump.intra.peff.net","threadId":"52269","inReplyTo":"20210116144147.14036-1-avarab@gmail.com","subject":"Re: [PATCH] test-lib: add tests for test_might_fail","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-17T16:48:54Z","receivedAt":"2021-01-17T16:49:58Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jan 16, 2021 at 03:41:47PM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> > The title confuses me. Isn't might_fail like \"must_fail ok=success\"?\n> >\n> > And certainly the code here shows us expecting the _opposite_ of what\n> > \"Must_fail ok=\" does.\n> \n> Yes, this made no sense. Here's a sensibe test.\n> \n> Junio: This is a stand-alone patch now. I'm splitting this off from my\n> WIP v2 of the \"set -o pipefail\" series.\n\nOK, I'm glad I wasn't just missing something. :) This one makes sense to\nme, and seems like a reasonable thing to be checking.\n\n-Peff\n"},{"id":"414552","messageId":"YARq3v8DYEKO9zOM@coredump.intra.peff.net","threadId":"52269","inReplyTo":"20210116153554.12604-1-avarab@gmail.com","subject":"Re: [PATCH v2 00/11] tests: add a bash \"set -o pipefail\" test mode","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-17T16:50:38Z","receivedAt":"2021-01-17T16:51:45Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jan 16, 2021 at 04:35:43PM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> I've now ejected all of that, in favor of just fixing some of the\n> tests instead as Jeff suggested. Jeff, I added your Signed-off-by to\n> 06/11 which you're mostly the author of. Please Ack that you're OK\n> with that (the original diff-for-discussin didn't have a SOB).\n\nOh, I just wrote my other response before reading this (reading emails\nin order? Preposterous!). So you can soften my lecture on S-o-b while\nreading that one. :)\n\nAnd just to repeat what I said there: yes, my signoff is fine there.\n\n-Peff\n"},{"id":"414553","messageId":"YARsCsgXuiXr4uFX@coredump.intra.peff.net","threadId":"52269","inReplyTo":"20210116153554.12604-3-avarab@gmail.com","subject":"Re: [PATCH v2 02/11] cache-tree tests: use a sub-shell with less indirection","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-17T16:55:38Z","receivedAt":"2021-01-17T16:56:24Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jan 16, 2021 at 04:35:45PM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\n> index 354b7f15f7..2e3efeb80e 100755\n> --- a/t/t0090-cache-tree.sh\n> +++ b/t/t0090-cache-tree.sh\n> @@ -27,20 +27,15 @@ generate_expected_cache_tree_rec () {\n>  \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n>  \tfor subtree in $subtrees\n>  \tdo\n> -\t\tcd \"$subtree\"\n> -\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n> -\t\tcd ..\n> +\t\t(\n> +\t\t\tcd \"$subtree\"\n> +\t\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n> +\t\t)\n>  \tdone\n\nWe don't check that \"cd\" worked either before or after your patch.\nShould we?\n\nAfter your patch, we \"return\" from inside a subshell. Is that portable?\nISTR issues around that before, but it just have been when we are not in\na function at all. Still, I wonder if:\n\n  for ...\n  do\n\t(\n\t\tcd \"$subtree\" &&\n\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\"\n\t) || return 1\n  done\n\nmight be more obvious.\n\n> -generate_expected_cache_tree () {\n> -\t(\n> -\t\tgenerate_expected_cache_tree_rec\n> -\t)\n> -}\n\nI wondered what the \"rec\" was for, but I guess it is \"recurse\". Not a\nproblem to keep it, but I wonder if it could be dropped in the name of\nshortness/simplicity (not worth a re-roll for sure, but maybe worth\ndoing so if you re-roll for the above issues).\n\n-Peff\n"},{"id":"414554","messageId":"YARvAf8p+0Oj9jhF@coredump.intra.peff.net","threadId":"52269","inReplyTo":"20210116153554.12604-10-avarab@gmail.com","subject":"Re: [PATCH v2 09/11] archive tests: use a cheaper \"zipinfo -h\" invocation to get header","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-01-17T17:08:17Z","receivedAt":"2021-01-17T17:09:01Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jan 16, 2021 at 04:35:52PM +0100, Ævar Arnfjörð Bjarmason wrote:\n\n> Change an invocation of zipinfo added in 19ee29401d (t5004: test ZIP\n> archives with many entries, 2015-08-22) to simply ask zipinfo for the\n> header info, rather than spewing out info about the entire archive and\n> race to kill it with SIGPIPE due to the downstream \"head -2\".\n> \n> I ran across this because I'm adding a \"set -o pipefail\" test\n> mode. This won't be needed for the version of the mode that I'm\n> introducing (which currently relies on a patch to GNU bash), but I\n> think this is a good idea anyway.\n\nMakes sense. The only risk here would be that \"-h\" is not portable. But\nI don't have any reason to think that's the case, and since it's just a\ntest, I'm fine with proceeding and seeing if anybody screams.\n\n-Peff\n"},{"id":"414560","messageId":"CAPig+cToj8nQmyBCqC1k7DXF2vXaonCEA-fCJ4x7JBZG2ixYBw@mail.gmail.com","threadId":"52269","inReplyTo":"YARsCsgXuiXr4uFX@coredump.intra.peff.net","subject":"Re: [PATCH v2 02/11] cache-tree tests: use a sub-shell with less indirection","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-01-17T22:23:05Z","receivedAt":"2021-01-17T22:26:00Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Jan 17, 2021 at 11:55 AM Jeff King <peff@peff.net> wrote:\n> On Sat, Jan 16, 2021 at 04:35:45PM +0100, Ævar Arnfjörð Bjarmason wrote:\n> >       for subtree in $subtrees\n> >       do\n> > +             (\n> > +                     cd \"$subtree\"\n> > +                     generate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n> > +             )\n> >       done\n>\n> We don't check that \"cd\" worked either before or after your patch.\n> Should we?\n\nI'd say \"yes\".\n\n> After your patch, we \"return\" from inside a subshell. Is that portable?\n> ISTR issues around that before, but it just have been when we are not in\n> a function at all. Still, I wonder if:\n>\n>   for ...\n>   do\n>         (\n>                 cd \"$subtree\" &&\n>                 generate_expected_cache_tree_rec \"$dir$subtree\"\n>         ) || return 1\n>   done\n>\n> might be more obvious.\n\nYes, a good recommendation. Normally, we `exit 1` from within\nsubshells[1], but that wouldn't help us exit this loop early, so the\n`|| return 1` outside the subshell seems a good solution.\n\n[1]: https://lore.kernel.org/git/20150325052952.GE31924@peff.net/\n"},{"id":"414565","messageId":"xmqq7dobkueb.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"YARsCsgXuiXr4uFX@coredump.intra.peff.net","subject":"Re: [PATCH v2 02/11] cache-tree tests: use a sub-shell with less indirection","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-17T23:37:00Z","receivedAt":"2021-01-17T23:38:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Sat, Jan 16, 2021 at 04:35:45PM +0100, Ævar Arnfjörð Bjarmason wrote:\n>\n>> diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\n>> index 354b7f15f7..2e3efeb80e 100755\n>> --- a/t/t0090-cache-tree.sh\n>> +++ b/t/t0090-cache-tree.sh\n>> @@ -27,20 +27,15 @@ generate_expected_cache_tree_rec () {\n>>  \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n>>  \tfor subtree in $subtrees\n>>  \tdo\n>> -\t\tcd \"$subtree\"\n>> -\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n>> -\t\tcd ..\n>> +\t\t(\n>> +\t\t\tcd \"$subtree\"\n>> +\t\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n>> +\t\t)\n>>  \tdone\n>\n> We don't check that \"cd\" worked either before or after your patch.\n> Should we?\n>\n> After your patch, we \"return\" from inside a subshell. Is that portable?\n> ISTR issues around that before, but it just have been when we are not in\n> a function at all. Still, I wonder if:\n>\n>   for ...\n>   do\n> \t(\n> \t\tcd \"$subtree\" &&\n> \t\tgenerate_expected_cache_tree_rec \"$dir$subtree\"\n> \t) || return 1\n>   done\n\nThanks, I missed that bogus/confusing return.\n\n>\n> might be more obvious.\n>\n>> -generate_expected_cache_tree () {\n>> -\t(\n>> -\t\tgenerate_expected_cache_tree_rec\n>> -\t)\n>> -}\n>\n> I wondered what the \"rec\" was for, but I guess it is \"recurse\". Not a\n> problem to keep it, but I wonder if it could be dropped in the name of\n> shortness/simplicity (not worth a re-roll for sure, but maybe worth\n> doing so if you re-roll for the above issues).\n>\n> -Peff\n"},{"id":"414793","messageId":"20210120130447.GB8396@szeder.dev","threadId":"52269","inReplyTo":"20210116153554.12604-12-avarab@gmail.com","subject":"Re: [PATCH v2 11/11] tests: add a \"set -o pipefail\" for a patched bash","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2021-01-20T13:04:47Z","receivedAt":"2021-01-20T14:10:09Z","isPatch":true,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Sat, Jan 16, 2021 at 04:35:54PM +0100, Ævar Arnfjörð Bjarmason wrote:\n> Add a \"set -o pipefail\" test mode to the test suite to detect failures\n> in \"git\" its output is fed directly to a pipe. Doing so is a pattern\n> we discourage[1] in the test suite, but we've got plenty of tests like\n> that. Now we can reliably detect those failures.\n> \n> There was a previous attempt in [2] to add such a test mode, but as\n> noted by Jeff King in [3] adding it is a matter of peeing against the\n> wind with current bash semantics of failing on SIGPIPE.\n> \n> This series relies on a patch of mine to bash, which I'm submitting\n> upstream, while not breaking anything for vanilla bash users. They\n> won't have GIT_TEST_PIPEFAIL turned on for them, and will only get\n> breakages if they turn it on explicitly with \"GIT_TEST_PIPEFAIL=true\".\n\nI'm not sure about adding code to our test framework that only works\nwith a patched shell.\n\n> Vanilla bash ignores SIGPIPE under \"set -e\" since version 3.1. It's\n> only under \"set -o pipefail\" (added in 3.2) that it doesn't take\n> account of SIGPIPE, in a seeming omission nobody bothered to fix yet.\n> \n> Patching bash[4] with:\n> \n>     diff --git a/jobs.c b/jobs.c\n>     index a581f305..fa5de82a 100644\n>     --- a/jobs.c\n>     +++ b/jobs.c\n>     @@ -2851,8 +2851,14 @@ raw_job_exit_status (job)\n>            p = jobs[job]->pipe;\n>            do\n>      \t{\n>     -\t  if (WSTATUS (p->status) != EXECUTION_SUCCESS)\n>     -\t    fail = WSTATUS(p->status);\n>     +\t  if (WSTATUS (p->status) != EXECUTION_SUCCESS\n>     +#if defined (DONT_REPORT_SIGPIPE)\n>     +              && WTERMSIG (p->status) != SIGPIPE\n>     +#endif\n>     +              )\n>     +            {\n>     +              fail = WSTATUS(p->status);\n>     +            }\n>      \t  p = p->next;\n>      \t}\n>            while (p != jobs[job]->pipe);\n> \n> Makes it useful for something like the git test suite.\n> \n> Under this test mode we only tests we need to skip those tests which\n> are explicitly testing that a piped command returned SIGPIPE. Those\n> tests will now return 0 instead of an exit code indicating SIGPIPE.\n> \n> Forcing the mode to run under vanilla bash with\n> \"GIT_TEST_PIPEFAIL=true\" doesn't fail any tests for me, except the\n> test in t0000-basic.sh which explicitly checks for the desired\n> pipefail semantics. However, as Jeff noted in [3] that absence of\n> failure isn't reliable. I might not see some of the failures due to\n> the racy nature of how vanilla \"set -o pipefail\" interacts with *nix\n> pipe semantics.\n> \n> 1. a378fee5b0 (Documentation: add shell guidelines, 2018-10-05)\n> 2. https://lore.kernel.org/git/cover.1573779465.git.liu.denton@gmail.com/\n> 3. https://lore.kernel.org/git/20191115040909.GA21654@sigill.intra.peff.net/\n> 4. https://github.com/bminor/bash/compare/master...avar:avar/ignore-sigterm-and-sigpipe-on-pipe-fail\n> \n> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\n\n> diff --git a/t/test-lib.sh b/t/test-lib.sh\n> index 9fa7c1d0f6..118dc80ffc 100644\n> --- a/t/test-lib.sh\n> +++ b/t/test-lib.sh\n> @@ -36,6 +36,31 @@ then\n>  fi\n>  GIT_BUILD_DIR=\"$TEST_DIRECTORY\"/..\n>  \n> +# Does \"set -o pipefail\" on this bash version handle SIGPIPE? Use it!\n> +. \"$TEST_DIRECTORY/lib-bash-detection.sh\"\n> +GIT_TEST_PIPEFAIL_TRUE=\n> +GIT_TEST_PIPEFAIL_DEFAULT=false\n> +if test -n \"$TEST_SH_IS_BIN_BASH\" &&\n> +       $BASH -c 'set -eo pipefail; yes | head -n 1 >/dev/null'\n> +then\n> +\tGIT_TEST_PIPEFAIL_DEFAULT=true\n> +fi\n> +# We're too early for test_bool_env\n> +if git env--helper --type=bool --default=\"$GIT_TEST_PIPEFAIL_DEFAULT\" \\\n\nWe're too early to invoke 'git' like this, period.\n\nAt this point PATH has not yet been set up to include the 'git' binary\nwe are testing, and we can't rely on a recent enough 'git' supporting\n'env--helper' to be present in the regular PATH, or that any 'git' is\npresent in PATH at all.  And indeed we have CI jobs whose output with\nthis patch now looks like this:\n\n  *** prove ***\n  t5401-update-hooks.sh: ./test-lib.sh: line 49: git: not found\n  t9001-send-email.sh: ./test-lib.sh: line 49: git: not found\n  t5608-clone-2gb.sh: ./test-lib.sh: line 49: git: not found\n  [22:05:24] t9001-send-email.sh ................................ ok    58390 ms ( 0.06 usr  0.00 sys + 27.37 cusr  7.49 csys = 34.92 CPU)\n  t2013-checkout-submodule.sh: ./test-lib.sh: line 49: git: not found\n  [22:05:34] t2013-checkout-submodule.sh ........................ ok     9412 ms ( 0.03 usr  0.01 sys +  5.68 cusr  3.00 csys =  8.72 CPU)\n  t0027-auto-crlf.sh: ./test-lib.sh: line 49: git: not found\n\n> +       --exit-code GIT_TEST_PIPEFAIL\n> +then\n> +\tset -o pipefail\n> +\n> +\t# Only \"set -o pipefail\" in the main test scripts, not any\n> +\t# sub-programs we spawn.\n> +\tGIT_TEST_PIPEFAIL=\n> +\texport GIT_TEST_PIPEFAIL\n> +\n> +\t# For the convenience of the prereq for it.\n> +\tGIT_TEST_PIPEFAIL_TRUE=true\n> +\texport GIT_TEST_PIPEFAIL_TRUE\n> +fi\n> +\n>  # If we were built with ASAN, it may complain about leaks\n>  # of program-lifetime variables. Disable it by default to lower\n>  # the noise level. This needs to happen at the start of the script,\n> @@ -1552,6 +1577,10 @@ test_lazy_prereq PIPE '\n>  \trm -f testfifo && mkfifo testfifo\n>  '\n>  \n> +test_lazy_prereq BASH_SET_O_PIPEFAIL '\n> +\ttest -n \"$GIT_TEST_PIPEFAIL_TRUE\"\n> +'\n> +\n>  test_lazy_prereq SYMLINKS '\n>  \t# test whether the filesystem supports symbolic links\n>  \tln -s x y && test -h y\n> -- \n> 2.29.2.222.g5d2a92d10f8\n> \n"},{"id":"415032","messageId":"xmqq5z3o5n8c.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210116153554.12604-12-avarab@gmail.com","subject":"Re: [PATCH v2 11/11] tests: add a \"set -o pipefail\" for a patched bash","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-23T03:46:43Z","receivedAt":"2021-01-23T03:48:07Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> -test_expect_success !MINGW 'a constipated git dies with SIGPIPE' '\n> +test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE' '\n>  \tOUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&\n>  \ttest_match_signal 13 \"$OUT\"\n>  '\n>  \n> -test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' '\n> +test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE even if parent ignores it' '\n>  \tOUT=$( ((trap \"\" PIPE; large_git; echo $? 1>&3) | :) 3>&1 ) &&\n>  \ttest_match_signal 13 \"$OUT\"\n>  '\n\nThe above have already !MINGW\n\n> diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\n> index 4f7e62d05c..7b5d92add5 100755\n> --- a/t/t3600-rm.sh\n> +++ b/t/t3600-rm.sh\n> @@ -251,7 +251,10 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n>  \t\ti=$(( $i + 1 ))\n>  \tdone | git update-index --index-info &&\n>  \tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n> -\ttest_match_signal 13 \"$OUT\" &&\n> +\tif ! test_have_prereq BASH_SET_O_PIPEFAIL\n> +\tthen\n> +\t\ttest_match_signal 13 \"$OUT\"\n> +\tfi &&\n>  \ttest_path_is_missing .git/index.lock\n>  '\n\nbut this one does not.  Yet, we've been using test_match_signal on 13\nwithout issues, it appears.\n\nAnd somehow with the lazy prereq on SET_O_PIPEFAIL, this part starts\nto break, like so:\n\n  https://github.com/git/git/runs/1752687552?check_suite_focus=true#step:7:37042\n\nThe output captured in OUT is 0 as we can see on #37032 in the test\nlog.\n\nI am tempted to eject 11/11 and probably 10/11 out of the topic, as\nthe earlier patches before them look more or less uncontroversial\ncleanups, and 11/11 seems to be more trouble than it is worth at\nthis moment.\n\nIt's not like this would allow us to loosen the rule that we\nshouldn't put a \"git\" invocation of the git subcommand being tested\non the upstream side of a pipe---not everybody is running bash, and\nit is unrealistic to tell our developers \"if you want to make sure\nyour tests are good, you must install and use this patched bash\".\n\nThanks.\n"},{"id":"415036","messageId":"xmqq1rec5ckf.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"xmqq5z3o5n8c.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v2 11/11] tests: add a \"set -o pipefail\" for a patched bash","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-23T07:37:04Z","receivedAt":"2021-01-23T07:38:11Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> ...\n> The above have already !MINGW\n>\n>> diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\n>> index 4f7e62d05c..7b5d92add5 100755\n>> --- a/t/t3600-rm.sh\n>> +++ b/t/t3600-rm.sh\n>> @@ -251,7 +251,10 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n>>  \t\ti=$(( $i + 1 ))\n>>  \tdone | git update-index --index-info &&\n>>  \tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n>> -\ttest_match_signal 13 \"$OUT\" &&\n>> +\tif ! test_have_prereq BASH_SET_O_PIPEFAIL\n>> +\tthen\n>> +\t\ttest_match_signal 13 \"$OUT\"\n>> +\tfi &&\n>>  \ttest_path_is_missing .git/index.lock\n>>  '\n>\n> but this one does not.  Yet, we've been using test_match_signal on 13\n> without issues, it appears.\n>\n> And somehow with the lazy prereq on SET_O_PIPEFAIL, this part starts\n> to break, like so:\n>\n>   https://github.com/git/git/runs/1752687552?check_suite_focus=true#step:7:37042\n>\n> The output captured in OUT is 0 as we can see on #37032 in the test\n> log.\n\nNah, it seems that t3600-rm's \"match signal 13\" is already broken\nwithout O_PIPEFAIL patch on Windows.  For example:\n\nhttps://github.com/git/git/runs/1753231308?check_suite_focus=true#step:7:36912\n\nThis was introduced by c15ffae5 (rm tests: actually test for SIGPIPE\nin SIGPIPE test, 2021-01-16) in the same series.\n\nI am not sure \"actually testing for SIGPIPE\" is more important than\n\"make sure 'git rm' choked should not die with cruft\", so without\nthinking too deeply about the issue, my gut reaction is that\nreverting is better than using !MINGW as other tests.  That is, no\nmatter how \"git rm\" gets killed, it should not leave .git/index.lock\nbehind, and the original already tests that.  The patch tried to\nmake sure it dies with signal #13 (and fails the test on Windows)\nbefore it even looks at the leftover index.lock file, which feels a\nbit backwards.\n\n\n"},{"id":"415039","messageId":"87sg6s6lrs.fsf@evledraar.gmail.com","threadId":"52269","inReplyTo":"xmqq1rec5ckf.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v2 11/11] tests: add a \"set -o pipefail\" for a patched bash","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T09:32:55Z","receivedAt":"2021-01-23T09:34:02Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Sat, Jan 23 2021, Junio C Hamano wrote:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> ...\n>> The above have already !MINGW\n>>\n>>> diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\n>>> index 4f7e62d05c..7b5d92add5 100755\n>>> --- a/t/t3600-rm.sh\n>>> +++ b/t/t3600-rm.sh\n>>> @@ -251,7 +251,10 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n>>>  \t\ti=$(( $i + 1 ))\n>>>  \tdone | git update-index --index-info &&\n>>>  \tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n>>> -\ttest_match_signal 13 \"$OUT\" &&\n>>> +\tif ! test_have_prereq BASH_SET_O_PIPEFAIL\n>>> +\tthen\n>>> +\t\ttest_match_signal 13 \"$OUT\"\n>>> +\tfi &&\n>>>  \ttest_path_is_missing .git/index.lock\n>>>  '\n>>\n>> but this one does not.  Yet, we've been using test_match_signal on 13\n>> without issues, it appears.\n>>\n>> And somehow with the lazy prereq on SET_O_PIPEFAIL, this part starts\n>> to break, like so:\n>>\n>>   https://github.com/git/git/runs/1752687552?check_suite_focus=true#step:7:37042\n>>\n>> The output captured in OUT is 0 as we can see on #37032 in the test\n>> log.\n>\n> Nah, it seems that t3600-rm's \"match signal 13\" is already broken\n> without O_PIPEFAIL patch on Windows.  For example:\n>\n> https://github.com/git/git/runs/1753231308?check_suite_focus=true#step:7:36912\n>\n> This was introduced by c15ffae5 (rm tests: actually test for SIGPIPE\n> in SIGPIPE test, 2021-01-16) in the same series.\n\nYes, not adding !MINGW here is a stupid oversight on my part, I can\nre-roll with that added, which seems to be like it'll work & be\nbetter. I.e. we'll actually test for SIGPIPE ...(read on)....\n\n> I am not sure \"actually testing for SIGPIPE\" is more important than\n> \"make sure 'git rm' choked should not die with cruft\", so without\n> thinking too deeply about the issue, my gut reaction is that\n> reverting is better than using !MINGW as other tests.  That is, no\n> matter how \"git rm\" gets killed, it should not leave .git/index.lock\n> behind, and the original already tests that.\n\nI don't get it. I understand why we'd do any of:\n\n 1. Keep my patch with !MINGW added. I.e. the intent of your 0693f9ddad\n    (Make sure lockfiles are unlocked when dying on SIGPIPE, 2008-12-18)\n    which added the test is to explicitly stress SIGPIPE, but we never\n    actually checked it explicitly...\n\n 2. Just remove/rewrite that part of the test. We have 7559a1be8a\n    (unblock and unignore SIGPIPE, 2014-09-18) (the other test whose\n    pattern I copied) now.\n\n    That along with 12e0437f23 (common-main: call\n    restore_sigpipe_to_default(), 2016-07-01) means we do this\n    everywhere, so why test \"git rm\" in particular in this one place but\n    not other git commands?\n\n 3. Remove the overly specific PIPE test added in 7559a1be8a in favor of\n    this \"git rm\" test. After all if we want to test the SIGPIPE pattern\n    but sometimes we get SIGPIPE, sometimes we don't (MINGW), but we\n    don't really care because we assume on some platforms it's being\n    tested.\n\nBut not why we'd keep the test as-is now that we've dug up this old code\nand found that since it got added we have a reliable way to test for\nactually-sigpipe.\n\nJust to maintain the coverage on MINGW? Wouldn't it be better to have\ntwo tests then, one without the prereq to run everywhere, and another\nidentical one with the \"trap\" on !MINGW?\n\nI don't really care and can re-roll in whatever way you prefer, I just\ndon't understand what I'd put as a reason in the commit message(s),\ndepending on which route we go...\n"},{"id":"415040","messageId":"87pn1w6lez.fsf@evledraar.gmail.com","threadId":"52269","inReplyTo":"xmqq5z3o5n8c.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v2 11/11] tests: add a \"set -o pipefail\" for a patched bash","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T09:40:36Z","receivedAt":"2021-01-23T09:41:57Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Sat, Jan 23 2021, Junio C Hamano wrote:\n\n> Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n>\n>> -test_expect_success !MINGW 'a constipated git dies with SIGPIPE' '\n>> +test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE' '\n>>  \tOUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) &&\n>>  \ttest_match_signal 13 \"$OUT\"\n>>  '\n>>  \n>> -test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' '\n>> +test_expect_success !MINGW,!BASH_SET_O_PIPEFAIL 'a constipated git dies with SIGPIPE even if parent ignores it' '\n>>  \tOUT=$( ((trap \"\" PIPE; large_git; echo $? 1>&3) | :) 3>&1 ) &&\n>>  \ttest_match_signal 13 \"$OUT\"\n>>  '\n>\n> The above have already !MINGW\n>\n>> diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\n>> index 4f7e62d05c..7b5d92add5 100755\n>> --- a/t/t3600-rm.sh\n>> +++ b/t/t3600-rm.sh\n>> @@ -251,7 +251,10 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n>>  \t\ti=$(( $i + 1 ))\n>>  \tdone | git update-index --index-info &&\n>>  \tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n>> -\ttest_match_signal 13 \"$OUT\" &&\n>> +\tif ! test_have_prereq BASH_SET_O_PIPEFAIL\n>> +\tthen\n>> +\t\ttest_match_signal 13 \"$OUT\"\n>> +\tfi &&\n>>  \ttest_path_is_missing .git/index.lock\n>>  '\n>\n> but this one does not.  Yet, we've been using test_match_signal on 13\n> without issues, it appears.\n>\n> And somehow with the lazy prereq on SET_O_PIPEFAIL, this part starts\n> to break, like so:\n>\n>   https://github.com/git/git/runs/1752687552?check_suite_focus=true#step:7:37042\n>\n> The output captured in OUT is 0 as we can see on #37032 in the test\n> log.\n>\n> I am tempted to eject 11/11 and probably 10/11 out of the topic, as\n> the earlier patches before them look more or less uncontroversial\n> cleanups, and 11/11 seems to be more trouble than it is worth at\n> this moment.\n\nI think that makes sense, once I fix the breakage on 07/11 you noted\ndownthread.\n\n> It's not like this would allow us to loosen the rule that we\n> shouldn't put a \"git\" invocation of the git subcommand being tested\n> on the upstream side of a pipe[...]\n\nFWIW it seems from my off-list discussion with the bash maintainer that\nno version of my patch is likely to make it into bash. He views it as a\nfeature that \"pipefail\" treats all non-zero exit codes equally.\n\nBut as it pertains to our test suite I mainly wrote this to check if we\nhad any failures that didn't make sense once SIGPIPE was ignored. I\nthink smoking out any potential historical cases (and finding we didn't\nhave any that mattered) was probably an effort worth it in itself. Then\nwe just have to continue not putting git on the LHS on a pipe for new\ntests.\n\n> [...]---not everybody is running bash, and it is unrealistic to tell\n> our developers \"if you want to make sure your tests are good, you must\n> install and use this patched bash\".\n\nI think if others think this was worth keeping and bash never accepted\nthe patches we could rather easily get most of the benefit from it by\nhaving a CI job that ran with such a patched bash. To test with \"set -o\npipefail\" it's enough that it's done semi-regularly by someone if you\nwant to smoke out bugs in the tests, not everyone has to do it all the\ntime.\n\n"},{"id":"415048","messageId":"20210123130046.21975-2-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 01/10] cache-tree tests: refactor for modern test style","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:37Z","receivedAt":"2021-01-23T13:02:11Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Refactor the cache-tree test file to use our current recommended\npatterns. This makes a subsequent meaningful change easier to read.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh | 28 ++++++++++++++--------------\n 1 file changed, 14 insertions(+), 14 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 5a633690bf..45e1cc82ed 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -10,7 +10,8 @@ cache-tree extension.\n cmp_cache_tree () {\n \ttest-tool dump-cache-tree | sed -e '/#(ref)/d' >actual &&\n \tsed \"s/$OID_REGEX/SHA/\" <actual >filtered &&\n-\ttest_cmp \"$1\" filtered\n+\ttest_cmp \"$1\" filtered &&\n+\trm filtered\n }\n \n # We don't bother with actually checking the SHA1:\n@@ -54,7 +55,7 @@ test_invalid_cache_tree () {\n }\n \n test_no_cache_tree () {\n-\t: >expect &&\n+\t>expect &&\n \tcmp_cache_tree expect\n }\n \n@@ -83,18 +84,6 @@ test_expect_success 'git-add in subdir invalidates cache-tree' '\n \ttest_invalid_cache_tree\n '\n \n-cat >before <<\\EOF\n-SHA  (3 entries, 2 subtrees)\n-SHA dir1/ (1 entries, 0 subtrees)\n-SHA dir2/ (1 entries, 0 subtrees)\n-EOF\n-\n-cat >expect <<\\EOF\n-invalid                                   (2 subtrees)\n-invalid                                  dir1/ (0 subtrees)\n-SHA dir2/ (1 entries, 0 subtrees)\n-EOF\n-\n test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '\n \tgit tag no-children &&\n \ttest_when_finished \"git reset --hard no-children; git read-tree HEAD\" &&\n@@ -102,9 +91,20 @@ test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '\n \ttest_commit dir1/a &&\n \ttest_commit dir2/b &&\n \techo \"I changed this file\" >dir1/a &&\n+\ttest_when_finished \"rm before\" &&\n+\tcat >before <<-\\EOF &&\n+\tSHA  (3 entries, 2 subtrees)\n+\tSHA dir1/ (1 entries, 0 subtrees)\n+\tSHA dir2/ (1 entries, 0 subtrees)\n+\tEOF\n \tcmp_cache_tree before &&\n \techo \"I changed this file\" >dir1/a &&\n \tgit add dir1/a &&\n+\tcat >expect <<-\\EOF &&\n+\tinvalid                                   (2 subtrees)\n+\tinvalid                                  dir1/ (0 subtrees)\n+\tSHA dir2/ (1 entries, 0 subtrees)\n+\tEOF\n \tcmp_cache_tree expect\n '\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415049","messageId":"20210123130046.21975-1-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 00/10] Miscellaneous \"set -o pipefail\"-related test cleanups","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:36Z","receivedAt":"2021-01-23T13:02:11Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"This started as an attempt to add a bash \"set -o pipefail\" test mode,\nbut now comes without that. Junio suggested dropping it in\n<xmqq5z3o5n8c.fsf@gitster.c.googlers.com>.\n\nThe \"cache-tree tests\" part is mostly rewritten. I'd removed the index\ndependency of the tests, but the point of the tests is to test the\nindex. Now we do that again in a more readable way.\n\nThe \"git rm\" test at the end fixes the current CI failure in this\ntopic, and does some version of what I suggested in\n<87sg6s6lrs.fsf@evledraar.gmail.com>. Junio, I think that makes sense\nas a fix while we're at it, but if you don't like it just drop it.\n\nJeff King (1):\n  git-svn tests: rewrite brittle tests to use \"--[no-]merges\".\n\nÆvar Arnfjörð Bjarmason (9):\n  cache-tree tests: refactor for modern test style\n  cache-tree tests: remove unused $2 parameter\n  cache-tree tests: use a sub-shell with less indirection\n  cache-tree tests: explicitly test HEAD and index differences\n  git svn mergeinfo tests: modernize redirection & quoting style\n  git svn mergeinfo tests: refactor \"test -z\" to use test_must_be_empty\n  upload-pack tests: avoid a non-zero \"grep\" exit status\n  archive tests: use a cheaper \"zipinfo -h\" invocation to get header\n  rm tests: actually test for SIGPIPE in SIGPIPE test\n\n t/t0090-cache-tree.sh              | 82 +++++++++++++++---------------\n t/t3600-rm.sh                      | 16 +++++-\n t/t5004-archive-corner-cases.sh    |  3 +-\n t/t5703-upload-pack-ref-in-want.sh |  3 +-\n t/t9151-svn-mergeinfo.sh           | 43 ++++++++--------\n 5 files changed, 80 insertions(+), 67 deletions(-)\n\nRange-diff:\n -:  ---------- >  1:  b30499c4e4 cache-tree tests: refactor for modern test style\n 1:  8e8e03fa3d =  2:  af0b25a048 cache-tree tests: remove unused $2 parameter\n 2:  828d25533c !  3:  09959568de cache-tree tests: use a sub-shell with less indirection\n    @@ Commit message\n         We did actually recover correctly if we failed in this function since\n         we were wrapped in a subshell one function call up. Let's just use the\n         sub-shell at the point where we want to change the directory\n    -    instead. This also allows us to get rid of the wrapper function.\n    +    instead.\n    +\n    +    It's important that the \"|| return 1\" is outside the\n    +    subshell. Normally, we `exit 1` from within subshells[1], but that\n    +    wouldn't help us exit this loop early[1][2].\n    +\n    +    Since we can get rid of the wrapper function let's rename the main\n    +    function to drop the \"rec\" (for \"recursion\") suffix[3].\n    +\n    +    1. https://lore.kernel.org/git/CAPig+cToj8nQmyBCqC1k7DXF2vXaonCEA-fCJ4x7JBZG2ixYBw@mail.gmail.com/\n    +    2. https://lore.kernel.org/git/20150325052952.GE31924@peff.net/\n    +    3. https://lore.kernel.org/git/YARsCsgXuiXr4uFX@coredump.intra.peff.net/\n     \n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n      ## t/t0090-cache-tree.sh ##\n    +@@ t/t0090-cache-tree.sh: cmp_cache_tree () {\n    + # We don't bother with actually checking the SHA1:\n    + # test-tool dump-cache-tree already verifies that all existing data is\n    + # correct.\n    +-generate_expected_cache_tree_rec () {\n    ++generate_expected_cache_tree () {\n    + \tdir=\"$1${1:+/}\" &&\n    + \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n    + \t# We want to count only foo because it's the only direct child\n     @@ t/t0090-cache-tree.sh: generate_expected_cache_tree_rec () {\n      \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n      \tfor subtree in $subtrees\n    @@ t/t0090-cache-tree.sh: generate_expected_cache_tree_rec () {\n     -\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n     -\t\tcd ..\n     +\t\t(\n    -+\t\t\tcd \"$subtree\"\n    -+\t\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n    -+\t\t)\n    ++\t\t\tcd \"$subtree\" &&\n    ++\t\t\tgenerate_expected_cache_tree \"$dir$subtree\"\n    ++\t\t) || return 1\n      \tdone\n      }\n      \n    @@ t/t0090-cache-tree.sh: generate_expected_cache_tree_rec () {\n     -}\n     -\n      test_cache_tree () {\n    --\tgenerate_expected_cache_tree >expect &&\n    -+\tgenerate_expected_cache_tree_rec >expect &&\n    + \tgenerate_expected_cache_tree >expect &&\n      \tcmp_cache_tree expect\n    - }\n    - \n 3:  fefdc570a5 !  4:  697b0084fd cache-tree tests: refactor overly complex function\n    @@ Metadata\n     Author: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n      ## Commit message ##\n    -    cache-tree tests: refactor overly complex function\n    +    cache-tree tests: explicitly test HEAD and index differences\n     \n    -    Refactor overly complex code added in 9c4d6c0297 (cache-tree: Write\n    -    updated cache-tree after commit, 2014-07-13).\n    +    The test code added in 9c4d6c0297 (cache-tree: Write updated\n    +    cache-tree after commit, 2014-07-13) used \"ls-files\" in lieu of\n    +    \"ls-tree\" because it wanted to test the data in the index, since this\n    +    test is testing the cache-tree extension.\n     \n    -    Interestingly, in the numerous commits[1][2][3] who fixed commits bugs\n    -    in this code since its introduction it seems not to have been noticed\n    -    that we didn't need to be doing some dance with grep/cut/uniq/awk to\n    -    extract this information. It can be done in a much simpler way with\n    -    just \"ls-tree\" and \"wc -l\".\n    +    Change the test to instead use \"ls-tree\" for traversal, and then\n    +    explicitly check how HEAD differs from the index. This is more easily\n    +    understood, and less fragile as numerous past bug fixes[1][2][3] to\n    +    the old code we're replacing demonstrate.\n     \n    -    I'm also removing the comment, because I think now that this code is\n    -    trivial to understand it's not needed anymore.\n    +    As an aside this would be a bit easier if empty pathspecs hadn't been\n    +    made an error in d426430e6e (pathspec: warn on empty strings as\n    +    pathspec, 2016-06-22) and 9e4e8a64c2 (pathspec: die on empty strings\n    +    as pathspec, 2017-06-06).\n    +\n    +    If that was still allowed this code could be simplified slightly:\n    +\n    +            diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\n    +            index 9bf66c9e68..0b02881f55 100755\n    +            --- a/t/t0090-cache-tree.sh\n    +            +++ b/t/t0090-cache-tree.sh\n    +            @@ -18,19 +18,18 @@ cmp_cache_tree () {\n    +             # test-tool dump-cache-tree already verifies that all existing data is\n    +             # correct.\n    +             generate_expected_cache_tree () {\n    +            -       pathspec=\"$1\" &&\n    +            -       dir=\"$2${2:+/}\" &&\n    +            +       pathspec=\"$1${1:+/}\" &&\n    +                    git ls-tree --name-only HEAD -- \"$pathspec\" >files &&\n    +                    git ls-tree --name-only -d HEAD -- \"$pathspec\" >subtrees &&\n    +            -       printf \"SHA %s (%d entries, %d subtrees)\\n\" \"$dir\" $(wc -l <files) $(wc -l <subtrees) &&\n    +            +       printf \"SHA %s (%d entries, %d subtrees)\\n\" \"$pathspec\" $(wc -l <files) $(wc -l <subtrees) &&\n    +                    while read subtree\n    +                    do\n    +            -               generate_expected_cache_tree \"$pathspec/$subtree/\" \"$subtree\" || return 1\n    +            +               generate_expected_cache_tree \"$subtree\" || return 1\n    +                    done <subtrees\n    +             }\n    +\n    +             test_cache_tree () {\n    +            -       generate_expected_cache_tree \".\" >expect &&\n    +            +       generate_expected_cache_tree >expect &&\n    +                    cmp_cache_tree expect &&\n    +                    rm expect actual files subtrees &&\n    +                    git status --porcelain -- ':!status' ':!expected.status' >status &&\n     \n         1. c8db708d5d (t0090: avoid passing empty string to printf %d,\n            2014-09-30)\n    @@ Commit message\n     \n      ## t/t0090-cache-tree.sh ##\n     @@ t/t0090-cache-tree.sh: cmp_cache_tree () {\n    + # test-tool dump-cache-tree already verifies that all existing data is\n      # correct.\n    - generate_expected_cache_tree_rec () {\n    - \tdir=\"$1${1:+/}\" &&\n    + generate_expected_cache_tree () {\n    +-\tdir=\"$1${1:+/}\" &&\n     -\t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n     -\t# We want to count only foo because it's the only direct child\n     -\tgit ls-files >files &&\n    @@ t/t0090-cache-tree.sh: cmp_cache_tree () {\n     -\tentries=$(wc -l <files) &&\n     -\tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n     -\tfor subtree in $subtrees\n    -+\tgit ls-tree --name-only HEAD >files &&\n    -+\tgit ls-tree --name-only -d HEAD >subtrees &&\n    ++\tpathspec=\"$1\" &&\n    ++\tdir=\"$2${2:+/}\" &&\n    ++\tgit ls-tree --name-only HEAD -- \"$pathspec\" >files &&\n    ++\tgit ls-tree --name-only -d HEAD -- \"$pathspec\" >subtrees &&\n     +\tprintf \"SHA %s (%d entries, %d subtrees)\\n\" \"$dir\" $(wc -l <files) $(wc -l <subtrees) &&\n     +\twhile read subtree\n      \tdo\n    - \t\t(\n    - \t\t\tcd \"$subtree\"\n    --\t\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n    -+\t\t\tgenerate_expected_cache_tree_rec \"$subtree\" || return 1\n    - \t\t)\n    +-\t\t(\n    +-\t\t\tcd \"$subtree\" &&\n    +-\t\t\tgenerate_expected_cache_tree \"$dir$subtree\"\n    +-\t\t) || return 1\n     -\tdone\n    ++\t\tgenerate_expected_cache_tree \"$pathspec/$subtree/\" \"$subtree\" || return 1\n     +\tdone <subtrees\n      }\n      \n      test_cache_tree () {\n    +-\tgenerate_expected_cache_tree >expect &&\n    +-\tcmp_cache_tree expect\n    ++\tgenerate_expected_cache_tree \".\" >expect &&\n    ++\tcmp_cache_tree expect &&\n    ++\trm expect actual files subtrees &&\n    ++\tgit status --porcelain -- ':!status' ':!expected.status' >status &&\n    ++\tif test -n \"$1\"\n    ++\tthen\n    ++\t\ttest_cmp \"$1\" status\n    ++\telse\n    ++\t\ttest_must_be_empty status\n    ++\tfi\n    + }\n    + \n    + test_invalid_cache_tree () {\n    +@@ t/t0090-cache-tree.sh: test_expect_success 'second commit has cache-tree' '\n    + '\n    + \n    + test_expect_success PERL 'commit --interactive gives cache-tree on partial commit' '\n    ++\ttest_when_finished \"git reset --hard\" &&\n    + \tcat <<-\\EOT >foo.c &&\n    + \tint foo()\n    + \t{\n    +@@ t/t0090-cache-tree.sh: test_expect_success PERL 'commit --interactive gives cache-tree on partial commi\n    + \tEOT\n    + \ttest_write_lines p 1 \"\" s n y q |\n    + \tgit commit --interactive -m foo &&\n    +-\ttest_cache_tree\n    ++\tcat <<-\\EOF >expected.status &&\n    ++\t M foo.c\n    ++\tEOF\n    ++\ttest_cache_tree expected.status\n    + '\n    + \n    + test_expect_success PERL 'commit -p with shrinking cache-tree' '\n    +@@ t/t0090-cache-tree.sh: test_expect_success 'partial commit gives cache-tree' '\n    + \tgit add one.t &&\n    + \techo \"some other change\" >two.t &&\n    + \tgit commit two.t -m partial &&\n    +-\ttest_cache_tree\n    ++\tcat <<-\\EOF >expected.status &&\n    ++\tM  one.t\n    ++\tEOF\n    ++\ttest_cache_tree expected.status\n    + '\n    + \n    + test_expect_success 'no phantom error when switching trees' '\n 4:  a16938e58d =  5:  5ede74a1ab git svn mergeinfo tests: modernize redirection & quoting style\n 5:  b520656240 =  6:  c287f5a24a git svn mergeinfo tests: refactor \"test -z\" to use test_must_be_empty\n 6:  f2e70ac911 !  7:  9bd6ad6e25 git-svn tests: rewrite brittle tests to use \"--[no-]merges\".\n    @@ Commit message\n         to figure out if a set of commits turned into merge commits or not.\n     \n         Signed-off-by: Jeff King <peff@peff.net>\n    +    [ÆAB: wrote commit message]\n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n    -    Commit-message-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n      ## t/t9151-svn-mergeinfo.sh ##\n     @@ t/t9151-svn-mergeinfo.sh: test_expect_success 'load svn dump' \"\n 7:  dcf001e165 <  -:  ---------- rm tests: actually test for SIGPIPE in SIGPIPE test\n 8:  2212fa65eb !  8:  fd40e818a7 upload-pack tests: avoid a non-zero \"grep\" exit status\n    @@ Commit message\n         upload-pack tests: avoid a non-zero \"grep\" exit status\n     \n         Continue changing a test that 763b47bafa (t5703: stop losing return\n    -    codes of git commands, 2019-11-27) already refactored. A follow-up\n    -    commit will add support for testing under bash's \"set -o pipefail\",\n    -    under that mode this test will fail because sometimes there's no\n    -    commits in the \"objs\" output.\n    +    codes of git commands, 2019-11-27) already refactored.\n     \n    -    It's easier to just fix this than to exempt these tests under a\n    -    soon-to-be added \"set -o pipefail\" test mode. So let's do that.\n    +    This was originally added as part of a series to add support for\n    +    running under bash's \"set -o pipefail\", under that mode this test will\n    +    fail because sometimes there's no commits in the \"objs\" output.\n    +\n    +    It's easier to fix that than exempt these tests under a hypothetical\n    +    \"set -o pipefail\" test mode. It looks like we probably won't have\n    +    that, but once we've dug this code up let's refactor it[2] so we don't\n    +    hide a potential pipe failure.\n    +\n    +    1. https://lore.kernel.org/git/xmqqzh18o8o6.fsf@gitster.c.googlers.com/\n     \n         Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n     \n    @@ t/t5703-upload-pack-ref-in-want.sh: get_actual_commits () {\n      \tgit index-pack o.pack &&\n      \tgit verify-pack -v o.idx >objs &&\n     -\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n    -+\t>actual_commits &&\n    -+\tif grep -q commit objs\n    -+\tthen\n    -+\t\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n    -+\tfi\n    ++\tsed -n -e 's/\\([0-9a-f][0-9a-f]*\\) commit .*/\\1/p' objs >objs.sed &&\n    ++\tsort >actual_commits <objs.sed\n      }\n      \n      check_output () {\n 9:  8167c2e346 =  9:  5405062665 archive tests: use a cheaper \"zipinfo -h\" invocation to get header\n10:  30c454ae7c <  -:  ---------- tests: split up bash detection library\n11:  6f290f850c <  -:  ---------- tests: add a \"set -o pipefail\" for a patched bash\n -:  ---------- > 10:  b526b3cb24 rm tests: actually test for SIGPIPE in SIGPIPE test\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415050","messageId":"20210123130046.21975-3-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 02/10] cache-tree tests: remove unused $2 parameter","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:38Z","receivedAt":"2021-01-23T13:02:12Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Remove the $2 paramater. This appears to have been some\nwork-in-progress code from an earlier version of\n9c4d6c0297 (cache-tree: Write updated cache-tree after commit,\n2014-07-13) which was left in the final version.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh | 6 ++----\n 1 file changed, 2 insertions(+), 4 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 45e1cc82ed..7ff7f04719 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -19,7 +19,6 @@ cmp_cache_tree () {\n # correct.\n generate_expected_cache_tree_rec () {\n \tdir=\"$1${1:+/}\" &&\n-\tparent=\"$2\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n \tgit ls-files >files &&\n@@ -30,10 +29,9 @@ generate_expected_cache_tree_rec () {\n \tfor subtree in $subtrees\n \tdo\n \t\tcd \"$subtree\"\n-\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" \"$dir\" || return 1\n+\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n \t\tcd ..\n-\tdone &&\n-\tdir=$parent\n+\tdone\n }\n \n generate_expected_cache_tree () {\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415051","messageId":"20210123130046.21975-4-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 03/10] cache-tree tests: use a sub-shell with less indirection","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:39Z","receivedAt":"2021-01-23T13:02:30Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change a \"cd xyz && work && cd ..\" pattern introduced in\n9c4d6c0297 (cache-tree: Write updated cache-tree after commit,\n2014-07-13) to use a sub-shell instead with less indirection.\n\nWe did actually recover correctly if we failed in this function since\nwe were wrapped in a subshell one function call up. Let's just use the\nsub-shell at the point where we want to change the directory\ninstead.\n\nIt's important that the \"|| return 1\" is outside the\nsubshell. Normally, we `exit 1` from within subshells[1], but that\nwouldn't help us exit this loop early[1][2].\n\nSince we can get rid of the wrapper function let's rename the main\nfunction to drop the \"rec\" (for \"recursion\") suffix[3].\n\n1. https://lore.kernel.org/git/CAPig+cToj8nQmyBCqC1k7DXF2vXaonCEA-fCJ4x7JBZG2ixYBw@mail.gmail.com/\n2. https://lore.kernel.org/git/20150325052952.GE31924@peff.net/\n3. https://lore.kernel.org/git/YARsCsgXuiXr4uFX@coredump.intra.peff.net/\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh | 15 +++++----------\n 1 file changed, 5 insertions(+), 10 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 7ff7f04719..5bb4f75443 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -17,7 +17,7 @@ cmp_cache_tree () {\n # We don't bother with actually checking the SHA1:\n # test-tool dump-cache-tree already verifies that all existing data is\n # correct.\n-generate_expected_cache_tree_rec () {\n+generate_expected_cache_tree () {\n \tdir=\"$1${1:+/}\" &&\n \t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n \t# We want to count only foo because it's the only direct child\n@@ -28,18 +28,13 @@ generate_expected_cache_tree_rec () {\n \tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n \tfor subtree in $subtrees\n \tdo\n-\t\tcd \"$subtree\"\n-\t\tgenerate_expected_cache_tree_rec \"$dir$subtree\" || return 1\n-\t\tcd ..\n+\t\t(\n+\t\t\tcd \"$subtree\" &&\n+\t\t\tgenerate_expected_cache_tree \"$dir$subtree\"\n+\t\t) || return 1\n \tdone\n }\n \n-generate_expected_cache_tree () {\n-\t(\n-\t\tgenerate_expected_cache_tree_rec\n-\t)\n-}\n-\n test_cache_tree () {\n \tgenerate_expected_cache_tree >expect &&\n \tcmp_cache_tree expect\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415052","messageId":"20210123130046.21975-5-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 04/10] cache-tree tests: explicitly test HEAD and index differences","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:40Z","receivedAt":"2021-01-23T13:02:30Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"The test code added in 9c4d6c0297 (cache-tree: Write updated\ncache-tree after commit, 2014-07-13) used \"ls-files\" in lieu of\n\"ls-tree\" because it wanted to test the data in the index, since this\ntest is testing the cache-tree extension.\n\nChange the test to instead use \"ls-tree\" for traversal, and then\nexplicitly check how HEAD differs from the index. This is more easily\nunderstood, and less fragile as numerous past bug fixes[1][2][3] to\nthe old code we're replacing demonstrate.\n\nAs an aside this would be a bit easier if empty pathspecs hadn't been\nmade an error in d426430e6e (pathspec: warn on empty strings as\npathspec, 2016-06-22) and 9e4e8a64c2 (pathspec: die on empty strings\nas pathspec, 2017-06-06).\n\nIf that was still allowed this code could be simplified slightly:\n\n\tdiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\n\tindex 9bf66c9e68..0b02881f55 100755\n\t--- a/t/t0090-cache-tree.sh\n\t+++ b/t/t0090-cache-tree.sh\n\t@@ -18,19 +18,18 @@ cmp_cache_tree () {\n\t # test-tool dump-cache-tree already verifies that all existing data is\n\t # correct.\n\t generate_expected_cache_tree () {\n\t-       pathspec=\"$1\" &&\n\t-       dir=\"$2${2:+/}\" &&\n\t+       pathspec=\"$1${1:+/}\" &&\n\t        git ls-tree --name-only HEAD -- \"$pathspec\" >files &&\n\t        git ls-tree --name-only -d HEAD -- \"$pathspec\" >subtrees &&\n\t-       printf \"SHA %s (%d entries, %d subtrees)\\n\" \"$dir\" $(wc -l <files) $(wc -l <subtrees) &&\n\t+       printf \"SHA %s (%d entries, %d subtrees)\\n\" \"$pathspec\" $(wc -l <files) $(wc -l <subtrees) &&\n\t        while read subtree\n\t        do\n\t-               generate_expected_cache_tree \"$pathspec/$subtree/\" \"$subtree\" || return 1\n\t+               generate_expected_cache_tree \"$subtree\" || return 1\n\t        done <subtrees\n\t }\n\n\t test_cache_tree () {\n\t-       generate_expected_cache_tree \".\" >expect &&\n\t+       generate_expected_cache_tree >expect &&\n\t        cmp_cache_tree expect &&\n\t        rm expect actual files subtrees &&\n\t        git status --porcelain -- ':!status' ':!expected.status' >status &&\n\n1. c8db708d5d (t0090: avoid passing empty string to printf %d,\n   2014-09-30)\n2. d69360c6b1 (t0090: tweak awk statement for Solaris\n   /usr/xpg4/bin/awk, 2014-12-22)\n3. 9b5a9fa60a (t0090: stop losing return codes of git commands,\n   2019-11-27)\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t0090-cache-tree.sh | 45 ++++++++++++++++++++++++++-----------------\n 1 file changed, 27 insertions(+), 18 deletions(-)\n\ndiff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\nindex 5bb4f75443..9bf66c9e68 100755\n--- a/t/t0090-cache-tree.sh\n+++ b/t/t0090-cache-tree.sh\n@@ -18,26 +18,28 @@ cmp_cache_tree () {\n # test-tool dump-cache-tree already verifies that all existing data is\n # correct.\n generate_expected_cache_tree () {\n-\tdir=\"$1${1:+/}\" &&\n-\t# ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux\n-\t# We want to count only foo because it's the only direct child\n-\tgit ls-files >files &&\n-\tsubtrees=$(grep / files|cut -d / -f 1|uniq) &&\n-\tsubtree_count=$(echo \"$subtrees\"|awk -v c=0 '$1 != \"\" {++c} END {print c}') &&\n-\tentries=$(wc -l <files) &&\n-\tprintf \"SHA $dir (%d entries, %d subtrees)\\n\" \"$entries\" \"$subtree_count\" &&\n-\tfor subtree in $subtrees\n+\tpathspec=\"$1\" &&\n+\tdir=\"$2${2:+/}\" &&\n+\tgit ls-tree --name-only HEAD -- \"$pathspec\" >files &&\n+\tgit ls-tree --name-only -d HEAD -- \"$pathspec\" >subtrees &&\n+\tprintf \"SHA %s (%d entries, %d subtrees)\\n\" \"$dir\" $(wc -l <files) $(wc -l <subtrees) &&\n+\twhile read subtree\n \tdo\n-\t\t(\n-\t\t\tcd \"$subtree\" &&\n-\t\t\tgenerate_expected_cache_tree \"$dir$subtree\"\n-\t\t) || return 1\n-\tdone\n+\t\tgenerate_expected_cache_tree \"$pathspec/$subtree/\" \"$subtree\" || return 1\n+\tdone <subtrees\n }\n \n test_cache_tree () {\n-\tgenerate_expected_cache_tree >expect &&\n-\tcmp_cache_tree expect\n+\tgenerate_expected_cache_tree \".\" >expect &&\n+\tcmp_cache_tree expect &&\n+\trm expect actual files subtrees &&\n+\tgit status --porcelain -- ':!status' ':!expected.status' >status &&\n+\tif test -n \"$1\"\n+\tthen\n+\t\ttest_cmp \"$1\" status\n+\telse\n+\t\ttest_must_be_empty status\n+\tfi\n }\n \n test_invalid_cache_tree () {\n@@ -126,6 +128,7 @@ test_expect_success 'second commit has cache-tree' '\n '\n \n test_expect_success PERL 'commit --interactive gives cache-tree on partial commit' '\n+\ttest_when_finished \"git reset --hard\" &&\n \tcat <<-\\EOT >foo.c &&\n \tint foo()\n \t{\n@@ -152,7 +155,10 @@ test_expect_success PERL 'commit --interactive gives cache-tree on partial commi\n \tEOT\n \ttest_write_lines p 1 \"\" s n y q |\n \tgit commit --interactive -m foo &&\n-\ttest_cache_tree\n+\tcat <<-\\EOF >expected.status &&\n+\t M foo.c\n+\tEOF\n+\ttest_cache_tree expected.status\n '\n \n test_expect_success PERL 'commit -p with shrinking cache-tree' '\n@@ -243,7 +249,10 @@ test_expect_success 'partial commit gives cache-tree' '\n \tgit add one.t &&\n \techo \"some other change\" >two.t &&\n \tgit commit two.t -m partial &&\n-\ttest_cache_tree\n+\tcat <<-\\EOF >expected.status &&\n+\tM  one.t\n+\tEOF\n+\ttest_cache_tree expected.status\n '\n \n test_expect_success 'no phantom error when switching trees' '\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415053","messageId":"20210123130046.21975-6-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 05/10] git svn mergeinfo tests: modernize redirection & quoting style","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:41Z","receivedAt":"2021-01-23T13:02:45Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Use \"<file\" instead of \"< file\", and don't put the closing quote for\nstrings on an indented line. This makes a follow-up refactoring commit\neasier to read.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t9151-svn-mergeinfo.sh | 16 ++++++++--------\n 1 file changed, 8 insertions(+), 8 deletions(-)\n\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 4f6c06ecb2..59c5847c5f 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -9,37 +9,37 @@ test_description='git-svn svn mergeinfo properties'\n \n test_expect_success 'load svn dump' \"\n \tsvnadmin load -q '$rawsvnrepo' \\\n-\t  < '$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&\n+\t  <'$TEST_DIRECTORY/t9151/svn-mergeinfo.dump' &&\n \tgit svn init --minimize-url -R svnmerge \\\n \t  --rewrite-root=http://svn.example.org \\\n \t  -T trunk -b branches '$svnrepo' &&\n \tgit svn fetch --all\n-\t\"\n+\"\n \n test_expect_success 'all svn merges became git merge commits' '\n \tunmarked=$(git rev-list --parents --all --grep=Merge |\n \t\tgrep -v \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$unmarked\" ]\n-\t'\n+'\n \n test_expect_success 'cherry picks did not become git merge commits' '\n \tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n \t\tgrep \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$bad_cherries\" ]\n-\t'\n+'\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n \tbad_non_merges=$(git rev-list --parents --all --grep=non-merge |\n \t\tgrep \" .* \" | cut -f1 -d\" \") &&\n \t[ -z \"$bad_non_merges\" ]\n-\t'\n+'\n \n test_expect_success 'commit made to merged branch is reachable from the merge' '\n \tbefore_commit=$(git rev-list --all --grep=\"trunk commit before merging trunk to b2\") &&\n \tmerge_commit=$(git rev-list --all --grep=\"Merge trunk to b2\") &&\n \tnot_reachable=$(git rev-list -1 $before_commit --not $merge_commit) &&\n \t[ -z \"$not_reachable\" ]\n-\t'\n+'\n \n test_expect_success 'merging two branches in one commit is detected correctly' '\n \tf1_commit=$(git rev-list --all --grep=\"make f1 branch from trunk\") &&\n@@ -47,11 +47,11 @@ test_expect_success 'merging two branches in one commit is detected correctly' '\n \tmerge_commit=$(git rev-list --all --grep=\"Merge f1 and f2 to trunk\") &&\n \tnot_reachable=$(git rev-list -1 $f1_commit $f2_commit --not $merge_commit) &&\n \t[ -z \"$not_reachable\" ]\n-\t'\n+'\n \n test_expect_failure 'everything got merged in the end' '\n \tunmerged=$(git rev-list --all --not master) &&\n \t[ -z \"$unmerged\" ]\n-\t'\n+'\n \n test_done\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415054","messageId":"20210123130046.21975-7-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 06/10] git svn mergeinfo tests: refactor \"test -z\" to use test_must_be_empty","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:42Z","receivedAt":"2021-01-23T13:02:47Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Refactor some old-style test code to use test_must_be_empty instead of\n\"test -z\". This makes a follow-up commit easier to read.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t9151-svn-mergeinfo.sh | 31 ++++++++++++++++---------------\n 1 file changed, 16 insertions(+), 15 deletions(-)\n\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 59c5847c5f..806eff4023 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -17,41 +17,42 @@ test_expect_success 'load svn dump' \"\n \"\n \n test_expect_success 'all svn merges became git merge commits' '\n-\tunmarked=$(git rev-list --parents --all --grep=Merge |\n-\t\tgrep -v \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$unmarked\" ]\n+\tgit rev-list --parents --all --grep=Merge |\n+\t\tgrep -v \" .* \" | cut -f1 -d\" \" >unmarked &&\n+\ttest_must_be_empty unmarked\n '\n \n+\n test_expect_success 'cherry picks did not become git merge commits' '\n-\tbad_cherries=$(git rev-list --parents --all --grep=Cherry |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$bad_cherries\" ]\n+\tgit rev-list --parents --all --grep=Cherry |\n+\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-cherries &&\n+\ttest_must_be_empty bad-cherries\n '\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n-\tbad_non_merges=$(git rev-list --parents --all --grep=non-merge |\n-\t\tgrep \" .* \" | cut -f1 -d\" \") &&\n-\t[ -z \"$bad_non_merges\" ]\n+\tgit rev-list --parents --all --grep=non-merge |\n+\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-non-merges &&\n+\ttest_must_be_empty bad-non-merges\n '\n \n test_expect_success 'commit made to merged branch is reachable from the merge' '\n \tbefore_commit=$(git rev-list --all --grep=\"trunk commit before merging trunk to b2\") &&\n \tmerge_commit=$(git rev-list --all --grep=\"Merge trunk to b2\") &&\n-\tnot_reachable=$(git rev-list -1 $before_commit --not $merge_commit) &&\n-\t[ -z \"$not_reachable\" ]\n+\tgit rev-list -1 $before_commit --not $merge_commit >not-reachable &&\n+\ttest_must_be_empty not-reachable\n '\n \n test_expect_success 'merging two branches in one commit is detected correctly' '\n \tf1_commit=$(git rev-list --all --grep=\"make f1 branch from trunk\") &&\n \tf2_commit=$(git rev-list --all --grep=\"make f2 branch from trunk\") &&\n \tmerge_commit=$(git rev-list --all --grep=\"Merge f1 and f2 to trunk\") &&\n-\tnot_reachable=$(git rev-list -1 $f1_commit $f2_commit --not $merge_commit) &&\n-\t[ -z \"$not_reachable\" ]\n+\tgit rev-list -1 $f1_commit $f2_commit --not $merge_commit >not-reachable &&\n+\ttest_must_be_empty not-reachable\n '\n \n test_expect_failure 'everything got merged in the end' '\n-\tunmerged=$(git rev-list --all --not master) &&\n-\t[ -z \"$unmerged\" ]\n+\tgit rev-list --all --not master >unmerged &&\n+\ttest_must_be_empty unmerged\n '\n \n test_done\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415055","messageId":"20210123130046.21975-8-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 07/10] git-svn tests: rewrite brittle tests to use \"--[no-]merges\".","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:43Z","receivedAt":"2021-01-23T13:02:48Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"From: Jeff King <peff@peff.net>\n\nRewrite a brittle tests which used \"rev-list\" without \"--[no-]merges\"\nto figure out if a set of commits turned into merge commits or not.\n\nSigned-off-by: Jeff King <peff@peff.net>\n[ÆAB: wrote commit message]\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t9151-svn-mergeinfo.sh | 10 +++-------\n 1 file changed, 3 insertions(+), 7 deletions(-)\n\ndiff --git a/t/t9151-svn-mergeinfo.sh b/t/t9151-svn-mergeinfo.sh\nindex 806eff4023..c33bae91fb 100755\n--- a/t/t9151-svn-mergeinfo.sh\n+++ b/t/t9151-svn-mergeinfo.sh\n@@ -17,21 +17,17 @@ test_expect_success 'load svn dump' \"\n \"\n \n test_expect_success 'all svn merges became git merge commits' '\n-\tgit rev-list --parents --all --grep=Merge |\n-\t\tgrep -v \" .* \" | cut -f1 -d\" \" >unmarked &&\n+\tgit rev-list --all --no-merges --grep=Merge >unmarked &&\n \ttest_must_be_empty unmarked\n '\n \n-\n test_expect_success 'cherry picks did not become git merge commits' '\n-\tgit rev-list --parents --all --grep=Cherry |\n-\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-cherries &&\n+\tgit rev-list --all --merges --grep=Cherry >bad-cherries &&\n \ttest_must_be_empty bad-cherries\n '\n \n test_expect_success 'svn non-merge merge commits did not become git merge commits' '\n-\tgit rev-list --parents --all --grep=non-merge |\n-\t\tgrep \" .* \" | cut -f1 -d\" \" >bad-non-merges &&\n+\tgit rev-list --all --merges --grep=non-merge >bad-non-merges &&\n \ttest_must_be_empty bad-non-merges\n '\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415056","messageId":"20210123130046.21975-9-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 08/10] upload-pack tests: avoid a non-zero \"grep\" exit status","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:44Z","receivedAt":"2021-01-23T13:02:53Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Continue changing a test that 763b47bafa (t5703: stop losing return\ncodes of git commands, 2019-11-27) already refactored.\n\nThis was originally added as part of a series to add support for\nrunning under bash's \"set -o pipefail\", under that mode this test will\nfail because sometimes there's no commits in the \"objs\" output.\n\nIt's easier to fix that than exempt these tests under a hypothetical\n\"set -o pipefail\" test mode. It looks like we probably won't have\nthat, but once we've dug this code up let's refactor it[2] so we don't\nhide a potential pipe failure.\n\n1. https://lore.kernel.org/git/xmqqzh18o8o6.fsf@gitster.c.googlers.com/\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t5703-upload-pack-ref-in-want.sh | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh\nindex eab966985b..5d825b1781 100755\n--- a/t/t5703-upload-pack-ref-in-want.sh\n+++ b/t/t5703-upload-pack-ref-in-want.sh\n@@ -16,7 +16,8 @@ get_actual_commits () {\n \ttest-tool pkt-line unpack-sideband <out >o.pack &&\n \tgit index-pack o.pack &&\n \tgit verify-pack -v o.idx >objs &&\n-\tgrep commit objs | cut -d\" \" -f1 | sort >actual_commits\n+\tsed -n -e 's/\\([0-9a-f][0-9a-f]*\\) commit .*/\\1/p' objs >objs.sed &&\n+\tsort >actual_commits <objs.sed\n }\n \n check_output () {\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415057","messageId":"20210123130046.21975-11-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 10/10] rm tests: actually test for SIGPIPE in SIGPIPE test","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:46Z","receivedAt":"2021-01-23T13:02:57Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change a test initially added in 50cd31c652 (t3600: comment on\ninducing SIGPIPE in `git rm`, 2019-11-27) to explicitly test for\nSIGPIPE using a pattern initially established in 7559a1be8a (unblock\nand unignore SIGPIPE, 2014-09-18).\n\nThe problem with using that pattern is that it requires us to skip the\ntest on MINGW[1]. If we kept the test with its initial semantics[2]\nwe'd get coverage there, at the cost of not checking whether we\nactually had SIGPIPE outside of MinGW.\n\nArguably we should just remove this test. Between the test added in\n7559a1be8a and the change made in 12e0437f23 (common-main: call\nrestore_sigpipe_to_default(), 2016-07-01) it's a bit arbitrary to only\ncheck this for \"git rm\".\n\nBut in lieu of having wider test coverage for other \"git\" subcommands\nlet's refactor this to explicitly test for SIGPIPE outside of MinGW,\nand then just that we remove the \".git/index.lock\" (as before) on all\nplatforms.\n\n1. https://lore.kernel.org/git/xmqq1rec5ckf.fsf@gitster.c.googlers.com/\n2. 0693f9ddad (Make sure lockfiles are unlocked when dying on SIGPIPE,\n   2008-12-18)\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t3600-rm.sh | 16 ++++++++++++++--\n 1 file changed, 14 insertions(+), 2 deletions(-)\n\ndiff --git a/t/t3600-rm.sh b/t/t3600-rm.sh\nindex efec8d13b6..185e39c390 100755\n--- a/t/t3600-rm.sh\n+++ b/t/t3600-rm.sh\n@@ -240,7 +240,7 @@ test_expect_success 'refresh index before checking if it is up-to-date' '\n \ttest_path_is_missing frotz/nitfol\n '\n \n-test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n+choke_git_rm_setup() {\n \tgit reset -q --hard &&\n \ttest_when_finished \"rm -f .git/index.lock && git reset -q --hard\" &&\n \ti=0 &&\n@@ -249,12 +249,24 @@ test_expect_success 'choking \"git rm\" should not let it die with cruft' '\n \tdo\n \t\techo \"100644 $hash 0\tsome-file-$i\"\n \t\ti=$(( $i + 1 ))\n-\tdone | git update-index --index-info &&\n+\tdone | git update-index --index-info\n+}\n+\n+test_expect_success 'choking \"git rm\" should not let it die with cruft (induce SIGPIPE)' '\n+\tchoke_git_rm_setup &&\n \t# git command is intentionally placed upstream of pipe to induce SIGPIPE\n \tgit rm -n \"some-file-*\" | : &&\n \ttest_path_is_missing .git/index.lock\n '\n \n+\n+test_expect_success !MINGW 'choking \"git rm\" should not let it die with cruft (induce and check SIGPIPE)' '\n+\tchoke_git_rm_setup &&\n+\tOUT=$( ((trap \"\" PIPE; git rm -n \"some-file-*\"; echo $? 1>&3) | :) 3>&1 ) &&\n+\ttest_match_signal 13 \"$OUT\" &&\n+\ttest_path_is_missing .git/index.lock\n+'\n+\n test_expect_success 'Resolving by removal is not a warning-worthy event' '\n \tgit reset -q --hard &&\n \ttest_when_finished \"rm -f .git/index.lock msg && git reset -q --hard\" &&\n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415058","messageId":"20210123130046.21975-10-avarab@gmail.com","threadId":"52269","inReplyTo":"87sg6s6lrs.fsf@evledraar.gmail.com","subject":"[PATCH v3 09/10] archive tests: use a cheaper \"zipinfo -h\" invocation to get header","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-01-23T13:00:45Z","receivedAt":"2021-01-23T13:03:08Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Change an invocation of zipinfo added in 19ee29401d (t5004: test ZIP\narchives with many entries, 2015-08-22) to simply ask zipinfo for the\nheader info, rather than spewing out info about the entire archive and\nrace to kill it with SIGPIPE due to the downstream \"head -2\".\n\nI ran across this because I'm adding a \"set -o pipefail\" test\nmode. This won't be needed for the version of the mode that I'm\nintroducing (which currently relies on a patch to GNU bash), but I\nthink this is a good idea anyway.\n\nSigned-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n---\n t/t5004-archive-corner-cases.sh | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh\nindex 3e7b23cb32..2d32d0ed12 100755\n--- a/t/t5004-archive-corner-cases.sh\n+++ b/t/t5004-archive-corner-cases.sh\n@@ -153,7 +153,8 @@ test_expect_success ZIPINFO 'zip archive with many entries' '\n \n \t# check the number of entries in the ZIP file directory\n \texpr 65536 + 256 >expect &&\n-\t\"$ZIPINFO\" many.zip | head -2 | sed -n \"2s/.* //p\" >actual &&\n+\t\"$ZIPINFO\" -h many.zip >zipinfo &&\n+\tsed -n \"2s/.* //p\" <zipinfo >actual &&\n \ttest_cmp expect actual\n '\n \n-- \n2.29.2.222.g5d2a92d10f8\n\n"},{"id":"415100","messageId":"xmqqtur72v7o.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210123130046.21975-2-avarab@gmail.com","subject":"Re: [PATCH v3 01/10] cache-tree tests: refactor for modern test style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-23T21:34:51Z","receivedAt":"2021-01-23T21:35:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh\n> index 5a633690bf..45e1cc82ed 100755\n> --- a/t/t0090-cache-tree.sh\n> +++ b/t/t0090-cache-tree.sh\n> @@ -10,7 +10,8 @@ cache-tree extension.\n>  cmp_cache_tree () {\n>  \ttest-tool dump-cache-tree | sed -e '/#(ref)/d' >actual &&\n>  \tsed \"s/$OID_REGEX/SHA/\" <actual >filtered &&\n> -\ttest_cmp \"$1\" filtered\n> +\ttest_cmp \"$1\" filtered &&\n> +\trm filtered\n>  }\n\nOK.  Cleaning after itself is good, and not cleaning when there is\nan error is probably a bit more helpful to those who debug, but I\nthink test_cmp would give them enough to work on.  A failure to\nremove filtered at the end CAN mistakenly make the caller to think\nthat the expected output was not obtained, though.\n\n> @@ -83,18 +84,6 @@ test_expect_success 'git-add in subdir invalidates cache-tree' '\n>  \ttest_invalid_cache_tree\n>  '\n>  \n> -cat >before <<\\EOF\n> -SHA  (3 entries, 2 subtrees)\n> -SHA dir1/ (1 entries, 0 subtrees)\n> -SHA dir2/ (1 entries, 0 subtrees)\n> -EOF\n> -\n> -cat >expect <<\\EOF\n> -invalid                                   (2 subtrees)\n> -invalid                                  dir1/ (0 subtrees)\n> -SHA dir2/ (1 entries, 0 subtrees)\n> -EOF\n> -\n>  test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '\n>  \tgit tag no-children &&\n>  \ttest_when_finished \"git reset --hard no-children; git read-tree HEAD\" &&\n> @@ -102,9 +91,20 @@ test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '\n>  \ttest_commit dir1/a &&\n>  \ttest_commit dir2/b &&\n>  \techo \"I changed this file\" >dir1/a &&\n> +\ttest_when_finished \"rm before\" &&\n> +\tcat >before <<-\\EOF &&\n> +\tSHA  (3 entries, 2 subtrees)\n> +\tSHA dir1/ (1 entries, 0 subtrees)\n> +\tSHA dir2/ (1 entries, 0 subtrees)\n> +\tEOF\n>  \tcmp_cache_tree before &&\n>  \techo \"I changed this file\" >dir1/a &&\n>  \tgit add dir1/a &&\n> +\tcat >expect <<-\\EOF &&\n> +\tinvalid                                   (2 subtrees)\n> +\tinvalid                                  dir1/ (0 subtrees)\n> +\tSHA dir2/ (1 entries, 0 subtrees)\n> +\tEOF\n>  \tcmp_cache_tree expect\n>  '\n\nWhy remove only 'before' and not 'expect' in when-finished handler?\n"},{"id":"415101","messageId":"xmqqpn1v2v72.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210123130046.21975-3-avarab@gmail.com","subject":"Re: [PATCH v3 02/10] cache-tree tests: remove unused $2 parameter","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-23T21:35:13Z","receivedAt":"2021-01-23T21:36:01Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Remove the $2 paramater. This appears to have been some\n> work-in-progress code from an earlier version of\n> 9c4d6c0297 (cache-tree: Write updated cache-tree after commit,\n> 2014-07-13) which was left in the final version.\n\nGood.\n"},{"id":"415102","messageId":"xmqqlfcj2v6e.fsf@gitster.c.googlers.com","threadId":"52269","inReplyTo":"20210123130046.21975-4-avarab@gmail.com","subject":"Re: [PATCH v3 03/10] cache-tree tests: use a sub-shell with less indirection","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-01-23T21:35:37Z","receivedAt":"2021-01-23T21:36:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:\n\n> Change a \"cd xyz && work && cd ..\" pattern introduced in\n> 9c4d6c0297 (cache-tree: Write updated cache-tree after commit,\n> 2014-07-13) to use a sub-shell instead with less indirection.\n\nMuch nicer.  Pleased.\n"}]}