On Thu, Apr 22, 2021 at 03:01:01PM +0200, Han-Wen Nienhuys wrote: > On Thu, Apr 22, 2021 at 6:59 AM SZEDER Gábor <szeder.dev@xxxxxxxxx> wrote: > > > See the comment above the changed line: we don't want auto-detection > > > to clobber the surrounding git repo. > > > > Indeed, but then this is not a faithful conversion of the original. > > That 'echo' will write sane content to HEAD no matter what state the > > repository is in. That 'symbolic-ref' command, however, won't, > > because 'git --git-dir .git' turns off only repository discovery, but > > not repository verification, and in case of a corrupt '.git/HEAD' it > > will bail out. > > > > $ cd test > > $ git init > > Initialized empty Git repository in /home/szeder/src/git/test/.git/ > > $ git commit --allow-empty -m initial > > [master (root-commit) ec0df0b] initial > > $ echo "foo bar baz" >.git/HEAD > > $ git --git-dir .git symbolic-ref HEAD refs/heads/master > > fatal: not a git repository: '.git' > > But then it's working as intended, no? It will not corrupt the > surrounding repository. No, it definitely does not. If one of the test cases fails because 'git symbolic-ref' were to write bogus content to HEAD, then that new 'git symbolic-ref' invocation in reset_to_sane() will not corrupt the surrounding repository, but, crucially, it won't restore the test repository's HEAD to a sane state either, and git commands invoked in subsequent tests won't recognize the trash dir as their git repository, and will operate on the surrounding repo instead: ~/src/git/t (master)$ vim t/t1401-symbolic-ref.sh ~/src/git/t (master *)$ git diff diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh index a4ebb0b65f..8f8d93bf6a 100755 --- a/t/t1401-symbolic-ref.sh +++ b/t/t1401-symbolic-ref.sh @@ -23,7 +23,11 @@ test_expect_success 'symbolic-ref reads HEAD' ' ' test_expect_success 'symbolic-ref refuses non-ref for HEAD' ' - test_must_fail git symbolic-ref HEAD foo + #test_must_fail git symbolic-ref HEAD foo && + # Lets pretend that the above "git symbolic-ref" did write that + # bogus content to HEAD: + echo foo >.git/HEAD && + false ' reset_to_sane ~/src/git/t (master *)$ ./t1401-symbolic-ref.sh ok 1 - symbolic-ref writes HEAD ok 2 - symbolic-ref reads HEAD not ok 3 - symbolic-ref refuses non-ref for HEAD # # #test_must_fail git symbolic-ref HEAD foo && # # Lets pretend that the above "git symbolic-ref" did write that # # bogus content to HEAD: # echo foo >.git/HEAD && # false # ok 4 - symbolic-ref refuses bare sha1 ok 5 - HEAD cannot be removed ok 6 - symbolic-ref can be deleted ok 7 - symbolic-ref can delete dangling symref ok 8 - symbolic-ref fails to delete missing FOO ok 9 - symbolic-ref fails to delete real ref ok 10 - create large ref name ok 11 - symbolic-ref can point to large ref name ok 12 - we can parse long symbolic ref ok 13 - symbolic-ref reports failure in exit code ok 14 - symbolic-ref writes reflog entry ok 15 - symbolic-ref does not create ref d/f conflicts ok 16 - symbolic-ref can overwrite pointer to invalid name ok 17 - symbolic-ref can resolve d/f name (EISDIR) ok 18 - symbolic-ref can resolve d/f name (ENOTDIR) # failed 1 among 18 test(s) 1..18 ~/src/git/t (master *)$ OK, only one test failed, and the surrounding repo is not affected. No lets switch to your 'git symbolic-ref command in reset_to_sane(): ~/src/git/t (master *)$ vim t/t1401-symbolic-ref.sh ~/src/git/t (master *)$ git diff diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh index a4ebb0b65f..6ef221d1bb 100755 --- a/t/t1401-symbolic-ref.sh +++ b/t/t1401-symbolic-ref.sh @@ -7,7 +7,8 @@ test_description='basic symbolic-ref tests' # the git repo, meaning that further tests will operate on # the surrounding git repo instead of the trash directory. reset_to_sane() { - echo ref: refs/heads/foo >.git/HEAD + #echo ref: refs/heads/foo >.git/HEAD + git --git-dir .git symbolic-ref HEAD refs/heads/foo } test_expect_success 'symbolic-ref writes HEAD' ' @@ -23,7 +24,11 @@ test_expect_success 'symbolic-ref reads HEAD' ' ' test_expect_success 'symbolic-ref refuses non-ref for HEAD' ' - test_must_fail git symbolic-ref HEAD foo + #test_must_fail git symbolic-ref HEAD foo && + # Lets pretend that the above "git symbolic-ref" did write that + # bogus content to HEAD: + echo foo >.git/HEAD && + false ' reset_to_sane ~/src/git/t (master *)$ ./t1401-symbolic-ref.sh ok 1 - symbolic-ref writes HEAD ok 2 - symbolic-ref reads HEAD not ok 3 - symbolic-ref refuses non-ref for HEAD # # #test_must_fail git symbolic-ref HEAD foo && # # Lets pretend that the above "git symbolic-ref" did write that # # bogus content to HEAD: # echo foo >.git/HEAD && # false # fatal: not a git repository: '.git' not ok 4 - symbolic-ref refuses bare sha1 # # echo content >file && git add file && git commit -m one && # test_must_fail git symbolic-ref HEAD $(git rev-parse HEAD) # fatal: not a git repository: '.git' ok 5 - HEAD cannot be removed fatal: not a git repository: '.git' not ok 6 - symbolic-ref can be deleted # # git symbolic-ref NOTHEAD refs/heads/foo && # git symbolic-ref -d NOTHEAD && # test_path_is_file .git/refs/heads/foo && # test_path_is_missing .git/NOTHEAD # fatal: not a git repository: '.git' ok 7 - symbolic-ref can delete dangling symref fatal: not a git repository: '.git' ok 8 - symbolic-ref fails to delete missing FOO fatal: not a git repository: '.git' not ok 9 - symbolic-ref fails to delete real ref # # echo "fatal: Cannot delete refs/heads/foo, not a symbolic ref" >expect && # test_must_fail git symbolic-ref -d refs/heads/foo >actual 2>&1 && # git rev-parse --verify refs/heads/foo && # test_cmp expect actual # fatal: not a git repository: '.git' ok 10 - create large ref name ok 11 - symbolic-ref can point to large ref name ok 12 - we can parse long symbolic ref not ok 13 - symbolic-ref reports failure in exit code # # test_when_finished "rm -f .git/HEAD.lock" && # >.git/HEAD.lock && # test_must_fail git symbolic-ref HEAD refs/heads/whatever # not ok 14 - symbolic-ref writes reflog entry # # git checkout -b log1 && # test_commit one && # git checkout -b log2 && # test_commit two && # git checkout --orphan orphan && # git symbolic-ref -m create HEAD refs/heads/log1 && # git symbolic-ref -m update HEAD refs/heads/log2 && # cat >expect <<-\EOF && # update # create # EOF # git log --format=%gs -g -2 >actual && # test_cmp expect actual # not ok 15 - symbolic-ref does not create ref d/f conflicts # # git checkout -b df && # test_commit df && # test_must_fail git symbolic-ref refs/heads/df/conflict refs/heads/df && # git pack-refs --all --prune && # test_must_fail git symbolic-ref refs/heads/df/conflict refs/heads/df # not ok 16 - symbolic-ref can overwrite pointer to invalid name # # test_when_finished reset_to_sane && # head=$(git rev-parse HEAD) && # git symbolic-ref HEAD refs/heads/outer && # test_when_finished "git update-ref -d refs/heads/outer/inner" && # git update-ref refs/heads/outer/inner $head && # git symbolic-ref HEAD refs/heads/unrelated # not ok 17 - symbolic-ref can resolve d/f name (EISDIR) # # test_when_finished reset_to_sane && # head=$(git rev-parse HEAD) && # git symbolic-ref HEAD refs/heads/outer/inner && # test_when_finished "git update-ref -d refs/heads/outer" && # git update-ref refs/heads/outer $head && # echo refs/heads/outer/inner >expect && # git symbolic-ref HEAD >actual && # test_cmp expect actual # not ok 18 - symbolic-ref can resolve d/f name (ENOTDIR) # # test_when_finished reset_to_sane && # head=$(git rev-parse HEAD) && # git symbolic-ref HEAD refs/heads/outer && # test_when_finished "git update-ref -d refs/heads/outer/inner" && # git update-ref refs/heads/outer/inner $head && # echo refs/heads/outer >expect && # git symbolic-ref HEAD >actual && # test_cmp expect actual # # failed 10 among 18 test(s) 1..18 Uh-oh, a lot more tests failes, and, much worse!, my git repo is now on a different and orphaned branch: ~/src/git/t (df *+)$ git status On branch df No commits yet Changes to be committed: [...] > I see it as the test writer's job to clean up to the extent that > git-symbolic-ref can reset to a sane state. No, it's the job of whoever updates the cleanup routine to make sure that the updated cleanup routine still works just as well as it did in the past. > We could reset back to a known state in a more drastic manner > (extracting .git from a tar archive), but that could interfere with > the test functions if they're not isolated from each other.