aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/object
diff options
context:
space:
mode:
Diffstat (limited to 'plumbing/object')
-rw-r--r--plumbing/object/blob_test.go23
-rw-r--r--plumbing/object/change.go21
-rw-r--r--plumbing/object/change_test.go61
-rw-r--r--plumbing/object/commit.go68
-rw-r--r--plumbing/object/commit_test.go132
-rw-r--r--plumbing/object/difftree.go13
-rw-r--r--plumbing/object/difftree_test.go16
-rw-r--r--plumbing/object/object.go6
-rw-r--r--plumbing/object/object_test.go5
-rw-r--r--plumbing/object/patch.go32
-rw-r--r--plumbing/object/tag_test.go2
-rw-r--r--plumbing/object/tree.go25
-rw-r--r--plumbing/object/tree_test.go6
13 files changed, 352 insertions, 58 deletions
diff --git a/plumbing/object/blob_test.go b/plumbing/object/blob_test.go
index 5ed9de0..181436d 100644
--- a/plumbing/object/blob_test.go
+++ b/plumbing/object/blob_test.go
@@ -1,6 +1,7 @@
package object
import (
+ "bytes"
"io"
"io/ioutil"
@@ -88,8 +89,26 @@ func (s *BlobsSuite) TestBlobIter(c *C) {
}
c.Assert(err, IsNil)
- c.Assert(b, DeepEquals, blobs[i])
- i += 1
+ c.Assert(b.ID(), Equals, blobs[i].ID())
+ c.Assert(b.Size, Equals, blobs[i].Size)
+ c.Assert(b.Type(), Equals, blobs[i].Type())
+
+ r1, err := b.Reader()
+ c.Assert(err, IsNil)
+
+ b1, err := ioutil.ReadAll(r1)
+ c.Assert(err, IsNil)
+ c.Assert(r1.Close(), IsNil)
+
+ r2, err := blobs[i].Reader()
+ c.Assert(err, IsNil)
+
+ b2, err := ioutil.ReadAll(r2)
+ c.Assert(err, IsNil)
+ c.Assert(r2.Close(), IsNil)
+
+ c.Assert(bytes.Compare(b1, b2), Equals, 0)
+ i++
}
iter.Close()
diff --git a/plumbing/object/change.go b/plumbing/object/change.go
index 729ff5a..a1b4c27 100644
--- a/plumbing/object/change.go
+++ b/plumbing/object/change.go
@@ -2,6 +2,7 @@ package object
import (
"bytes"
+ "context"
"fmt"
"strings"
@@ -81,7 +82,15 @@ func (c *Change) String() string {
// Patch returns a Patch with all the file changes in chunks. This
// representation can be used to create several diff outputs.
func (c *Change) Patch() (*Patch, error) {
- return getPatch("", c)
+ return c.PatchContext(context.Background())
+}
+
+// Patch returns a Patch with all the file changes in chunks. This
+// representation can be used to create several diff outputs.
+// If context expires, an non-nil error will be returned
+// Provided context must be non-nil
+func (c *Change) PatchContext(ctx context.Context) (*Patch, error) {
+ return getPatchContext(ctx, "", c)
}
func (c *Change) name() string {
@@ -136,5 +145,13 @@ func (c Changes) String() string {
// Patch returns a Patch with all the changes in chunks. This
// representation can be used to create several diff outputs.
func (c Changes) Patch() (*Patch, error) {
- return getPatch("", c...)
+ return c.PatchContext(context.Background())
+}
+
+// Patch returns a Patch with all the changes in chunks. This
+// representation can be used to create several diff outputs.
+// If context expires, an non-nil error will be returned
+// Provided context must be non-nil
+func (c Changes) PatchContext(ctx context.Context) (*Patch, error) {
+ return getPatchContext(ctx, "", c...)
}
diff --git a/plumbing/object/change_test.go b/plumbing/object/change_test.go
index 7036fa3..b0e89c7 100644
--- a/plumbing/object/change_test.go
+++ b/plumbing/object/change_test.go
@@ -1,6 +1,7 @@
package object
import (
+ "context"
"sort"
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -82,6 +83,12 @@ func (s *ChangeSuite) TestInsert(c *C) {
c.Assert(len(p.FilePatches()[0].Chunks()), Equals, 1)
c.Assert(p.FilePatches()[0].Chunks()[0].Type(), Equals, diff.Add)
+ p, err = change.PatchContext(context.Background())
+ c.Assert(err, IsNil)
+ c.Assert(len(p.FilePatches()), Equals, 1)
+ c.Assert(len(p.FilePatches()[0].Chunks()), Equals, 1)
+ c.Assert(p.FilePatches()[0].Chunks()[0].Type(), Equals, diff.Add)
+
str := change.String()
c.Assert(str, Equals, "<Action: Insert, Path: examples/clone/main.go>")
}
@@ -134,6 +141,12 @@ func (s *ChangeSuite) TestDelete(c *C) {
c.Assert(len(p.FilePatches()[0].Chunks()), Equals, 1)
c.Assert(p.FilePatches()[0].Chunks()[0].Type(), Equals, diff.Delete)
+ p, err = change.PatchContext(context.Background())
+ c.Assert(err, IsNil)
+ c.Assert(len(p.FilePatches()), Equals, 1)
+ c.Assert(len(p.FilePatches()[0].Chunks()), Equals, 1)
+ c.Assert(p.FilePatches()[0].Chunks()[0].Type(), Equals, diff.Delete)
+
str := change.String()
c.Assert(str, Equals, "<Action: Delete, Path: utils/difftree/difftree.go>")
}
@@ -206,6 +219,18 @@ func (s *ChangeSuite) TestModify(c *C) {
c.Assert(p.FilePatches()[0].Chunks()[5].Type(), Equals, diff.Add)
c.Assert(p.FilePatches()[0].Chunks()[6].Type(), Equals, diff.Equal)
+ p, err = change.PatchContext(context.Background())
+ c.Assert(err, IsNil)
+ c.Assert(len(p.FilePatches()), Equals, 1)
+ c.Assert(len(p.FilePatches()[0].Chunks()), Equals, 7)
+ c.Assert(p.FilePatches()[0].Chunks()[0].Type(), Equals, diff.Equal)
+ c.Assert(p.FilePatches()[0].Chunks()[1].Type(), Equals, diff.Delete)
+ c.Assert(p.FilePatches()[0].Chunks()[2].Type(), Equals, diff.Add)
+ c.Assert(p.FilePatches()[0].Chunks()[3].Type(), Equals, diff.Equal)
+ c.Assert(p.FilePatches()[0].Chunks()[4].Type(), Equals, diff.Delete)
+ c.Assert(p.FilePatches()[0].Chunks()[5].Type(), Equals, diff.Add)
+ c.Assert(p.FilePatches()[0].Chunks()[6].Type(), Equals, diff.Equal)
+
str := change.String()
c.Assert(str, Equals, "<Action: Modify, Path: utils/difftree/difftree.go>")
}
@@ -367,3 +392,39 @@ func (s *ChangeSuite) TestChangesSort(c *C) {
sort.Sort(changes)
c.Assert(changes.String(), Equals, expected)
}
+
+func (s *ChangeSuite) TestCancel(c *C) {
+ // Commit a5078b19f08f63e7948abd0a5e2fb7d319d3a565 of the go-git
+ // fixture inserted "examples/clone/main.go".
+ //
+ // On that commit, the "examples/clone" tree is
+ // 6efca3ff41cab651332f9ebc0c96bb26be809615
+ //
+ // and the "examples/colone/main.go" is
+ // f95dc8f7923add1a8b9f72ecb1e8db1402de601a
+
+ path := "examples/clone/main.go"
+ name := "main.go"
+ mode := filemode.Regular
+ blob := plumbing.NewHash("f95dc8f7923add1a8b9f72ecb1e8db1402de601a")
+ tree := plumbing.NewHash("6efca3ff41cab651332f9ebc0c96bb26be809615")
+
+ change := &Change{
+ From: empty,
+ To: ChangeEntry{
+ Name: path,
+ Tree: s.tree(c, tree),
+ TreeEntry: TreeEntry{
+ Name: name,
+ Mode: mode,
+ Hash: blob,
+ },
+ },
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ cancel()
+ p, err := change.PatchContext(ctx)
+ c.Assert(p, IsNil)
+ c.Assert(err, ErrorMatches, "operation canceled")
+}
diff --git a/plumbing/object/commit.go b/plumbing/object/commit.go
index c9a4c0e..e254342 100644
--- a/plumbing/object/commit.go
+++ b/plumbing/object/commit.go
@@ -3,6 +3,7 @@ package object
import (
"bufio"
"bytes"
+ "context"
"errors"
"fmt"
"io"
@@ -16,8 +17,9 @@ import (
)
const (
- beginpgp string = "-----BEGIN PGP SIGNATURE-----"
- endpgp string = "-----END PGP SIGNATURE-----"
+ beginpgp string = "-----BEGIN PGP SIGNATURE-----"
+ endpgp string = "-----END PGP SIGNATURE-----"
+ headerpgp string = "gpgsig"
)
// Hash represents the hash of an object
@@ -75,7 +77,8 @@ func (c *Commit) Tree() (*Tree, error) {
}
// Patch returns the Patch between the actual commit and the provided one.
-func (c *Commit) Patch(to *Commit) (*Patch, error) {
+// Error will be return if context expires. Provided context must be non-nil
+func (c *Commit) PatchContext(ctx context.Context, to *Commit) (*Patch, error) {
fromTree, err := c.Tree()
if err != nil {
return nil, err
@@ -86,7 +89,12 @@ func (c *Commit) Patch(to *Commit) (*Patch, error) {
return nil, err
}
- return fromTree.Patch(toTree)
+ return fromTree.PatchContext(ctx, toTree)
+}
+
+// Patch returns the Patch between the actual commit and the provided one.
+func (c *Commit) Patch(to *Commit) (*Patch, error) {
+ return c.PatchContext(context.Background(), to)
}
// Parents return a CommitIter to the parent Commits.
@@ -174,23 +182,13 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
}
if pgpsig {
- // Check if it's the end of a PGP signature.
- if bytes.Contains(line, []byte(endpgp)) {
- c.PGPSignature += endpgp + "\n"
- pgpsig = false
- } else {
- // Trim the left padding.
+ if len(line) > 0 && line[0] == ' ' {
line = bytes.TrimLeft(line, " ")
c.PGPSignature += string(line)
+ continue
+ } else {
+ pgpsig = false
}
- continue
- }
-
- // Check if it's the beginning of a PGP signature.
- if bytes.Contains(line, []byte(beginpgp)) {
- c.PGPSignature += beginpgp + "\n"
- pgpsig = true
- continue
}
if !message {
@@ -201,15 +199,24 @@ func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
}
split := bytes.SplitN(line, []byte{' '}, 2)
+
+ var data []byte
+ if len(split) == 2 {
+ data = split[1]
+ }
+
switch string(split[0]) {
case "tree":
- c.TreeHash = plumbing.NewHash(string(split[1]))
+ c.TreeHash = plumbing.NewHash(string(data))
case "parent":
- c.ParentHashes = append(c.ParentHashes, plumbing.NewHash(string(split[1])))
+ c.ParentHashes = append(c.ParentHashes, plumbing.NewHash(string(data)))
case "author":
- c.Author.Decode(split[1])
+ c.Author.Decode(data)
case "committer":
- c.Committer.Decode(split[1])
+ c.Committer.Decode(data)
+ case headerpgp:
+ c.PGPSignature += string(data) + "\n"
+ pgpsig = true
}
} else {
c.Message += string(line)
@@ -262,17 +269,18 @@ func (b *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
}
if b.PGPSignature != "" && includeSig {
- if _, err = fmt.Fprint(w, "pgpsig"); err != nil {
+ if _, err = fmt.Fprint(w, "\n"+headerpgp+" "); err != nil {
return err
}
- // Split all the signature lines and write with a left padding and
- // newline at the end.
- lines := strings.Split(b.PGPSignature, "\n")
- for _, line := range lines {
- if _, err = fmt.Fprintf(w, " %s\n", line); err != nil {
- return err
- }
+ // Split all the signature lines and re-write with a left padding and
+ // newline. Use join for this so it's clear that a newline should not be
+ // added after this section, as it will be added when the message is
+ // printed.
+ signature := strings.TrimSuffix(b.PGPSignature, "\n")
+ lines := strings.Split(signature, "\n")
+ if _, err = fmt.Fprint(w, strings.Join(lines, "\n ")); err != nil {
+ return err
}
}
diff --git a/plumbing/object/commit_test.go b/plumbing/object/commit_test.go
index 191b14d..e72b703 100644
--- a/plumbing/object/commit_test.go
+++ b/plumbing/object/commit_test.go
@@ -2,6 +2,7 @@ package object
import (
"bytes"
+ "context"
"io"
"strings"
"time"
@@ -132,6 +133,59 @@ Binary files /dev/null and b/binary.jpg differ
c.Assert(buf.String(), Equals, patch.String())
}
+func (s *SuiteCommit) TestPatchContext(c *C) {
+ from := s.commit(c, plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"))
+ to := s.commit(c, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
+
+ patch, err := from.PatchContext(context.Background(), to)
+ c.Assert(err, IsNil)
+
+ buf := bytes.NewBuffer(nil)
+ err = patch.Encode(buf)
+ c.Assert(err, IsNil)
+
+ c.Assert(buf.String(), Equals, `diff --git a/vendor/foo.go b/vendor/foo.go
+new file mode 100644
+index 0000000000000000000000000000000000000000..9dea2395f5403188298c1dabe8bdafe562c491e3
+--- /dev/null
++++ b/vendor/foo.go
+@@ -0,0 +1,7 @@
++package main
++
++import "fmt"
++
++func main() {
++ fmt.Println("Hello, playground")
++}
+`)
+ c.Assert(buf.String(), Equals, patch.String())
+
+ from = s.commit(c, plumbing.NewHash("b8e471f58bcbca63b07bda20e428190409c2db47"))
+ to = s.commit(c, plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"))
+
+ patch, err = from.PatchContext(context.Background(), to)
+ c.Assert(err, IsNil)
+
+ buf.Reset()
+ err = patch.Encode(buf)
+ c.Assert(err, IsNil)
+
+ c.Assert(buf.String(), Equals, `diff --git a/CHANGELOG b/CHANGELOG
+deleted file mode 100644
+index d3ff53e0564a9f87d8e84b6e28e5060e517008aa..0000000000000000000000000000000000000000
+--- a/CHANGELOG
++++ /dev/null
+@@ -1 +0,0 @@
+-Initial changelog
+diff --git a/binary.jpg b/binary.jpg
+new file mode 100644
+index 0000000000000000000000000000000000000000..d5c0f4ab811897cadf03aec358ae60d21f91c50d
+Binary files /dev/null and b/binary.jpg differ
+`)
+
+ c.Assert(buf.String(), Equals, patch.String())
+}
+
func (s *SuiteCommit) TestCommitEncodeDecodeIdempotent(c *C) {
ts, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05-07:00")
c.Assert(err, IsNil)
@@ -270,6 +324,54 @@ RUysgqjcpT8+iQM1PblGfHR4XAhuOqN5Fx06PSaFZhqvWFezJ28/CLyX5q+oIVk=
err = decoded.Decode(encoded)
c.Assert(err, IsNil)
c.Assert(decoded.PGPSignature, Equals, pgpsignature)
+
+ // signature with extra empty line, it caused "index out of range" when
+ // parsing it
+
+ pgpsignature2 := "\n" + pgpsignature
+
+ commit.PGPSignature = pgpsignature2
+ encoded = &plumbing.MemoryObject{}
+ decoded = &Commit{}
+
+ err = commit.Encode(encoded)
+ c.Assert(err, IsNil)
+
+ err = decoded.Decode(encoded)
+ c.Assert(err, IsNil)
+ c.Assert(decoded.PGPSignature, Equals, pgpsignature2)
+
+ // signature in author name
+
+ commit.PGPSignature = ""
+ commit.Author.Name = beginpgp
+ encoded = &plumbing.MemoryObject{}
+ decoded = &Commit{}
+
+ err = commit.Encode(encoded)
+ c.Assert(err, IsNil)
+
+ err = decoded.Decode(encoded)
+ c.Assert(err, IsNil)
+ c.Assert(decoded.PGPSignature, Equals, "")
+ c.Assert(decoded.Author.Name, Equals, beginpgp)
+
+ // broken signature
+
+ commit.PGPSignature = beginpgp + "\n" +
+ "some\n" +
+ "trash\n" +
+ endpgp +
+ "text\n"
+ encoded = &plumbing.MemoryObject{}
+ decoded = &Commit{}
+
+ err = commit.Encode(encoded)
+ c.Assert(err, IsNil)
+
+ err = decoded.Decode(encoded)
+ c.Assert(err, IsNil)
+ c.Assert(decoded.PGPSignature, Equals, commit.PGPSignature)
}
func (s *SuiteCommit) TestStat(c *C) {
@@ -363,3 +465,33 @@ sYyf9RfOnw/KUFAQbdtvLx3ikODQC+D3KBtuKI9ISHQfgw==
_, ok := e.Identities["Sunny <me@darkowlzz.space>"]
c.Assert(ok, Equals, true)
}
+
+func (s *SuiteCommit) TestPatchCancel(c *C) {
+ from := s.commit(c, plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"))
+ to := s.commit(c, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
+
+ ctx, cancel := context.WithCancel(context.Background())
+ cancel()
+ patch, err := from.PatchContext(ctx, to)
+ c.Assert(patch, IsNil)
+ c.Assert(err, ErrorMatches, "operation canceled")
+
+}
+
+func (s *SuiteCommit) TestMalformedHeader(c *C) {
+ encoded := &plumbing.MemoryObject{}
+ decoded := &Commit{}
+ commit := *s.Commit
+
+ commit.PGPSignature = "\n"
+ commit.Author.Name = "\n"
+ commit.Author.Email = "\n"
+ commit.Committer.Name = "\n"
+ commit.Committer.Email = "\n"
+
+ err := commit.Encode(encoded)
+ c.Assert(err, IsNil)
+
+ err = decoded.Decode(encoded)
+ c.Assert(err, IsNil)
+}
diff --git a/plumbing/object/difftree.go b/plumbing/object/difftree.go
index ac58c4d..a30a29e 100644
--- a/plumbing/object/difftree.go
+++ b/plumbing/object/difftree.go
@@ -2,6 +2,7 @@ package object
import (
"bytes"
+ "context"
"gopkg.in/src-d/go-git.v4/utils/merkletrie"
"gopkg.in/src-d/go-git.v4/utils/merkletrie/noder"
@@ -10,6 +11,13 @@ import (
// DiffTree compares the content and mode of the blobs found via two
// tree objects.
func DiffTree(a, b *Tree) (Changes, error) {
+ return DiffTreeContext(context.Background(), a, b)
+}
+
+// DiffTree compares the content and mode of the blobs found via two
+// tree objects. Provided context must be non-nil.
+// An error will be return if context expires
+func DiffTreeContext(ctx context.Context, a, b *Tree) (Changes, error) {
from := NewTreeRootNode(a)
to := NewTreeRootNode(b)
@@ -17,8 +25,11 @@ func DiffTree(a, b *Tree) (Changes, error) {
return bytes.Equal(a.Hash(), b.Hash())
}
- merkletrieChanges, err := merkletrie.DiffTree(from, to, hashEqual)
+ merkletrieChanges, err := merkletrie.DiffTreeContext(ctx, from, to, hashEqual)
if err != nil {
+ if err == merkletrie.ErrCanceled {
+ return nil, ErrCanceled
+ }
return nil, err
}
diff --git a/plumbing/object/difftree_test.go b/plumbing/object/difftree_test.go
index 40af8f2..ff9ecbc 100644
--- a/plumbing/object/difftree_test.go
+++ b/plumbing/object/difftree_test.go
@@ -45,25 +45,17 @@ func (s *DiffTreeSuite) storageFromPackfile(f *fixtures.Fixture) storer.EncodedO
return sto
}
- sto = memory.NewStorage()
+ storer := 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 {
+ if err := packfile.UpdateObjectStorage(storer, pf); err != nil {
panic(err)
}
- s.cache[f.URL] = sto
- return sto
+ s.cache[f.URL] = storer
+ return storer
}
var _ = Suite(&DiffTreeSuite{})
diff --git a/plumbing/object/object.go b/plumbing/object/object.go
index 4b59aba..e960e50 100644
--- a/plumbing/object/object.go
+++ b/plumbing/object/object.go
@@ -152,7 +152,11 @@ func (s *Signature) decodeTimeAndTimeZone(b []byte) {
}
func (s *Signature) encodeTimeAndTimeZone(w io.Writer) error {
- _, err := fmt.Fprintf(w, "%d %s", s.When.Unix(), s.When.Format("-0700"))
+ u := s.When.Unix()
+ if u < 0 {
+ u = 0
+ }
+ _, err := fmt.Fprintf(w, "%d %s", u, s.When.Format("-0700"))
return err
}
diff --git a/plumbing/object/object_test.go b/plumbing/object/object_test.go
index 4f0fcb3..68aa1a1 100644
--- a/plumbing/object/object_test.go
+++ b/plumbing/object/object_test.go
@@ -197,8 +197,9 @@ func (s *ObjectsSuite) TestObjectIter(c *C) {
}
c.Assert(err, IsNil)
- c.Assert(o, DeepEquals, objects[i])
- i += 1
+ c.Assert(o.ID(), Equals, objects[i].ID())
+ c.Assert(o.Type(), Equals, objects[i].Type())
+ i++
}
iter.Close()
diff --git a/plumbing/object/patch.go b/plumbing/object/patch.go
index aa96a96..adeaccb 100644
--- a/plumbing/object/patch.go
+++ b/plumbing/object/patch.go
@@ -2,6 +2,8 @@ package object
import (
"bytes"
+ "context"
+ "errors"
"fmt"
"io"
"math"
@@ -15,10 +17,25 @@ import (
dmp "github.com/sergi/go-diff/diffmatchpatch"
)
+var (
+ ErrCanceled = errors.New("operation canceled")
+)
+
func getPatch(message string, changes ...*Change) (*Patch, error) {
+ ctx := context.Background()
+ return getPatchContext(ctx, message, changes...)
+}
+
+func getPatchContext(ctx context.Context, message string, changes ...*Change) (*Patch, error) {
var filePatches []fdiff.FilePatch
for _, c := range changes {
- fp, err := filePatch(c)
+ select {
+ case <-ctx.Done():
+ return nil, ErrCanceled
+ default:
+ }
+
+ fp, err := filePatchWithContext(ctx, c)
if err != nil {
return nil, err
}
@@ -29,7 +46,7 @@ func getPatch(message string, changes ...*Change) (*Patch, error) {
return &Patch{message, filePatches}, nil
}
-func filePatch(c *Change) (fdiff.FilePatch, error) {
+func filePatchWithContext(ctx context.Context, c *Change) (fdiff.FilePatch, error) {
from, to, err := c.Files()
if err != nil {
return nil, err
@@ -52,6 +69,12 @@ func filePatch(c *Change) (fdiff.FilePatch, error) {
var chunks []fdiff.Chunk
for _, d := range diffs {
+ select {
+ case <-ctx.Done():
+ return nil, ErrCanceled
+ default:
+ }
+
var op fdiff.Operation
switch d.Type {
case dmp.DiffEqual:
@@ -70,6 +93,11 @@ func filePatch(c *Change) (fdiff.FilePatch, error) {
from: c.From,
to: c.To,
}, nil
+
+}
+
+func filePatch(c *Change) (fdiff.FilePatch, error) {
+ return filePatchWithContext(context.Background(), c)
}
func fileContent(f *File) (content string, isBinary bool, err error) {
diff --git a/plumbing/object/tag_test.go b/plumbing/object/tag_test.go
index 9900093..e7dd06e 100644
--- a/plumbing/object/tag_test.go
+++ b/plumbing/object/tag_test.go
@@ -265,7 +265,7 @@ func (s *TagSuite) TestStringNonCommit(c *C) {
c.Assert(tag.String(), Equals,
"tag TAG TWO\n"+
"Tagger: <>\n"+
- "Date: Mon Jan 01 00:00:00 0001 +0000\n"+
+ "Date: Thu Jan 01 00:00:00 1970 +0000\n"+
"\n"+
"tag two\n")
}
diff --git a/plumbing/object/tree.go b/plumbing/object/tree.go
index 30bbcb0..c36a137 100644
--- a/plumbing/object/tree.go
+++ b/plumbing/object/tree.go
@@ -2,6 +2,7 @@ package object
import (
"bufio"
+ "context"
"errors"
"fmt"
"io"
@@ -25,6 +26,7 @@ var (
ErrMaxTreeDepth = errors.New("maximum tree depth exceeded")
ErrFileNotFound = errors.New("file not found")
ErrDirectoryNotFound = errors.New("directory not found")
+ ErrEntryNotFound = errors.New("entry not found")
)
// Tree is basically like a directory - it references a bunch of other trees
@@ -166,8 +168,6 @@ func (t *Tree) dir(baseName string) (*Tree, error) {
return tree, err
}
-var errEntryNotFound = errors.New("entry not found")
-
func (t *Tree) entry(baseName string) (*TreeEntry, error) {
if t.m == nil {
t.buildMap()
@@ -175,7 +175,7 @@ func (t *Tree) entry(baseName string) (*TreeEntry, error) {
entry, ok := t.m[baseName]
if !ok {
- return nil, errEntryNotFound
+ return nil, ErrEntryNotFound
}
return entry, nil
@@ -295,15 +295,30 @@ func (from *Tree) Diff(to *Tree) (Changes, error) {
return DiffTree(from, to)
}
+// Diff returns a list of changes between this tree and the provided one
+// Error will be returned if context expires
+// Provided context must be non nil
+func (from *Tree) DiffContext(ctx context.Context, to *Tree) (Changes, error) {
+ return DiffTreeContext(ctx, from, to)
+}
+
// Patch returns a slice of Patch objects with all the changes between trees
// in chunks. This representation can be used to create several diff outputs.
func (from *Tree) Patch(to *Tree) (*Patch, error) {
- changes, err := DiffTree(from, to)
+ return from.PatchContext(context.Background(), to)
+}
+
+// Patch returns a slice of Patch objects with all the changes between trees
+// in chunks. This representation can be used to create several diff outputs.
+// If context expires, an error will be returned
+// Provided context must be non-nil
+func (from *Tree) PatchContext(ctx context.Context, to *Tree) (*Patch, error) {
+ changes, err := DiffTreeContext(ctx, from, to)
if err != nil {
return nil, err
}
- return changes.Patch()
+ return changes.PatchContext(ctx)
}
// treeEntryIter facilitates iterating through the TreeEntry objects in a Tree.
diff --git a/plumbing/object/tree_test.go b/plumbing/object/tree_test.go
index 3a687dd..59d5d21 100644
--- a/plumbing/object/tree_test.go
+++ b/plumbing/object/tree_test.go
@@ -114,6 +114,12 @@ func (s *TreeSuite) TestFindEntry(c *C) {
c.Assert(e.Name, Equals, "foo.go")
}
+func (s *TreeSuite) TestFindEntryNotFound(c *C) {
+ e, err := s.Tree.FindEntry("not-found")
+ c.Assert(e, IsNil)
+ c.Assert(err, Equals, ErrEntryNotFound)
+}
+
// Overrides returned plumbing.EncodedObject for given hash.
// Otherwise, delegates to actual storer to get real object
type fakeStorer struct {