{"thread":{"id":"57645","subject":"[PATCH] t5510-fetch: upgrade to a more modern style","startedAt":"2022-03-31T17:54:26Z","lastAt":"2022-04-02T07:32:14Z","messageCount":4,"participants":["Elia Pinto","Junio C Hamano","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"452812","messageId":"20220331175412.305968-1-gitter.spiros@gmail.com","threadId":"57645","inReplyTo":null,"subject":"[PATCH] t5510-fetch: upgrade to a more modern style","fromName":"Elia Pinto","fromEmail":"gitter.spiros@gmail.com","sentAt":"2022-03-31T17:54:12Z","receivedAt":"2022-03-31T17:54:26Z","isPatch":true,"sender":{"key":"gitter.spiros@gmail.com","avatar":"https://avatars.githubusercontent.com/u/158490?v=4"},"body":"Clean up the code style so all the tests, and not just a few,\nthat chdir around isolate themselves in a subshell.\n\nSigned-off-by: Elia Pinto <gitter.spiros@gmail.com>\n---\nthis patch was inspired by a Junio #leftoverbit\nhttps://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/\n t/t5510-fetch.sh | 927 ++++++++++++++++++++++++-----------------------\n 1 file changed, 477 insertions(+), 450 deletions(-)\n\ndiff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\nindex 6f38a69fbb..d0b249d276 100755\n--- a/t/t5510-fetch.sh\n+++ b/t/t5510-fetch.sh\n@@ -48,342 +48,349 @@ test_expect_success \"clone and setup child repos\" '\n '\n \n test_expect_success \"fetch test\" '\n-\tcd \"$D\" &&\n-\techo >file updated by origin &&\n-\tgit commit -a -m \"updated by origin\" &&\n-\tcd two &&\n-\tgit fetch &&\n-\tgit rev-parse --verify refs/heads/one &&\n-\tmine=$(git rev-parse refs/heads/one) &&\n-\this=$(cd ../one && git rev-parse refs/heads/main) &&\n-\ttest \"z$mine\" = \"z$his\"\n+\t(\n+\t\tcd \"$D\" &&\n+\t\techo >file updated by origin &&\n+\t\tgit commit -a -m \"updated by origin\" &&\n+\t\t(\n+\t\t\tcd two &&\n+\t\t\tgit fetch &&\n+\t\t\tgit rev-parse --verify refs/heads/one &&\n+\t\t\tmine=$(git rev-parse refs/heads/one) &&\n+\t\t\this=$(cd ../one && git rev-parse refs/heads/main) &&\n+\t\t\ttest \"z$mine\" = \"z$his\"\n+\t\t)\n+\t)\n '\n \n test_expect_success \"fetch test for-merge\" '\n-\tcd \"$D\" &&\n-\tcd three &&\n-\tgit fetch &&\n-\tgit rev-parse --verify refs/heads/two &&\n-\tgit rev-parse --verify refs/heads/one &&\n-\tmain_in_two=$(cd ../two && git rev-parse main) &&\n-\tone_in_two=$(cd ../two && git rev-parse one) &&\n-\t{\n-\t\techo \"$one_in_two\t\" &&\n-\t\techo \"$main_in_two\tnot-for-merge\"\n-\t} >expected &&\n-\tcut -f -2 .git/FETCH_HEAD >actual &&\n-\ttest_cmp expected actual'\n+\t(\n+\t\tcd \"$D\" &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\tgit fetch &&\n+\t\t\tgit rev-parse --verify refs/heads/two &&\n+\t\t\tgit rev-parse --verify refs/heads/one &&\n+\t\t\tmain_in_two=$(cd ../two && git rev-parse main) &&\n+\t\t\tone_in_two=$(cd ../two && git rev-parse one) &&\n+\t\t\t{\n+\t\t\t\techo \"$one_in_two\t\" &&\n+\t\t\t\techo \"$main_in_two\tnot-for-merge\"\n+\t\t\t} >expected &&\n+\t\t\tcut -f -2 .git/FETCH_HEAD >actual &&\n+\t\t\ttest_cmp expected actual\n+\t\t)\n+\t)\n+'\n \n test_expect_success 'fetch --prune on its own works as expected' '\n-\tcd \"$D\" &&\n-\tgit clone . prune &&\n-\tcd prune &&\n-\tgit update-ref refs/remotes/origin/extrabranch main &&\n-\n-\tgit fetch --prune origin &&\n-\ttest_must_fail git rev-parse origin/extrabranch\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . prune &&\n+\t\tcd prune &&\n+\t\tgit update-ref refs/remotes/origin/extrabranch main &&\n+\t\tgit fetch --prune origin &&\n+\t\ttest_must_fail git rev-parse origin/extrabranch\n+\t)\n '\n \n test_expect_success 'fetch --prune with a branch name keeps branches' '\n-\tcd \"$D\" &&\n-\tgit clone . prune-branch &&\n-\tcd prune-branch &&\n-\tgit update-ref refs/remotes/origin/extrabranch main &&\n-\n-\tgit fetch --prune origin main &&\n-\tgit rev-parse origin/extrabranch\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . prune-branch &&\n+\t\tcd prune-branch &&\n+\t\tgit update-ref refs/remotes/origin/extrabranch main &&\n+\t\tgit fetch --prune origin main &&\n+\t\tgit rev-parse origin/extrabranch\n+\t)\n '\n \n test_expect_success 'fetch --prune with a namespace keeps other namespaces' '\n-\tcd \"$D\" &&\n-\tgit clone . prune-namespace &&\n-\tcd prune-namespace &&\n-\n-\tgit fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&\n-\tgit rev-parse origin/main\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . prune-namespace &&\n+\t\tcd prune-namespace &&\n+\t\tgit fetch --prune origin refs/heads/a/*:refs/remotes/origin/a/* &&\n+\t\tgit rev-parse origin/main\n+\t)\n '\n \n test_expect_success 'fetch --prune handles overlapping refspecs' '\n-\tcd \"$D\" &&\n-\tgit update-ref refs/pull/42/head main &&\n-\tgit clone . prune-overlapping &&\n-\tcd prune-overlapping &&\n-\tgit config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n-\n-\tgit fetch --prune origin &&\n-\tgit rev-parse origin/main &&\n-\tgit rev-parse origin/pr/42 &&\n-\n-\tgit config --unset-all remote.origin.fetch &&\n-\tgit config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n-\tgit config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&\n-\n-\tgit fetch --prune origin &&\n-\tgit rev-parse origin/main &&\n-\tgit rev-parse origin/pr/42\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit update-ref refs/pull/42/head main &&\n+\t\tgit clone . prune-overlapping &&\n+\t\tcd prune-overlapping &&\n+\t\tgit config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n+\t\tgit fetch --prune origin &&\n+\t\tgit rev-parse origin/main &&\n+\t\tgit rev-parse origin/pr/42 &&\n+\t\tgit config --unset-all remote.origin.fetch &&\n+\t\tgit config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n+\t\tgit config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&\n+\t\tgit fetch --prune origin &&\n+\t\tgit rev-parse origin/main &&\n+\t\tgit rev-parse origin/pr/42\n+\t)\n '\n \n test_expect_success 'fetch --prune --tags prunes branches but not tags' '\n-\tcd \"$D\" &&\n-\tgit clone . prune-tags &&\n-\tcd prune-tags &&\n-\tgit tag sometag main &&\n-\t# Create what looks like a remote-tracking branch from an earlier\n-\t# fetch that has since been deleted from the remote:\n-\tgit update-ref refs/remotes/origin/fake-remote main &&\n-\n-\tgit fetch --prune --tags origin &&\n-\tgit rev-parse origin/main &&\n-\ttest_must_fail git rev-parse origin/fake-remote &&\n-\tgit rev-parse sometag\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . prune-tags &&\n+\t\tcd prune-tags &&\n+\t\tgit tag sometag main &&\n+\t\t# Create what looks like a remote-tracking branch from an earlier\n+\t\t# fetch that has since been deleted from the remote:\n+\t\tgit update-ref refs/remotes/origin/fake-remote main &&\n+\t\tgit fetch --prune --tags origin &&\n+\t\tgit rev-parse origin/main &&\n+\t\ttest_must_fail git rev-parse origin/fake-remote &&\n+\t\tgit rev-parse sometag\n+\t)\n '\n \n test_expect_success 'fetch --prune --tags with branch does not prune other things' '\n-\tcd \"$D\" &&\n-\tgit clone . prune-tags-branch &&\n-\tcd prune-tags-branch &&\n-\tgit tag sometag main &&\n-\tgit update-ref refs/remotes/origin/extrabranch main &&\n-\n-\tgit fetch --prune --tags origin main &&\n-\tgit rev-parse origin/extrabranch &&\n-\tgit rev-parse sometag\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . prune-tags-branch &&\n+\t\tcd prune-tags-branch &&\n+\t\tgit tag sometag main &&\n+\t\tgit update-ref refs/remotes/origin/extrabranch main &&\n+\t\tgit fetch --prune --tags origin main &&\n+\t\tgit rev-parse origin/extrabranch &&\n+\t\tgit rev-parse sometag\n+\t)\n '\n \n test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' '\n-\tcd \"$D\" &&\n-\tgit clone . prune-tags-refspec &&\n-\tcd prune-tags-refspec &&\n-\tgit tag sometag main &&\n-\tgit update-ref refs/remotes/origin/foo/otherbranch main &&\n-\tgit update-ref refs/remotes/origin/extrabranch main &&\n-\n-\tgit fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&\n-\ttest_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&\n-\tgit rev-parse origin/extrabranch &&\n-\tgit rev-parse sometag\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . prune-tags-refspec &&\n+\t\tcd prune-tags-refspec &&\n+\t\tgit tag sometag main &&\n+\t\tgit update-ref refs/remotes/origin/foo/otherbranch main &&\n+\t\tgit update-ref refs/remotes/origin/extrabranch main &&\n+\t\tgit fetch --prune --tags origin refs/heads/foo/*:refs/remotes/origin/foo/* &&\n+\t\ttest_must_fail git rev-parse refs/remotes/origin/foo/otherbranch &&\n+\t\tgit rev-parse origin/extrabranch &&\n+\t\tgit rev-parse sometag\n+\t)\n '\n \n test_expect_success REFFILES 'fetch --prune fails to delete branches' '\n-\tcd \"$D\" &&\n-\tgit clone . prune-fail &&\n-\tcd prune-fail &&\n-\tgit update-ref refs/remotes/origin/extrabranch main &&\n-\t: this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds  &&\n-\t>.git/packed-refs.new &&\n-\n-\ttest_must_fail git fetch --prune origin\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . prune-fail &&\n+\t\tcd prune-fail &&\n+\t\tgit update-ref refs/remotes/origin/extrabranch main &&\n+\t\t: this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds  &&\n+\t\t>.git/packed-refs.new &&\n+\t\ttest_must_fail git fetch --prune origin\n+\t)\n '\n \n test_expect_success 'fetch --atomic works with a single branch' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit clone . atomic &&\n-\tgit branch atomic-branch &&\n-\toid=$(git rev-parse atomic-branch) &&\n-\techo \"$oid\" >expected &&\n-\n-\tgit -C atomic fetch --atomic origin &&\n-\tgit -C atomic rev-parse origin/atomic-branch >actual &&\n-\ttest_cmp expected actual &&\n-\ttest $oid = \"$(git -C atomic rev-parse --verify FETCH_HEAD)\"\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . atomic &&\n+\t\tgit branch atomic-branch &&\n+\t\toid=$(git rev-parse atomic-branch) &&\n+\t\techo \"$oid\" >expected &&\n+\t\tgit -C atomic fetch --atomic origin &&\n+\t\tgit -C atomic rev-parse origin/atomic-branch >actual &&\n+\t\ttest_cmp expected actual &&\n+\t\ttest $oid = \"$(git -C atomic rev-parse --verify FETCH_HEAD)\"\n+\t)\n '\n \n test_expect_success 'fetch --atomic works with multiple branches' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit clone . atomic &&\n-\tgit branch atomic-branch-1 &&\n-\tgit branch atomic-branch-2 &&\n-\tgit branch atomic-branch-3 &&\n-\tgit rev-parse refs/heads/atomic-branch-1 refs/heads/atomic-branch-2 refs/heads/atomic-branch-3 >actual &&\n-\n-\tgit -C atomic fetch --atomic origin &&\n-\tgit -C atomic rev-parse refs/remotes/origin/atomic-branch-1 refs/remotes/origin/atomic-branch-2 refs/remotes/origin/atomic-branch-3 >expected &&\n-\ttest_cmp expected actual\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . atomic &&\n+\t\tgit branch atomic-branch-1 &&\n+\t\tgit branch atomic-branch-2 &&\n+\t\tgit branch atomic-branch-3 &&\n+\t\tgit rev-parse refs/heads/atomic-branch-1 refs/heads/atomic-branch-2 refs/heads/atomic-branch-3 >actual &&\n+\t\tgit -C atomic fetch --atomic origin &&\n+\t\tgit -C atomic rev-parse refs/remotes/origin/atomic-branch-1 refs/remotes/origin/atomic-branch-2 refs/remotes/origin/atomic-branch-3 >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n '\n \n test_expect_success 'fetch --atomic works with mixed branches and tags' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit clone . atomic &&\n-\tgit branch atomic-mixed-branch &&\n-\tgit tag atomic-mixed-tag &&\n-\tgit rev-parse refs/heads/atomic-mixed-branch refs/tags/atomic-mixed-tag >actual &&\n-\n-\tgit -C atomic fetch --tags --atomic origin &&\n-\tgit -C atomic rev-parse refs/remotes/origin/atomic-mixed-branch refs/tags/atomic-mixed-tag >expected &&\n-\ttest_cmp expected actual\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . atomic &&\n+\t\tgit branch atomic-mixed-branch &&\n+\t\tgit tag atomic-mixed-tag &&\n+\t\tgit rev-parse refs/heads/atomic-mixed-branch refs/tags/atomic-mixed-tag >actual &&\n+\t\tgit -C atomic fetch --tags --atomic origin &&\n+\t\tgit -C atomic rev-parse refs/remotes/origin/atomic-mixed-branch refs/tags/atomic-mixed-tag >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n '\n \n test_expect_success 'fetch --atomic prunes references' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit branch atomic-prune-delete &&\n-\tgit clone . atomic &&\n-\tgit branch --delete atomic-prune-delete &&\n-\tgit branch atomic-prune-create &&\n-\tgit rev-parse refs/heads/atomic-prune-create >actual &&\n-\n-\tgit -C atomic fetch --prune --atomic origin &&\n-\ttest_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-prune-delete &&\n-\tgit -C atomic rev-parse refs/remotes/origin/atomic-prune-create >expected &&\n-\ttest_cmp expected actual\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit branch atomic-prune-delete &&\n+\t\tgit clone . atomic &&\n+\t\tgit branch --delete atomic-prune-delete &&\n+\t\tgit branch atomic-prune-create &&\n+\t\tgit rev-parse refs/heads/atomic-prune-create >actual &&\n+\t\tgit -C atomic fetch --prune --atomic origin &&\n+\t\ttest_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-prune-delete &&\n+\t\tgit -C atomic rev-parse refs/remotes/origin/atomic-prune-create >expected &&\n+\t\ttest_cmp expected actual\n+\t)\n '\n \n test_expect_success 'fetch --atomic aborts with non-fast-forward update' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit branch atomic-non-ff &&\n-\tgit clone . atomic &&\n-\tgit rev-parse HEAD >actual &&\n-\n-\tgit branch atomic-new-branch &&\n-\tparent_commit=$(git rev-parse atomic-non-ff~) &&\n-\tgit update-ref refs/heads/atomic-non-ff $parent_commit &&\n-\n-\ttest_must_fail git -C atomic fetch --atomic origin refs/heads/*:refs/remotes/origin/* &&\n-\ttest_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-new-branch &&\n-\tgit -C atomic rev-parse refs/remotes/origin/atomic-non-ff >expected &&\n-\ttest_cmp expected actual &&\n-\ttest_must_be_empty atomic/.git/FETCH_HEAD\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit branch atomic-non-ff &&\n+\t\tgit clone . atomic &&\n+\t\tgit rev-parse HEAD >actual &&\n+\t\tgit branch atomic-new-branch &&\n+\t\tparent_commit=$(git rev-parse atomic-non-ff~) &&\n+\t\tgit update-ref refs/heads/atomic-non-ff $parent_commit &&\n+\t\ttest_must_fail git -C atomic fetch --atomic origin refs/heads/*:refs/remotes/origin/* &&\n+\t\ttest_must_fail git -C atomic rev-parse refs/remotes/origin/atomic-new-branch &&\n+\t\tgit -C atomic rev-parse refs/remotes/origin/atomic-non-ff >expected &&\n+\t\ttest_cmp expected actual &&\n+\t\ttest_must_be_empty atomic/.git/FETCH_HEAD\n+\t)\n '\n \n test_expect_success 'fetch --atomic executes a single reference transaction only' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit clone . atomic &&\n-\tgit branch atomic-hooks-1 &&\n-\tgit branch atomic-hooks-2 &&\n-\thead_oid=$(git rev-parse HEAD) &&\n-\n-\tcat >expected <<-EOF &&\n-\t\tprepared\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2\n-\t\tcommitted\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2\n-\tEOF\n-\n-\trm -f atomic/actual &&\n-\ttest_hook -C atomic reference-transaction <<-\\EOF &&\n-\t\t( echo \"$*\" && cat ) >>actual\n-\tEOF\n-\n-\tgit -C atomic fetch --atomic origin &&\n-\ttest_cmp expected atomic/actual\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . atomic &&\n+\t\tgit branch atomic-hooks-1 &&\n+\t\tgit branch atomic-hooks-2 &&\n+\t\thead_oid=$(git rev-parse HEAD) &&\n+\t\tcat >expected <<-EOF &&\n+\t\t\tprepared\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2\n+\t\t\tcommitted\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2\n+\t\tEOF\n+\t\trm -f atomic/actual &&\n+\t\twrite_script atomic/.git/hooks/reference-transaction <<-\\EOF &&\n+\t\t\t( echo \"$*\" && cat ) >>actual\n+\t\tEOF\n+\t\tgit -C atomic fetch --atomic origin &&\n+\t\ttest_cmp expected atomic/actual\n+\t)\n '\n \n test_expect_success 'fetch --atomic aborts all reference updates if hook aborts' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit clone . atomic &&\n-\tgit branch atomic-hooks-abort-1 &&\n-\tgit branch atomic-hooks-abort-2 &&\n-\tgit branch atomic-hooks-abort-3 &&\n-\tgit tag atomic-hooks-abort &&\n-\thead_oid=$(git rev-parse HEAD) &&\n-\n-\tcat >expected <<-EOF &&\n-\t\tprepared\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3\n-\t\t$ZERO_OID $head_oid refs/tags/atomic-hooks-abort\n-\t\taborted\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3\n-\t\t$ZERO_OID $head_oid refs/tags/atomic-hooks-abort\n-\tEOF\n-\n-\trm -f atomic/actual &&\n-\ttest_hook -C atomic/.git reference-transaction <<-\\EOF &&\n-\t\t( echo \"$*\" && cat ) >>actual\n-\t\texit 1\n-\tEOF\n-\n-\tgit -C atomic for-each-ref >expected-refs &&\n-\ttest_must_fail git -C atomic fetch --tags --atomic origin &&\n-\tgit -C atomic for-each-ref >actual-refs &&\n-\ttest_cmp expected-refs actual-refs &&\n-\ttest_must_be_empty atomic/.git/FETCH_HEAD\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . atomic &&\n+\t\tgit branch atomic-hooks-abort-1 &&\n+\t\tgit branch atomic-hooks-abort-2 &&\n+\t\tgit branch atomic-hooks-abort-3 &&\n+\t\tgit tag atomic-hooks-abort &&\n+\t\thead_oid=$(git rev-parse HEAD) &&\n+\t\tcat >expected <<-EOF &&\n+\t\t\tprepared\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3\n+\t\t\t$ZERO_OID $head_oid refs/tags/atomic-hooks-abort\n+\t\t\taborted\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-1\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-2\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-abort-3\n+\t\t\t$ZERO_OID $head_oid refs/tags/atomic-hooks-abort\n+\t\tEOF\n+\t\trm -f atomic/actual &&\n+\t\twrite_script atomic/.git/hooks/reference-transaction <<-\\EOF &&\n+\t\t\t( echo \"$*\" && cat ) >>actual\n+\t\t\texit 1\n+\t\tEOF\n+\t\tgit -C atomic for-each-ref >expected-refs &&\n+\t\ttest_must_fail git -C atomic fetch --tags --atomic origin &&\n+\t\tgit -C atomic for-each-ref >actual-refs &&\n+\t\ttest_cmp expected-refs actual-refs &&\n+\t\ttest_must_be_empty atomic/.git/FETCH_HEAD\n+\t)\n '\n \n test_expect_success 'fetch --atomic --append appends to FETCH_HEAD' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit clone . atomic &&\n-\toid=$(git rev-parse HEAD) &&\n-\n-\tgit branch atomic-fetch-head-1 &&\n-\tgit -C atomic fetch --atomic origin atomic-fetch-head-1 &&\n-\ttest_line_count = 1 atomic/.git/FETCH_HEAD &&\n-\n-\tgit branch atomic-fetch-head-2 &&\n-\tgit -C atomic fetch --atomic --append origin atomic-fetch-head-2 &&\n-\ttest_line_count = 2 atomic/.git/FETCH_HEAD &&\n-\tcp atomic/.git/FETCH_HEAD expected &&\n-\n-\ttest_hook -C atomic reference-transaction <<-\\EOF &&\n-\t\texit 1\n-\tEOF\n-\n-\tgit branch atomic-fetch-head-3 &&\n-\ttest_must_fail git -C atomic fetch --atomic --append origin atomic-fetch-head-3 &&\n-\ttest_cmp expected atomic/.git/FETCH_HEAD\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit clone . atomic &&\n+\t\toid=$(git rev-parse HEAD) &&\n+\t\tgit branch atomic-fetch-head-1 &&\n+\t\tgit -C atomic fetch --atomic origin atomic-fetch-head-1 &&\n+\t\ttest_line_count = 1 atomic/.git/FETCH_HEAD &&\n+\t\tgit branch atomic-fetch-head-2 &&\n+\t\tgit -C atomic fetch --atomic --append origin atomic-fetch-head-2 &&\n+\t\ttest_line_count = 2 atomic/.git/FETCH_HEAD &&\n+\t\tcp atomic/.git/FETCH_HEAD expected &&\n+\t\twrite_script atomic/.git/hooks/reference-transaction <<-\\EOF &&\n+\t\t\texit 1\n+\t\tEOF\n+\t\tgit branch atomic-fetch-head-3 &&\n+\t\ttest_must_fail git -C atomic fetch --atomic --append origin atomic-fetch-head-3 &&\n+\t\ttest_cmp expected atomic/.git/FETCH_HEAD\n+\t)\n '\n \n test_expect_success 'fetch --atomic --prune executes a single reference transaction only' '\n \ttest_when_finished \"rm -rf \\\"$D\\\"/atomic\" &&\n-\n-\tcd \"$D\" &&\n-\tgit branch scheduled-for-deletion &&\n-\tgit clone . atomic &&\n-\tgit branch -D scheduled-for-deletion &&\n-\tgit branch new-branch &&\n-\thead_oid=$(git rev-parse HEAD) &&\n-\n-\t# Fetching with the `--atomic` flag should update all references in a\n-\t# single transaction.\n-\tcat >expected <<-EOF &&\n-\t\tprepared\n-\t\t$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/new-branch\n-\t\tcommitted\n-\t\t$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion\n-\t\t$ZERO_OID $head_oid refs/remotes/origin/new-branch\n-\tEOF\n-\n-\ttest_hook -C atomic reference-transaction <<-\\EOF &&\n-\t\t( echo \"$*\" && cat ) >>actual\n-\tEOF\n-\n-\tgit -C atomic fetch --atomic --prune origin &&\n-\ttest_cmp expected atomic/actual\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit branch scheduled-for-deletion &&\n+\t\tgit clone . atomic &&\n+\t\tgit branch -D scheduled-for-deletion &&\n+\t\tgit branch new-branch &&\n+\t\thead_oid=$(git rev-parse HEAD) &&\n+\t\t# Fetching with the `--atomic` flag should update all references in a\n+\t\t# single transaction.\n+\t\tcat >expected <<-EOF &&\n+\t\t\tprepared\n+\t\t\t$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/new-branch\n+\t\t\tcommitted\n+\t\t\t$ZERO_OID $ZERO_OID refs/remotes/origin/scheduled-for-deletion\n+\t\t\t$ZERO_OID $head_oid refs/remotes/origin/new-branch\n+\t\tEOF\n+\t\twrite_script atomic/.git/hooks/reference-transaction <<-\\EOF &&\n+\t\t\t( echo \"$*\" && cat ) >>actual\n+\t\tEOF\n+\t\tgit -C atomic fetch --atomic --prune origin &&\n+\t\ttest_cmp expected atomic/actual\n+\t)\n '\n \n test_expect_success '--refmap=\"\" ignores configured refspec' '\n-\tcd \"$TRASH_DIRECTORY\" &&\n-\tgit clone \"$D\" remote-refs &&\n-\tgit -C remote-refs rev-parse remotes/origin/main >old &&\n-\tgit -C remote-refs update-ref refs/remotes/origin/main main~1 &&\n-\tgit -C remote-refs rev-parse remotes/origin/main >new &&\n-\tgit -C remote-refs fetch --refmap= origin \"+refs/heads/*:refs/hidden/origin/*\" &&\n-\tgit -C remote-refs rev-parse remotes/origin/main >actual &&\n-\ttest_cmp new actual &&\n-\tgit -C remote-refs fetch origin &&\n-\tgit -C remote-refs rev-parse remotes/origin/main >actual &&\n-\ttest_cmp old actual\n+\t(\n+\t\tcd \"$TRASH_DIRECTORY\" &&\n+\t\tgit clone \"$D\" remote-refs &&\n+\t\tgit -C remote-refs rev-parse remotes/origin/main >old &&\n+\t\tgit -C remote-refs update-ref refs/remotes/origin/main main~1 &&\n+\t\tgit -C remote-refs rev-parse remotes/origin/main >new &&\n+\t\tgit -C remote-refs fetch --refmap= origin \"+refs/heads/*:refs/hidden/origin/*\" &&\n+\t\tgit -C remote-refs rev-parse remotes/origin/main >actual &&\n+\t\ttest_cmp new actual &&\n+\t\tgit -C remote-refs fetch origin &&\n+\t\tgit -C remote-refs rev-parse remotes/origin/main >actual &&\n+\t\ttest_cmp old actual\n+\t)\n '\n \n test_expect_success '--refmap=\"\" and --prune' '\n@@ -397,89 +404,86 @@ test_expect_success '--refmap=\"\" and --prune' '\n '\n \n test_expect_success 'fetch tags when there is no tags' '\n-\n-    cd \"$D\" &&\n-\n-    mkdir notags &&\n-    cd notags &&\n-    git init &&\n-\n-    git fetch -t ..\n-\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tmkdir notags &&\n+\t\tcd notags &&\n+\t\tgit init &&\n+\t\tgit fetch -t ..\n+\t)\n '\n \n test_expect_success 'fetch following tags' '\n-\n-\tcd \"$D\" &&\n-\tgit tag -a -m \"annotated\" anno HEAD &&\n-\tgit tag light HEAD &&\n-\n-\tmkdir four &&\n-\tcd four &&\n-\tgit init &&\n-\n-\tgit fetch .. :track &&\n-\tgit show-ref --verify refs/tags/anno &&\n-\tgit show-ref --verify refs/tags/light\n-\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit tag -a -m \"annotated\" anno HEAD &&\n+\t\tgit tag light HEAD &&\n+\t\tmkdir four &&\n+\t\tcd four &&\n+\t\tgit init &&\n+\t\tgit fetch .. :track &&\n+\t\tgit show-ref --verify refs/tags/anno &&\n+\t\tgit show-ref --verify refs/tags/light\n+\t)\n '\n \n test_expect_success 'fetch uses remote ref names to describe new refs' '\n-\tcd \"$D\" &&\n-\tgit init descriptive &&\n-\t(\n-\t\tcd descriptive &&\n-\t\tgit config remote.o.url .. &&\n-\t\tgit config remote.o.fetch \"refs/heads/*:refs/crazyheads/*\" &&\n-\t\tgit config --add remote.o.fetch \"refs/others/*:refs/heads/*\" &&\n-\t\tgit fetch o\n-\t) &&\n-\tgit tag -a -m \"Descriptive tag\" descriptive-tag &&\n-\tgit branch descriptive-branch &&\n-\tgit checkout descriptive-branch &&\n-\techo \"Nuts\" >crazy &&\n-\tgit add crazy &&\n-\tgit commit -a -m \"descriptive commit\" &&\n-\tgit update-ref refs/others/crazy HEAD &&\n \t(\n-\t\tcd descriptive &&\n-\t\tgit fetch o 2>actual &&\n-\t\ttest_i18ngrep \"new branch.* -> refs/crazyheads/descriptive-branch$\" actual &&\n-\t\ttest_i18ngrep \"new tag.* -> descriptive-tag$\" actual &&\n-\t\ttest_i18ngrep \"new ref.* -> crazy$\" actual\n-\t) &&\n-\tgit checkout main\n+\t\tcd \"$D\" &&\n+\t\tgit init descriptive &&\n+\t\t(\n+\t\t\tcd descriptive &&\n+\t\t\tgit config remote.o.url .. &&\n+\t\t\tgit config remote.o.fetch \"refs/heads/*:refs/crazyheads/*\" &&\n+\t\t\tgit config --add remote.o.fetch \"refs/others/*:refs/heads/*\" &&\n+\t\t\tgit fetch o\n+\t\t) &&\n+\t\tgit tag -a -m \"Descriptive tag\" descriptive-tag &&\n+\t\tgit branch descriptive-branch &&\n+\t\tgit checkout descriptive-branch &&\n+\t\techo \"Nuts\" >crazy &&\n+\t\tgit add crazy &&\n+\t\tgit commit -a -m \"descriptive commit\" &&\n+\t\tgit update-ref refs/others/crazy HEAD &&\n+\t\t(\n+\t\t\tcd descriptive &&\n+\t\t\tgit fetch o 2>actual &&\n+\t\t\ttest_i18ngrep \"new branch.* -> refs/crazyheads/descriptive-branch$\" actual &&\n+\t\t\ttest_i18ngrep \"new tag.* -> descriptive-tag$\" actual &&\n+\t\t\ttest_i18ngrep \"new ref.* -> crazy$\" actual\n+\t\t) &&\n+\t\tgit checkout main\n+\t)\n '\n \n test_expect_success 'fetch must not resolve short tag name' '\n-\n-\tcd \"$D\" &&\n-\n-\tmkdir five &&\n-\tcd five &&\n-\tgit init &&\n-\n-\ttest_must_fail git fetch .. anno:five\n-\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tmkdir five &&\n+\t\tcd five &&\n+\t\tgit init &&\n+\t\ttest_must_fail git fetch .. anno:five\n+\t)\n '\n \n test_expect_success 'fetch can now resolve short remote name' '\n-\n-\tcd \"$D\" &&\n-\tgit update-ref refs/remotes/six/HEAD HEAD &&\n-\n-\tmkdir six &&\n-\tcd six &&\n-\tgit init &&\n-\n-\tgit fetch .. six:six\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit update-ref refs/remotes/six/HEAD HEAD &&\n+\t\tmkdir six &&\n+\t\tcd six &&\n+\t\tgit init &&\n+\t\tgit fetch .. six:six\n+\t)\n '\n \n test_expect_success 'create bundle 1' '\n-\tcd \"$D\" &&\n-\techo >file updated again by origin &&\n-\tgit commit -a -m \"tip\" &&\n-\tgit bundle create --version=3 bundle1 main^..main\n+\t(\n+\t\tcd \"$D\" &&\n+\t\techo >file updated again by origin &&\n+\t\tgit commit -a -m \"tip\" &&\n+\t\tgit bundle create --version=3 bundle1 main^..main\n+\t)\n '\n \n test_expect_success 'header of bundle looks right' '\n@@ -495,43 +499,53 @@ test_expect_success 'header of bundle looks right' '\n '\n \n test_expect_success 'create bundle 2' '\n-\tcd \"$D\" &&\n-\tgit bundle create bundle2 main~2..main\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit bundle create bundle2 main~2..main\n+\t)\n '\n \n test_expect_success 'unbundle 1' '\n-\tcd \"$D/bundle\" &&\n-\tgit checkout -b some-branch &&\n-\ttest_must_fail git fetch \"$D/bundle1\" main:main\n+\t(\n+\t\tcd \"$D/bundle\" &&\n+\t\tgit checkout -b some-branch &&\n+\t\ttest_must_fail git fetch \"$D/bundle1\" main:main\n+\t)\n '\n \n \n test_expect_success 'bundle 1 has only 3 files ' '\n-\tcd \"$D\" &&\n-\ttest_bundle_object_count bundle1 3\n+\t(\n+\t\tcd \"$D\" &&\n+\t\ttest_bundle_object_count bundle1 3\n+\t)\n '\n \n test_expect_success 'unbundle 2' '\n-\tcd \"$D/bundle\" &&\n-\tgit fetch ../bundle2 main:main &&\n-\ttest \"tip\" = \"$(git log -1 --pretty=oneline main | cut -d\" \" -f2)\"\n+\t(\n+\t\tcd \"$D/bundle\" &&\n+\t\tgit fetch ../bundle2 main:main &&\n+\t\ttest \"tip\" = \"$(git log -1 --pretty=oneline main | cut -d\" \" -f2)\"\n+\t)\n '\n \n test_expect_success 'bundle does not prerequisite objects' '\n-\tcd \"$D\" &&\n-\ttouch file2 &&\n-\tgit add file2 &&\n-\tgit commit -m add.file2 file2 &&\n-\tgit bundle create bundle3 -1 HEAD &&\n-\ttest_bundle_object_count bundle3 3\n+\t(\n+\t\tcd \"$D\" &&\n+\t\ttouch file2 &&\n+\t\tgit add file2 &&\n+\t\tgit commit -m add.file2 file2 &&\n+\t\tgit bundle create bundle3 -1 HEAD &&\n+\t\ttest_bundle_object_count bundle3 3\n+\t)\n '\n \n test_expect_success 'bundle should be able to create a full history' '\n-\n-\tcd \"$D\" &&\n-\tgit tag -a -m \"1.0\" v1.0 main &&\n-\tgit bundle create bundle4 v1.0\n-\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit tag -a -m \"1.0\" v1.0 main &&\n+\t\tgit bundle create bundle4 v1.0\n+\t)\n '\n \n test_expect_success 'fetch with a non-applying branch.<name>.merge' '\n@@ -581,15 +595,16 @@ test_expect_success 'quoting of a strangely named repo' '\n '\n \n test_expect_success 'bundle should record HEAD correctly' '\n-\n-\tcd \"$D\" &&\n-\tgit bundle create bundle5 HEAD main &&\n-\tgit bundle list-heads bundle5 >actual &&\n-\tfor h in HEAD refs/heads/main\n-\tdo\n-\t\techo \"$(git rev-parse --verify $h) $h\" || return 1\n-\tdone >expect &&\n-\ttest_cmp expect actual\n+\t(\n+\t\tcd \"$D\" &&\n+\t\tgit bundle create bundle5 HEAD main &&\n+\t\tgit bundle list-heads bundle5 >actual &&\n+\t\tfor h in HEAD refs/heads/main\n+\t\tdo\n+\t\t\techo \"$(git rev-parse --verify $h) $h\" || return 1\n+\t\tdone >expect &&\n+\t\ttest_cmp expect actual\n+\t)\n \n '\n \n@@ -601,127 +616,139 @@ test_expect_success 'mark initial state of origin/main' '\n '\n \n test_expect_success 'explicit fetch should update tracking' '\n-\n-\tcd \"$D\" &&\n-\tgit branch -f side &&\n \t(\n-\t\tcd three &&\n-\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n-\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\tgit fetch origin main &&\n-\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\ttest \"$o\" != \"$n\" &&\n-\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n+\t\tcd \"$D\" &&\n+\t\tgit branch -f side &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n+\t\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\tgit fetch origin main &&\n+\t\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\ttest \"$o\" != \"$n\" &&\n+\t\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n+\t\t)\n \t)\n '\n \n test_expect_success 'explicit pull should update tracking' '\n-\n-\tcd \"$D\" &&\n-\tgit branch -f side &&\n \t(\n-\t\tcd three &&\n-\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n-\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\tgit pull origin main &&\n-\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\ttest \"$o\" != \"$n\" &&\n-\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n+\t\tcd \"$D\" &&\n+\t\tgit branch -f side &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n+\t\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\tgit pull origin main &&\n+\t\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\ttest \"$o\" != \"$n\" &&\n+\t\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n+\t\t)\n \t)\n '\n \n test_expect_success 'explicit --refmap is allowed only with command-line refspec' '\n-\tcd \"$D\" &&\n \t(\n-\t\tcd three &&\n-\t\ttest_must_fail git fetch --refmap=\"*:refs/remotes/none/*\"\n+\t\tcd \"$D\" &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\ttest_must_fail git fetch --refmap=\"*:refs/remotes/none/*\"\n+\t\t)\n \t)\n '\n \n test_expect_success 'explicit --refmap option overrides remote.*.fetch' '\n-\tcd \"$D\" &&\n-\tgit branch -f side &&\n \t(\n-\t\tcd three &&\n-\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n-\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\tgit fetch --refmap=\"refs/heads/*:refs/remotes/other/*\" origin main &&\n-\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\ttest \"$o\" = \"$n\" &&\n-\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side &&\n-\t\tgit rev-parse --verify refs/remotes/other/main\n+\t\tcd \"$D\" &&\n+\t\tgit branch -f side &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n+\t\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\tgit fetch --refmap=\"refs/heads/*:refs/remotes/other/*\" origin main &&\n+\t\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\ttest \"$o\" = \"$n\" &&\n+\t\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side &&\n+\t\t\tgit rev-parse --verify refs/remotes/other/main\n+\t\t)\n \t)\n '\n \n test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' '\n-\tcd \"$D\" &&\n-\tgit branch -f side &&\n \t(\n-\t\tcd three &&\n-\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n-\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\tgit fetch --refmap=\"\" origin main &&\n-\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\ttest \"$o\" = \"$n\" &&\n-\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n+\t\tcd \"$D\" &&\n+\t\tgit branch -f side &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n+\t\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\tgit fetch --refmap=\"\" origin main &&\n+\t\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\ttest \"$o\" = \"$n\" &&\n+\t\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/side\n+\t\t)\n \t)\n '\n \n test_expect_success 'configured fetch updates tracking' '\n-\n-\tcd \"$D\" &&\n-\tgit branch -f side &&\n \t(\n-\t\tcd three &&\n-\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n-\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\tgit fetch origin &&\n-\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\ttest \"$o\" != \"$n\" &&\n-\t\tgit rev-parse --verify refs/remotes/origin/side\n+\t\tcd \"$D\" &&\n+\t\tgit branch -f side &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n+\t\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\tgit fetch origin &&\n+\t\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\ttest \"$o\" != \"$n\" &&\n+\t\t\tgit rev-parse --verify refs/remotes/origin/side\n+\t\t)\n \t)\n '\n \n test_expect_success 'non-matching refspecs do not confuse tracking update' '\n-\tcd \"$D\" &&\n-\tgit update-ref refs/odd/location HEAD &&\n \t(\n-\t\tcd three &&\n-\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n-\t\tgit config --add remote.origin.fetch \\\n-\t\t\trefs/odd/location:refs/remotes/origin/odd &&\n-\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\tgit fetch origin main &&\n-\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n-\t\ttest \"$o\" != \"$n\" &&\n-\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/odd\n+\t\tcd \"$D\" &&\n+\t\tgit update-ref refs/odd/location HEAD &&\n+\t\t(\n+\t\t\tcd three &&\n+\t\t\tgit update-ref refs/remotes/origin/main base-origin-main &&\n+\t\t\tgit config --add remote.origin.fetch \\\n+\t\t\t\trefs/odd/location:refs/remotes/origin/odd &&\n+\t\t\to=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\tgit fetch origin main &&\n+\t\t\tn=$(git rev-parse --verify refs/remotes/origin/main) &&\n+\t\t\ttest \"$o\" != \"$n\" &&\n+\t\t\ttest_must_fail git rev-parse --verify refs/remotes/origin/odd\n+\t\t)\n \t)\n '\n \n test_expect_success 'pushing nonexistent branch by mistake should not segv' '\n-\n-\tcd \"$D\" &&\n-\ttest_must_fail git push seven no:no\n-\n+\t(\n+\t\tcd \"$D\" &&\n+\t\ttest_must_fail git push seven no:no\n+\t)\n '\n \n test_expect_success 'auto tag following fetches minimum' '\n-\n-\tcd \"$D\" &&\n-\tgit clone .git follow &&\n-\tgit checkout HEAD^0 &&\n \t(\n-\t\tfor i in 1 2 3 4 5 6 7\n-\t\tdo\n-\t\t\techo $i >>file &&\n-\t\t\tgit commit -m $i -a &&\n-\t\t\tgit tag -a -m $i excess-$i || exit 1\n-\t\tdone\n-\t) &&\n-\tgit checkout main &&\n-\t(\n-\t\tcd follow &&\n-\t\tgit fetch\n+\t\tcd \"$D\" &&\n+\t\tgit clone .git follow &&\n+\t\tgit checkout HEAD^0 &&\n+\t\t(\n+\t\t\tfor i in 1 2 3 4 5 6 7\n+\t\t\tdo\n+\t\t\t\techo $i >>file &&\n+\t\t\t\tgit commit -m $i -a &&\n+\t\t\t\tgit tag -a -m $i excess-$i || exit 1\n+\t\t\tdone\n+\t\t) &&\n+\t\tgit checkout main &&\n+\t\t(\n+\t\t\tcd follow &&\n+\t\t\tgit fetch\n+\t\t)\n \t)\n '\n \n-- \n2.35.1\n\n"},{"id":"452918","messageId":"xmqqo81kva1j.fsf@gitster.g","threadId":"57645","inReplyTo":"20220331175412.305968-1-gitter.spiros@gmail.com","subject":"Re: [PATCH] t5510-fetch: upgrade to a more modern style","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-04-01T20:11:20Z","receivedAt":"2022-04-01T20:11:50Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Elia Pinto <gitter.spiros@gmail.com> writes:\n\n> Clean up the code style so all the tests, and not just a few,\n> that chdir around isolate themselves in a subshell.\n>\n> Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>\n> ---\n> this patch was inspired by a Junio #leftoverbit\n> https://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/\n>  t/t5510-fetch.sh | 927 ++++++++++++++++++++++++-----------------------\n>  1 file changed, 477 insertions(+), 450 deletions(-)\n>\n> diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\n> index 6f38a69fbb..d0b249d276 100755\n> --- a/t/t5510-fetch.sh\n> +++ b/t/t5510-fetch.sh\n> @@ -48,342 +48,349 @@ test_expect_success \"clone and setup child repos\" '\n>  '\n>  \n>  test_expect_success \"fetch test\" '\n> -\tcd \"$D\" &&\n> -\techo >file updated by origin &&\n> -\tgit commit -a -m \"updated by origin\" &&\n> -\tcd two &&\n> -\tgit fetch &&\n> -\tgit rev-parse --verify refs/heads/one &&\n> -\tmine=$(git rev-parse refs/heads/one) &&\n> -\this=$(cd ../one && git rev-parse refs/heads/main) &&\n> -\ttest \"z$mine\" = \"z$his\"\n> +\t(\n> +\t\tcd \"$D\" &&\n> +\t\techo >file updated by origin &&\n> +\t\tgit commit -a -m \"updated by origin\" &&\n> +\t\t(\n> +\t\t\tcd two &&\n> +\t\t\tgit fetch &&\n> +\t\t\tgit rev-parse --verify refs/heads/one &&\n> +\t\t\tmine=$(git rev-parse refs/heads/one) &&\n> +\t\t\this=$(cd ../one && git rev-parse refs/heads/main) &&\n> +\t\t\ttest \"z$mine\" = \"z$his\"\n> +\t\t)\n> +\t)\n>  '\n\nI think the idea of the \"first unconditionally go to $D and then do\nthese things\" pattern was that these tests anticipate that the step\nbefore them will leave the process in an unexpected directory when\nthey begin.  If the original version of this test fails when we\ncreated the first commit \"updated by origin\", the next test piece\nwill start in \"$D\" directory, and if we successfully run it to the\nend, the next test piece will start in \"$D/ two\".\n\nNow, the point of this patch is to make sure each test piece will\nnot chdir around by isolating the parts that run in different\ndirectories inside subshells.  The purpose of doing so is?  It is to\nrelieve later tests from having to worry about \"going back to the\nknown starting place\".\n\nSo, it is dubious that we want the subshell around the whole thing,\nwhose first command is to go to \"$D\", after we apply this patch.\nRemoval of that part was the primary reason why we are writing this\npatch.\n\nSo I'd expect that the above test piece would become more like\nin \"git diff -w\" output.\n\nIt is important to notice that the reason why we had 'cd \"$D\"' in\nthis test is *not* because the previous test has chdir'ed around,\nbut to look similar to later tests in the series.\n\nThanks.\n\n\ndiff --git c/t/t5510-fetch.sh w/t/t5510-fetch.sh\nindex 6f38a69fbb..1ed27607e2 100755\n--- c/t/t5510-fetch.sh\n+++ w/t/t5510-fetch.sh\n@@ -48,15 +48,16 @@ test_expect_success \"clone and setup child repos\" '\n '\n \n test_expect_success \"fetch test\" '\n-\tcd \"$D\" &&\n \techo >file updated by origin &&\n \tgit commit -a -m \"updated by origin\" &&\n+\t(\n \t\tcd two &&\n \t\tgit fetch &&\n \t\tgit rev-parse --verify refs/heads/one &&\n \t\tmine=$(git rev-parse refs/heads/one) &&\n \t\this=$(cd ../one && git rev-parse refs/heads/main) &&\n \t\ttest \"z$mine\" = \"z$his\"\n+\t)\n '\n \n test_expect_success \"fetch test for-merge\" '\n"},{"id":"452923","messageId":"220402.86v8vsmg5r.gmgdl@evledraar.gmail.com","threadId":"57645","inReplyTo":"20220331175412.305968-1-gitter.spiros@gmail.com","subject":"Re: [PATCH] t5510-fetch: upgrade to a more modern style","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2022-04-02T01:14:37Z","receivedAt":"2022-04-02T01:24:06Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Thu, Mar 31 2022, Elia Pinto wrote:\n\n> Clean up the code style so all the tests, and not just a few,\n> that chdir around isolate themselves in a subshell.\n\nSounds sensible.\n\n>  test_expect_success \"fetch test\" '\n> -\tcd \"$D\" &&\n> -\techo >file updated by origin &&\n> -\tgit commit -a -m \"updated by origin\" &&\n> -\tcd two &&\n> -\tgit fetch &&\n> -\tgit rev-parse --verify refs/heads/one &&\n> -\tmine=$(git rev-parse refs/heads/one) &&\n> -\this=$(cd ../one && git rev-parse refs/heads/main) &&\n> -\ttest \"z$mine\" = \"z$his\"\n> +\t(\n> +\t\tcd \"$D\" &&\n> +\t\techo >file updated by origin &&\n> +\t\tgit commit -a -m \"updated by origin\" &&\n> +\t\t(\n> +\t\t\tcd two &&\n\nWhy the two levels of subshelling though? We don't need a new one every\ntime we change directories, or do we?\n\nThe point is usually to avoid cd-ing in our main shell, not that each\nlevel needs a new shell & indentation...\n\n> -\ttest_cmp expected actual'\n> +\t(\n> +\t\tcd \"$D\" &&\n> +\t\t(\n> +\t\t\tcd three &&\n\nditto..\n\n> +\t\t\tgit fetch &&\n> +\t\t\tgit rev-parse --verify refs/heads/two &&\n> +\t\t\tgit rev-parse --verify refs/heads/one &&\n\nFWIW an alternative here is to use git -C \"$D/three\", but that may end\nup being too verbose..\n\n>  test_expect_success 'fetch --prune handles overlapping refspecs' '\n> -\tcd \"$D\" &&\n> -\tgit update-ref refs/pull/42/head main &&\n> -\tgit clone . prune-overlapping &&\n> -\tcd prune-overlapping &&\n> -\tgit config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n> -\n> -\tgit fetch --prune origin &&\n> -\tgit rev-parse origin/main &&\n> -\tgit rev-parse origin/pr/42 &&\n> -\n> -\tgit config --unset-all remote.origin.fetch &&\n> -\tgit config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n> -\tgit config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&\n> -\n> -\tgit fetch --prune origin &&\n> -\tgit rev-parse origin/main &&\n> -\tgit rev-parse origin/pr/42\n> +\t(\n> +\t\tcd \"$D\" &&\n> +\t\tgit update-ref refs/pull/42/head main &&\n> +\t\tgit clone . prune-overlapping &&\n> +\t\tcd prune-overlapping &&\n> +\t\tgit config --add remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n> +\t\tgit fetch --prune origin &&\n> +\t\tgit rev-parse origin/main &&\n> +\t\tgit rev-parse origin/pr/42 &&\n> +\t\tgit config --unset-all remote.origin.fetch &&\n> +\t\tgit config remote.origin.fetch refs/pull/*/head:refs/remotes/origin/pr/* &&\n> +\t\tgit config --add remote.origin.fetch refs/heads/*:refs/remotes/origin/* &&\n> +\t\tgit fetch --prune origin &&\n> +\t\tgit rev-parse origin/main &&\n> +\t\tgit rev-parse origin/pr/42\n> +\t)\n>  '\n\nPlease don't lose grouping whitespace while at it.  I.e. the pre-image\nintentionally splits \"steps\" by \\n\\n.\n\n>  \n>  test_expect_success 'fetch --prune --tags prunes branches but not tags' '\n> -\tcd \"$D\" &&\n> -\tgit clone . prune-tags &&\n> -\tcd prune-tags &&\n> -\tgit tag sometag main &&\n> -\t# Create what looks like a remote-tracking branch from an earlier\n> -\t# fetch that has since been deleted from the remote:\n> -\tgit update-ref refs/remotes/origin/fake-remote main &&\n> -\n> -\tgit fetch --prune --tags origin &&\n> -\tgit rev-parse origin/main &&\n> -\ttest_must_fail git rev-parse origin/fake-remote &&\n> -\tgit rev-parse sometag\n> +\t(\n> +\t\tcd \"$D\" &&\n> +\t\tgit clone . prune-tags &&\n> +\t\tcd prune-tags &&\n> +\t\tgit tag sometag main &&\n> +\t\t# Create what looks like a remote-tracking branch from an earlier\n> +\t\t# fetch that has since been deleted from the remote:\n> +\t\tgit update-ref refs/remotes/origin/fake-remote main &&\n> +\t\tgit fetch --prune --tags origin &&\n> +\t\tgit rev-parse origin/main &&\n> +\t\ttest_must_fail git rev-parse origin/fake-remote &&\n> +\t\tgit rev-parse sometag\n> +\t)\n>  '\n>  \n>  test_expect_success 'fetch --prune --tags with branch does not prune other things' '\n> -\tcd \"$D\" &&\n> -\tgit clone . prune-tags-branch &&\n> -\tcd prune-tags-branch &&\n> -\tgit tag sometag main &&\n> -\tgit update-ref refs/remotes/origin/extrabranch main &&\n> -\n> -\tgit fetch --prune --tags origin main &&\n> -\tgit rev-parse origin/extrabranch &&\n> -\tgit rev-parse sometag\n> +\t(\n> +\t\tcd \"$D\" &&\n> +\t\tgit clone . prune-tags-branch &&\n> +\t\tcd prune-tags-branch &&\n> +\t\tgit tag sometag main &&\n> +\t\tgit update-ref refs/remotes/origin/extrabranch main &&\n> +\t\tgit fetch --prune --tags origin main &&\n> +\t\tgit rev-parse origin/extrabranch &&\n> +\t\tgit rev-parse sometag\n> +\t)\n>  '\n\nSkimming these these seem like much of the same code over & over again\nwith tiny variations. Perhaps even better would be splitting much of\nthis into a helper function(s)?\n\n> -\tgit -C atomic fetch --atomic origin &&\n> -\tgit -C atomic rev-parse origin/atomic-branch >actual &&\n> -\ttest_cmp expected actual &&\n> -\ttest $oid = \"$(git -C atomic rev-parse --verify FETCH_HEAD)\"\n> +\t(\n> +\t\tcd \"$D\" &&\n> +\t\tgit clone . atomic &&\n> +\t\tgit branch atomic-branch &&\n> +\t\toid=$(git rev-parse atomic-branch) &&\n> +\t\techo \"$oid\" >expected &&\n> +\t\tgit -C atomic fetch --atomic origin &&\n> +\t\tgit -C atomic rev-parse origin/atomic-branch >actual &&\n> +\t\ttest_cmp expected actual &&\n> +\t\ttest $oid = \"$(git -C atomic rev-parse --verify FETCH_HEAD)\"\n\nspeaking of modern style, perhaps it's worth it to fix these exit code\nhiding issues? I.e. use test_cmp, test_cmp_rev etc.\n\n> +\t\thead_oid=$(git rev-parse HEAD) &&\n> +\t\tcat >expected <<-EOF &&\n> +\t\t\tprepared\n> +\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1\n> +\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2\n> +\t\t\tcommitted\n> +\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-1\n> +\t\t\t$ZERO_OID $head_oid refs/remotes/origin/atomic-hooks-2\n> +\t\tEOF\n\nThere was a discussion on-list the other day about how this particular\nhere-doc style is the odd one out, and we'd prefer the content aligned\nwith the \"cat\".\n\nSo if we're re-indenting all of these that would be a nice change while\nwe're at it, particularly as it would make the diff smaller, they'd\nalready be at the \"right\" indent level.\n"},{"id":"452924","messageId":"CA+EOSBmGkgi4EmEXnu8PQ6VhZ7jLoa_fjV03fYFeihdN3hCk_g@mail.gmail.com","threadId":"57645","inReplyTo":"xmqqo81kva1j.fsf@gitster.g","subject":"Re: [PATCH] t5510-fetch: upgrade to a more modern style","fromName":"Elia Pinto","fromEmail":"gitter.spiros@gmail.com","sentAt":"2022-04-02T07:32:03Z","receivedAt":"2022-04-02T07:32:14Z","isPatch":true,"sender":{"key":"gitter.spiros@gmail.com","avatar":"https://avatars.githubusercontent.com/u/158490?v=4"},"body":"Il giorno ven 1 apr 2022 alle ore 22:11 Junio C Hamano\n<gitster@pobox.com> ha scritto:\n>\n> Elia Pinto <gitter.spiros@gmail.com> writes:\n>\n> > Clean up the code style so all the tests, and not just a few,\n> > that chdir around isolate themselves in a subshell.\n> >\n> > Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>\n> > ---\n> > this patch was inspired by a Junio #leftoverbit\n> > https://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/\n> >  t/t5510-fetch.sh | 927 ++++++++++++++++++++++++-----------------------\n> >  1 file changed, 477 insertions(+), 450 deletions(-)\n> >\n> > diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh\n> > index 6f38a69fbb..d0b249d276 100755\n> > --- a/t/t5510-fetch.sh\n> > +++ b/t/t5510-fetch.sh\n> > @@ -48,342 +48,349 @@ test_expect_success \"clone and setup child repos\" '\n> >  '\n> >\n> >  test_expect_success \"fetch test\" '\n> > -     cd \"$D\" &&\n> > -     echo >file updated by origin &&\n> > -     git commit -a -m \"updated by origin\" &&\n> > -     cd two &&\n> > -     git fetch &&\n> > -     git rev-parse --verify refs/heads/one &&\n> > -     mine=$(git rev-parse refs/heads/one) &&\n> > -     his=$(cd ../one && git rev-parse refs/heads/main) &&\n> > -     test \"z$mine\" = \"z$his\"\n> > +     (\n> > +             cd \"$D\" &&\n> > +             echo >file updated by origin &&\n> > +             git commit -a -m \"updated by origin\" &&\n> > +             (\n> > +                     cd two &&\n> > +                     git fetch &&\n> > +                     git rev-parse --verify refs/heads/one &&\n> > +                     mine=$(git rev-parse refs/heads/one) &&\n> > +                     his=$(cd ../one && git rev-parse refs/heads/main) &&\n> > +                     test \"z$mine\" = \"z$his\"\n> > +             )\n> > +     )\n> >  '\n>\n> I think the idea of the \"first unconditionally go to $D and then do\n> these things\" pattern was that these tests anticipate that the step\n> before them will leave the process in an unexpected directory when\n> they begin.  If the original version of this test fails when we\n> created the first commit \"updated by origin\", the next test piece\n> will start in \"$D\" directory, and if we successfully run it to the\n> end, the next test piece will start in \"$D/ two\".\n>\n> Now, the point of this patch is to make sure each test piece will\n> not chdir around by isolating the parts that run in different\n> directories inside subshells.  The purpose of doing so is?  It is to\n> relieve later tests from having to worry about \"going back to the\n> known starting place\".\n>\n> So, it is dubious that we want the subshell around the whole thing,\n> whose first command is to go to \"$D\", after we apply this patch.\n> Removal of that part was the primary reason why we are writing this\n> patch.\nThat is fine. I had misinterpreted your answer here\nhttps://lore.kernel.org/git/xmqqmtjh0x5f.fsf@gitster.g/\n\nSo the right thing to do is to leave \"cd $ D\" not in a subshell while\nthe actual test yes.\nBut at this point \"cd $D\" should be removed from subsequent tests, as\nit is redundant.\nIn fact, if the first test of the chain fails, all the others would\nalways execute\nwith the current directory equal to $D for sure.\n>\n> So I'd expect that the above test piece would become more like\n> in \"git diff -w\" output.\n>\n> It is important to notice that the reason why we had 'cd \"$D\"' in\n> this test is *not* because the previous test has chdir'ed around,\n> but to look similar to later tests in the series.\n>\n> Thanks.\n>\n>\n> diff --git c/t/t5510-fetch.sh w/t/t5510-fetch.sh\n> index 6f38a69fbb..1ed27607e2 100755\n> --- c/t/t5510-fetch.sh\n> +++ w/t/t5510-fetch.sh\n> @@ -48,15 +48,16 @@ test_expect_success \"clone and setup child repos\" '\n>  '\n>\n>  test_expect_success \"fetch test\" '\n> -       cd \"$D\" &&\n>         echo >file updated by origin &&\n>         git commit -a -m \"updated by origin\" &&\n> +       (\n>                 cd two &&\n>                 git fetch &&\n>                 git rev-parse --verify refs/heads/one &&\n>                 mine=$(git rev-parse refs/heads/one) &&\n>                 his=$(cd ../one && git rev-parse refs/heads/main) &&\n>                 test \"z$mine\" = \"z$his\"\n> +       )\n>  '\n>\n>  test_expect_success \"fetch test for-merge\" '\n"}]}