diff options
author | Javier Alvarez Garcia <ja@daedalean.ai> | 2024-06-17 19:10:33 +0200 |
---|---|---|
committer | Javier Alvarez <javier.alvarez@allthingsembedded.net> | 2024-06-29 01:46:58 +0200 |
commit | 101c1ab3deb100eb9522c689bc8bdaa0728373fd (patch) | |
tree | 306cd4cd24b882243cff0bda190d059aa8382023 /storage/filesystem/dotgit/dotgit_test.go | |
parent | 1e72372fced2c3b5300f1408e6e71b1a50adc6e3 (diff) | |
download | go-git-101c1ab3deb100eb9522c689bc8bdaa0728373fd.tar.gz |
storage: Fix reference updated concurrently error for the filesystem storer
If a reference exists in the packed refs file but not in the actual
refs folder, we need to fall back to reading the pack refs file when
storing the reference.
This happens because by the time we are storing the reference, we open
the file with write permissions and read from it. At that point, if the
file is empty, we still need to read the valid reference. Otherwise, it
will read 0, and assume that the references do not match (because the
old value was read from the packed file).
Diffstat (limited to 'storage/filesystem/dotgit/dotgit_test.go')
-rw-r--r-- | storage/filesystem/dotgit/dotgit_test.go | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/storage/filesystem/dotgit/dotgit_test.go b/storage/filesystem/dotgit/dotgit_test.go index c224397..be66fee 100644 --- a/storage/filesystem/dotgit/dotgit_test.go +++ b/storage/filesystem/dotgit/dotgit_test.go @@ -16,6 +16,7 @@ import ( "github.com/go-git/go-billy/v5/util" fixtures "github.com/go-git/go-git-fixtures/v4" "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/storage" "github.com/stretchr/testify/assert" . "gopkg.in/check.v1" ) @@ -1046,3 +1047,63 @@ func (s *SuiteDotGit) TestDeletedRefs(c *C) { c.Assert(refs, HasLen, 1) c.Assert(refs[0].Name(), Equals, plumbing.ReferenceName("refs/heads/foo")) } + +// Checks that seting a reference that has been packed and checking its old value is successful +func (s *SuiteDotGit) TestSetPackedRef(c *C) { + fs, clean := s.TemporalFilesystem() + defer clean() + + dir := New(fs) + + err := dir.SetRef(plumbing.NewReferenceFromStrings( + "refs/heads/foo", + "e8d3ffab552895c19b9fcf7aa264d277cde33881", + ), nil) + c.Assert(err, IsNil) + + refs, err := dir.Refs() + c.Assert(err, IsNil) + c.Assert(refs, HasLen, 1) + looseCount, err := dir.CountLooseRefs() + c.Assert(err, IsNil) + c.Assert(looseCount, Equals, 1) + + err = dir.PackRefs() + c.Assert(err, IsNil) + + // Make sure the refs are still there, but no longer loose. + refs, err = dir.Refs() + c.Assert(err, IsNil) + c.Assert(refs, HasLen, 1) + looseCount, err = dir.CountLooseRefs() + c.Assert(err, IsNil) + c.Assert(looseCount, Equals, 0) + + ref, err := dir.Ref("refs/heads/foo") + c.Assert(err, IsNil) + c.Assert(ref, NotNil) + c.Assert(ref.Hash().String(), Equals, "e8d3ffab552895c19b9fcf7aa264d277cde33881") + + // Attempt to update the reference using an invalid old reference value + err = dir.SetRef(plumbing.NewReferenceFromStrings( + "refs/heads/foo", + "b8d3ffab552895c19b9fcf7aa264d277cde33881", + ), plumbing.NewReferenceFromStrings( + "refs/heads/foo", + "e8d3ffab552895c19b9fcf7aa264d277cde33882", + )) + c.Assert(err, Equals, storage.ErrReferenceHasChanged) + + // Now update the reference and it should pass + err = dir.SetRef(plumbing.NewReferenceFromStrings( + "refs/heads/foo", + "b8d3ffab552895c19b9fcf7aa264d277cde33881", + ), plumbing.NewReferenceFromStrings( + "refs/heads/foo", + "e8d3ffab552895c19b9fcf7aa264d277cde33881", + )) + c.Assert(err, IsNil) + looseCount, err = dir.CountLooseRefs() + c.Assert(err, IsNil) + c.Assert(looseCount, Equals, 1) +} |