package serverinfo import ( "io" "strings" "testing" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/memfs" fixtures "github.com/go-git/go-git-fixtures/v4" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/plumbing/storer" "github.com/go-git/go-git/v5/storage" "github.com/go-git/go-git/v5/storage/memory" . "gopkg.in/check.v1" ) type ServerInfoSuite struct{} var _ = Suite(&ServerInfoSuite{}) func Test(t *testing.T) { TestingT(t) } func (s *ServerInfoSuite) TestUpdateServerInfoInit(c *C) { fs := memfs.New() st := memory.NewStorage() r, err := git.Init(st, fs) c.Assert(err, IsNil) c.Assert(r, NotNil) err = UpdateServerInfo(st, fs) c.Assert(err, IsNil) } func assertInfoRefs(c *C, st storage.Storer, fs billy.Filesystem) { refsFile, err := fs.Open("info/refs") c.Assert(err, IsNil) defer refsFile.Close() bts, err := io.ReadAll(refsFile) c.Assert(err, IsNil) localRefs := make(map[plumbing.ReferenceName]plumbing.Hash) for _, line := range strings.Split(string(bts), "\n") { if line == "" { continue } parts := strings.Split(line, "\t") c.Assert(parts, HasLen, 2) hash := plumbing.NewHash(parts[0]) name := plumbing.ReferenceName(parts[1]) localRefs[name] = hash } refs, err := st.IterReferences() c.Assert(err, IsNil) err = refs.ForEach(func(ref *plumbing.Reference) error { name := ref.Name() hash := ref.Hash() switch ref.Type() { case plumbing.SymbolicReference: if name == plumbing.HEAD { return nil } ref, err := st.Reference(ref.Target()) c.Assert(err, IsNil) hash = ref.Hash() fallthrough case plumbing.HashReference: h, ok := localRefs[name] c.Assert(ok, Equals, true) c.Assert(h, Equals, hash) if name.IsTag() { tag, err := object.GetTag(st, hash) if err == nil { t, ok := localRefs[name+"^{}"] c.Assert(ok, Equals, true) c.Assert(t, Equals, tag.Target) } } } return nil }) c.Assert(err, IsNil) } func assertObjectPacks(c *C, st storage.Storer, fs billy.Filesystem) { infoPacks, err := fs.Open("objects/info/packs") c.Assert(err, IsNil) defer infoPacks.Close() bts, err := io.ReadAll(infoPacks) c.Assert(err, IsNil) pos, ok := st.(storer.PackedObjectStorer) c.Assert(ok, Equals, true) localPacks := make(map[string]struct{}) packs, err := pos.ObjectPacks() c.Assert(err, IsNil) for _, line := range strings.Split(string(bts), "\n") { if line == "" { continue } parts := strings.Split(line, " ") c.Assert(parts, HasLen, 2) pack := strings.TrimPrefix(parts[1], "pack-") pack = strings.TrimSuffix(pack, ".pack") localPacks[pack] = struct{}{} } for _, p := range packs { _, ok := localPacks[p.String()] c.Assert(ok, Equals, true) } } func (s *ServerInfoSuite) TestUpdateServerInfoTags(c *C) { fs := memfs.New() st := memory.NewStorage() r, err := git.Clone(st, fs, &git.CloneOptions{ URL: fixtures.ByURL("https://github.com/git-fixtures/tags.git").One().URL, }) c.Assert(err, IsNil) c.Assert(r, NotNil) err = UpdateServerInfo(st, fs) c.Assert(err, IsNil) assertInfoRefs(c, st, fs) assertObjectPacks(c, st, fs) } func (s *ServerInfoSuite) TestUpdateServerInfoBasic(c *C) { fs := memfs.New() st := memory.NewStorage() r, err := git.Clone(st, fs, &git.CloneOptions{ URL: fixtures.Basic().One().URL, }) c.Assert(err, IsNil) c.Assert(r, NotNil) err = UpdateServerInfo(st, fs) c.Assert(err, IsNil) assertInfoRefs(c, st, fs) assertObjectPacks(c, st, fs) } func (s *ServerInfoSuite) TestUpdateServerInfoBasicChange(c *C) { fs := memfs.New() st := memory.NewStorage() r, err := git.Clone(st, fs, &git.CloneOptions{ URL: fixtures.Basic().One().URL, }) c.Assert(err, IsNil) c.Assert(r, NotNil) err = UpdateServerInfo(st, fs) c.Assert(err, IsNil) assertInfoRefs(c, st, fs) assertObjectPacks(c, st, fs) head, err := r.Head() c.Assert(err, IsNil) ref := plumbing.NewHashReference("refs/heads/my-branch", head.Hash()) err = r.Storer.SetReference(ref) c.Assert(err, IsNil) _, err = r.CreateTag("test-tag", head.Hash(), &git.CreateTagOptions{ Message: "test-tag", }) c.Assert(err, IsNil) err = UpdateServerInfo(st, fs) assertInfoRefs(c, st, fs) assertObjectPacks(c, st, fs) }