From 916755f7652d4a3189aa717c7f2668c9aa0b1373 Mon Sep 17 00:00:00 2001 From: Joshua Sjoding Date: Fri, 19 Feb 2016 15:42:00 -0800 Subject: Improved support for Blob objects --- commit.go | 2 +- common_test.go | 2 +- repository.go | 38 ++++++++++++++++++++++++++------------ tag.go | 34 ++++++++++++++++++++++++++++------ tag_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 20 deletions(-) diff --git a/commit.go b/commit.go index 9e499d2..492a928 100644 --- a/commit.go +++ b/commit.go @@ -29,7 +29,7 @@ type Commit struct { } func (c *Commit) Tree() *Tree { - tree, _ := c.r.Tree(c.tree) + tree, _ := c.r.Tree(c.tree) // FIXME: Return error as well? return tree } diff --git a/common_test.go b/common_test.go index fe8227b..53160a7 100644 --- a/common_test.go +++ b/common_test.go @@ -71,7 +71,7 @@ func unpackFixtures(c *C, fixtures ...[]packedFixture) map[string]*Repository { c.Assert(err, IsNil) r := packfile.NewReader(d) - r.Format = packfile.OFSDeltaFormat // TODO: how to know the format of a pack file ahead of time? + r.Format = packfile.OFSDeltaFormat // This is hardcoded because we don't have a good way to sniff the format _, err = r.Read(repos[fixture.url].Storage) c.Assert(err, IsNil) diff --git a/repository.go b/repository.go index a553f91..cce7097 100644 --- a/repository.go +++ b/repository.go @@ -110,8 +110,8 @@ func (r *Repository) Commits() *CommitIter { return NewCommitIter(r, r.Storage.Iter(core.CommitObject)) } -// Tag returns a tag with the given hash. -func (r *Repository) Tag(h core.Hash) (*Tag, error) { +// Tree return the tree with the given hash +func (r *Repository) Tree(h core.Hash) (*Tree, error) { obj, err := r.Storage.Get(h) if err != nil { if err == core.ObjectNotFoundErr { @@ -120,18 +120,26 @@ func (r *Repository) Tag(h core.Hash) (*Tag, error) { return nil, err } - tag := &Tag{r: r} - return tag, tag.Decode(obj) + tree := &Tree{r: r} + return tree, tree.Decode(obj) } -// Tags returns a TagIter that can step through all of the annotated tags -// in the repository. -func (r *Repository) Tags() *TagIter { - return NewTagIter(r, r.Storage.Iter(core.TagObject)) +// Blob returns the blob with the given hash +func (r *Repository) Blob(h core.Hash) (*Blob, error) { + obj, err := r.Storage.Get(h) + if err != nil { + if err == core.ObjectNotFoundErr { + return nil, ObjectNotFoundErr + } + return nil, err + } + + blob := &Blob{} + return blob, blob.Decode(obj) } -// Tree return the tree with the given hash -func (r *Repository) Tree(h core.Hash) (*Tree, error) { +// Tag returns a tag with the given hash. +func (r *Repository) Tag(h core.Hash) (*Tag, error) { obj, err := r.Storage.Get(h) if err != nil { if err == core.ObjectNotFoundErr { @@ -140,6 +148,12 @@ func (r *Repository) Tree(h core.Hash) (*Tree, error) { return nil, err } - tree := &Tree{r: r} - return tree, tree.Decode(obj) + tag := &Tag{r: r} + return tag, tag.Decode(obj) +} + +// Tags returns a TagIter that can step through all of the annotated tags +// in the repository. +func (r *Repository) Tags() *TagIter { + return NewTagIter(r, r.Storage.Iter(core.TagObject)) } diff --git a/tag.go b/tag.go index 13743b4..4d2253a 100644 --- a/tag.go +++ b/tag.go @@ -78,20 +78,41 @@ func (t *Tag) Decode(o core.Object) error { } // Commit returns the commit pointed to by the tag. If the tag points to a -// different type of object an error will be returned. +// different type of object ErrUnsupportedObject will be returned. func (t *Tag) Commit() (*Commit, error) { + if t.Type != core.CommitObject { + return nil, ErrUnsupportedObject + } return t.r.Commit(t.object) } -// Tree returns the tree pointed to by the tag. If the tag points to a -// different type of object an error will be returned. +// Tree returns the tree pointed to by the tag. If the tag points to a commit +// object the tree of that commit will be returned. If the tag does not point +// to a commit or tree object ErrUnsupportedObject will be returned. func (t *Tag) Tree() (*Tree, error) { // TODO: If the tag is of type commit, follow the commit to its tree? - return t.r.Tree(t.object) + switch t.Type { + case core.CommitObject: + commit, err := t.r.Commit(t.object) + if err != nil { + return nil, err + } + return commit.Tree(), nil + case core.TreeObject: + return t.r.Tree(t.object) + default: + return nil, ErrUnsupportedObject + } } -// TODO: Add support for retrieving blobs? We don't have a type for that -// currently. +// Blob returns the blob pointed to by the tag. If the tag points to a +// different type of object ErrUnsupportedObject will be returned. +func (t *Tag) Blob() (*Blob, error) { + if t.Type != core.BlobObject { + return nil, ErrUnsupportedObject + } + return t.r.Blob(t.object) +} // Object returns the object pointed to by the tag. func (t *Tag) Object() (core.Object, error) { @@ -132,4 +153,5 @@ func (iter *TagIter) Next() (*Tag, error) { // Close releases any resources used by the iterator. func (iter *TagIter) Close() { + iter.Close() } diff --git a/tag_test.go b/tag_test.go index 65d423b..1874c11 100644 --- a/tag_test.go +++ b/tag_test.go @@ -41,6 +41,8 @@ var tagTests = []struct { "95ee6e6c750ded1f4dc5499bad730ce3f58c6c3a": {"2c748387f5e9c35d001de3c9ba3072d0b3f10a72", core.CommitObject, "v0.4.0", "cfieber", "cfieber@netflix.com", "2015-11-15T18:18:51Z", "Release of 0.4.0\n\n- 2c748387f5e9c35d001de3c9ba3072d0b3f10a72: Create LICENSE.txt\n- 0c6968e24796a67fa602c94d7a82fd4fd375ec59: Create AUTHORS\n- 3ce7b902a51bac2f10994f7d1f251b616c975e54: Drop trailing slash.\n"}, "8b6002b614b454d45bafbd244b127839421f92ff": {"65e37611b1ff9cb589e3060507427a9a2645907e", core.CommitObject, "v0.3.0", "cfieber", "cfieber@netflix.com", "2015-11-15T18:07:03Z", "Release of 0.3.0\n\n- 65e37611b1ff9cb589e3060507427a9a2645907e: need java plugin for manifest generation\n- bc02440df2ff95a014a7b3cb11b98c3a2bded777: newer gradle plugin\n- 791bcd1592828d9d5d16e83f3a825fb08b0ba22d: Don't need to rename the service.\n"}, }}, + // TODO: Add fixture with tagged trees + // TODO: Add fixture with tagged blobs } type SuiteTag struct { @@ -72,6 +74,44 @@ func (s *SuiteTag) TestCommit(c *C) { } } +func (s *SuiteTag) TestTree(c *C) { + for _, t := range tagTests { + r, ok := s.repos[t.repo] + c.Assert(ok, Equals, true) + k := 0 + for hash, expected := range t.tags { + if expected.Type != core.TreeObject { + continue + } + tag, err := r.Tag(core.NewHash(hash)) + c.Assert(err, IsNil) + tree, err := tag.Tree() + c.Assert(err, IsNil) + c.Assert(tree.Hash.String(), Equals, expected.Object) + k++ + } + } +} + +func (s *SuiteTag) TestBlob(c *C) { + for _, t := range tagTests { + r, ok := s.repos[t.repo] + c.Assert(ok, Equals, true) + k := 0 + for hash, expected := range t.tags { + if expected.Type != core.BlobObject { + continue + } + tag, err := r.Tag(core.NewHash(hash)) + c.Assert(err, IsNil) + blob, err := tag.Blob() + c.Assert(err, IsNil) + c.Assert(blob.Hash.String(), Equals, expected.Object) + k++ + } + } +} + func testTagExpected(c *C, tag *Tag, expected expectedTag, comment string) { when, err := time.Parse(time.RFC3339, expected.When) c.Assert(err, IsNil) -- cgit