diff options
author | Santiago M. Mola <santi@mola.io> | 2016-12-14 23:12:44 +0100 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2016-12-14 23:12:44 +0100 |
commit | 0af572dd21c0aa79d13745b633ee24ba6c4d6cf1 (patch) | |
tree | 49e81e74e82d84fd88b2fc1e4b0dc7c7bfe9c40f | |
parent | df0f38af83f972f026d7e14150f3d37b95f13484 (diff) | |
download | go-git-0af572dd21c0aa79d13745b633ee24ba6c4d6cf1.tar.gz |
move plumbing from top level package to plumbing (#183)
* plumbing: rename Object -> EncodedObject.
* plumbing/storer: rename ObjectStorer -> EncodedObjectStorer.
* move difftree to plumbing/difftree.
* move diff -> utils/diff
* make Object/Tag/Blob/Tree/Commit/File depend on storer.
* Object and its implementations now depend only on
storer.EncodedObjectStorer, not git.Repository.
* Tests are decoupled accordingly.
* move Object/Commit/File/Tag/Tree to plumbing/object.
* move Object/Commit/File/Tag/Tree to plumbing/object.
* move checkClose to utils/ioutil.
* move RevListObjects to plumbing/revlist.Objects.
* move DiffTree to plumbing/difftree package.
* rename files with plural nouns to singular
* plumbing/object: add GetBlob/GetCommit/GetTag/GetTree.
-rw-r--r-- | blame.go | 39 | ||||
-rw-r--r-- | blame_test.go | 6 | ||||
-rw-r--r-- | common.go | 26 | ||||
-rw-r--r-- | common_test.go | 3 | ||||
-rw-r--r-- | cshared/blame_cshared.go | 8 | ||||
-rw-r--r-- | cshared/commit_cshared.go | 43 | ||||
-rw-r--r-- | cshared/file_cshared.go | 29 | ||||
-rw-r--r-- | cshared/objects_cshared.go | 22 | ||||
-rw-r--r-- | cshared/tag_cshared.go | 40 | ||||
-rw-r--r-- | cshared/tree_cshared.go | 26 | ||||
-rw-r--r-- | examples/showcase/main.go | 4 | ||||
-rw-r--r-- | examples/storage/aerospike/storage.go | 20 | ||||
-rw-r--r-- | plumbing/difftree/difftree.go (renamed from tree_diff.go) | 34 | ||||
-rw-r--r-- | plumbing/difftree/difftree_test.go (renamed from tree_diff_test.go) | 117 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/doc.go (renamed from difftree/internal/merkletrie/doc.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/frame.go (renamed from difftree/internal/merkletrie/frame.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/frame_test.go (renamed from difftree/internal/merkletrie/frame_test.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/iter.go (renamed from difftree/internal/merkletrie/iter.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/iter_fixtures_test.go (renamed from difftree/internal/merkletrie/iter_fixtures_test.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/iter_test.go (renamed from difftree/internal/merkletrie/iter_test.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/node.go (renamed from difftree/internal/merkletrie/node.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/node_test.go (renamed from difftree/internal/merkletrie/node_test.go) | 0 | ||||
-rw-r--r-- | plumbing/difftree/internal/merkletrie/noder.go (renamed from difftree/internal/merkletrie/noder.go) | 0 | ||||
-rw-r--r-- | plumbing/error.go (renamed from plumbing/errors.go) | 0 | ||||
-rw-r--r-- | plumbing/format/packfile/decoder.go | 34 | ||||
-rw-r--r-- | plumbing/format/packfile/decoder_test.go | 12 | ||||
-rw-r--r-- | plumbing/format/packfile/diff_delta.go | 6 | ||||
-rw-r--r-- | plumbing/format/packfile/encoder.go | 6 | ||||
-rw-r--r-- | plumbing/format/packfile/encoder_test.go | 34 | ||||
-rw-r--r-- | plumbing/format/packfile/object_pack.go | 11 | ||||
-rw-r--r-- | plumbing/format/packfile/patch_delta.go | 2 | ||||
-rw-r--r-- | plumbing/object.go | 2 | ||||
-rw-r--r-- | plumbing/object/blob.go (renamed from blobs.go) | 57 | ||||
-rw-r--r-- | plumbing/object/blob_test.go (renamed from blobs_test.go) | 10 | ||||
-rw-r--r-- | plumbing/object/commit.go (renamed from commit.go) | 69 | ||||
-rw-r--r-- | plumbing/object/commit_test.go (renamed from commit_test.go) | 20 | ||||
-rw-r--r-- | plumbing/object/commit_walker.go (renamed from commit_walker.go) | 2 | ||||
-rw-r--r-- | plumbing/object/commit_walker_test.go (renamed from commit_walker_test.go) | 10 | ||||
-rw-r--r-- | plumbing/object/file.go (renamed from file.go) | 13 | ||||
-rw-r--r-- | plumbing/object/file_test.go (renamed from file_test.go) | 42 | ||||
-rw-r--r-- | plumbing/object/object.go (renamed from objects.go) | 54 | ||||
-rw-r--r-- | plumbing/object/object_test.go (renamed from objects_test.go) | 55 | ||||
-rw-r--r-- | plumbing/object/tag.go (renamed from tag.go) | 90 | ||||
-rw-r--r-- | plumbing/object/tag_test.go (renamed from tag_test.go) | 49 | ||||
-rw-r--r-- | plumbing/object/tree.go (renamed from tree.go) | 90 | ||||
-rw-r--r-- | plumbing/object/tree_test.go (renamed from tree_test.go) | 40 | ||||
-rw-r--r-- | plumbing/revlist/revlist.go (renamed from revlist.go) | 37 | ||||
-rw-r--r-- | plumbing/revlist/revlist_test.go (renamed from revlist_test.go) | 69 | ||||
-rw-r--r-- | plumbing/storer/object.go | 131 | ||||
-rw-r--r-- | plumbing/storer/object_test.go | 44 | ||||
-rw-r--r-- | references.go | 45 | ||||
-rw-r--r-- | references_test.go | 9 | ||||
-rw-r--r-- | remote.go | 7 | ||||
-rw-r--r-- | remote_test.go | 4 | ||||
-rw-r--r-- | repository.go | 95 | ||||
-rw-r--r-- | repository_test.go | 3 | ||||
-rw-r--r-- | storage/filesystem/object.go | 40 | ||||
-rw-r--r-- | storage/filesystem/object_test.go | 12 | ||||
-rw-r--r-- | storage/memory/storage.go | 48 | ||||
-rw-r--r-- | storage/test/storage_suite.go | 54 | ||||
-rw-r--r-- | utils/binary/write_test.go (renamed from utils/binary/writer_test.go) | 0 | ||||
-rw-r--r-- | utils/diff/diff.go (renamed from diff/diff.go) | 0 | ||||
-rw-r--r-- | utils/diff/diff_ext_test.go (renamed from diff/diff_ext_test.go) | 2 | ||||
-rw-r--r-- | utils/ioutil/common.go | 20 |
64 files changed, 974 insertions, 771 deletions
@@ -8,11 +8,12 @@ import ( "strings" "unicode/utf8" - "gopkg.in/src-d/go-git.v4/diff" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/utils/diff" ) -type Blame struct { +type BlameResult struct { Path string Rev plumbing.Hash Lines []*line @@ -62,7 +63,7 @@ type Blame struct { // 1. Add memoization between revlist and assign. // // 2. It is using much more memory than needed, see the TODOs below. -func (c *Commit) Blame(path string) (*Blame, error) { +func Blame(c *object.Commit, path string) (*BlameResult, error) { b := new(blame) b.fRev = c b.path = path @@ -92,7 +93,7 @@ func (c *Commit) Blame(path string) (*Blame, error) { return nil, err } - return &Blame{ + return &BlameResult{ Path: path, Rev: c.Hash, Lines: lines, @@ -111,7 +112,7 @@ func newLine(author, text string) *line { } } -func newLines(contents []string, commits []*Commit) ([]*line, error) { +func newLines(contents []string, commits []*object.Commit) ([]*line, error) { if len(contents) != len(commits) { return nil, errors.New("contents and commits have different length") } @@ -126,18 +127,18 @@ func newLines(contents []string, commits []*Commit) ([]*line, error) { // this struct is internally used by the blame function to hold its // inputs, outputs and state. type blame struct { - path string // the path of the file to blame - fRev *Commit // the commit of the final revision of the file to blame - revs []*Commit // the chain of revisions affecting the the file to blame - data []string // the contents of the file across all its revisions - graph [][]*Commit // the graph of the lines in the file across all the revisions TODO: not all commits are needed, only the current rev and the prev + path string // the path of the file to blame + fRev *object.Commit // the commit of the final revision of the file to blame + revs []*object.Commit // the chain of revisions affecting the the file to blame + data []string // the contents of the file across all its revisions + graph [][]*object.Commit // the graph of the lines in the file across all the revisions TODO: not all commits are needed, only the current rev and the prev } // calculte the history of a file "path", starting from commit "from", sorted by commit date. func (b *blame) fillRevs() error { var err error - b.revs, err = b.fRev.References(b.path) + b.revs, err = References(b.fRev, b.path) if err != nil { return err } @@ -146,7 +147,7 @@ func (b *blame) fillRevs() error { // build graph of a file from its revision history func (b *blame) fillGraphAndData() error { - b.graph = make([][]*Commit, len(b.revs)) + b.graph = make([][]*object.Commit, len(b.revs)) b.data = make([]string, len(b.revs)) // file contents in all the revisions // for every revision of the file, starting with the first // one... @@ -162,13 +163,13 @@ func (b *blame) fillGraphAndData() error { } nLines := countLines(b.data[i]) // create a node for each line - b.graph[i] = make([]*Commit, nLines) + b.graph[i] = make([]*object.Commit, nLines) // assign a commit to each node // if this is the first revision, then the node is assigned to // this first commit. if i == 0 { for j := 0; j < nLines; j++ { - b.graph[i][j] = (*Commit)(b.revs[i]) + b.graph[i][j] = (*object.Commit)(b.revs[i]) } } else { // if this is not the first commit, then assign to the old @@ -182,11 +183,11 @@ func (b *blame) fillGraphAndData() error { // sliceGraph returns a slice of commits (one per line) for a particular // revision of a file (0=first revision). -func (b *blame) sliceGraph(i int) []*Commit { +func (b *blame) sliceGraph(i int) []*object.Commit { fVs := b.graph[i] - result := make([]*Commit, 0, len(fVs)) + result := make([]*object.Commit, 0, len(fVs)) for _, v := range fVs { - c := Commit(*v) + c := object.Commit(*v) result = append(result, &c) } return result @@ -209,7 +210,7 @@ func (b *blame) assignOrigin(c, p int) { b.graph[c][dl] = b.graph[p][sl] case hunks[h].Type == 1: dl++ - b.graph[c][dl] = (*Commit)(b.revs[c]) + b.graph[c][dl] = (*object.Commit)(b.revs[c]) case hunks[h].Type == -1: sl++ default: @@ -249,7 +250,7 @@ func (b *blame) GoString() string { } // utility function to pretty print the author. -func prettyPrintAuthor(c *Commit) string { +func prettyPrintAuthor(c *object.Commit) string { return fmt.Sprintf("%s %s", c.Author.Name, c.Author.When.Format("2006-01-02")) } diff --git a/blame_test.go b/blame_test.go index f4203b8..1ff430e 100644 --- a/blame_test.go +++ b/blame_test.go @@ -29,13 +29,13 @@ func (s *BlameSuite) TestBlame(c *C) { commit, err := r.Commit(plumbing.NewHash(t.rev)) c.Assert(err, IsNil) - obt, err := commit.Blame(t.path) + obt, err := Blame(commit, t.path) c.Assert(err, IsNil) c.Assert(obt, DeepEquals, exp) } } -func (s *BlameSuite) mockBlame(c *C, t blameTest, r *Repository) (blame *Blame) { +func (s *BlameSuite) mockBlame(c *C, t blameTest, r *Repository) (blame *BlameResult) { commit, err := r.Commit(plumbing.NewHash(t.rev)) c.Assert(err, IsNil, Commentf("%v: repo=%s, rev=%s", err, t.repo, t.rev)) @@ -57,7 +57,7 @@ func (s *BlameSuite) mockBlame(c *C, t blameTest, r *Repository) (blame *Blame) blamedLines = append(blamedLines, l) } - return &Blame{ + return &BlameResult{ Path: t.path, Rev: plumbing.NewHash(t.rev), Lines: blamedLines, @@ -1,7 +1,6 @@ package git import ( - "io" "strings" "gopkg.in/src-d/go-git.v4/config" @@ -13,7 +12,7 @@ import ( // information in an system directory (such as `.git`) and others // implementations are in memmory being ephemeral type Storer interface { - storer.ObjectStorer + storer.EncodedObjectStorer storer.ReferenceStorer config.ConfigStorer } @@ -34,26 +33,3 @@ func countLines(s string) int { return nEOL + 1 } - -// checkClose is used with defer to close the given io.Closer and check its -// returned error value. If Close returns an error and the given *error -// is not nil, *error is set to the error returned by Close. -// -// checkClose is typically used with named return values like so: -// -// func do(obj *Object) (err error) { -// w, err := obj.Writer() -// if err != nil { -// return nil -// } -// defer checkClose(w, &err) -// // work with w -// } -func checkClose(c io.Closer, err *error) { - if cerr := c.Close(); cerr != nil && *err == nil { - *err = cerr - } -} - -// DateFormat is the format being use in the orignal git implementation -const DateFormat = "Mon Jan 02 15:04:05 2006 -0700" diff --git a/common_test.go b/common_test.go index 2dabf6b..980c191 100644 --- a/common_test.go +++ b/common_test.go @@ -6,6 +6,7 @@ import ( "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing/format/packfile" + "gopkg.in/src-d/go-git.v4/plumbing/storer" "gopkg.in/src-d/go-git.v4/plumbing/transport/client" . "gopkg.in/check.v1" @@ -16,6 +17,7 @@ func Test(t *testing.T) { TestingT(t) } type BaseSuite struct { fixtures.Suite Repository *Repository + Storer storer.EncodedObjectStorer cache map[string]*Repository } @@ -31,6 +33,7 @@ func (s *BaseSuite) SetUpSuite(c *C) { func (s *BaseSuite) buildBasicRepository(c *C) { f := fixtures.Basic().One() s.Repository = s.NewRepository(f) + s.Storer = s.Repository.s } func (s *BaseSuite) NewRepository(f *fixtures.Fixture) *Repository { diff --git a/cshared/blame_cshared.go b/cshared/blame_cshared.go index 8cb55e8..0f31cea 100644 --- a/cshared/blame_cshared.go +++ b/cshared/blame_cshared.go @@ -13,7 +13,7 @@ func c_Blame_get_Path(b uint64) *C.char { if !ok { return nil } - blame := obj.(*git.Blame) + blame := obj.(*git.BlameResult) return C.CString(blame.Path) } @@ -23,7 +23,7 @@ func c_Blame_get_Rev(b uint64) *C.char { if !ok { return nil } - blame := obj.(*git.Blame) + blame := obj.(*git.BlameResult) return CBytes(blame.Rev[:]) } @@ -33,7 +33,7 @@ func c_Blame_get_Lines_len(b uint64) int { if !ok { return 0 } - blame := obj.(*git.Blame) + blame := obj.(*git.BlameResult) return len(blame.Lines) } @@ -43,7 +43,7 @@ func c_Blame_get_Lines_item(b uint64, i int) { if !ok { return } - blame := obj.(*git.Blame) + blame := obj.(*git.BlameResult) line := blame.Lines[i] _ = line } diff --git a/cshared/commit_cshared.go b/cshared/commit_cshared.go index 756b0b2..cd46d7d 100644 --- a/cshared/commit_cshared.go +++ b/cshared/commit_cshared.go @@ -9,8 +9,9 @@ import ( "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) -import "gopkg.in/src-d/go-git.v4/plumbing/storer" //export c_Commit_get_Hash func c_Commit_get_Hash(c uint64) *C.char { @@ -18,7 +19,7 @@ func c_Commit_get_Hash(c uint64) *C.char { if !ok { return nil } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) return CBytes(commit.Hash[:]) } @@ -28,7 +29,7 @@ func c_Commit_get_Author(c uint64) uint64 { if !ok { return IH } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) author := &commit.Author author_handle := RegisterObject(author) return uint64(author_handle) @@ -40,7 +41,7 @@ func c_Commit_get_Committer(c uint64) uint64 { if !ok { return IH } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) committer := &commit.Committer committer_handle := RegisterObject(committer) return uint64(committer_handle) @@ -52,7 +53,7 @@ func c_Commit_get_Message(c uint64) *C.char { if !ok { return nil } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) return C.CString(commit.Message) } @@ -62,7 +63,7 @@ func c_Commit_Tree(c uint64) uint64 { if !ok { return IH } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) tree, err := commit.Tree() if err != nil { return IH @@ -78,7 +79,7 @@ func c_Commit_Parents(c uint64) uint64 { if !ok { return IH } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) parents := commit.Parents() parents_handle := RegisterObject(parents) return uint64(parents_handle) @@ -90,7 +91,7 @@ func c_Commit_NumParents(c uint64) int { if !ok { return -1 } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) return commit.NumParents() } @@ -100,7 +101,7 @@ func c_Commit_File(c uint64, path string) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) file, err := commit.File(CopyString(path)) if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) @@ -120,18 +121,18 @@ func c_Commit_Type(c uint64) int8 { if !ok { return -1 } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) return int8(commit.Type()) } //export c_Commit_Decode func c_Commit_Decode(o uint64) (uint64, int, *C.char) { - commit := git.Commit{} + commit := object.Commit{} obj, ok := GetObject(Handle(o)) if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - cobj := obj.(*plumbing.Object) + cobj := obj.(*plumbing.EncodedObject) err := commit.Decode(*cobj) if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) @@ -145,7 +146,7 @@ func c_Commit_String(c uint64) *C.char { if !ok { return nil } - commit := obj.(*git.Commit) + commit := obj.(*object.Commit) return C.CString(commit.String()) } @@ -155,8 +156,8 @@ func c_Commit_References(c uint64, path string) (*C.char, int, int, *C.char) { if !ok { return nil, 0, ErrorCodeNotFound, C.CString(MessageNotFound) } - commit := obj.(*git.Commit) - refs, err := commit.References(CopyString(path)) + commit := obj.(*object.Commit) + refs, err := git.References(commit, CopyString(path)) if err != nil { return nil, 0, ErrorCodeInternal, C.CString(err.Error()) } @@ -178,8 +179,8 @@ func c_Commit_Blame(c uint64, path string) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - commit := obj.(*git.Commit) - blame, err := commit.Blame(CopyString(path)) + commit := obj.(*object.Commit) + blame, err := git.Blame(commit, CopyString(path)) if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) } @@ -192,13 +193,13 @@ func c_NewCommitIter(r uint64, iter uint64) uint64 { if !ok { return IH } - repo := obj.(*git.Repository) + s := obj.(storer.EncodedObjectStorer) obj, ok = GetObject(Handle(iter)) if !ok { return IH } - obj_iter := obj.(*storer.ObjectIter) - commit_iter := git.NewCommitIter(repo, *obj_iter) + obj_iter := obj.(storer.EncodedObjectIter) + commit_iter := object.NewCommitIter(s, obj_iter) handle := RegisterObject(commit_iter) return uint64(handle) } @@ -209,7 +210,7 @@ func c_CommitIter_Next(iter uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - commitIter := obj.(*git.CommitIter) + commitIter := obj.(*object.CommitIter) commit, err := commitIter.Next() if err != nil { if err == io.EOF { diff --git a/cshared/file_cshared.go b/cshared/file_cshared.go index 8ef6427..d9c95b0 100644 --- a/cshared/file_cshared.go +++ b/cshared/file_cshared.go @@ -5,8 +5,9 @@ import ( "io" "io/ioutil" - "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) //export c_File_get_Name @@ -15,7 +16,7 @@ func c_File_get_Name(f uint64) *C.char { if !ok { return nil } - file := obj.(*git.File) + file := obj.(*object.File) return C.CString(file.Name) } @@ -25,7 +26,7 @@ func c_File_get_Mode(f uint64) uint32 { if !ok { return 0 } - file := obj.(*git.File) + file := obj.(*object.File) return uint32(file.Mode) } @@ -35,7 +36,7 @@ func c_File_get_Hash(b uint64) *C.char { if !ok { return nil } - file := obj.(*git.File) + file := obj.(*object.File) return CBytes(file.Hash[:]) } @@ -45,7 +46,7 @@ func c_File_Size(b uint64) int64 { if !ok { return -1 } - file := obj.(*git.File) + file := obj.(*object.File) return file.Size } @@ -55,8 +56,8 @@ func c_File_Decode(o uint64) uint64 { if !ok { return IH } - cobj := obj.(*plumbing.Object) - file := git.File{} + cobj := obj.(*plumbing.EncodedObject) + file := object.File{} file.Decode(*cobj) return uint64(RegisterObject(&file)) } @@ -67,7 +68,7 @@ func c_File_Read(b uint64) (int, *C.char) { if !ok { return ErrorCodeNotFound, C.CString(MessageNotFound) } - file := obj.(*git.File) + file := obj.(*object.File) reader, err := file.Reader() if err != nil { return ErrorCodeInternal, C.CString(err.Error()) @@ -86,7 +87,7 @@ func c_File_Type(c uint64) int8 { if !ok { return -1 } - file := obj.(*git.File) + file := obj.(*object.File) return int8(file.Type()) } @@ -96,13 +97,13 @@ func c_NewFileIter(r uint64, t uint64) uint64 { if !ok { return IH } - repo := obj.(*git.Repository) + storer := obj.(storer.EncodedObjectStorer) obj, ok = GetObject(Handle(t)) if !ok { return IH } - tree := obj.(*git.Tree) - iter := git.NewFileIter(repo, tree) + tree := obj.(*object.Tree) + iter := object.NewFileIter(storer, tree) return uint64(RegisterObject(iter)) } @@ -112,7 +113,7 @@ func c_FileIter_Next(i uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - iter := obj.(*git.FileIter) + iter := obj.(*object.FileIter) file, err := iter.Next() if err != nil { if err == io.EOF { @@ -129,6 +130,6 @@ func c_FileIter_Close(i uint64) { if !ok { return } - iter := obj.(*git.FileIter) + iter := obj.(*object.FileIter) iter.Close() } diff --git a/cshared/objects_cshared.go b/cshared/objects_cshared.go index 54b9426..60bac40 100644 --- a/cshared/objects_cshared.go +++ b/cshared/objects_cshared.go @@ -6,8 +6,8 @@ import ( "io/ioutil" "time" - "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" ) //export c_Signature_Name @@ -16,7 +16,7 @@ func c_Signature_Name(s uint64) *C.char { if !ok { return nil } - sign := obj.(*git.Signature) + sign := obj.(*object.Signature) return C.CString(sign.Name) } @@ -26,7 +26,7 @@ func c_Signature_Email(s uint64) *C.char { if !ok { return nil } - sign := obj.(*git.Signature) + sign := obj.(*object.Signature) return C.CString(sign.Email) } @@ -36,13 +36,13 @@ func c_Signature_When(s uint64) *C.char { if !ok { return nil } - sign := obj.(*git.Signature) + sign := obj.(*object.Signature) return C.CString(sign.When.Format(time.RFC3339)) } //export c_Signature_Decode func c_Signature_Decode(b []byte) uint64 { - sign := git.Signature{} + sign := object.Signature{} sign.Decode(b) return uint64(RegisterObject(&sign)) } @@ -53,7 +53,7 @@ func c_Blob_get_Hash(b uint64) *C.char { if !ok { return nil } - blob := obj.(*git.Blob) + blob := obj.(*object.Blob) return CBytes(blob.Hash[:]) } @@ -63,7 +63,7 @@ func c_Blob_Size(b uint64) int64 { if !ok { return -1 } - blob := obj.(*git.Blob) + blob := obj.(*object.Blob) return blob.Size } @@ -73,8 +73,8 @@ func c_Blob_Decode(o uint64) uint64 { if !ok { return IH } - cobj := obj.(*plumbing.Object) - blob := git.Blob{} + cobj := obj.(*plumbing.EncodedObject) + blob := object.Blob{} blob.Decode(*cobj) return uint64(RegisterObject(&blob)) } @@ -85,7 +85,7 @@ func c_Blob_Read(b uint64) (int, *C.char) { if !ok { return ErrorCodeNotFound, C.CString(MessageNotFound) } - blob := obj.(*git.Blob) + blob := obj.(*object.Blob) reader, err := blob.Reader() if err != nil { return ErrorCodeInternal, C.CString(err.Error()) @@ -104,6 +104,6 @@ func c_Blob_Type(c uint64) int8 { if !ok { return -1 } - blob := obj.(*git.Blob) + blob := obj.(*object.Blob) return int8(blob.Type()) } diff --git a/cshared/tag_cshared.go b/cshared/tag_cshared.go index dd0814a..860a1c6 100644 --- a/cshared/tag_cshared.go +++ b/cshared/tag_cshared.go @@ -5,17 +5,17 @@ import ( "C" "io" - "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) -import "gopkg.in/src-d/go-git.v4/plumbing/storer" func c_Tag_get_Hash(t uint64) *C.char { obj, ok := GetObject(Handle(t)) if !ok { return nil } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return CBytes(tag.Hash[:]) } @@ -24,7 +24,7 @@ func c_Tag_get_Name(t uint64) *C.char { if !ok { return nil } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return C.CString(tag.Name) } @@ -33,7 +33,7 @@ func c_Tag_get_Tagger(t uint64) uint64 { if !ok { return IH } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return uint64(RegisterObject(&tag.Tagger)) } @@ -42,7 +42,7 @@ func c_Tag_get_Message(t uint64) *C.char { if !ok { return nil } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return C.CString(tag.Message) } @@ -51,7 +51,7 @@ func c_Tag_get_TargetType(t uint64) int8 { if !ok { return -1 } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return int8(tag.TargetType) } @@ -60,7 +60,7 @@ func c_Tag_get_Target(t uint64) *C.char { if !ok { return nil } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return CBytes(tag.Target[:]) } @@ -70,7 +70,7 @@ func c_Tag_Type(t uint64) int8 { if !ok { return -1 } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return int8(tag.Type()) } @@ -80,8 +80,8 @@ func c_Tag_Decode(o uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - cobj := obj.(*plumbing.Object) - tag := git.Tag{} + cobj := obj.(*plumbing.EncodedObject) + tag := object.Tag{} err := tag.Decode(*cobj) if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) @@ -95,7 +95,7 @@ func c_Tag_Commit(t uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) commit, err := tag.Commit() if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) @@ -109,7 +109,7 @@ func c_Tag_Tree(t uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) tree, err := tag.Tree() if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) @@ -123,7 +123,7 @@ func c_Tag_Blob(t uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) blob, err := tag.Blob() if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) @@ -137,7 +137,7 @@ func c_Tag_Object(t uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) object, err := tag.Object() if err != nil { return IH, ErrorCodeInternal, C.CString(err.Error()) @@ -151,7 +151,7 @@ func c_Tag_String(t uint64) *C.char { if !ok { return nil } - tag := obj.(*git.Tag) + tag := obj.(*object.Tag) return C.CString(tag.String()) } @@ -161,13 +161,13 @@ func c_NewTagIter(r uint64, i uint64) uint64 { if !ok { return IH } - repo := obj.(*git.Repository) + s := obj.(storer.EncodedObjectStorer) obj, ok = GetObject(Handle(i)) if !ok { return IH } - iter := obj.(*storer.ObjectIter) - return uint64(RegisterObject(git.NewTagIter(repo, *iter))) + iter := obj.(*storer.EncodedObjectIter) + return uint64(RegisterObject(object.NewTagIter(s, *iter))) } //export c_TagIter_Next @@ -176,7 +176,7 @@ func c_TagIter_Next(i uint64) (uint64, int, *C.char) { if !ok { return IH, ErrorCodeNotFound, C.CString(MessageNotFound) } - tagiter := obj.(*git.TagIter) + tagiter := obj.(*object.TagIter) tag, err := tagiter.Next() if err != nil { if err == io.EOF { diff --git a/cshared/tree_cshared.go b/cshared/tree_cshared.go index 8533f60..12e360e 100644 --- a/cshared/tree_cshared.go +++ b/cshared/tree_cshared.go @@ -21,7 +21,7 @@ func c_Tree_get_Entries_len(t uint64) int { if !ok { return 0 } - tree := obj.(*git.Tree) + tree := obj.(*object.Tree) return len(tree.Entries) } @@ -33,7 +33,7 @@ func c_Tree_get_Entries_item(t uint64, index int) (*_Ctype_char, uint32, *_Ctype if !ok { return nil, 0, nil } - tree := obj.(*git.Tree) + tree := obj.(*object.Tree) item := tree.Entries[index] return _Cfunc_CString(item.Name), uint32(item.Mode), CBytes(item.Hash[:]) } @@ -46,7 +46,7 @@ func c_Tree_get_Hash(t uint64) *_Ctype_char { if !ok { return nil } - tree := obj.(*git.Tree) + tree := obj.(*object.Tree) return CBytes(tree.Hash[:]) } @@ -58,7 +58,7 @@ func c_Tree_File(t uint64, path string) (uint64, int, *_Ctype_char) { if !ok { return IH, ErrorCodeNotFound, _Cfunc_CString(MessageNotFound) } - tree := obj.(*git.Tree) + tree := obj.(*object.Tree) file, err := tree.File(CopyString(path)) if err != nil { return IH, ErrorCodeInternal, _Cfunc_CString(err.Error()) @@ -74,7 +74,7 @@ func c_Tree_Type(t uint64) int8 { if !ok { return -1 } - tree := obj.(*git.Tree) + tree := obj.(*object.Tree) return int8(tree.Type()) } @@ -86,7 +86,7 @@ func c_Tree_Files(t uint64) uint64 { if !ok { return IH } - tree := obj.(*git.Tree) + tree := obj.(*object.Tree) iter := tree.Files() return uint64(RegisterObject(iter)) } @@ -99,8 +99,8 @@ func c_Tree_Decode(o uint64) (uint64, int, *_Ctype_char) { if !ok { return IH, ErrorCodeNotFound, _Cfunc_CString(MessageNotFound) } - cobj := obj.(*plumbing.Object) - tree := git.Tree{} + cobj := obj.(*plumbing.EncodedObject) + tree := object.Tree{} err := tree.Decode(*cobj) if err != nil { return IH, ErrorCodeInternal, _Cfunc_CString(err.Error()) @@ -121,8 +121,8 @@ func c_NewTreeWalker(r uint64, t uint64) uint64 { if !ok { return IH } - tree := obj.(*git.Tree) - walker := git.NewTreeIter(repo, tree) + tree := obj.(*object.Tree) + walker := object.NewTreeIter(repo, tree) return uint64(RegisterObject(walker)) } @@ -134,7 +134,7 @@ func c_TreeWalker_Next(tw uint64) (*_Ctype_char, *_Ctype_char, uint32, *_Ctype_c if !ok { return nil, nil, 0, nil, ErrorCodeNotFound, _Cfunc_CString(MessageNotFound) } - walker := obj.(*git.TreeIter) + walker := obj.(*object.TreeIter) name, entry, err := walker.Next() if err != nil { return nil, nil, 0, nil, ErrorCodeInternal, _Cfunc_CString(err.Error()) @@ -151,7 +151,7 @@ func c_TreeWalker_Tree(tw uint64) uint64 { if !ok { return IH } - walker := obj.(*git.TreeIter) + walker := obj.(*object.TreeIter) return uint64(RegisterObject(walker.Tree())) } @@ -163,7 +163,7 @@ func c_TreeWalker_Close(tw uint64) { if !ok { return } - walker := obj.(*git.TreeIter) + walker := obj.(*object.TreeIter) walker.Close() } */ diff --git a/examples/showcase/main.go b/examples/showcase/main.go index ff5c7d3..4d1206d 100644 --- a/examples/showcase/main.go +++ b/examples/showcase/main.go @@ -6,6 +6,8 @@ import ( "strings" "gopkg.in/src-d/go-git.v4" + "gopkg.in/src-d/go-git.v4/plumbing/object" + . "gopkg.in/src-d/go-git.v4/examples" ) @@ -42,7 +44,7 @@ func main() { CheckIfError(err) // ... get the files iterator and print the file - tree.Files().ForEach(func(f *git.File) error { + tree.Files().ForEach(func(f *object.File) error { fmt.Printf("100644 blob %s %s\n", f.Hash, f.Name) return nil }) diff --git a/examples/storage/aerospike/storage.go b/examples/storage/aerospike/storage.go index a1d8c00..87d4a29 100644 --- a/examples/storage/aerospike/storage.go +++ b/examples/storage/aerospike/storage.go @@ -33,11 +33,11 @@ func NewStorage(client *driver.Client, ns, url string) (*Storage, error) { return &Storage{client: client, ns: ns, url: url}, nil } -func (s *Storage) NewObject() plumbing.Object { +func (s *Storage) NewEncodedObject() plumbing.EncodedObject { return &plumbing.MemoryObject{} } -func (s *Storage) SetObject(obj plumbing.Object) (plumbing.Hash, error) { +func (s *Storage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) { key, err := s.buildKey(obj.Hash(), obj.Type()) if err != nil { return obj.Hash(), err @@ -64,7 +64,7 @@ func (s *Storage) SetObject(obj plumbing.Object) (plumbing.Hash, error) { return obj.Hash(), err } -func (s *Storage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing.Object, error) { +func (s *Storage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { key, err := s.buildKey(h, t) if err != nil { return nil, err @@ -82,7 +82,7 @@ func (s *Storage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing.Objec return objectFromRecord(rec, t) } -func (s *Storage) IterObjects(t plumbing.ObjectType) (storer.ObjectIter, error) { +func (s *Storage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) { stmnt := driver.NewStatement(s.ns, t.String()) err := stmnt.Addfilter(driver.NewEqualFilter(urlField, s.url)) @@ -91,19 +91,19 @@ func (s *Storage) IterObjects(t plumbing.ObjectType) (storer.ObjectIter, error) return nil, err } - return &ObjectIter{t, rs.Records}, nil + return &EncodedObjectIter{t, rs.Records}, nil } func (s *Storage) buildKey(h plumbing.Hash, t plumbing.ObjectType) (*driver.Key, error) { return driver.NewKey(s.ns, t.String(), fmt.Sprintf("%s|%s", s.url, h.String())) } -type ObjectIter struct { +type EncodedObjectIter struct { t plumbing.ObjectType ch chan *driver.Record } -func (i *ObjectIter) Next() (plumbing.Object, error) { +func (i *EncodedObjectIter) Next() (plumbing.EncodedObject, error) { r := <-i.ch if r == nil { return nil, io.EOF @@ -112,7 +112,7 @@ func (i *ObjectIter) Next() (plumbing.Object, error) { return objectFromRecord(r, i.t) } -func (i *ObjectIter) ForEach(cb func(obj plumbing.Object) error) error { +func (i *EncodedObjectIter) ForEach(cb func(obj plumbing.EncodedObject) error) error { for { obj, err := i.Next() if err != nil { @@ -133,9 +133,9 @@ func (i *ObjectIter) ForEach(cb func(obj plumbing.Object) error) error { } } -func (i *ObjectIter) Close() {} +func (i *EncodedObjectIter) Close() {} -func objectFromRecord(r *driver.Record, t plumbing.ObjectType) (plumbing.Object, error) { +func objectFromRecord(r *driver.Record, t plumbing.ObjectType) (plumbing.EncodedObject, error) { content := r.Bins["blob"].([]byte) o := &plumbing.MemoryObject{} diff --git a/tree_diff.go b/plumbing/difftree/difftree.go index d5f0377..3bc4d63 100644 --- a/tree_diff.go +++ b/plumbing/difftree/difftree.go @@ -8,6 +8,7 @@ import ( "strings" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" ) type Action int @@ -39,13 +40,13 @@ type Change struct { type ChangeEntry struct { Name string - Tree *Tree - TreeEntry TreeEntry + Tree *object.Tree + TreeEntry object.TreeEntry } -func (c *Change) Files() (from *File, to *File, err error) { +func (c *Change) Files() (from, to *object.File, err error) { if c.Action == Insert || c.Action == Modify { - to, err = newFileFromTreeEntry(c.To.Tree, &c.To.TreeEntry) + to, err = c.To.Tree.TreeEntryFile(&c.To.TreeEntry) if err != nil { return } @@ -53,7 +54,7 @@ func (c *Change) Files() (from *File, to *File, err error) { } if c.Action == Delete || c.Action == Modify { - from, err = newFileFromTreeEntry(c.From.Tree, &c.From.TreeEntry) + from, err = c.From.Tree.TreeEntryFile(&c.From.TreeEntry) if err != nil { return } @@ -62,15 +63,6 @@ func (c *Change) Files() (from *File, to *File, err error) { return } -func newFileFromTreeEntry(t *Tree, e *TreeEntry) (*File, error) { - blob, err := t.r.Blob(e.Hash) - if err != nil { - return nil, err - } - - return NewFile(e.Name, e.Mode, blob), nil -} - func (c *Change) String() string { return fmt.Sprintf("<Action: %s, Path: %s>", c.Action, c.name()) } @@ -89,7 +81,7 @@ func newEmpty() Changes { return make([]*Change, 0, 0) } -func DiffTree(a, b *Tree) ([]*Change, error) { +func DiffTree(a, b *object.Tree) ([]*Change, error) { if a == b { return newEmpty(), nil } @@ -127,11 +119,11 @@ func (c Changes) String() string { return buffer.String() } -func newWithEmpty(a, b *Tree) (Changes, error) { +func newWithEmpty(a, b *object.Tree) (Changes, error) { changes := newEmpty() var action Action - var tree *Tree + var tree *object.Tree if a == nil { action = Insert tree = b @@ -140,7 +132,7 @@ func newWithEmpty(a, b *Tree) (Changes, error) { tree = a } - w := NewTreeWalker(tree.r, tree, true) + w := object.NewTreeWalker(tree, true) defer w.Close() for { @@ -177,7 +169,7 @@ func newWithEmpty(a, b *Tree) (Changes, error) { // The proper way to do this is to implement a diff-tree algorithm, // while taking advantage of the tree hashes to avoid traversing // subtrees when the hash is equal in both inputs. -func newDiffTree(a, b *Tree) ([]*Change, error) { +func newDiffTree(a, b *object.Tree) ([]*Change, error) { var result []*Change aChanges, err := newWithEmpty(a, nil) @@ -236,7 +228,7 @@ func mergeInsertAndDeleteIntoModify(a, b *Change) *Change { return c } -func hasChange(a, b *Tree, path string) (bool, error) { +func hasChange(a, b *object.Tree, path string) (bool, error) { ha, err := hash(a, path) if err != nil { return false, err @@ -250,7 +242,7 @@ func hasChange(a, b *Tree, path string) (bool, error) { return ha != hb, nil } -func hash(tree *Tree, path string) (plumbing.Hash, error) { +func hash(tree *object.Tree, path string) (plumbing.Hash, error) { file, err := tree.File(path) if err != nil { var empty plumbing.Hash diff --git a/tree_diff_test.go b/plumbing/difftree/difftree_test.go index e78fbf1..c95e879 100644 --- a/tree_diff_test.go +++ b/plumbing/difftree/difftree_test.go @@ -2,15 +2,76 @@ package git import ( "sort" + "testing" "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/format/packfile" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/storage/filesystem" + "gopkg.in/src-d/go-git.v4/storage/memory" . "gopkg.in/check.v1" ) +func Test(t *testing.T) { TestingT(t) } + type DiffTreeSuite struct { - BaseSuite + fixtures.Suite + Storer storer.EncodedObjectStorer + Fixture *fixtures.Fixture + cache map[string]storer.EncodedObjectStorer +} + +func (s *DiffTreeSuite) SetUpSuite(c *C) { + s.Suite.SetUpSuite(c) + s.Fixture = fixtures.Basic().One() + sto, err := filesystem.NewStorage(s.Fixture.DotGit()) + c.Assert(err, IsNil) + s.Storer = sto + s.cache = make(map[string]storer.EncodedObjectStorer) +} + +func (s *DiffTreeSuite) tree(c *C, h plumbing.Hash) *object.Tree { + t, err := object.GetTree(s.Storer, h) + c.Assert(err, IsNil) + return t +} + +func (s *DiffTreeSuite) commitFromStorer(c *C, sto storer.EncodedObjectStorer, + h plumbing.Hash) *object.Commit { + + commit, err := object.GetCommit(sto, h) + c.Assert(err, IsNil) + return commit +} + +func (s *DiffTreeSuite) storageFromPackfile(f *fixtures.Fixture) storer.EncodedObjectStorer { + sto, ok := s.cache[f.URL] + if ok { + return sto + } + + sto = memory.NewStorage() + + pf := f.Packfile() + + defer pf.Close() + + n := packfile.NewScanner(pf) + d, err := packfile.NewDecoder(n, sto) + if err != nil { + panic(err) + } + + _, err = d.Decode() + if err != nil { + panic(err) + } + + s.cache[f.URL] = sto + return sto } var _ = Suite(&DiffTreeSuite{}) @@ -37,8 +98,7 @@ func (s *DiffTreeSuite) TestActionString(c *C) { } func (s *DiffTreeSuite) TestChangeFilesInsert(c *C) { - tree, err := s.Repository.Tree(plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c")) - c.Assert(err, IsNil) + tree := s.tree(c, plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c")) change := &Change{Action: Insert} change.To.Name = "json/long.json" @@ -52,8 +112,7 @@ func (s *DiffTreeSuite) TestChangeFilesInsert(c *C) { } func (s *DiffTreeSuite) TestChangeFilesDelete(c *C) { - tree, err := s.Repository.Tree(plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c")) - c.Assert(err, IsNil) + tree := s.tree(c, plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c")) change := &Change{Action: Delete} change.From.Name = "json/long.json" @@ -67,8 +126,7 @@ func (s *DiffTreeSuite) TestChangeFilesDelete(c *C) { } func (s *DiffTreeSuite) TestChangeFilesModify(c *C) { - tree, err := s.Repository.Tree(plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c")) - c.Assert(err, IsNil) + tree := s.tree(c, plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c")) change := &Change{Action: Modify} change.To.Name = "json/long.json" @@ -308,17 +366,21 @@ func (s *DiffTreeSuite) TestDiffTree(c *C) { {Action: Modify, Name: "app-tools/rumprun"}, }, }} { - r := s.NewRepositoryFromPackfile(fixtures.ByURL(t.repository).One()) - - tree1, err := tree(r, t.commit1) - c.Assert(err, IsNil, - Commentf("subtest %d: unable to retrieve tree from commit %s and repo %s: %s", i, t.commit1, t.repository, err)) + f := fixtures.ByURL(t.repository).One() + sto := s.storageFromPackfile(f) + + var tree1, tree2 *object.Tree + var err error + if t.commit1 != "" { + tree1, err = s.commitFromStorer(c, sto, + plumbing.NewHash(t.commit1)).Tree() + c.Assert(err, IsNil, + Commentf("subtest %d: unable to retrieve tree from commit %s and repo %s: %s", i, t.commit1, t.repository, err)) + } - var tree2 *Tree - if t.commit1 == t.commit2 { - tree2 = tree1 - } else { - tree2, err = tree(r, t.commit2) + if t.commit2 != "" { + tree2, err = s.commitFromStorer(c, sto, + plumbing.NewHash(t.commit2)).Tree() c.Assert(err, IsNil, Commentf("subtest %d: unable to retrieve tree from commit %s and repo %s", i, t.commit2, t.repository, err)) } @@ -351,14 +413,6 @@ func assertChanges(a Changes, c *C) { } func equalChanges(a Changes, b []expectChange) bool { - if a == nil && b == nil { - return true - } - - if a == nil || b == nil { - return false - } - if len(a) != len(b) { return false } @@ -374,16 +428,3 @@ func equalChanges(a Changes, b []expectChange) bool { return true } - -func tree(repo *Repository, commitHashStr string) (*Tree, error) { - if commitHashStr == "" { - return nil, nil - } - - commit, err := repo.Commit(plumbing.NewHash(commitHashStr)) - if err != nil { - return nil, err - } - - return commit.Tree() -} diff --git a/difftree/internal/merkletrie/doc.go b/plumbing/difftree/internal/merkletrie/doc.go index f8c3b2f..f8c3b2f 100644 --- a/difftree/internal/merkletrie/doc.go +++ b/plumbing/difftree/internal/merkletrie/doc.go diff --git a/difftree/internal/merkletrie/frame.go b/plumbing/difftree/internal/merkletrie/frame.go index a40c6ad..a40c6ad 100644 --- a/difftree/internal/merkletrie/frame.go +++ b/plumbing/difftree/internal/merkletrie/frame.go diff --git a/difftree/internal/merkletrie/frame_test.go b/plumbing/difftree/internal/merkletrie/frame_test.go index 0ef036a..0ef036a 100644 --- a/difftree/internal/merkletrie/frame_test.go +++ b/plumbing/difftree/internal/merkletrie/frame_test.go diff --git a/difftree/internal/merkletrie/iter.go b/plumbing/difftree/internal/merkletrie/iter.go index e175966..e175966 100644 --- a/difftree/internal/merkletrie/iter.go +++ b/plumbing/difftree/internal/merkletrie/iter.go diff --git a/difftree/internal/merkletrie/iter_fixtures_test.go b/plumbing/difftree/internal/merkletrie/iter_fixtures_test.go index 20bddaf..20bddaf 100644 --- a/difftree/internal/merkletrie/iter_fixtures_test.go +++ b/plumbing/difftree/internal/merkletrie/iter_fixtures_test.go diff --git a/difftree/internal/merkletrie/iter_test.go b/plumbing/difftree/internal/merkletrie/iter_test.go index 65116e1..65116e1 100644 --- a/difftree/internal/merkletrie/iter_test.go +++ b/plumbing/difftree/internal/merkletrie/iter_test.go diff --git a/difftree/internal/merkletrie/node.go b/plumbing/difftree/internal/merkletrie/node.go index 99be5b8..99be5b8 100644 --- a/difftree/internal/merkletrie/node.go +++ b/plumbing/difftree/internal/merkletrie/node.go diff --git a/difftree/internal/merkletrie/node_test.go b/plumbing/difftree/internal/merkletrie/node_test.go index 1622952..1622952 100644 --- a/difftree/internal/merkletrie/node_test.go +++ b/plumbing/difftree/internal/merkletrie/node_test.go diff --git a/difftree/internal/merkletrie/noder.go b/plumbing/difftree/internal/merkletrie/noder.go index 3566657..3566657 100644 --- a/difftree/internal/merkletrie/noder.go +++ b/plumbing/difftree/internal/merkletrie/noder.go diff --git a/plumbing/errors.go b/plumbing/error.go index a3ebed3..a3ebed3 100644 --- a/plumbing/errors.go +++ b/plumbing/error.go diff --git a/plumbing/format/packfile/decoder.go b/plumbing/format/packfile/decoder.go index 4ab8eb0..59a2f8d 100644 --- a/plumbing/format/packfile/decoder.go +++ b/plumbing/format/packfile/decoder.go @@ -52,7 +52,7 @@ var ( // ObjectStorer was provided or not. type Decoder struct { s *Scanner - o storer.ObjectStorer + o storer.EncodedObjectStorer tx storer.Transaction isDecoded bool @@ -71,7 +71,7 @@ type Decoder struct { // // If the ObjectStorer implements storer.Transactioner, a transaction is created // during the Decode execution, if something fails the Rollback is called -func NewDecoder(s *Scanner, o storer.ObjectStorer) (*Decoder, error) { +func NewDecoder(s *Scanner, o storer.EncodedObjectStorer) (*Decoder, error) { if !canResolveDeltas(s, o) { return nil, ErrResolveDeltasNotSupported } @@ -86,7 +86,7 @@ func NewDecoder(s *Scanner, o storer.ObjectStorer) (*Decoder, error) { }, nil } -func canResolveDeltas(s *Scanner, o storer.ObjectStorer) bool { +func canResolveDeltas(s *Scanner, o storer.EncodedObjectStorer) bool { return s.IsSeekable || o != nil } @@ -140,7 +140,7 @@ func (d *Decoder) decodeObjectsWithObjectStorer(count int) error { return err } - if _, err := d.o.SetObject(obj); err != nil { + if _, err := d.o.SetEncodedObject(obj); err != nil { return err } } @@ -157,7 +157,7 @@ func (d *Decoder) decodeObjectsWithObjectStorerTx(count int) error { return err } - if _, err := d.tx.SetObject(obj); err != nil { + if _, err := d.tx.SetEncodedObject(obj); err != nil { if rerr := d.tx.Rollback(); rerr != nil { return ErrRollback.AddDetails( "error: %s, during tx.Set error: %s", rerr, err, @@ -175,7 +175,7 @@ func (d *Decoder) decodeObjectsWithObjectStorerTx(count int) error { // DecodeObject reads the next object from the scanner and returns it. This // method can be used in replacement of the Decode method, to work in a // interative way -func (d *Decoder) DecodeObject() (plumbing.Object, error) { +func (d *Decoder) DecodeObject() (plumbing.EncodedObject, error) { h, err := d.s.NextObjectHeader() if err != nil { return nil, err @@ -207,17 +207,17 @@ func (d *Decoder) DecodeObject() (plumbing.Object, error) { return obj, nil } -func (d *Decoder) newObject() plumbing.Object { +func (d *Decoder) newObject() plumbing.EncodedObject { if d.o == nil { return &plumbing.MemoryObject{} } - return d.o.NewObject() + return d.o.NewEncodedObject() } // DecodeObjectAt reads an object at the given location, if Decode wasn't called // previously objects offset should provided using the SetOffsets method -func (d *Decoder) DecodeObjectAt(offset int64) (plumbing.Object, error) { +func (d *Decoder) DecodeObjectAt(offset int64) (plumbing.EncodedObject, error) { if !d.s.IsSeekable { return nil, ErrNonSeekable } @@ -237,7 +237,7 @@ func (d *Decoder) DecodeObjectAt(offset int64) (plumbing.Object, error) { return d.DecodeObject() } -func (d *Decoder) fillRegularObjectContent(obj plumbing.Object) (uint32, error) { +func (d *Decoder) fillRegularObjectContent(obj plumbing.EncodedObject) (uint32, error) { w, err := obj.Writer() if err != nil { return 0, err @@ -247,7 +247,7 @@ func (d *Decoder) fillRegularObjectContent(obj plumbing.Object) (uint32, error) return crc, err } -func (d *Decoder) fillREFDeltaObjectContent(obj plumbing.Object, ref plumbing.Hash) (uint32, error) { +func (d *Decoder) fillREFDeltaObjectContent(obj plumbing.EncodedObject, ref plumbing.Hash) (uint32, error) { buf := bytes.NewBuffer(nil) _, crc, err := d.s.NextObject(buf) if err != nil { @@ -263,7 +263,7 @@ func (d *Decoder) fillREFDeltaObjectContent(obj plumbing.Object, ref plumbing.Ha return crc, ApplyDelta(obj, base, buf.Bytes()) } -func (d *Decoder) fillOFSDeltaObjectContent(obj plumbing.Object, offset int64) (uint32, error) { +func (d *Decoder) fillOFSDeltaObjectContent(obj plumbing.EncodedObject, offset int64) (uint32, error) { buf := bytes.NewBuffer(nil) _, crc, err := d.s.NextObject(buf) if err != nil { @@ -288,7 +288,7 @@ func (d *Decoder) setCRC(h plumbing.Hash, crc uint32) { d.crcs[h] = crc } -func (d *Decoder) recallByOffset(o int64) (plumbing.Object, error) { +func (d *Decoder) recallByOffset(o int64) (plumbing.EncodedObject, error) { if d.s.IsSeekable { return d.DecodeObjectAt(o) } @@ -300,7 +300,7 @@ func (d *Decoder) recallByOffset(o int64) (plumbing.Object, error) { return nil, plumbing.ErrObjectNotFound } -func (d *Decoder) recallByHash(h plumbing.Hash) (plumbing.Object, error) { +func (d *Decoder) recallByHash(h plumbing.Hash) (plumbing.EncodedObject, error) { if d.s.IsSeekable { if o, ok := d.hashToOffset[h]; ok { return d.DecodeObjectAt(o) @@ -312,11 +312,11 @@ func (d *Decoder) recallByHash(h plumbing.Hash) (plumbing.Object, error) { // recallByHashNonSeekable if we are in a transaction the objects are read from // the transaction, if not are directly read from the ObjectStorer -func (d *Decoder) recallByHashNonSeekable(h plumbing.Hash) (obj plumbing.Object, err error) { +func (d *Decoder) recallByHashNonSeekable(h plumbing.Hash) (obj plumbing.EncodedObject, err error) { if d.tx != nil { - obj, err = d.tx.Object(plumbing.AnyObject, h) + obj, err = d.tx.EncodedObject(plumbing.AnyObject, h) } else { - obj, err = d.o.Object(plumbing.AnyObject, h) + obj, err = d.o.EncodedObject(plumbing.AnyObject, h) } if err != plumbing.ErrObjectNotFound { diff --git a/plumbing/format/packfile/decoder_test.go b/plumbing/format/packfile/decoder_test.go index 865cdae..fdf4c96 100644 --- a/plumbing/format/packfile/decoder_test.go +++ b/plumbing/format/packfile/decoder_test.go @@ -95,7 +95,7 @@ func (s *ReaderSuite) TestDecodeNoSeekableWithTxStorer(c *C) { scanner := packfile.NewScanner(reader) - var storage storer.ObjectStorer = memory.NewStorage() + var storage storer.EncodedObjectStorer = memory.NewStorage() _, isTxStorer := storage.(storer.Transactioner) c.Assert(isTxStorer, Equals, true) @@ -119,7 +119,7 @@ func (s *ReaderSuite) TestDecodeNoSeekableWithoutTxStorer(c *C) { scanner := packfile.NewScanner(reader) - var storage storer.ObjectStorer + var storage storer.EncodedObjectStorer storage, _ = filesystem.NewStorage(fs.New()) _, isTxStorer := storage.(storer.Transactioner) c.Assert(isTxStorer, Equals, false) @@ -236,18 +236,18 @@ func (s *ReaderSuite) TestSetOffsets(c *C) { c.Assert(o[h], Equals, int64(42)) } -func assertObjects(c *C, s storer.ObjectStorer, expects []string) { +func assertObjects(c *C, s storer.EncodedObjectStorer, expects []string) { - i, err := s.IterObjects(plumbing.AnyObject) + i, err := s.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) var count int - err = i.ForEach(func(plumbing.Object) error { count++; return nil }) + err = i.ForEach(func(plumbing.EncodedObject) error { count++; return nil }) c.Assert(err, IsNil) c.Assert(count, Equals, len(expects)) for _, exp := range expects { - obt, err := s.Object(plumbing.AnyObject, plumbing.NewHash(exp)) + obt, err := s.EncodedObject(plumbing.AnyObject, plumbing.NewHash(exp)) c.Assert(err, IsNil) c.Assert(obt.Hash().String(), Equals, exp) } diff --git a/plumbing/format/packfile/diff_delta.go b/plumbing/format/packfile/diff_delta.go index fb05a79..bc4fafa 100644 --- a/plumbing/format/packfile/diff_delta.go +++ b/plumbing/format/packfile/diff_delta.go @@ -17,17 +17,17 @@ const ( // GetOFSDelta returns an offset delta that knows the way of how to transform // base object to target object -func GetOFSDelta(base, target plumbing.Object) (plumbing.Object, error) { +func GetOFSDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, error) { return getDelta(base, target, plumbing.OFSDeltaObject) } // GetRefDelta returns a reference delta that knows the way of how to transform // base object to target object -func GetRefDelta(base, target plumbing.Object) (plumbing.Object, error) { +func GetRefDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, error) { return getDelta(base, target, plumbing.REFDeltaObject) } -func getDelta(base, target plumbing.Object, t plumbing.ObjectType) (plumbing.Object, error) { +func getDelta(base, target plumbing.EncodedObject, t plumbing.ObjectType) (plumbing.EncodedObject, error) { if t != plumbing.OFSDeltaObject && t != plumbing.REFDeltaObject { return nil, fmt.Errorf("Type not supported: %v", t) } diff --git a/plumbing/format/packfile/encoder.go b/plumbing/format/packfile/encoder.go index eb1c532..847e9e1 100644 --- a/plumbing/format/packfile/encoder.go +++ b/plumbing/format/packfile/encoder.go @@ -14,7 +14,7 @@ import ( // Encoder gets the data from the storage and write it into the writer in PACK // format type Encoder struct { - storage storer.ObjectStorer + storage storer.EncodedObjectStorer w *offsetWriter zw *zlib.Writer hasher plumbing.Hasher @@ -23,7 +23,7 @@ type Encoder struct { // NewEncoder creates a new packfile encoder using a specific Writer and // ObjectStorer -func NewEncoder(w io.Writer, s storer.ObjectStorer) *Encoder { +func NewEncoder(w io.Writer, s storer.EncodedObjectStorer) *Encoder { h := plumbing.Hasher{ Hash: sha1.New(), } @@ -44,7 +44,7 @@ func NewEncoder(w io.Writer, s storer.ObjectStorer) *Encoder { func (e *Encoder) Encode(hashes []plumbing.Hash) (plumbing.Hash, error) { var objects []*ObjectToPack for _, h := range hashes { - o, err := e.storage.Object(plumbing.AnyObject, h) + o, err := e.storage.EncodedObject(plumbing.AnyObject, h) if err != nil { return plumbing.ZeroHash, err } diff --git a/plumbing/format/packfile/encoder_test.go b/plumbing/format/packfile/encoder_test.go index b07e2f4..1a94d16 100644 --- a/plumbing/format/packfile/encoder_test.go +++ b/plumbing/format/packfile/encoder_test.go @@ -44,7 +44,7 @@ func (s *EncoderSuite) TestCorrectPackWithOneEmptyObject(c *C) { o := &plumbing.MemoryObject{} o.SetType(plumbing.CommitObject) o.SetSize(0) - _, err := s.store.SetObject(o) + _, err := s.store.SetEncodedObject(o) c.Assert(err, IsNil) hash, err := s.enc.Encode([]plumbing.Hash{o.Hash()}) @@ -69,10 +69,10 @@ func (s *EncoderSuite) TestCorrectPackWithOneEmptyObject(c *C) { } func (s *EncoderSuite) TestMaxObjectSize(c *C) { - o := s.store.NewObject() + o := s.store.NewEncodedObject() o.SetSize(9223372036854775807) o.SetType(plumbing.CommitObject) - _, err := s.store.SetObject(o) + _, err := s.store.SetEncodedObject(o) c.Assert(err, IsNil) hash, err := s.enc.Encode([]plumbing.Hash{o.Hash()}) c.Assert(err, IsNil) @@ -98,14 +98,14 @@ func (s *EncoderSuite) TestDecodeEncodeDecode(c *C) { c.Assert(err, IsNil) c.Assert(ch, Equals, f.PackfileHash) - objIter, err := d.o.IterObjects(plumbing.AnyObject) + objIter, err := d.o.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) - objects := []plumbing.Object{} + objects := []plumbing.EncodedObject{} hashes := []plumbing.Hash{} - err = objIter.ForEach(func(o plumbing.Object) error { + err = objIter.ForEach(func(o plumbing.EncodedObject) error { objects = append(objects, o) - hash, err := s.store.SetObject(o) + hash, err := s.store.SetEncodedObject(o) c.Assert(err, IsNil) hashes = append(hashes, hash) @@ -124,10 +124,10 @@ func (s *EncoderSuite) TestDecodeEncodeDecode(c *C) { _, err = d.Decode() c.Assert(err, IsNil) - objIter, err = d.o.IterObjects(plumbing.AnyObject) + objIter, err = d.o.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) - obtainedObjects := []plumbing.Object{} - err = objIter.ForEach(func(o plumbing.Object) error { + obtainedObjects := []plumbing.EncodedObject{} + err = objIter.ForEach(func(o plumbing.EncodedObject) error { obtainedObjects = append(obtainedObjects, o) return nil @@ -187,11 +187,11 @@ func (s *EncoderSuite) simpleDeltaTest(c *C, t plumbing.ObjectType) { _, err = d.Decode() c.Assert(err, IsNil) - decSrc, err := storage.Object(srcObject.Type(), srcObject.Hash()) + decSrc, err := storage.EncodedObject(srcObject.Type(), srcObject.Hash()) c.Assert(err, IsNil) c.Assert(decSrc, DeepEquals, srcObject) - decTarget, err := storage.Object(targetObject.Type(), targetObject.Hash()) + decTarget, err := storage.EncodedObject(targetObject.Type(), targetObject.Hash()) c.Assert(err, IsNil) c.Assert(decTarget, DeepEquals, targetObject) } @@ -226,20 +226,20 @@ func (s *EncoderSuite) deltaOverDeltaTest(c *C, t plumbing.ObjectType) { _, err = d.Decode() c.Assert(err, IsNil) - decSrc, err := storage.Object(srcObject.Type(), srcObject.Hash()) + decSrc, err := storage.EncodedObject(srcObject.Type(), srcObject.Hash()) c.Assert(err, IsNil) c.Assert(decSrc, DeepEquals, srcObject) - decTarget, err := storage.Object(targetObject.Type(), targetObject.Hash()) + decTarget, err := storage.EncodedObject(targetObject.Type(), targetObject.Hash()) c.Assert(err, IsNil) c.Assert(decTarget, DeepEquals, targetObject) - decOtherTarget, err := storage.Object(otherTargetObject.Type(), otherTargetObject.Hash()) + decOtherTarget, err := storage.EncodedObject(otherTargetObject.Type(), otherTargetObject.Hash()) c.Assert(err, IsNil) c.Assert(decOtherTarget, DeepEquals, otherTargetObject) } -func delta(base, target plumbing.Object, t plumbing.ObjectType) (plumbing.Object, error) { +func delta(base, target plumbing.EncodedObject, t plumbing.ObjectType) (plumbing.EncodedObject, error) { switch t { case plumbing.OFSDeltaObject: return GetOFSDelta(base, target) @@ -250,7 +250,7 @@ func delta(base, target plumbing.Object, t plumbing.ObjectType) (plumbing.Object } } -func newObject(t plumbing.ObjectType, cont []byte) plumbing.Object { +func newObject(t plumbing.ObjectType, cont []byte) plumbing.EncodedObject { o := plumbing.MemoryObject{} o.SetType(t) o.SetSize(int64(len(cont))) diff --git a/plumbing/format/packfile/object_pack.go b/plumbing/format/packfile/object_pack.go index dc5a3c7..dfe9bb2 100644 --- a/plumbing/format/packfile/object_pack.go +++ b/plumbing/format/packfile/object_pack.go @@ -6,20 +6,21 @@ import "gopkg.in/src-d/go-git.v4/plumbing" // pack file. type ObjectToPack struct { // The main object to pack, it could be any object, including deltas - Object plumbing.Object + Object plumbing.EncodedObject // Base is the object that a delta is based on (it could be also another delta). // If the main object is not a delta, Base will be null Base *ObjectToPack // Original is the object that we can generate applying the delta to - // Base, or the same object as Object in the case of a non-delta object. - Original plumbing.Object + // Base, or the same object as EncodedObject in the case of a non-delta + // object. + Original plumbing.EncodedObject // Depth is the amount of deltas needed to resolve to obtain Original // (delta based on delta based on ...) Depth int } // newObjectToPack creates a correct ObjectToPack based on a non-delta object -func newObjectToPack(o plumbing.Object) *ObjectToPack { +func newObjectToPack(o plumbing.EncodedObject) *ObjectToPack { return &ObjectToPack{ Object: o, Original: o, @@ -29,7 +30,7 @@ func newObjectToPack(o plumbing.Object) *ObjectToPack { // newDeltaObjectToPack creates a correct ObjectToPack for a delta object, based on // his base (could be another delta), the delta target (in this case called original), // and the delta Object itself -func newDeltaObjectToPack(base *ObjectToPack, original, delta plumbing.Object) *ObjectToPack { +func newDeltaObjectToPack(base *ObjectToPack, original, delta plumbing.EncodedObject) *ObjectToPack { return &ObjectToPack{ Object: delta, Base: base, diff --git a/plumbing/format/packfile/patch_delta.go b/plumbing/format/packfile/patch_delta.go index 2493a39..36219bb 100644 --- a/plumbing/format/packfile/patch_delta.go +++ b/plumbing/format/packfile/patch_delta.go @@ -14,7 +14,7 @@ import ( const deltaSizeMin = 4 // ApplyDelta writes to taget the result of applying the modification deltas in delta to base. -func ApplyDelta(target, base plumbing.Object, delta []byte) error { +func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) error { r, err := base.Reader() if err != nil { return err diff --git a/plumbing/object.go b/plumbing/object.go index 23abd4f..3304da2 100644 --- a/plumbing/object.go +++ b/plumbing/object.go @@ -13,7 +13,7 @@ var ( ) // Object is a generic representation of any git object -type Object interface { +type EncodedObject interface { Hash() Hash Type() ObjectType SetType(ObjectType) diff --git a/blobs.go b/plumbing/object/blob.go index 9585af8..b0cac41 100644 --- a/blobs.go +++ b/plumbing/object/blob.go @@ -1,10 +1,11 @@ -package git +package object import ( "io" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/utils/ioutil" ) // Blob is used to store file data - it is generally a file. @@ -12,7 +13,26 @@ type Blob struct { Hash plumbing.Hash Size int64 - obj plumbing.Object + obj plumbing.EncodedObject +} + +// GetBlob gets a blob from an object storer and decodes it. +func GetBlob(s storer.EncodedObjectStorer, h plumbing.Hash) (*Blob, error) { + o, err := s.EncodedObject(plumbing.BlobObject, h) + if err != nil { + return nil, err + } + + return DecodeBlob(o) +} + +func DecodeBlob(o plumbing.EncodedObject) (*Blob, error) { + b := &Blob{} + if err := b.Decode(o); err != nil { + return nil, err + } + + return b, nil } // ID returns the object ID of the blob. The returned value will always match @@ -30,8 +50,8 @@ func (b *Blob) Type() plumbing.ObjectType { return plumbing.BlobObject } -// Decode transforms a plumbing.Object into a Blob struct. -func (b *Blob) Decode(o plumbing.Object) error { +// Decode transforms a plumbing.EncodedObject into a Blob struct. +func (b *Blob) Decode(o plumbing.EncodedObject) error { if o.Type() != plumbing.BlobObject { return ErrUnsupportedObject } @@ -43,18 +63,18 @@ func (b *Blob) Decode(o plumbing.Object) error { return nil } -// Encode transforms a Blob into a plumbing.Object. -func (b *Blob) Encode(o plumbing.Object) error { +// Encode transforms a Blob into a plumbing.EncodedObject. +func (b *Blob) Encode(o plumbing.EncodedObject) error { w, err := o.Writer() if err != nil { return err } - defer checkClose(w, &err) + defer ioutil.CheckClose(w, &err) r, err := b.Reader() if err != nil { return err } - defer checkClose(r, &err) + defer ioutil.CheckClose(r, &err) _, err = io.Copy(w, r) o.SetType(plumbing.BlobObject) return err @@ -67,23 +87,23 @@ func (b *Blob) Reader() (io.ReadCloser, error) { // BlobIter provides an iterator for a set of blobs. type BlobIter struct { - storer.ObjectIter - r *Repository + storer.EncodedObjectIter + s storer.EncodedObjectStorer } // NewBlobIter returns a CommitIter for the given repository and underlying // object iterator. // // The returned BlobIter will automatically skip over non-blob objects. -func NewBlobIter(r *Repository, iter storer.ObjectIter) *BlobIter { - return &BlobIter{iter, r} +func NewBlobIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *BlobIter { + return &BlobIter{iter, s} } // Next moves the iterator to the next blob and returns a pointer to it. If it // has reached the end of the set it will return io.EOF. func (iter *BlobIter) Next() (*Blob, error) { for { - obj, err := iter.ObjectIter.Next() + obj, err := iter.EncodedObjectIter.Next() if err != nil { return nil, err } @@ -92,8 +112,7 @@ func (iter *BlobIter) Next() (*Blob, error) { continue } - blob := &Blob{} - return blob, blob.Decode(obj) + return DecodeBlob(obj) } } @@ -101,16 +120,16 @@ func (iter *BlobIter) Next() (*Blob, error) { // an error happens or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. func (iter *BlobIter) ForEach(cb func(*Blob) error) error { - return iter.ObjectIter.ForEach(func(obj plumbing.Object) error { + return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { if obj.Type() != plumbing.BlobObject { return nil } - blob := &Blob{} - if err := blob.Decode(obj); err != nil { + b, err := DecodeBlob(obj) + if err != nil { return err } - return cb(blob) + return cb(b) }) } diff --git a/blobs_test.go b/plumbing/object/blob_test.go index a323744..5ed9de0 100644 --- a/blobs_test.go +++ b/plumbing/object/blob_test.go @@ -1,4 +1,4 @@ -package git +package object import ( "io" @@ -10,7 +10,7 @@ import ( ) type BlobsSuite struct { - BaseSuite + BaseObjectsSuite } var _ = Suite(&BlobsSuite{}) @@ -63,8 +63,9 @@ func (s *BlobsSuite) TestBlobDecodeEncodeIdempotent(c *C) { } func (s *BlobsSuite) TestBlobIter(c *C) { - iter, err := s.Repository.Blobs() + encIter, err := s.Storer.IterEncodedObjects(plumbing.BlobObject) c.Assert(err, IsNil) + iter := NewBlobIter(s.Storer, encIter) blobs := []*Blob{} iter.ForEach(func(b *Blob) error { @@ -75,8 +76,9 @@ func (s *BlobsSuite) TestBlobIter(c *C) { c.Assert(len(blobs) > 0, Equals, true) iter.Close() - iter, err = s.Repository.Blobs() + encIter, err = s.Storer.IterEncodedObjects(plumbing.BlobObject) c.Assert(err, IsNil) + iter = NewBlobIter(s.Storer, encIter) i := 0 for { diff --git a/commit.go b/plumbing/object/commit.go index 6f93832..f0ce6e8 100644 --- a/commit.go +++ b/plumbing/object/commit.go @@ -1,4 +1,4 @@ -package git +package object import ( "bufio" @@ -10,6 +10,7 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/utils/ioutil" ) // Hash hash of an object @@ -28,18 +29,39 @@ type Commit struct { tree plumbing.Hash parents []plumbing.Hash - r *Repository + s storer.EncodedObjectStorer +} + +// GetCommit gets a commit from an object storer and decodes it. +func GetCommit(s storer.EncodedObjectStorer, h plumbing.Hash) (*Commit, error) { + o, err := s.EncodedObject(plumbing.CommitObject, h) + if err != nil { + return nil, err + } + + return DecodeCommit(s, o) +} + +// DecodeCommit decodes an encoded object into a *Commit and associates it to +// the given object storer. +func DecodeCommit(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Commit, error) { + c := &Commit{s: s} + if err := c.Decode(o); err != nil { + return nil, err + } + + return c, nil } // Tree returns the Tree from the commit func (c *Commit) Tree() (*Tree, error) { - return c.r.Tree(c.tree) + return GetTree(c.s, c.tree) } // Parents return a CommitIter to the parent Commits func (c *Commit) Parents() *CommitIter { - return NewCommitIter(c.r, - storer.NewObjectLookupIter(c.r.s, plumbing.CommitObject, c.parents), + return NewCommitIter(c.s, + storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, c.parents), ) } @@ -85,8 +107,8 @@ func (c *Commit) Type() plumbing.ObjectType { return plumbing.CommitObject } -// Decode transforms a plumbing.Object into a Commit struct. -func (c *Commit) Decode(o plumbing.Object) (err error) { +// Decode transforms a plumbing.EncodedObject into a Commit struct. +func (c *Commit) Decode(o plumbing.EncodedObject) (err error) { if o.Type() != plumbing.CommitObject { return ErrUnsupportedObject } @@ -97,7 +119,7 @@ func (c *Commit) Decode(o plumbing.Object) (err error) { if err != nil { return err } - defer checkClose(reader, &err) + defer ioutil.CheckClose(reader, &err) r := bufio.NewReader(reader) @@ -148,14 +170,14 @@ func (c *Commit) History() ([]*Commit, error) { return commits, err } -// Encode transforms a Commit into a plumbing.Object. -func (b *Commit) Encode(o plumbing.Object) error { +// Encode transforms a Commit into a plumbing.EncodedObject. +func (b *Commit) Encode(o plumbing.EncodedObject) error { o.SetType(plumbing.CommitObject) w, err := o.Writer() if err != nil { return err } - defer checkClose(w, &err) + defer ioutil.CheckClose(w, &err) if _, err = fmt.Fprintf(w, "tree %s\n", b.tree.String()); err != nil { return err } @@ -205,41 +227,40 @@ func indent(t string) string { // CommitIter provides an iterator for a set of commits. type CommitIter struct { - storer.ObjectIter - r *Repository + storer.EncodedObjectIter + s storer.EncodedObjectStorer } -// NewCommitIter returns a CommitIter for the given repository and underlying +// NewCommitIter returns a CommitIter for the given object storer and underlying // object iterator. // // The returned CommitIter will automatically skip over non-commit objects. -func NewCommitIter(r *Repository, iter storer.ObjectIter) *CommitIter { - return &CommitIter{iter, r} +func NewCommitIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *CommitIter { + return &CommitIter{iter, s} } // Next moves the iterator to the next commit and returns a pointer to it. If it // has reached the end of the set it will return io.EOF. func (iter *CommitIter) Next() (*Commit, error) { - obj, err := iter.ObjectIter.Next() + obj, err := iter.EncodedObjectIter.Next() if err != nil { return nil, err } - commit := &Commit{r: iter.r} - return commit, commit.Decode(obj) + return DecodeCommit(iter.s, obj) } // ForEach call the cb function for each commit contained on this iter until -// an error happends or the end of the iter is reached. If ErrStop is sent +// an error appends or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. func (iter *CommitIter) ForEach(cb func(*Commit) error) error { - return iter.ObjectIter.ForEach(func(obj plumbing.Object) error { - commit := &Commit{r: iter.r} - if err := commit.Decode(obj); err != nil { + return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { + c, err := DecodeCommit(iter.s, obj) + if err != nil { return err } - return cb(commit) + return cb(c) }) } diff --git a/commit_test.go b/plumbing/object/commit_test.go index ed240e8..abf92dd 100644 --- a/commit_test.go +++ b/plumbing/object/commit_test.go @@ -1,4 +1,4 @@ -package git +package object import ( "io" @@ -8,28 +8,27 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing" . "gopkg.in/check.v1" + "gopkg.in/src-d/go-git.v4/storage/filesystem" ) type SuiteCommit struct { - BaseSuite + BaseObjectsSuite Commit *Commit } var _ = Suite(&SuiteCommit{}) func (s *SuiteCommit) SetUpSuite(c *C) { - s.BaseSuite.SetUpSuite(c) + s.BaseObjectsSuite.SetUpSuite(c) hash := plumbing.NewHash("1669dce138d9b841a518c64b10914d88f5e488ea") - var err error - s.Commit, err = s.Repository.Commit(hash) - c.Assert(err, IsNil) + s.Commit = s.commit(c, hash) } func (s *SuiteCommit) TestDecodeNonCommit(c *C) { hash := plumbing.NewHash("9a48f23120e880dfbe41f7c9b7b708e9ee62a492") - blob, err := s.Repository.s.Object(plumbing.AnyObject, hash) + blob, err := s.Storer.EncodedObject(plumbing.AnyObject, hash) c.Assert(err, IsNil) commit := &Commit{} @@ -132,9 +131,12 @@ func (s *SuiteCommit) TestString(c *C) { func (s *SuiteCommit) TestStringMultiLine(c *C) { hash := plumbing.NewHash("e7d896db87294e33ca3202e536d4d9bb16023db3") - r := s.NewRepositoryFromPackfile(fixtures.ByURL("https://github.com/src-d/go-git.git").One()) + f := fixtures.ByURL("https://github.com/src-d/go-git.git").One() + sto, err := filesystem.NewStorage(f.DotGit()) - commit, err := r.Commit(hash) + o, err := sto.EncodedObject(plumbing.CommitObject, hash) + c.Assert(err, IsNil) + commit, err := DecodeCommit(sto, o) c.Assert(err, IsNil) c.Assert(commit.String(), Equals, ""+ diff --git a/commit_walker.go b/plumbing/object/commit_walker.go index 8685801..dcce6b9 100644 --- a/commit_walker.go +++ b/plumbing/object/commit_walker.go @@ -1,4 +1,4 @@ -package git +package object import ( "io" diff --git a/commit_walker_test.go b/plumbing/object/commit_walker_test.go index cf239bc..67d6695 100644 --- a/commit_walker_test.go +++ b/plumbing/object/commit_walker_test.go @@ -1,19 +1,15 @@ -package git +package object import . "gopkg.in/check.v1" type CommitWalkerSuite struct { - BaseSuite + BaseObjectsSuite } var _ = Suite(&CommitWalkerSuite{}) func (s *CommitWalkerSuite) TestWalkerNext(c *C) { - r, err := s.Repository.Head() - c.Assert(err, IsNil) - - commit, err := s.Repository.Commit(r.Hash()) - c.Assert(err, IsNil) + commit := s.commit(c, s.Fixture.Head) var commits []*Commit diff --git a/file.go b/plumbing/object/file.go index e735723..4846f98 100644 --- a/file.go +++ b/plumbing/object/file.go @@ -1,4 +1,4 @@ -package git +package object import ( "bytes" @@ -7,6 +7,7 @@ import ( "strings" "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/utils/ioutil" ) // File represents git file objects. @@ -27,7 +28,7 @@ func (f *File) Contents() (content string, err error) { if err != nil { return "", err } - defer checkClose(reader, &err) + defer ioutil.CheckClose(reader, &err) buf := new(bytes.Buffer) if _, err := buf.ReadFrom(reader); err != nil { @@ -56,12 +57,12 @@ func (f *File) Lines() ([]string, error) { } type FileIter struct { - r *Repository + s storer.EncodedObjectStorer w TreeWalker } -func NewFileIter(r *Repository, t *Tree) *FileIter { - return &FileIter{r: r, w: *NewTreeWalker(r, t, true)} +func NewFileIter(s storer.EncodedObjectStorer, t *Tree) *FileIter { + return &FileIter{s: s, w: *NewTreeWalker(t, true)} } func (iter *FileIter) Next() (*File, error) { @@ -75,7 +76,7 @@ func (iter *FileIter) Next() (*File, error) { continue } - blob, err := iter.r.Blob(entry.Hash) + blob, err := GetBlob(iter.s, entry.Hash) if err != nil { return nil, err } diff --git a/file_test.go b/plumbing/object/file_test.go index 507dbc4..f734455 100644 --- a/file_test.go +++ b/plumbing/object/file_test.go @@ -1,4 +1,4 @@ -package git +package object import ( "io" @@ -6,12 +6,13 @@ import ( "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/storage/filesystem" . "gopkg.in/check.v1" ) type FileSuite struct { - BaseSuite + BaseObjectsSuite } var _ = Suite(&FileSuite{}) @@ -41,14 +42,18 @@ var fileIterTests = []struct { func (s *FileSuite) TestIter(c *C) { for i, t := range fileIterTests { - r := s.NewRepository(fixtures.ByURL(t.repo).One()) - commit, err := r.Commit(plumbing.NewHash(t.commit)) + f := fixtures.ByURL(t.repo).One() + sto, err := filesystem.NewStorage(f.DotGit()) + c.Assert(err, IsNil) + + h := plumbing.NewHash(t.commit) + commit, err := GetCommit(sto, h) c.Assert(err, IsNil, Commentf("subtest %d: %v (%s)", i, err, t.commit)) tree, err := commit.Tree() c.Assert(err, IsNil) - iter := NewFileIter(s.Repository, tree) + iter := NewFileIter(sto, tree) for k := 0; k < len(t.files); k++ { exp := t.files[k] file, err := iter.Next() @@ -99,8 +104,12 @@ hs_err_pid* func (s *FileSuite) TestContents(c *C) { for i, t := range contentsTests { - r := s.NewRepository(fixtures.ByURL(t.repo).One()) - commit, err := r.Commit(plumbing.NewHash(t.commit)) + f := fixtures.ByURL(t.repo).One() + sto, err := filesystem.NewStorage(f.DotGit()) + c.Assert(err, IsNil) + + h := plumbing.NewHash(t.commit) + commit, err := GetCommit(sto, h) c.Assert(err, IsNil, Commentf("subtest %d: %v (%s)", i, err, t.commit)) file, err := commit.File(t.path) @@ -149,8 +158,12 @@ var linesTests = []struct { func (s *FileSuite) TestLines(c *C) { for i, t := range linesTests { - r := s.NewRepository(fixtures.ByURL(t.repo).One()) - commit, err := r.Commit(plumbing.NewHash(t.commit)) + f := fixtures.ByURL(t.repo).One() + sto, err := filesystem.NewStorage(f.DotGit()) + c.Assert(err, IsNil) + + h := plumbing.NewHash(t.commit) + commit, err := GetCommit(sto, h) c.Assert(err, IsNil, Commentf("subtest %d: %v (%s)", i, err, t.commit)) file, err := commit.File(t.path) @@ -180,8 +193,12 @@ var ignoreEmptyDirEntriesTests = []struct { // we don't ignore empty dirs. func (s *FileSuite) TestIgnoreEmptyDirEntries(c *C) { for i, t := range ignoreEmptyDirEntriesTests { - r := s.NewRepository(fixtures.ByURL(t.repo).One()) - commit, err := r.Commit(plumbing.NewHash(t.commit)) + f := fixtures.ByURL(t.repo).One() + sto, err := filesystem.NewStorage(f.DotGit()) + c.Assert(err, IsNil) + + h := plumbing.NewHash(t.commit) + commit, err := GetCommit(sto, h) c.Assert(err, IsNil, Commentf("subtest %d: %v (%s)", i, err, t.commit)) tree, err := commit.Tree() @@ -198,8 +215,7 @@ func (s *FileSuite) TestIgnoreEmptyDirEntries(c *C) { func (s *FileSuite) TestFileIter(c *C) { hash := plumbing.NewHash("1669dce138d9b841a518c64b10914d88f5e488ea") - - commit, err := s.Repository.Commit(hash) + commit, err := GetCommit(s.Storer, hash) c.Assert(err, IsNil) tree, err := commit.Tree() diff --git a/objects.go b/plumbing/object/object.go index d75d98a..8bdbb2a 100644 --- a/objects.go +++ b/plumbing/object/object.go @@ -1,4 +1,4 @@ -package git +package object import ( "bytes" @@ -35,15 +35,45 @@ var ErrUnsupportedObject = errors.New("unsupported object type") // } // } // -// This interface is intentionally different from plumbing.Object, which is a lower +// This interface is intentionally different from plumbing.EncodedObject, which is a lower // level interface used by storage implementations to read and write objects. type Object interface { ID() plumbing.Hash Type() plumbing.ObjectType - Decode(plumbing.Object) error - Encode(plumbing.Object) error + Decode(plumbing.EncodedObject) error + Encode(plumbing.EncodedObject) error } +// GetObject gets an object from an object storer and decodes it. +func GetObject(s storer.EncodedObjectStorer, h plumbing.Hash) (Object, error) { + o, err := s.EncodedObject(plumbing.AnyObject, h) + if err != nil { + return nil, err + } + + return DecodeObject(s, o) +} + +// DecodeObject decodes an encoded object into an Object and associates it to +// the given object storer. +func DecodeObject(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (Object, error) { + switch o.Type() { + case plumbing.CommitObject: + return DecodeCommit(s, o) + case plumbing.TreeObject: + return DecodeTree(s, o) + case plumbing.BlobObject: + return DecodeBlob(o) + case plumbing.TagObject: + return DecodeTag(s, o) + default: + return nil, plumbing.ErrInvalidType + } +} + +// DateFormat is the format being use in the orignal git implementation +const DateFormat = "Mon Jan 02 15:04:05 2006 -0700" + // Signature represents an action signed by a person type Signature struct { Name string @@ -117,21 +147,21 @@ func (s *Signature) String() string { // ObjectIter provides an iterator for a set of objects. type ObjectIter struct { - storer.ObjectIter - r *Repository + storer.EncodedObjectIter + s storer.EncodedObjectStorer } // NewObjectIter returns a ObjectIter for the given repository and underlying // object iterator. -func NewObjectIter(r *Repository, iter storer.ObjectIter) *ObjectIter { - return &ObjectIter{iter, r} +func NewObjectIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *ObjectIter { + return &ObjectIter{iter, s} } // Next moves the iterator to the next object and returns a pointer to it. If it // has reached the end of the set it will return io.EOF. func (iter *ObjectIter) Next() (Object, error) { for { - obj, err := iter.ObjectIter.Next() + obj, err := iter.EncodedObjectIter.Next() if err != nil { return nil, err } @@ -153,7 +183,7 @@ func (iter *ObjectIter) Next() (Object, error) { // an error happens or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. func (iter *ObjectIter) ForEach(cb func(Object) error) error { - return iter.ObjectIter.ForEach(func(obj plumbing.Object) error { + return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { o, err := iter.toObject(obj) if err == plumbing.ErrInvalidType { return nil @@ -167,13 +197,13 @@ func (iter *ObjectIter) ForEach(cb func(Object) error) error { }) } -func (iter *ObjectIter) toObject(obj plumbing.Object) (Object, error) { +func (iter *ObjectIter) toObject(obj plumbing.EncodedObject) (Object, error) { switch obj.Type() { case plumbing.BlobObject: blob := &Blob{} return blob, blob.Decode(obj) case plumbing.TreeObject: - tree := &Tree{r: iter.r} + tree := &Tree{s: iter.s} return tree, tree.Decode(obj) case plumbing.CommitObject: commit := &Commit{} diff --git a/objects_test.go b/plumbing/object/object_test.go index 78ebc6a..04f2b73 100644 --- a/objects_test.go +++ b/plumbing/object/object_test.go @@ -1,25 +1,62 @@ -package git +package object import ( + "io" "io/ioutil" + "testing" "time" + "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/storage/filesystem" . "gopkg.in/check.v1" - "io" ) +func Test(t *testing.T) { TestingT(t) } + +type BaseObjectsSuite struct { + fixtures.Suite + Storer storer.EncodedObjectStorer + Fixture *fixtures.Fixture +} + +func (s *BaseObjectsSuite) SetUpSuite(c *C) { + s.Suite.SetUpSuite(c) + s.Fixture = fixtures.Basic().One() + storer, err := filesystem.NewStorage(s.Fixture.DotGit()) + c.Assert(err, IsNil) + s.Storer = storer +} + +func (s *BaseObjectsSuite) tag(c *C, h plumbing.Hash) *Tag { + t, err := GetTag(s.Storer, h) + c.Assert(err, IsNil) + return t +} + +func (s *BaseObjectsSuite) tree(c *C, h plumbing.Hash) *Tree { + t, err := GetTree(s.Storer, h) + c.Assert(err, IsNil) + return t +} + +func (s *BaseObjectsSuite) commit(c *C, h plumbing.Hash) *Commit { + commit, err := GetCommit(s.Storer, h) + c.Assert(err, IsNil) + return commit +} + type ObjectsSuite struct { - BaseSuite + BaseObjectsSuite } var _ = Suite(&ObjectsSuite{}) func (s *ObjectsSuite) TestNewCommit(c *C) { hash := plumbing.NewHash("a5b8b09e2f8fcb0bb99d3ccb0958157b40890d69") - commit, err := s.Repository.Commit(hash) - c.Assert(err, IsNil) + commit := s.commit(c, hash) c.Assert(commit.Hash, Equals, commit.ID()) c.Assert(commit.Hash.String(), Equals, "a5b8b09e2f8fcb0bb99d3ccb0958157b40890d69") @@ -46,7 +83,7 @@ func (s *ObjectsSuite) TestNewCommit(c *C) { func (s *ObjectsSuite) TestParseTree(c *C) { hash := plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c") - tree, err := s.Repository.Tree(hash) + tree, err := GetTree(s.Storer, hash) c.Assert(err, IsNil) c.Assert(tree.Entries, HasLen, 8) @@ -124,8 +161,9 @@ func (s *ObjectsSuite) TestParseSignature(c *C) { } func (s *ObjectsSuite) TestObjectIter(c *C) { - iter, err := s.Repository.Objects() + encIter, err := s.Storer.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) + iter := NewObjectIter(s.Storer, encIter) objects := []Object{} iter.ForEach(func(o Object) error { @@ -136,8 +174,9 @@ func (s *ObjectsSuite) TestObjectIter(c *C) { c.Assert(len(objects) > 0, Equals, true) iter.Close() - iter, err = s.Repository.Objects() + encIter, err = s.Storer.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) + iter = NewObjectIter(s.Storer, encIter) i := 0 for { diff --git a/tag.go b/plumbing/object/tag.go index 7ab3689..5ca363d 100644 --- a/tag.go +++ b/plumbing/object/tag.go @@ -1,14 +1,15 @@ -package git +package object import ( "bufio" "bytes" "fmt" "io" - "io/ioutil" + stdioutil "io/ioutil" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/utils/ioutil" ) // Tag represents an annotated tag object. It points to a single git object of @@ -26,7 +27,28 @@ type Tag struct { TargetType plumbing.ObjectType Target plumbing.Hash - r *Repository + s storer.EncodedObjectStorer +} + +// GetTag gets a tag from an object storer and decodes it. +func GetTag(s storer.EncodedObjectStorer, h plumbing.Hash) (*Tag, error) { + o, err := s.EncodedObject(plumbing.TagObject, h) + if err != nil { + return nil, err + } + + return DecodeTag(s, o) +} + +// DecodeTag decodes an encoded object into a *Commit and associates it to the +// given object storer. +func DecodeTag(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Tag, error) { + t := &Tag{s: s} + if err := t.Decode(o); err != nil { + return nil, err + } + + return t, nil } // ID returns the object ID of the tag, not the object that the tag references. @@ -44,8 +66,8 @@ func (t *Tag) Type() plumbing.ObjectType { return plumbing.TagObject } -// Decode transforms a plumbing.Object into a Tag struct. -func (t *Tag) Decode(o plumbing.Object) (err error) { +// Decode transforms a plumbing.EncodedObject into a Tag struct. +func (t *Tag) Decode(o plumbing.EncodedObject) (err error) { if o.Type() != plumbing.TagObject { return ErrUnsupportedObject } @@ -56,7 +78,7 @@ func (t *Tag) Decode(o plumbing.Object) (err error) { if err != nil { return err } - defer checkClose(reader, &err) + defer ioutil.CheckClose(reader, &err) r := bufio.NewReader(reader) for { @@ -90,7 +112,7 @@ func (t *Tag) Decode(o plumbing.Object) (err error) { } } - data, err := ioutil.ReadAll(r) + data, err := stdioutil.ReadAll(r) if err != nil { return err } @@ -99,14 +121,14 @@ func (t *Tag) Decode(o plumbing.Object) (err error) { return nil } -// Encode transforms a Tag into a plumbing.Object. -func (t *Tag) Encode(o plumbing.Object) error { +// Encode transforms a Tag into a plumbing.EncodedObject. +func (t *Tag) Encode(o plumbing.EncodedObject) error { o.SetType(plumbing.TagObject) w, err := o.Writer() if err != nil { return err } - defer checkClose(w, &err) + defer ioutil.CheckClose(w, &err) if _, err = fmt.Fprintf(w, "object %s\ntype %s\ntag %s\ntagger ", @@ -135,7 +157,13 @@ func (t *Tag) Commit() (*Commit, error) { if t.TargetType != plumbing.CommitObject { return nil, ErrUnsupportedObject } - return t.r.Commit(t.Target) + + o, err := t.s.EncodedObject(plumbing.CommitObject, t.Target) + if err != nil { + return nil, err + } + + return DecodeCommit(t.s, o) } // Tree returns the tree pointed to by the tag. If the tag points to a commit @@ -144,13 +172,14 @@ func (t *Tag) Commit() (*Commit, error) { func (t *Tag) Tree() (*Tree, error) { switch t.TargetType { case plumbing.CommitObject: - commit, err := t.r.Commit(t.Target) + c, err := t.Commit() if err != nil { return nil, err } - return commit.Tree() + + return c.Tree() case plumbing.TreeObject: - return t.r.Tree(t.Target) + return GetTree(t.s, t.Target) default: return nil, ErrUnsupportedObject } @@ -162,12 +191,18 @@ func (t *Tag) Blob() (*Blob, error) { if t.TargetType != plumbing.BlobObject { return nil, ErrUnsupportedObject } - return t.r.Blob(t.Target) + + return GetBlob(t.s, t.Target) } // Object returns the object pointed to by the tag. func (t *Tag) Object() (Object, error) { - return t.r.Object(t.TargetType, t.Target) + o, err := t.s.EncodedObject(t.TargetType, t.Target) + if err != nil { + return nil, err + } + + return DecodeObject(t.s, o) } // String returns the meta information contained in the tag as a formatted @@ -184,41 +219,40 @@ func (t *Tag) String() string { // TagIter provides an iterator for a set of tags. type TagIter struct { - storer.ObjectIter - r *Repository + storer.EncodedObjectIter + s storer.EncodedObjectStorer } -// NewTagIter returns a TagIter for the given repository and underlying +// NewTagIter returns a TagIter for the given object storer and underlying // object iterator. // // The returned TagIter will automatically skip over non-tag objects. -func NewTagIter(r *Repository, iter storer.ObjectIter) *TagIter { - return &TagIter{iter, r} +func NewTagIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *TagIter { + return &TagIter{iter, s} } // Next moves the iterator to the next tag and returns a pointer to it. If it // has reached the end of the set it will return io.EOF. func (iter *TagIter) Next() (*Tag, error) { - obj, err := iter.ObjectIter.Next() + obj, err := iter.EncodedObjectIter.Next() if err != nil { return nil, err } - tag := &Tag{r: iter.r} - return tag, tag.Decode(obj) + return DecodeTag(iter.s, obj) } // ForEach call the cb function for each tag contained on this iter until // an error happends or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. func (iter *TagIter) ForEach(cb func(*Tag) error) error { - return iter.ObjectIter.ForEach(func(obj plumbing.Object) error { - tag := &Tag{r: iter.r} - if err := tag.Decode(obj); err != nil { + return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { + t, err := DecodeTag(iter.s, obj) + if err != nil { return err } - return cb(tag) + return cb(t) }) } diff --git a/tag_test.go b/plumbing/object/tag_test.go index 89fe1f5..2721442 100644 --- a/tag_test.go +++ b/plumbing/object/tag_test.go @@ -1,40 +1,41 @@ -package git +package object import ( "fmt" "time" - . "gopkg.in/check.v1" "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/storage/filesystem" + + . "gopkg.in/check.v1" ) type TagSuite struct { - BaseSuite + BaseObjectsSuite } var _ = Suite(&TagSuite{}) func (s *TagSuite) SetUpSuite(c *C) { - s.BaseSuite.SetUpSuite(c) - s.Repository = s.NewRepository(fixtures.ByURL("https://github.com/git-fixtures/tags.git").One()) + s.BaseObjectsSuite.SetUpSuite(c) + storer, err := filesystem.NewStorage(fixtures.ByURL("https://github.com/git-fixtures/tags.git").One().DotGit()) + c.Assert(err, IsNil) + s.Storer = storer } func (s *TagSuite) TestName(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) c.Assert(tag.Name, Equals, "annotated-tag") } func (s *TagSuite) TestTagger(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) c.Assert(tag.Tagger.String(), Equals, "Máximo Cuadros <mcuadros@gmail.com>") } func (s *TagSuite) TestAnnotated(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) c.Assert(tag.Message, Equals, "example annotated tag\n") commit, err := tag.Commit() @@ -44,8 +45,7 @@ func (s *TagSuite) TestAnnotated(c *C) { } func (s *TagSuite) TestCommit(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc")) c.Assert(tag.Message, Equals, "a tagged commit\n") commit, err := tag.Commit() @@ -55,8 +55,7 @@ func (s *TagSuite) TestCommit(c *C) { } func (s *TagSuite) TestBlob(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("fe6cb94756faa81e5ed9240f9191b833db5f40ae")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("fe6cb94756faa81e5ed9240f9191b833db5f40ae")) c.Assert(tag.Message, Equals, "a tagged blob\n") blob, err := tag.Blob() @@ -66,8 +65,7 @@ func (s *TagSuite) TestBlob(c *C) { } func (s *TagSuite) TestTree(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("152175bf7e5580299fa1f0ba41ef6474cc043b70")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("152175bf7e5580299fa1f0ba41ef6474cc043b70")) c.Assert(tag.Message, Equals, "a tagged tree\n") tree, err := tag.Tree() @@ -77,8 +75,7 @@ func (s *TagSuite) TestTree(c *C) { } func (s *TagSuite) TestTreeFromCommit(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc")) c.Assert(tag.Message, Equals, "a tagged commit\n") tree, err := tag.Tree() @@ -88,8 +85,7 @@ func (s *TagSuite) TestTreeFromCommit(c *C) { } func (s *TagSuite) TestObject(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc")) obj, err := tag.Object() c.Assert(err, IsNil) @@ -98,11 +94,11 @@ func (s *TagSuite) TestObject(c *C) { } func (s *TagSuite) TestTagItter(c *C) { - iter, err := s.Repository.s.IterObjects(plumbing.TagObject) + iter, err := s.Storer.IterEncodedObjects(plumbing.TagObject) c.Assert(err, IsNil) var count int - i := NewTagIter(s.Repository, iter) + i := NewTagIter(s.Storer, iter) err = i.ForEach(func(t *Tag) error { count++ return nil @@ -113,10 +109,10 @@ func (s *TagSuite) TestTagItter(c *C) { } func (s *TagSuite) TestTagIterError(c *C) { - iter, err := s.Repository.s.IterObjects(plumbing.TagObject) + iter, err := s.Storer.IterEncodedObjects(plumbing.TagObject) c.Assert(err, IsNil) - i := NewTagIter(s.Repository, iter) + i := NewTagIter(s.Storer, iter) err = i.ForEach(func(t *Tag) error { return fmt.Errorf("a random error") }) @@ -155,8 +151,7 @@ func (s *TagSuite) TestTagEncodeDecodeIdempotent(c *C) { } func (s *TagSuite) TestString(c *C) { - tag, err := s.Repository.Tag(plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) - c.Assert(err, IsNil) + tag := s.tag(c, plumbing.NewHash("b742a2a9fa0afcfa9a6fad080980fbc26b007c69")) c.Assert(tag.String(), Equals, ""+ "tag annotated-tag\n"+ "Tagger: Máximo Cuadros <mcuadros@gmail.com>\n"+ diff --git a/tree.go b/plumbing/object/tree.go index 753ed0c..7a8c1a3 100644 --- a/tree.go +++ b/plumbing/object/tree.go @@ -1,4 +1,4 @@ -package git +package object import ( "bufio" @@ -12,6 +12,7 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/utils/ioutil" ) const ( @@ -33,10 +34,31 @@ type Tree struct { Entries []TreeEntry Hash plumbing.Hash - r *Repository + s storer.EncodedObjectStorer m map[string]*TreeEntry } +// GetTree gets a tree from an object storer and decodes it. +func GetTree(s storer.EncodedObjectStorer, h plumbing.Hash) (*Tree, error) { + o, err := s.EncodedObject(plumbing.TreeObject, h) + if err != nil { + return nil, err + } + + return DecodeTree(s, o) +} + +// DecodeTree decodes an encoded object into a *Tree and associates it to the +// given object storer. +func DecodeTree(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Tree, error) { + t := &Tree{s: s} + if err := t.Decode(o); err != nil { + return nil, err + } + + return t, nil +} + // TreeEntry represents a file type TreeEntry struct { Name string @@ -52,17 +74,24 @@ func (t *Tree) File(path string) (*File, error) { return nil, ErrFileNotFound } - obj, err := t.r.s.Object(plumbing.BlobObject, e.Hash) + blob, err := GetBlob(t.s, e.Hash) if err != nil { return nil, err } - blob := &Blob{} - blob.Decode(obj) - return NewFile(path, e.Mode, blob), nil } +// TreeEntryFile returns the *File for a given *TreeEntry. +func (t *Tree) TreeEntryFile(e *TreeEntry) (*File, error) { + blob, err := GetBlob(t.s, e.Hash) + if err != nil { + return nil, err + } + + return NewFile(e.Name, e.Mode, blob), nil +} + func (t *Tree) findEntry(path string) (*TreeEntry, error) { pathParts := strings.Split(path, "/") @@ -85,12 +114,12 @@ func (t *Tree) dir(baseName string) (*Tree, error) { return nil, errDirNotFound } - obj, err := t.r.s.Object(plumbing.TreeObject, entry.Hash) + obj, err := t.s.EncodedObject(plumbing.TreeObject, entry.Hash) if err != nil { return nil, err } - tree := &Tree{r: t.r} + tree := &Tree{s: t.s} tree.Decode(obj) return tree, nil @@ -112,7 +141,7 @@ func (t *Tree) entry(baseName string) (*TreeEntry, error) { // Files returns a FileIter allowing to iterate over the Tree func (t *Tree) Files() *FileIter { - return NewFileIter(t.r, t) + return NewFileIter(t.s, t) } // ID returns the object ID of the tree. The returned value will always match @@ -128,8 +157,8 @@ func (t *Tree) Type() plumbing.ObjectType { return plumbing.TreeObject } -// Decode transform an plumbing.Object into a Tree struct -func (t *Tree) Decode(o plumbing.Object) (err error) { +// Decode transform an plumbing.EncodedObject into a Tree struct +func (t *Tree) Decode(o plumbing.EncodedObject) (err error) { if o.Type() != plumbing.TreeObject { return ErrUnsupportedObject } @@ -146,7 +175,7 @@ func (t *Tree) Decode(o plumbing.Object) (err error) { if err != nil { return err } - defer checkClose(reader, &err) + defer ioutil.CheckClose(reader, &err) r := bufio.NewReader(reader) for { @@ -202,8 +231,8 @@ func (t *Tree) decodeFileMode(mode string) (os.FileMode, error) { return m, nil } -// Encode transforms a Tree into a plumbing.Object. -func (t *Tree) Encode(o plumbing.Object) error { +// Encode transforms a Tree into a plumbing.EncodedObject. +func (t *Tree) Encode(o plumbing.EncodedObject) error { o.SetType(plumbing.TreeObject) w, err := o.Writer() if err != nil { @@ -211,7 +240,7 @@ func (t *Tree) Encode(o plumbing.Object) error { } var size int - defer checkClose(w, &err) + defer ioutil.CheckClose(w, &err) for _, entry := range t.Entries { n, err := fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name) if err != nil { @@ -263,15 +292,15 @@ type TreeWalker struct { base string recursive bool - r *Repository + s storer.EncodedObjectStorer t *Tree } -// NewTreeWalker returns a new TreeWalker for the given repository and tree. +// NewTreeWalker returns a new TreeWalker for the given tree. // // It is the caller's responsibility to call Close() when finished with the // tree walker. -func NewTreeWalker(r *Repository, t *Tree, recursive bool) *TreeWalker { +func NewTreeWalker(t *Tree, recursive bool) *TreeWalker { stack := make([]treeEntryIter, 0, startingStackSize) stack = append(stack, treeEntryIter{t, 0}) @@ -279,7 +308,7 @@ func NewTreeWalker(r *Repository, t *Tree, recursive bool) *TreeWalker { stack: stack, recursive: recursive, - r: r, + s: t.s, t: t, } } @@ -326,7 +355,7 @@ func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) { } if entry.Mode.IsDir() { - obj, err = w.r.Tree(entry.Hash) + obj, err = GetTree(w.s, entry.Hash) } name = path.Join(w.base, entry.Name) @@ -372,23 +401,23 @@ func (w *TreeWalker) Close() { // TreeIter provides an iterator for a set of trees. type TreeIter struct { - storer.ObjectIter - r *Repository + storer.EncodedObjectIter + s storer.EncodedObjectStorer } // NewTreeIter returns a TreeIter for the given repository and underlying // object iterator. // // The returned TreeIter will automatically skip over non-tree objects. -func NewTreeIter(r *Repository, iter storer.ObjectIter) *TreeIter { - return &TreeIter{iter, r} +func NewTreeIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *TreeIter { + return &TreeIter{iter, s} } // Next moves the iterator to the next tree and returns a pointer to it. If it // has reached the end of the set it will return io.EOF. func (iter *TreeIter) Next() (*Tree, error) { for { - obj, err := iter.ObjectIter.Next() + obj, err := iter.EncodedObjectIter.Next() if err != nil { return nil, err } @@ -397,8 +426,7 @@ func (iter *TreeIter) Next() (*Tree, error) { continue } - tree := &Tree{r: iter.r} - return tree, tree.Decode(obj) + return DecodeTree(iter.s, obj) } } @@ -406,16 +434,16 @@ func (iter *TreeIter) Next() (*Tree, error) { // an error happens or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. func (iter *TreeIter) ForEach(cb func(*Tree) error) error { - return iter.ObjectIter.ForEach(func(obj plumbing.Object) error { + return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error { if obj.Type() != plumbing.TreeObject { return nil } - tree := &Tree{r: iter.r} - if err := tree.Decode(obj); err != nil { + t, err := DecodeTree(iter.s, obj) + if err != nil { return err } - return cb(tree) + return cb(t) }) } diff --git a/tree_test.go b/plumbing/object/tree_test.go index 6e12ceb..00601c1 100644 --- a/tree_test.go +++ b/plumbing/object/tree_test.go @@ -1,4 +1,4 @@ -package git +package object import ( "io" @@ -7,22 +7,21 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing" . "gopkg.in/check.v1" + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) type TreeSuite struct { - BaseSuite + BaseObjectsSuite Tree *Tree } var _ = Suite(&TreeSuite{}) func (s *TreeSuite) SetUpSuite(c *C) { - s.BaseSuite.SetUpSuite(c) + s.BaseObjectsSuite.SetUpSuite(c) hash := plumbing.NewHash("a8d315b2b1c615d43042c3a62402b8a54288cf5c") - var err error - s.Tree, err = s.Repository.Tree(hash) - c.Assert(err, IsNil) + s.Tree = s.tree(c, hash) } func (s *TreeSuite) TestDecode(c *C) { @@ -37,7 +36,7 @@ func (s *TreeSuite) TestDecode(c *C) { func (s *TreeSuite) TestDecodeNonTree(c *C) { hash := plumbing.NewHash("9a48f23120e880dfbe41f7c9b7b708e9ee62a492") - blob, err := s.Repository.s.Object(plumbing.BlobObject, hash) + blob, err := s.Storer.EncodedObject(plumbing.BlobObject, hash) c.Assert(err, IsNil) tree := &Tree{} @@ -72,7 +71,7 @@ func (s *TreeSuite) TestFiles(c *C) { c.Assert(count, Equals, 9) } -// This plumbing.Object implementation has a reader that only returns 6 +// This plumbing.EncodedObject implementation has a reader that only returns 6 // bytes at a time, this should simulate the conditions when a read // returns less bytes than asked, for example when reading a hash which // is bigger than 6 bytes. @@ -147,12 +146,13 @@ func (s *TreeSuite) TestTreeDecodeEncodeIdempotent(c *C) { } func (s *TreeSuite) TestTreeIter(c *C) { - iter, err := s.Repository.Trees() + encIter, err := s.Storer.IterEncodedObjects(plumbing.TreeObject) c.Assert(err, IsNil) + iter := NewTreeIter(s.Storer, encIter) trees := []*Tree{} iter.ForEach(func(t *Tree) error { - t.r = nil + t.s = nil trees = append(trees, t) return nil }) @@ -160,8 +160,9 @@ func (s *TreeSuite) TestTreeIter(c *C) { c.Assert(len(trees) > 0, Equals, true) iter.Close() - iter, err = s.Repository.Trees() + encIter, err = s.Storer.IterEncodedObjects(plumbing.TreeObject) c.Assert(err, IsNil) + iter = NewTreeIter(s.Storer, encIter) i := 0 for { @@ -170,7 +171,7 @@ func (s *TreeSuite) TestTreeIter(c *C) { break } - t.r = nil + t.s = nil c.Assert(err, IsNil) c.Assert(t, DeepEquals, trees[i]) i += 1 @@ -180,14 +181,12 @@ func (s *TreeSuite) TestTreeIter(c *C) { } func (s *TreeSuite) TestTreeWalkerNext(c *C) { - r := s.Repository - commit, err := r.Commit(plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) + commit, err := GetCommit(s.Storer, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) c.Assert(err, IsNil) - tree, err := commit.Tree() c.Assert(err, IsNil) - walker := NewTreeWalker(r, tree, true) + walker := NewTreeWalker(tree, true) for _, e := range treeWalkerExpects { name, entry, err := walker.Next() if err == io.EOF { @@ -205,15 +204,12 @@ func (s *TreeSuite) TestTreeWalkerNext(c *C) { } func (s *TreeSuite) TestTreeWalkerNextNonRecursive(c *C) { - r := s.Repository - commit, err := r.Commit(plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) - c.Assert(err, IsNil) - + commit := s.commit(c, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) tree, err := commit.Tree() c.Assert(err, IsNil) var count int - walker := NewTreeWalker(r, tree, false) + walker := NewTreeWalker(tree, false) for { name, entry, err := walker.Next() if err == io.EOF { @@ -1418,7 +1414,7 @@ func (s *TreeSuite) TestTreeDecodeReadBug(c *C) { }, }, Hash: plumbing.Hash{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - r: (*Repository)(nil), + s: (storer.EncodedObjectStorer)(nil), m: map[string]*TreeEntry(nil), } diff --git a/revlist.go b/plumbing/revlist/revlist.go index 70dcb95..106e78b 100644 --- a/revlist.go +++ b/plumbing/revlist/revlist.go @@ -1,25 +1,30 @@ -package git +// Package revlist implements functions to walk the objects referenced by a +// commit history. Roughly equivalent to git-rev-list command. +package revlist import ( "io" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) -// RevListObjects applies a complementary set. It gets all the hashes from all +// Objects applies a complementary set. It gets all the hashes from all // the reachable objects from the given commits. Ignore param are object hashes // that we want to ignore on the result. It is a list because is // easier to interact with other porcelain elements, but internally it is -// converted to a map. All that objects must be accessible from the Repository. -func RevListObjects( - r *Repository, - commits []*Commit, +// converted to a map. All that objects must be accessible from the object +// storer. +func Objects( + s storer.EncodedObjectStorer, + commits []*object.Commit, ignore []plumbing.Hash) ([]plumbing.Hash, error) { seen := hashListToSet(ignore) result := make(map[plumbing.Hash]bool) for _, c := range commits { - err := reachableObjects(r, c, seen, func(h plumbing.Hash) error { + err := reachableObjects(s, c, seen, func(h plumbing.Hash) error { if !seen[h] { result[h] = true seen[h] = true @@ -41,12 +46,12 @@ func RevListObjects( // if a commit hash is into the 'seen' set, we will not iterate all his trees // and blobs objects. func reachableObjects( - r *Repository, - commit *Commit, + s storer.EncodedObjectStorer, + commit *object.Commit, seen map[plumbing.Hash]bool, cb func(h plumbing.Hash) error) error { - return iterateCommits(commit, func(commit *Commit) error { + return iterateCommits(commit, func(commit *object.Commit) error { if seen[commit.Hash] { return nil } @@ -55,27 +60,27 @@ func reachableObjects( return err } - return iterateCommitTrees(r, commit, func(h plumbing.Hash) error { + return iterateCommitTrees(s, commit, func(h plumbing.Hash) error { return cb(h) }) }) } // iterateCommits iterate all reachable commits from the given one -func iterateCommits(commit *Commit, cb func(c *Commit) error) error { +func iterateCommits(commit *object.Commit, cb func(c *object.Commit) error) error { if err := cb(commit); err != nil { return err } - return WalkCommitHistory(commit, func(c *Commit) error { + return object.WalkCommitHistory(commit, func(c *object.Commit) error { return cb(c) }) } // iterateCommitTrees iterate all reachable trees from the given commit func iterateCommitTrees( - repository *Repository, - commit *Commit, + s storer.EncodedObjectStorer, + commit *object.Commit, cb func(h plumbing.Hash) error) error { tree, err := commit.Tree() @@ -86,7 +91,7 @@ func iterateCommitTrees( return err } - treeWalker := NewTreeWalker(repository, tree, true) + treeWalker := object.NewTreeWalker(tree, true) for { _, e, err := treeWalker.Next() diff --git a/revlist_test.go b/plumbing/revlist/revlist_test.go index c47e7a8..60ae660 100644 --- a/revlist_test.go +++ b/plumbing/revlist/revlist_test.go @@ -1,15 +1,22 @@ -package git +package revlist import ( + "testing" + "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/plumbing/storer" + "gopkg.in/src-d/go-git.v4/storage/filesystem" . "gopkg.in/check.v1" ) +func Test(t *testing.T) { TestingT(t) } + type RevListSuite struct { - BaseSuite - r *Repository + fixtures.Suite + Storer storer.EncodedObjectStorer } var _ = Suite(&RevListSuite{}) @@ -43,9 +50,16 @@ const ( // * b029517 Initial commit func (s *RevListSuite) SetUpTest(c *C) { - r, err := NewFilesystemRepository(fixtures.Basic().One().DotGit().Base()) + s.Suite.SetUpSuite(c) + sto, err := filesystem.NewStorage(fixtures.Basic().One().DotGit()) + c.Assert(err, IsNil) + s.Storer = sto +} + +func (s *RevListSuite) commit(c *C, h plumbing.Hash) *object.Commit { + commit, err := object.GetCommit(s.Storer, h) c.Assert(err, IsNil) - s.r = r + return commit } // --- @@ -62,15 +76,13 @@ func (s *RevListSuite) TestRevListObjects(c *C) { "d3ff53e0564a9f87d8e84b6e28e5060e517008aa": true, // CHANGELOG } - initCommit, err := s.r.Commit(plumbing.NewHash(initialCommit)) - c.Assert(err, IsNil) - secondCommit, err := s.r.Commit(plumbing.NewHash(secondCommit)) - c.Assert(err, IsNil) + initCommit := s.commit(c, plumbing.NewHash(initialCommit)) + secondCommit := s.commit(c, plumbing.NewHash(secondCommit)) - localHist, err := RevListObjects(s.r, []*Commit{initCommit}, nil) + localHist, err := Objects(s.Storer, []*object.Commit{initCommit}, nil) c.Assert(err, IsNil) - remoteHist, err := RevListObjects(s.r, []*Commit{secondCommit}, localHist) + remoteHist, err := Objects(s.Storer, []*object.Commit{secondCommit}, localHist) c.Assert(err, IsNil) for _, h := range remoteHist { @@ -80,29 +92,25 @@ func (s *RevListSuite) TestRevListObjects(c *C) { } func (s *RevListSuite) TestRevListObjectsReverse(c *C) { - initCommit, err := s.r.Commit(plumbing.NewHash(initialCommit)) - c.Assert(err, IsNil) + initCommit := s.commit(c, plumbing.NewHash(initialCommit)) + secondCommit := s.commit(c, plumbing.NewHash(secondCommit)) - secondCommit, err := s.r.Commit(plumbing.NewHash(secondCommit)) + localHist, err := Objects(s.Storer, []*object.Commit{secondCommit}, nil) c.Assert(err, IsNil) - localHist, err := RevListObjects(s.r, []*Commit{secondCommit}, nil) - c.Assert(err, IsNil) - - remoteHist, err := RevListObjects(s.r, []*Commit{initCommit}, localHist) + remoteHist, err := Objects(s.Storer, []*object.Commit{initCommit}, localHist) c.Assert(err, IsNil) c.Assert(len(remoteHist), Equals, 0) } func (s *RevListSuite) TestRevListObjectsSameCommit(c *C) { - commit, err := s.r.Commit(plumbing.NewHash(secondCommit)) - c.Assert(err, IsNil) + commit := s.commit(c, plumbing.NewHash(secondCommit)) - localHist, err := RevListObjects(s.r, []*Commit{commit}, nil) + localHist, err := Objects(s.Storer, []*object.Commit{commit}, nil) c.Assert(err, IsNil) - remoteHist, err := RevListObjects(s.r, []*Commit{commit}, localHist) + remoteHist, err := Objects(s.Storer, []*object.Commit{commit}, localHist) c.Assert(err, IsNil) c.Assert(len(remoteHist), Equals, 0) @@ -114,20 +122,15 @@ func (s *RevListSuite) TestRevListObjectsSameCommit(c *C) { // * 918c48b some code // ----- func (s *RevListSuite) TestRevListObjectsNewBranch(c *C) { - someCommit, err := s.r.Commit(plumbing.NewHash(someCommit)) - c.Assert(err, IsNil) - - someCommitBranch, err := s.r.Commit(plumbing.NewHash(someCommitBranch)) - c.Assert(err, IsNil) - - someCommitOtherBranch, err := s.r.Commit(plumbing.NewHash(someCommitOtherBranch)) - c.Assert(err, IsNil) + someCommit := s.commit(c, plumbing.NewHash(someCommit)) + someCommitBranch := s.commit(c, plumbing.NewHash(someCommitBranch)) + someCommitOtherBranch := s.commit(c, plumbing.NewHash(someCommitOtherBranch)) - localHist, err := RevListObjects(s.r, []*Commit{someCommit}, nil) + localHist, err := Objects(s.Storer, []*object.Commit{someCommit}, nil) c.Assert(err, IsNil) - remoteHist, err := RevListObjects( - s.r, []*Commit{someCommitBranch, someCommitOtherBranch}, localHist) + remoteHist, err := Objects( + s.Storer, []*object.Commit{someCommitBranch, someCommitOtherBranch}, localHist) c.Assert(err, IsNil) revList := map[string]bool{ diff --git a/plumbing/storer/object.go b/plumbing/storer/object.go index 60b9171..a733ee6 100644 --- a/plumbing/storer/object.go +++ b/plumbing/storer/object.go @@ -12,27 +12,30 @@ var ( ErrStop = errors.New("stop iter") ) -// ObjectStorer generic storage of objects -type ObjectStorer interface { - // NewObject returns a new plumbing.Object, the real type of the object can - // be a custom implementation or the defaul one, plumbing.MemoryObject - NewObject() plumbing.Object - // SetObject save an object into the storage, the object shuld be create - // with the NewObject, method, and file if the type is not supported. - SetObject(plumbing.Object) (plumbing.Hash, error) - // Object get an object by hash with the given plumbing.ObjectType. - // Implementors should return (nil, plumbing.ErrObjectNotFound) if an object - // doesn't exist with both the given hash and object type. +// EncodedObjectStorer generic storage of objects +type EncodedObjectStorer interface { + // NewEncodedObject returns a new plumbing.EncodedObject, the real type + // of the object can be a custom implementation or the default one, + // plumbing.MemoryObject. + NewEncodedObject() plumbing.EncodedObject + // SetEncodedObject saves an object into the storage, the object should + // be create with the NewEncodedObject, method, and file if the type is + // not supported. + SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error) + // EncodedObject gets an object by hash with the given + // plumbing.ObjectType. Implementors should return + // (nil, plumbing.ErrObjectNotFound) if an object doesn't exist with + // both the given hash and object type. // // Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject, // TreeObject and AnyObject. If plumbing.AnyObject is given, the object must // be looked up regardless of its type. - Object(plumbing.ObjectType, plumbing.Hash) (plumbing.Object, error) - // IterObjects returns a custom ObjectIter over all the object on the - // storage. + EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error) + // IterObjects returns a custom EncodedObjectStorer over all the object + // on the storage. // // Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject, - IterObjects(plumbing.ObjectType) (ObjectIter, error) + IterEncodedObjects(plumbing.ObjectType) (EncodedObjectIter, error) } // Transactioner is a optional method for ObjectStorer, it enable transaction @@ -52,41 +55,41 @@ type PackfileWriter interface { PackfileWriter() (io.WriteCloser, error) } -// ObjectIter is a generic closable interface for iterating over objects. -type ObjectIter interface { - Next() (plumbing.Object, error) - ForEach(func(plumbing.Object) error) error +// EncodedObjectIter is a generic closable interface for iterating over objects. +type EncodedObjectIter interface { + Next() (plumbing.EncodedObject, error) + ForEach(func(plumbing.EncodedObject) error) error Close() } // Transaction is an in-progress storage transaction. A transaction must end // with a call to Commit or Rollback. type Transaction interface { - SetObject(plumbing.Object) (plumbing.Hash, error) - Object(plumbing.ObjectType, plumbing.Hash) (plumbing.Object, error) + SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error) + EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error) Commit() error Rollback() error } -// ObjectLookupIter implements ObjectIter. It iterates over a series of object -// hashes and yields their associated objects by retrieving each one from -// object storage. The retrievals are lazy and only occur when the iterator -// moves forward with a call to Next(). +// EncodedObjectLookupIter implements EncodedObjectIter. It iterates over a +// series of object hashes and yields their associated objects by retrieving +// each one from object storage. The retrievals are lazy and only occur when the +// iterator moves forward with a call to Next(). // -// The ObjectLookupIter must be closed with a call to Close() when it is no -// longer needed. -type ObjectLookupIter struct { - storage ObjectStorer +// The EncodedObjectLookupIter must be closed with a call to Close() when it is +// no longer needed. +type EncodedObjectLookupIter struct { + storage EncodedObjectStorer series []plumbing.Hash t plumbing.ObjectType pos int } -// NewObjectLookupIter returns an object iterator given an object storage and -// a slice of object hashes. -func NewObjectLookupIter( - storage ObjectStorer, t plumbing.ObjectType, series []plumbing.Hash) *ObjectLookupIter { - return &ObjectLookupIter{ +// NewEncodedObjectLookupIter returns an object iterator given an object storage +// and a slice of object hashes. +func NewEncodedObjectLookupIter( + storage EncodedObjectStorer, t plumbing.ObjectType, series []plumbing.Hash) *EncodedObjectLookupIter { + return &EncodedObjectLookupIter{ storage: storage, series: series, t: t, @@ -97,13 +100,13 @@ func NewObjectLookupIter( // the end it will return io.EOF as an error. If the object can't be found in // the object storage, it will return plumbing.ErrObjectNotFound as an error. // If the object is retreieved successfully error will be nil. -func (iter *ObjectLookupIter) Next() (plumbing.Object, error) { +func (iter *EncodedObjectLookupIter) Next() (plumbing.EncodedObject, error) { if iter.pos >= len(iter.series) { return nil, io.EOF } hash := iter.series[iter.pos] - obj, err := iter.storage.Object(iter.t, hash) + obj, err := iter.storage.EncodedObject(iter.t, hash) if err == nil { iter.pos++ } @@ -114,28 +117,30 @@ func (iter *ObjectLookupIter) Next() (plumbing.Object, error) { // ForEach call the cb function for each object contained on this iter until // an error happends or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. -func (iter *ObjectLookupIter) ForEach(cb func(plumbing.Object) error) error { +func (iter *EncodedObjectLookupIter) ForEach(cb func(plumbing.EncodedObject) error) error { return ForEachIterator(iter, cb) } // Close releases any resources used by the iterator. -func (iter *ObjectLookupIter) Close() { +func (iter *EncodedObjectLookupIter) Close() { iter.pos = len(iter.series) } -// ObjectSliceIter implements ObjectIter. It iterates over a series of objects -// stored in a slice and yields each one in turn when Next() is called. +// EncodedObjectSliceIter implements EncodedObjectIter. It iterates over a +// series of objects stored in a slice and yields each one in turn when Next() +// is called. // -// The ObjectSliceIter must be closed with a call to Close() when it is no -// longer needed. -type ObjectSliceIter struct { - series []plumbing.Object +// The EncodedObjectSliceIter must be closed with a call to Close() when it is +// no longer needed. +type EncodedObjectSliceIter struct { + series []plumbing.EncodedObject pos int } -// NewObjectSliceIter returns an object iterator for the given slice of objects. -func NewObjectSliceIter(series []plumbing.Object) *ObjectSliceIter { - return &ObjectSliceIter{ +// NewEncodedObjectSliceIter returns an object iterator for the given slice of +// objects. +func NewEncodedObjectSliceIter(series []plumbing.EncodedObject) *EncodedObjectSliceIter { + return &EncodedObjectSliceIter{ series: series, } } @@ -143,7 +148,7 @@ func NewObjectSliceIter(series []plumbing.Object) *ObjectSliceIter { // Next returns the next object from the iterator. If the iterator has reached // the end it will return io.EOF as an error. If the object is retreieved // successfully error will be nil. -func (iter *ObjectSliceIter) Next() (plumbing.Object, error) { +func (iter *EncodedObjectSliceIter) Next() (plumbing.EncodedObject, error) { if len(iter.series) == 0 { return nil, io.EOF } @@ -157,32 +162,34 @@ func (iter *ObjectSliceIter) Next() (plumbing.Object, error) { // ForEach call the cb function for each object contained on this iter until // an error happends or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. -func (iter *ObjectSliceIter) ForEach(cb func(plumbing.Object) error) error { +func (iter *EncodedObjectSliceIter) ForEach(cb func(plumbing.EncodedObject) error) error { return ForEachIterator(iter, cb) } // Close releases any resources used by the iterator. -func (iter *ObjectSliceIter) Close() { - iter.series = []plumbing.Object{} +func (iter *EncodedObjectSliceIter) Close() { + iter.series = []plumbing.EncodedObject{} } -// MultiObjectIter implements ObjectIter. It iterates over several ObjectIter, +// MultiEncodedObjectIter implements EncodedObjectIter. It iterates over several +// EncodedObjectIter, // // The MultiObjectIter must be closed with a call to Close() when it is no // longer needed. -type MultiObjectIter struct { - iters []ObjectIter +type MultiEncodedObjectIter struct { + iters []EncodedObjectIter pos int } -// NewMultiObjectIter returns an object iterator for the given slice of objects. -func NewMultiObjectIter(iters []ObjectIter) ObjectIter { - return &MultiObjectIter{iters: iters} +// NewMultiEncodedObjectIter returns an object iterator for the given slice of +// objects. +func NewMultiEncodedObjectIter(iters []EncodedObjectIter) EncodedObjectIter { + return &MultiEncodedObjectIter{iters: iters} } // Next returns the next object from the iterator, if one iterator reach io.EOF // is removed and the next one is used. -func (iter *MultiObjectIter) Next() (plumbing.Object, error) { +func (iter *MultiEncodedObjectIter) Next() (plumbing.EncodedObject, error) { if len(iter.iters) == 0 { return nil, io.EOF } @@ -200,25 +207,25 @@ func (iter *MultiObjectIter) Next() (plumbing.Object, error) { // ForEach call the cb function for each object contained on this iter until // an error happends or the end of the iter is reached. If ErrStop is sent // the iteration is stop but no error is returned. The iterator is closed. -func (iter *MultiObjectIter) ForEach(cb func(plumbing.Object) error) error { +func (iter *MultiEncodedObjectIter) ForEach(cb func(plumbing.EncodedObject) error) error { return ForEachIterator(iter, cb) } // Close releases any resources used by the iterator. -func (iter *MultiObjectIter) Close() { +func (iter *MultiEncodedObjectIter) Close() { for _, i := range iter.iters { i.Close() } } type bareIterator interface { - Next() (plumbing.Object, error) + Next() (plumbing.EncodedObject, error) Close() } // ForEachIterator is a helper function to build iterators without need to // rewrite the same ForEach function each time. -func ForEachIterator(iter bareIterator, cb func(plumbing.Object) error) error { +func ForEachIterator(iter bareIterator, cb func(plumbing.EncodedObject) error) error { defer iter.Close() for { obj, err := iter.Next() diff --git a/plumbing/storer/object_test.go b/plumbing/storer/object_test.go index a0a7755..6bdd25c 100644 --- a/plumbing/storer/object_test.go +++ b/plumbing/storer/object_test.go @@ -11,14 +11,14 @@ import ( func Test(t *testing.T) { TestingT(t) } type ObjectSuite struct { - Objects []plumbing.Object + Objects []plumbing.EncodedObject Hash []plumbing.Hash } var _ = Suite(&ObjectSuite{}) func (s *ObjectSuite) SetUpSuite(c *C) { - s.Objects = []plumbing.Object{ + s.Objects = []plumbing.EncodedObject{ s.buildObject([]byte("foo")), s.buildObject([]byte("bar")), } @@ -29,7 +29,7 @@ func (s *ObjectSuite) SetUpSuite(c *C) { } func (s *ObjectSuite) TestMultiObjectIterNext(c *C) { - expected := []plumbing.Object{ + expected := []plumbing.EncodedObject{ &plumbing.MemoryObject{}, &plumbing.MemoryObject{}, &plumbing.MemoryObject{}, @@ -38,14 +38,14 @@ func (s *ObjectSuite) TestMultiObjectIterNext(c *C) { &plumbing.MemoryObject{}, } - iter := NewMultiObjectIter([]ObjectIter{ - NewObjectSliceIter(expected[0:2]), - NewObjectSliceIter(expected[2:4]), - NewObjectSliceIter(expected[4:5]), + iter := NewMultiEncodedObjectIter([]EncodedObjectIter{ + NewEncodedObjectSliceIter(expected[0:2]), + NewEncodedObjectSliceIter(expected[2:4]), + NewEncodedObjectSliceIter(expected[4:5]), }) var i int - iter.ForEach(func(o plumbing.Object) error { + iter.ForEach(func(o plumbing.EncodedObject) error { c.Assert(o, Equals, expected[i]) i++ return nil @@ -54,7 +54,7 @@ func (s *ObjectSuite) TestMultiObjectIterNext(c *C) { iter.Close() } -func (s *ObjectSuite) buildObject(content []byte) plumbing.Object { +func (s *ObjectSuite) buildObject(content []byte) plumbing.EncodedObject { o := &plumbing.MemoryObject{} o.Write(content) @@ -65,8 +65,8 @@ func (s *ObjectSuite) TestObjectLookupIter(c *C) { var count int storage := &MockObjectStorage{s.Objects} - i := NewObjectLookupIter(storage, plumbing.CommitObject, s.Hash) - err := i.ForEach(func(o plumbing.Object) error { + i := NewEncodedObjectLookupIter(storage, plumbing.CommitObject, s.Hash) + err := i.ForEach(func(o plumbing.EncodedObject) error { c.Assert(o, NotNil) c.Assert(o.Hash().String(), Equals, s.Hash[count].String()) count++ @@ -80,8 +80,8 @@ func (s *ObjectSuite) TestObjectLookupIter(c *C) { func (s *ObjectSuite) TestObjectSliceIter(c *C) { var count int - i := NewObjectSliceIter(s.Objects) - err := i.ForEach(func(o plumbing.Object) error { + i := NewEncodedObjectSliceIter(s.Objects) + err := i.ForEach(func(o plumbing.EncodedObject) error { c.Assert(o, NotNil) c.Assert(o.Hash().String(), Equals, s.Hash[count].String()) count++ @@ -94,10 +94,10 @@ func (s *ObjectSuite) TestObjectSliceIter(c *C) { } func (s *ObjectSuite) TestObjectSliceIterStop(c *C) { - i := NewObjectSliceIter(s.Objects) + i := NewEncodedObjectSliceIter(s.Objects) var count = 0 - err := i.ForEach(func(o plumbing.Object) error { + err := i.ForEach(func(o plumbing.EncodedObject) error { c.Assert(o, NotNil) c.Assert(o.Hash().String(), Equals, s.Hash[count].String()) count++ @@ -109,11 +109,11 @@ func (s *ObjectSuite) TestObjectSliceIterStop(c *C) { } func (s *ObjectSuite) TestObjectSliceIterError(c *C) { - i := NewObjectSliceIter([]plumbing.Object{ + i := NewEncodedObjectSliceIter([]plumbing.EncodedObject{ s.buildObject([]byte("foo")), }) - err := i.ForEach(func(plumbing.Object) error { + err := i.ForEach(func(plumbing.EncodedObject) error { return fmt.Errorf("a random error") }) @@ -121,18 +121,18 @@ func (s *ObjectSuite) TestObjectSliceIterError(c *C) { } type MockObjectStorage struct { - db []plumbing.Object + db []plumbing.EncodedObject } -func (o *MockObjectStorage) NewObject() plumbing.Object { +func (o *MockObjectStorage) NewEncodedObject() plumbing.EncodedObject { return nil } -func (o *MockObjectStorage) SetObject(obj plumbing.Object) (plumbing.Hash, error) { +func (o *MockObjectStorage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) { return plumbing.ZeroHash, nil } -func (o *MockObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing.Object, error) { +func (o *MockObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { for _, o := range o.db { if o.Hash() == h { return o, nil @@ -141,7 +141,7 @@ func (o *MockObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plum return nil, plumbing.ErrObjectNotFound } -func (o *MockObjectStorage) IterObjects(t plumbing.ObjectType) (ObjectIter, error) { +func (o *MockObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (EncodedObjectIter, error) { return nil, nil } diff --git a/references.go b/references.go index 0ce7ea6..035e5c1 100644 --- a/references.go +++ b/references.go @@ -3,8 +3,9 @@ package git import ( "io" - "gopkg.in/src-d/go-git.v4/diff" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" + "gopkg.in/src-d/go-git.v4/utils/diff" "github.com/sergi/go-diff/diffmatchpatch" ) @@ -18,22 +19,22 @@ import ( // - Cherry-picks are not detected unless there are no commits between them and // therefore can appear repeated in the list. // (see git path-id for hints on how to fix this). -func (c *Commit) References(path string) ([]*Commit, error) { - var result []*Commit +func References(c *object.Commit, path string) ([]*object.Commit, error) { + var result []*object.Commit seen := make(map[plumbing.Hash]struct{}, 0) - if err := walkGraph(&result, &seen, c.r, c, path); err != nil { + if err := walkGraph(&result, &seen, c, path); err != nil { return nil, err } - SortCommits(result) + object.SortCommits(result) // for merges of identical cherry-picks return removeComp(path, result, equivalent) } -// Recursive traversal of the commit graph, generating a linear history -// of the path. -func walkGraph(result *[]*Commit, seen *map[plumbing.Hash]struct{}, repo *Repository, current *Commit, path string) error { +// Recursive traversal of the commit graph, generating a linear history of the +// path. +func walkGraph(result *[]*object.Commit, seen *map[plumbing.Hash]struct{}, current *object.Commit, path string) error { // check and update seen if _, ok := (*seen)[current.Hash]; ok { return nil @@ -67,12 +68,12 @@ func walkGraph(result *[]*Commit, seen *map[plumbing.Hash]struct{}, repo *Reposi *result = append(*result, current) } // in any case, walk the parent - return walkGraph(result, seen, repo, parents[0], path) + return walkGraph(result, seen, parents[0], path) default: // more than one parent contains the path // TODO: detect merges that had a conflict, because they must be // included in the result here. for _, p := range parents { - err := walkGraph(result, seen, repo, p, path) + err := walkGraph(result, seen, p, path) if err != nil { return err } @@ -81,10 +82,10 @@ func walkGraph(result *[]*Commit, seen *map[plumbing.Hash]struct{}, repo *Reposi return nil } -// TODO: benchmark this making git.Commit.parent public instead of using +// TODO: benchmark this making git.object.Commit.parent public instead of using // an iterator -func parentsContainingPath(path string, c *Commit) []*Commit { - var result []*Commit +func parentsContainingPath(path string, c *object.Commit) []*object.Commit { + var result []*object.Commit iter := c.Parents() for { parent, err := iter.Next() @@ -102,11 +103,11 @@ func parentsContainingPath(path string, c *Commit) []*Commit { // Returns an slice of the commits in "cs" that has the file "path", but with different // contents than what can be found in "c". -func differentContents(path string, c *Commit, cs []*Commit) ([]*Commit, error) { - result := make([]*Commit, 0, len(cs)) +func differentContents(path string, c *object.Commit, cs []*object.Commit) ([]*object.Commit, error) { + result := make([]*object.Commit, 0, len(cs)) h, found := blobHash(path, c) if !found { - return nil, ErrFileNotFound + return nil, object.ErrFileNotFound } for _, cx := range cs { if hx, found := blobHash(path, cx); found && h != hx { @@ -117,7 +118,7 @@ func differentContents(path string, c *Commit, cs []*Commit) ([]*Commit, error) } // blobHash returns the hash of a path in a commit -func blobHash(path string, commit *Commit) (hash plumbing.Hash, found bool) { +func blobHash(path string, commit *object.Commit) (hash plumbing.Hash, found bool) { file, err := commit.File(path) if err != nil { var empty plumbing.Hash @@ -126,13 +127,13 @@ func blobHash(path string, commit *Commit) (hash plumbing.Hash, found bool) { return file.Hash, true } -type contentsComparatorFn func(path string, a, b *Commit) (bool, error) +type contentsComparatorFn func(path string, a, b *object.Commit) (bool, error) // Returns a new slice of commits, with duplicates removed. Expects a // sorted commit list. Duplication is defined according to "comp". It // will always keep the first commit of a series of duplicated commits. -func removeComp(path string, cs []*Commit, comp contentsComparatorFn) ([]*Commit, error) { - result := make([]*Commit, 0, len(cs)) +func removeComp(path string, cs []*object.Commit, comp contentsComparatorFn) ([]*object.Commit, error) { + result := make([]*object.Commit, 0, len(cs)) if len(cs) == 0 { return result, nil } @@ -150,7 +151,7 @@ func removeComp(path string, cs []*Commit, comp contentsComparatorFn) ([]*Commit } // Equivalent commits are commits whose patch is the same. -func equivalent(path string, a, b *Commit) (bool, error) { +func equivalent(path string, a, b *object.Commit) (bool, error) { numParentsA := a.NumParents() numParentsB := b.NumParents() @@ -172,7 +173,7 @@ func equivalent(path string, a, b *Commit) (bool, error) { return sameDiffs(diffsA, diffsB), nil } -func patch(c *Commit, path string) ([]diffmatchpatch.Diff, error) { +func patch(c *object.Commit, path string) ([]diffmatchpatch.Diff, error) { // get contents of the file in the commit file, err := c.File(path) if err != nil { diff --git a/references_test.go b/references_test.go index 2147f49..1223df6 100644 --- a/references_test.go +++ b/references_test.go @@ -6,6 +6,7 @@ import ( "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" . "gopkg.in/check.v1" ) @@ -293,7 +294,7 @@ func (s *ReferencesSuite) TestRevList(c *C) { commit, err := r.Commit(plumbing.NewHash(t.commit)) c.Assert(err, IsNil) - revs, err := commit.References(t.path) + revs, err := References(commit, t.path) c.Assert(err, IsNil) c.Assert(len(revs), Equals, len(t.revs)) @@ -315,7 +316,7 @@ func (s *ReferencesSuite) TestRevList(c *C) { } // same length is assumed -func compareSideBySide(a []string, b []*Commit) string { +func compareSideBySide(a []string, b []*object.Commit) string { var buf bytes.Buffer buf.WriteString("\t EXPECTED OBTAINED ") var sep string @@ -352,10 +353,10 @@ func (s *ReferencesSuite) TestEquivalent(c *C) { } // returns the commits from a slice of hashes -func (s *ReferencesSuite) commits(c *C, repo string, hs ...string) []*Commit { +func (s *ReferencesSuite) commits(c *C, repo string, hs ...string) []*object.Commit { r := s.NewRepositoryFromPackfile(fixtures.ByURL(repo).One()) - result := make([]*Commit, 0, len(hs)) + result := make([]*object.Commit, 0, len(hs)) for _, h := range hs { commit, err := r.Commit(plumbing.NewHash(h)) c.Assert(err, IsNil) @@ -15,6 +15,7 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing/transport" "gopkg.in/src-d/go-git.v4/plumbing/transport/client" "gopkg.in/src-d/go-git.v4/storage/memory" + "gopkg.in/src-d/go-git.v4/utils/ioutil" ) var NoErrAlreadyUpToDate = errors.New("already up-to-date") @@ -126,7 +127,7 @@ func (r *Remote) Fetch(o *FetchOptions) (err error) { return err } - defer checkClose(reader, &err) + defer ioutil.CheckClose(reader, &err) if err = r.updateObjectStorage( r.buildSidebandIfSupported(req.Capabilities, reader), @@ -163,7 +164,7 @@ func (r *Remote) getWantedReferences(spec []config.RefSpec) ([]*plumbing.Referen } } - _, err := r.s.Object(plumbing.CommitObject, ref.Hash()) + _, err := r.s.EncodedObject(plumbing.CommitObject, ref.Hash()) if err == plumbing.ErrObjectNotFound { refs = append(refs, ref) return nil @@ -281,7 +282,7 @@ func (r *Remote) buildFetchedTags() error { return nil } - _, err := r.s.Object(plumbing.AnyObject, ref.Hash()) + _, err := r.s.EncodedObject(plumbing.AnyObject, ref.Hash()) if err == plumbing.ErrObjectNotFound { return nil } diff --git a/remote_test.go b/remote_test.go index a4e8e35..8296f8e 100644 --- a/remote_test.go +++ b/remote_test.go @@ -178,10 +178,10 @@ func (s *RemoteSuite) TestFetchWithPackfileWriter(c *C) { c.Assert(err, IsNil) var count int - iter, err := mock.IterObjects(plumbing.AnyObject) + iter, err := mock.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) - iter.ForEach(func(plumbing.Object) error { + iter.ForEach(func(plumbing.EncodedObject) error { count++ return nil }) diff --git a/repository.go b/repository.go index ae73885..6a6e01d 100644 --- a/repository.go +++ b/repository.go @@ -6,6 +6,7 @@ import ( "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/sideband" "gopkg.in/src-d/go-git.v4/plumbing/storer" "gopkg.in/src-d/go-git.v4/storage/filesystem" @@ -296,124 +297,90 @@ func (r *Repository) Pull(o *PullOptions) error { return r.createReferences(head) } -// Commit return the commit with the given hash -func (r *Repository) Commit(h plumbing.Hash) (*Commit, error) { - commit, err := r.Object(plumbing.CommitObject, h) - if err != nil { - return nil, err - } - - return commit.(*Commit), nil +// object.Commit return the commit with the given hash +func (r *Repository) Commit(h plumbing.Hash) (*object.Commit, error) { + return object.GetCommit(r.s, h) } // Commits decode the objects into commits -func (r *Repository) Commits() (*CommitIter, error) { - iter, err := r.s.IterObjects(plumbing.CommitObject) +func (r *Repository) Commits() (*object.CommitIter, error) { + iter, err := r.s.IterEncodedObjects(plumbing.CommitObject) if err != nil { return nil, err } - return NewCommitIter(r, iter), nil + return object.NewCommitIter(r.s, iter), nil } // Tree return the tree with the given hash -func (r *Repository) Tree(h plumbing.Hash) (*Tree, error) { - tree, err := r.Object(plumbing.TreeObject, h) - if err != nil { - return nil, err - } - - return tree.(*Tree), nil +func (r *Repository) Tree(h plumbing.Hash) (*object.Tree, error) { + return object.GetTree(r.s, h) } // Trees decodes the objects into trees -func (r *Repository) Trees() (*TreeIter, error) { - iter, err := r.s.IterObjects(plumbing.TreeObject) +func (r *Repository) Trees() (*object.TreeIter, error) { + iter, err := r.s.IterEncodedObjects(plumbing.TreeObject) if err != nil { return nil, err } - return NewTreeIter(r, iter), nil + return object.NewTreeIter(r.s, iter), nil } // Blob returns the blob with the given hash -func (r *Repository) Blob(h plumbing.Hash) (*Blob, error) { - blob, err := r.Object(plumbing.BlobObject, h) - if err != nil { - return nil, err - } - - return blob.(*Blob), nil +func (r *Repository) Blob(h plumbing.Hash) (*object.Blob, error) { + return object.GetBlob(r.s, h) } // Blobs decodes the objects into blobs -func (r *Repository) Blobs() (*BlobIter, error) { - iter, err := r.s.IterObjects(plumbing.BlobObject) +func (r *Repository) Blobs() (*object.BlobIter, error) { + iter, err := r.s.IterEncodedObjects(plumbing.BlobObject) if err != nil { return nil, err } - return NewBlobIter(r, iter), nil + return object.NewBlobIter(r.s, iter), nil } // Tag returns a tag with the given hash. -func (r *Repository) Tag(h plumbing.Hash) (*Tag, error) { - tag, err := r.Object(plumbing.TagObject, h) - if err != nil { - return nil, err - } - - return tag.(*Tag), nil +func (r *Repository) Tag(h plumbing.Hash) (*object.Tag, error) { + return object.GetTag(r.s, h) } -// Tags returns a TagIter that can step through all of the annotated tags +// Tags returns a object.TagIter that can step through all of the annotated tags // in the repository. -func (r *Repository) Tags() (*TagIter, error) { - iter, err := r.s.IterObjects(plumbing.TagObject) +func (r *Repository) Tags() (*object.TagIter, error) { + iter, err := r.s.IterEncodedObjects(plumbing.TagObject) if err != nil { return nil, err } - return NewTagIter(r, iter), nil + return object.NewTagIter(r.s, iter), nil } // Object returns an object with the given hash. -func (r *Repository) Object(t plumbing.ObjectType, h plumbing.Hash) (Object, error) { - obj, err := r.s.Object(t, h) +func (r *Repository) Object(t plumbing.ObjectType, h plumbing.Hash) (object.Object, error) { + obj, err := r.s.EncodedObject(t, h) if err != nil { if err == plumbing.ErrObjectNotFound { return nil, ErrObjectNotFound } + return nil, err } - switch obj.Type() { - case plumbing.CommitObject: - commit := &Commit{r: r} - return commit, commit.Decode(obj) - case plumbing.TreeObject: - tree := &Tree{r: r} - return tree, tree.Decode(obj) - case plumbing.BlobObject: - blob := &Blob{} - return blob, blob.Decode(obj) - case plumbing.TagObject: - tag := &Tag{r: r} - return tag, tag.Decode(obj) - default: - return nil, plumbing.ErrInvalidType - } + return object.DecodeObject(r.s, obj) } -// Objects returns an ObjectIter that can step through all of the annotated tags +// Objects returns an object.ObjectIter that can step through all of the annotated tags // in the repository. -func (r *Repository) Objects() (*ObjectIter, error) { - iter, err := r.s.IterObjects(plumbing.AnyObject) +func (r *Repository) Objects() (*object.ObjectIter, error) { + iter, err := r.s.IterEncodedObjects(plumbing.AnyObject) if err != nil { return nil, err } - return NewObjectIter(r, iter), nil + return object.NewObjectIter(r.s, iter), nil } // Head returns the reference where HEAD is pointing to. diff --git a/repository_test.go b/repository_test.go index b8f57cd..91a5c71 100644 --- a/repository_test.go +++ b/repository_test.go @@ -11,6 +11,7 @@ import ( "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/fixtures" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/object" "gopkg.in/src-d/go-git.v4/storage/memory" . "gopkg.in/check.v1" @@ -400,7 +401,7 @@ func (s *RepositorySuite) TestTags(c *C) { tags, err := r.Tags() c.Assert(err, IsNil) - tags.ForEach(func(tag *Tag) error { + tags.ForEach(func(tag *object.Tag) error { count++ c.Assert(tag.Hash.IsZero(), Equals, false) diff --git a/storage/filesystem/object.go b/storage/filesystem/object.go index 7b7bc18..836e7f3 100644 --- a/storage/filesystem/object.go +++ b/storage/filesystem/object.go @@ -53,7 +53,7 @@ func (s *ObjectStorage) loadIdxFile(h plumbing.Hash) error { return s.index[h].Decode(idx) } -func (s *ObjectStorage) NewObject() plumbing.Object { +func (s *ObjectStorage) NewEncodedObject() plumbing.EncodedObject { return &plumbing.MemoryObject{} } @@ -73,8 +73,8 @@ func (s *ObjectStorage) PackfileWriter() (io.WriteCloser, error) { return w, nil } -// Set adds a new object to the storage. -func (s *ObjectStorage) SetObject(o plumbing.Object) (plumbing.Hash, error) { +// SetEncodedObject adds a new object to the storage. +func (s *ObjectStorage) SetEncodedObject(o plumbing.EncodedObject) (plumbing.Hash, error) { if o.Type() == plumbing.OFSDeltaObject || o.Type() == plumbing.REFDeltaObject { return plumbing.ZeroHash, plumbing.ErrInvalidType } @@ -104,9 +104,9 @@ func (s *ObjectStorage) SetObject(o plumbing.Object) (plumbing.Hash, error) { return o.Hash(), nil } -// Get returns the object with the given hash, by searching for it in +// EncodedObject returns the object with the given hash, by searching for it in // the packfile and the git object directories. -func (s *ObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing.Object, error) { +func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { obj, err := s.getFromUnpacked(h) if err == plumbing.ErrObjectNotFound { obj, err = s.getFromPackfile(h) @@ -123,7 +123,7 @@ func (s *ObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing return obj, nil } -func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.Object, err error) { +func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedObject, err error) { f, err := s.dir.Object(h) if err != nil { if os.IsNotExist(err) { @@ -135,7 +135,7 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.Object, e defer f.Close() - obj = s.NewObject() + obj = s.NewEncodedObject() r, err := objfile.NewReader(f) if err != nil { return nil, err @@ -161,7 +161,7 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.Object, e // Get returns the object with the given hash, by searching for it in // the packfile. -func (s *ObjectStorage) getFromPackfile(h plumbing.Hash) (plumbing.Object, error) { +func (s *ObjectStorage) getFromPackfile(h plumbing.Hash) (plumbing.EncodedObject, error) { pack, offset := s.findObjectInPackfile(h) if offset == -1 { return nil, plumbing.ErrObjectNotFound @@ -194,16 +194,16 @@ func (s *ObjectStorage) findObjectInPackfile(h plumbing.Hash) (plumbing.Hash, in return plumbing.ZeroHash, -1 } -// Iter returns an iterator for all the objects in the packfile with the -// given type. -func (s *ObjectStorage) IterObjects(t plumbing.ObjectType) (storer.ObjectIter, error) { +// IterEncodedObjects returns an iterator for all the objects in the packfile +// with the given type. +func (s *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) { objects, err := s.dir.Objects() if err != nil { return nil, err } seen := make(map[plumbing.Hash]bool, 0) - var iters []storer.ObjectIter + var iters []storer.EncodedObjectIter if len(objects) != 0 { iters = append(iters, &objectsIter{s: s, t: t, h: objects}) seen = hashListAsMap(objects) @@ -215,17 +215,17 @@ func (s *ObjectStorage) IterObjects(t plumbing.ObjectType) (storer.ObjectIter, e } iters = append(iters, packi...) - return storer.NewMultiObjectIter(iters), nil + return storer.NewMultiEncodedObjectIter(iters), nil } func (s *ObjectStorage) buildPackfileIters( - t plumbing.ObjectType, seen map[plumbing.Hash]bool) ([]storer.ObjectIter, error) { + t plumbing.ObjectType, seen map[plumbing.Hash]bool) ([]storer.EncodedObjectIter, error) { packs, err := s.dir.ObjectPacks() if err != nil { return nil, err } - var iters []storer.ObjectIter + var iters []storer.EncodedObjectIter for _, h := range packs { pack, err := s.dir.ObjectPack(h) if err != nil { @@ -270,7 +270,7 @@ type packfileIter struct { total uint32 } -func newPackfileIter(f fs.File, t plumbing.ObjectType, seen map[plumbing.Hash]bool) (storer.ObjectIter, error) { +func newPackfileIter(f fs.File, t plumbing.ObjectType, seen map[plumbing.Hash]bool) (storer.EncodedObjectIter, error) { s := packfile.NewScanner(f) _, total, err := s.Header() if err != nil { @@ -292,7 +292,7 @@ func newPackfileIter(f fs.File, t plumbing.ObjectType, seen map[plumbing.Hash]bo }, nil } -func (iter *packfileIter) Next() (plumbing.Object, error) { +func (iter *packfileIter) Next() (plumbing.EncodedObject, error) { if iter.position >= iter.total { return nil, io.EOF } @@ -315,7 +315,7 @@ func (iter *packfileIter) Next() (plumbing.Object, error) { } // ForEach is never called since is used inside of a MultiObjectIterator -func (iter *packfileIter) ForEach(cb func(plumbing.Object) error) error { +func (iter *packfileIter) ForEach(cb func(plumbing.EncodedObject) error) error { return nil } @@ -330,7 +330,7 @@ type objectsIter struct { h []plumbing.Hash } -func (iter *objectsIter) Next() (plumbing.Object, error) { +func (iter *objectsIter) Next() (plumbing.EncodedObject, error) { if len(iter.h) == 0 { return nil, io.EOF } @@ -350,7 +350,7 @@ func (iter *objectsIter) Next() (plumbing.Object, error) { } // ForEach is never called since is used inside of a MultiObjectIterator -func (iter *objectsIter) ForEach(cb func(plumbing.Object) error) error { +func (iter *objectsIter) ForEach(cb func(plumbing.EncodedObject) error) error { return nil } diff --git a/storage/filesystem/object_test.go b/storage/filesystem/object_test.go index f839420..a3a5e68 100644 --- a/storage/filesystem/object_test.go +++ b/storage/filesystem/object_test.go @@ -20,7 +20,7 @@ func (s *FsSuite) TestGetFromObjectFile(c *C) { c.Assert(err, IsNil) expected := plumbing.NewHash("f3dfe29d268303fc6e1bbce268605fc99573406e") - obj, err := o.Object(plumbing.AnyObject, expected) + obj, err := o.EncodedObject(plumbing.AnyObject, expected) c.Assert(err, IsNil) c.Assert(obj.Hash(), Equals, expected) } @@ -32,7 +32,7 @@ func (s *FsSuite) TestGetFromPackfile(c *C) { c.Assert(err, IsNil) expected := plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5") - obj, err := o.Object(plumbing.AnyObject, expected) + obj, err := o.EncodedObject(plumbing.AnyObject, expected) c.Assert(err, IsNil) c.Assert(obj.Hash(), Equals, expected) }) @@ -60,11 +60,11 @@ func (s *FsSuite) TestIter(c *C) { o, err := newObjectStorage(dotgit.New(fs)) c.Assert(err, IsNil) - iter, err := o.IterObjects(plumbing.AnyObject) + iter, err := o.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) var count int32 - err = iter.ForEach(func(o plumbing.Object) error { + err = iter.ForEach(func(o plumbing.EncodedObject) error { count++ return nil }) @@ -80,10 +80,10 @@ func (s *FsSuite) TestIterWithType(c *C) { o, err := newObjectStorage(dotgit.New(fs)) c.Assert(err, IsNil) - iter, err := o.IterObjects(plumbing.CommitObject) + iter, err := o.IterEncodedObjects(plumbing.CommitObject) c.Assert(err, IsNil) - err = iter.ForEach(func(o plumbing.Object) error { + err = iter.ForEach(func(o plumbing.EncodedObject) error { c.Assert(o.Type(), Equals, plumbing.CommitObject) return nil }) diff --git a/storage/memory/storage.go b/storage/memory/storage.go index a7a2150..a912e94 100644 --- a/storage/memory/storage.go +++ b/storage/memory/storage.go @@ -27,11 +27,11 @@ func NewStorage() *Storage { ReferenceStorage: make(ReferenceStorage, 0), ConfigStorage: ConfigStorage{}, ObjectStorage: ObjectStorage{ - Objects: make(map[plumbing.Hash]plumbing.Object, 0), - Commits: make(map[plumbing.Hash]plumbing.Object, 0), - Trees: make(map[plumbing.Hash]plumbing.Object, 0), - Blobs: make(map[plumbing.Hash]plumbing.Object, 0), - Tags: make(map[plumbing.Hash]plumbing.Object, 0), + Objects: make(map[plumbing.Hash]plumbing.EncodedObject, 0), + Commits: make(map[plumbing.Hash]plumbing.EncodedObject, 0), + Trees: make(map[plumbing.Hash]plumbing.EncodedObject, 0), + Blobs: make(map[plumbing.Hash]plumbing.EncodedObject, 0), + Tags: make(map[plumbing.Hash]plumbing.EncodedObject, 0), }, } } @@ -58,18 +58,18 @@ func (c *ConfigStorage) Config() (*config.Config, error) { } type ObjectStorage struct { - Objects map[plumbing.Hash]plumbing.Object - Commits map[plumbing.Hash]plumbing.Object - Trees map[plumbing.Hash]plumbing.Object - Blobs map[plumbing.Hash]plumbing.Object - Tags map[plumbing.Hash]plumbing.Object + Objects map[plumbing.Hash]plumbing.EncodedObject + Commits map[plumbing.Hash]plumbing.EncodedObject + Trees map[plumbing.Hash]plumbing.EncodedObject + Blobs map[plumbing.Hash]plumbing.EncodedObject + Tags map[plumbing.Hash]plumbing.EncodedObject } -func (o *ObjectStorage) NewObject() plumbing.Object { +func (o *ObjectStorage) NewEncodedObject() plumbing.EncodedObject { return &plumbing.MemoryObject{} } -func (o *ObjectStorage) SetObject(obj plumbing.Object) (plumbing.Hash, error) { +func (o *ObjectStorage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) { h := obj.Hash() o.Objects[h] = obj @@ -89,7 +89,7 @@ func (o *ObjectStorage) SetObject(obj plumbing.Object) (plumbing.Hash, error) { return h, nil } -func (o *ObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing.Object, error) { +func (o *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { obj, ok := o.Objects[h] if !ok || (plumbing.AnyObject != t && obj.Type() != t) { return nil, plumbing.ErrObjectNotFound @@ -98,8 +98,8 @@ func (o *ObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing return obj, nil } -func (o *ObjectStorage) IterObjects(t plumbing.ObjectType) (storer.ObjectIter, error) { - var series []plumbing.Object +func (o *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) { + var series []plumbing.EncodedObject switch t { case plumbing.AnyObject: series = flattenObjectMap(o.Objects) @@ -113,11 +113,11 @@ func (o *ObjectStorage) IterObjects(t plumbing.ObjectType) (storer.ObjectIter, e series = flattenObjectMap(o.Tags) } - return storer.NewObjectSliceIter(series), nil + return storer.NewEncodedObjectSliceIter(series), nil } -func flattenObjectMap(m map[plumbing.Hash]plumbing.Object) []plumbing.Object { - objects := make([]plumbing.Object, 0, len(m)) +func flattenObjectMap(m map[plumbing.Hash]plumbing.EncodedObject) []plumbing.EncodedObject { + objects := make([]plumbing.EncodedObject, 0, len(m)) for _, obj := range m { objects = append(objects, obj) } @@ -127,23 +127,23 @@ func flattenObjectMap(m map[plumbing.Hash]plumbing.Object) []plumbing.Object { func (o *ObjectStorage) Begin() storer.Transaction { return &TxObjectStorage{ Storage: o, - Objects: make(map[plumbing.Hash]plumbing.Object, 0), + Objects: make(map[plumbing.Hash]plumbing.EncodedObject, 0), } } type TxObjectStorage struct { Storage *ObjectStorage - Objects map[plumbing.Hash]plumbing.Object + Objects map[plumbing.Hash]plumbing.EncodedObject } -func (tx *TxObjectStorage) SetObject(obj plumbing.Object) (plumbing.Hash, error) { +func (tx *TxObjectStorage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) { h := obj.Hash() tx.Objects[h] = obj return h, nil } -func (tx *TxObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumbing.Object, error) { +func (tx *TxObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { obj, ok := tx.Objects[h] if !ok || (plumbing.AnyObject != t && obj.Type() != t) { return nil, plumbing.ErrObjectNotFound @@ -155,7 +155,7 @@ func (tx *TxObjectStorage) Object(t plumbing.ObjectType, h plumbing.Hash) (plumb func (tx *TxObjectStorage) Commit() error { for h, obj := range tx.Objects { delete(tx.Objects, h) - if _, err := tx.Storage.SetObject(obj); err != nil { + if _, err := tx.Storage.SetEncodedObject(obj); err != nil { return err } } @@ -164,7 +164,7 @@ func (tx *TxObjectStorage) Commit() error { } func (tx *TxObjectStorage) Rollback() error { - tx.Objects = make(map[plumbing.Hash]plumbing.Object, 0) + tx.Objects = make(map[plumbing.Hash]plumbing.EncodedObject, 0) return nil } diff --git a/storage/test/storage_suite.go b/storage/test/storage_suite.go index 732c7a9..9d63ff8 100644 --- a/storage/test/storage_suite.go +++ b/storage/test/storage_suite.go @@ -15,13 +15,13 @@ import ( ) type Storer interface { - storer.ObjectStorer + storer.EncodedObjectStorer storer.ReferenceStorer config.ConfigStorer } type TestObject struct { - Object plumbing.Object + Object plumbing.EncodedObject Hash string Type plumbing.ObjectType } @@ -59,19 +59,19 @@ func NewBaseStorageSuite(s Storer) BaseStorageSuite { }} } -func (s *BaseStorageSuite) TestSetObjectAndGetObject(c *C) { +func (s *BaseStorageSuite) TestSetEncodedObjectAndEncodedObject(c *C) { for _, to := range s.testObjects { comment := Commentf("failed for type %s", to.Type.String()) - h, err := s.Storer.SetObject(to.Object) + h, err := s.Storer.SetEncodedObject(to.Object) c.Assert(err, IsNil) c.Assert(h.String(), Equals, to.Hash, comment) - o, err := s.Storer.Object(to.Type, h) + o, err := s.Storer.EncodedObject(to.Type, h) c.Assert(err, IsNil) c.Assert(objectEquals(o, to.Object), IsNil) - o, err = s.Storer.Object(plumbing.AnyObject, h) + o, err = s.Storer.EncodedObject(plumbing.AnyObject, h) c.Assert(err, IsNil) c.Assert(objectEquals(o, to.Object), IsNil) @@ -80,31 +80,31 @@ func (s *BaseStorageSuite) TestSetObjectAndGetObject(c *C) { continue } - o, err = s.Storer.Object(t, h) + o, err = s.Storer.EncodedObject(t, h) c.Assert(o, IsNil) c.Assert(err, Equals, plumbing.ErrObjectNotFound) } } } -func (s *BaseStorageSuite) TestSetObjectInvalid(c *C) { - o := s.Storer.NewObject() +func (s *BaseStorageSuite) TestSetEncodedObjectInvalid(c *C) { + o := s.Storer.NewEncodedObject() o.SetType(plumbing.REFDeltaObject) - _, err := s.Storer.SetObject(o) + _, err := s.Storer.SetEncodedObject(o) c.Assert(err, NotNil) } -func (s *BaseStorageSuite) TestStorerIter(c *C) { +func (s *BaseStorageSuite) TestIterEncodedObjects(c *C) { for _, o := range s.testObjects { - h, err := s.Storer.SetObject(o.Object) + h, err := s.Storer.SetEncodedObject(o.Object) c.Assert(err, IsNil) c.Assert(h, Equals, o.Object.Hash()) } for _, t := range s.validTypes { comment := Commentf("failed for type %s)", t.String()) - i, err := s.Storer.IterObjects(t) + i, err := s.Storer.IterEncodedObjects(t) c.Assert(err, IsNil, comment) o, err := i.Next() @@ -116,11 +116,11 @@ func (s *BaseStorageSuite) TestStorerIter(c *C) { c.Assert(err, Equals, io.EOF, comment) } - i, err := s.Storer.IterObjects(plumbing.AnyObject) + i, err := s.Storer.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) - foundObjects := []plumbing.Object{} - i.ForEach(func(o plumbing.Object) error { + foundObjects := []plumbing.EncodedObject{} + i.ForEach(func(o plumbing.EncodedObject) error { foundObjects = append(foundObjects, o) return nil }) @@ -138,7 +138,7 @@ func (s *BaseStorageSuite) TestStorerIter(c *C) { } } -func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndCommit(c *C) { +func (s *BaseStorageSuite) TestObjectStorerTxSetEncodedObjectAndCommit(c *C) { storer, ok := s.Storer.(storer.Transactioner) if !ok { c.Skip("not a plumbing.ObjectStorerTx") @@ -146,12 +146,12 @@ func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndCommit(c *C) { tx := storer.Begin() for _, o := range s.testObjects { - h, err := tx.SetObject(o.Object) + h, err := tx.SetEncodedObject(o.Object) c.Assert(err, IsNil) c.Assert(h.String(), Equals, o.Hash) } - iter, err := s.Storer.IterObjects(plumbing.AnyObject) + iter, err := s.Storer.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) _, err = iter.Next() c.Assert(err, Equals, io.EOF) @@ -159,11 +159,11 @@ func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndCommit(c *C) { err = tx.Commit() c.Assert(err, IsNil) - iter, err = s.Storer.IterObjects(plumbing.AnyObject) + iter, err = s.Storer.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) var count int - iter.ForEach(func(o plumbing.Object) error { + iter.ForEach(func(o plumbing.EncodedObject) error { count++ return nil }) @@ -179,11 +179,11 @@ func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndGetObject(c *C) { tx := storer.Begin() for _, expected := range s.testObjects { - h, err := tx.SetObject(expected.Object) + h, err := tx.SetEncodedObject(expected.Object) c.Assert(err, IsNil) c.Assert(h.String(), Equals, expected.Hash) - o, err := tx.Object(expected.Type, plumbing.NewHash(expected.Hash)) + o, err := tx.EncodedObject(expected.Type, plumbing.NewHash(expected.Hash)) c.Assert(err, IsNil) c.Assert(o.Hash().String(), DeepEquals, expected.Hash) } @@ -196,7 +196,7 @@ func (s *BaseStorageSuite) TestObjectStorerTxGetObjectNotFound(c *C) { } tx := storer.Begin() - o, err := tx.Object(plumbing.AnyObject, plumbing.ZeroHash) + o, err := tx.EncodedObject(plumbing.AnyObject, plumbing.ZeroHash) c.Assert(o, IsNil) c.Assert(err, Equals, plumbing.ErrObjectNotFound) } @@ -209,7 +209,7 @@ func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndRollback(c *C) { tx := storer.Begin() for _, o := range s.testObjects { - h, err := tx.SetObject(o.Object) + h, err := tx.SetEncodedObject(o.Object) c.Assert(err, IsNil) c.Assert(h.String(), Equals, o.Hash) } @@ -217,7 +217,7 @@ func (s *BaseStorageSuite) TestObjectStorerTxSetObjectAndRollback(c *C) { err := tx.Rollback() c.Assert(err, IsNil) - iter, err := s.Storer.IterObjects(plumbing.AnyObject) + iter, err := s.Storer.IterEncodedObjects(plumbing.AnyObject) c.Assert(err, IsNil) _, err = iter.Next() c.Assert(err, Equals, io.EOF) @@ -287,7 +287,7 @@ func (s *BaseStorageSuite) TestSetConfigInvalid(c *C) { c.Assert(err, NotNil) } -func objectEquals(a plumbing.Object, b plumbing.Object) error { +func objectEquals(a plumbing.EncodedObject, b plumbing.EncodedObject) error { ha := a.Hash() hb := b.Hash() if ha != hb { diff --git a/utils/binary/writer_test.go b/utils/binary/write_test.go index 1380280..1380280 100644 --- a/utils/binary/writer_test.go +++ b/utils/binary/write_test.go diff --git a/diff/diff.go b/utils/diff/diff.go index b840ad6..b840ad6 100644 --- a/diff/diff.go +++ b/utils/diff/diff.go diff --git a/diff/diff_ext_test.go b/utils/diff/diff_ext_test.go index 484c26e..adda276 100644 --- a/diff/diff_ext_test.go +++ b/utils/diff/diff_ext_test.go @@ -3,7 +3,7 @@ package diff_test import ( "testing" - "gopkg.in/src-d/go-git.v4/diff" + "gopkg.in/src-d/go-git.v4/utils/diff" "github.com/sergi/go-diff/diffmatchpatch" . "gopkg.in/check.v1" diff --git a/utils/ioutil/common.go b/utils/ioutil/common.go index f5b78df..a847abd 100644 --- a/utils/ioutil/common.go +++ b/utils/ioutil/common.go @@ -62,3 +62,23 @@ func (writeNopCloser) Close() error { return nil } func WriteNopCloser(w io.Writer) io.WriteCloser { return writeNopCloser{w} } + +// CheckClose is used with defer to close the given io.Closer and check its +// returned error value. If Close returns an error and the given *error +// is not nil, *error is set to the error returned by Close. +// +// CheckClose is typically used with named return values like so: +// +// func do(obj *Object) (err error) { +// w, err := obj.Writer() +// if err != nil { +// return nil +// } +// defer CheckClose(w, &err) +// // work with w +// } +func CheckClose(c io.Closer, err *error) { + if cerr := c.Close(); cerr != nil && *err == nil { + *err = cerr + } +} |