aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remote.go16
-rw-r--r--remote_test.go19
-rw-r--r--utils/merkletrie/iter.go4
-rw-r--r--utils/merkletrie/iter_test.go11
-rw-r--r--worktree_status.go33
-rw-r--r--worktree_test.go19
6 files changed, 83 insertions, 19 deletions
diff --git a/remote.go b/remote.go
index b2c5d1c..8f1da2f 100644
--- a/remote.go
+++ b/remote.go
@@ -362,20 +362,30 @@ func getHaves(localRefs storer.ReferenceStorer) ([]plumbing.Hash, error) {
return nil, err
}
- var haves []plumbing.Hash
+ haves := map[plumbing.Hash]bool{}
err = iter.ForEach(func(ref *plumbing.Reference) error {
+ if haves[ref.Hash()] == true {
+ return nil
+ }
+
if ref.Type() != plumbing.HashReference {
return nil
}
- haves = append(haves, ref.Hash())
+ haves[ref.Hash()] = true
return nil
})
+
if err != nil {
return nil, err
}
- return haves, nil
+ var result []plumbing.Hash
+ for h := range haves {
+ result = append(result, h)
+ }
+
+ return result, nil
}
func calculateRefs(spec []config.RefSpec,
diff --git a/remote_test.go b/remote_test.go
index 2c02877..7ffe040 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -553,6 +553,25 @@ func (s *RemoteSuite) TestPushWrongRemoteName(c *C) {
c.Assert(err, ErrorMatches, ".*remote names don't match.*")
}
+func (s *RemoteSuite) TestGetHaves(c *C) {
+ st := memory.NewStorage()
+ st.SetReference(plumbing.NewReferenceFromStrings(
+ "foo", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f",
+ ))
+
+ st.SetReference(plumbing.NewReferenceFromStrings(
+ "bar", "fe6cb94756faa81e5ed9240f9191b833db5f40ae",
+ ))
+
+ st.SetReference(plumbing.NewReferenceFromStrings(
+ "qux", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f",
+ ))
+
+ l, err := getHaves(st)
+ c.Assert(err, IsNil)
+ c.Assert(l, HasLen, 2)
+}
+
const bareConfig = `[core]
repositoryformatversion = 0
filemode = true
diff --git a/utils/merkletrie/iter.go b/utils/merkletrie/iter.go
index c84f6fc..e3f3055 100644
--- a/utils/merkletrie/iter.go
+++ b/utils/merkletrie/iter.go
@@ -83,6 +83,10 @@ func newIter(root noder.Noder, base noder.Path) (*Iter, error) {
base: base,
}
+ if root == nil {
+ return ret, nil
+ }
+
frame, err := frame.New(root)
if err != nil {
return nil, err
diff --git a/utils/merkletrie/iter_test.go b/utils/merkletrie/iter_test.go
index 7e8c302..b334cf1 100644
--- a/utils/merkletrie/iter_test.go
+++ b/utils/merkletrie/iter_test.go
@@ -19,13 +19,13 @@ var _ = Suite(&IterSuite{})
// A test is a list of operations we want to perform on an iterator and
// their expected results.
//
-// The operations are expresed as a sequence of `n` and `s`,
+// The operations are expressed as a sequence of `n` and `s`,
// representing the amount of next and step operations we want to call
// on the iterator and their order. For example, an operations value of
// "nns" means: call a `n`ext, then another `n`ext and finish with a
// `s`tep.
//
-// The expeced is the full path of the noders returned by the
+// The expected is the full path of the noders returned by the
// operations, separated by spaces.
//
// For instance:
@@ -446,6 +446,13 @@ func (e *errorNoder) Children() ([]noder.Noder, error) {
return nil, fmt.Errorf("mock error")
}
+func (s *IterSuite) TestNewIterNil(c *C) {
+ i, err := merkletrie.NewIter(nil)
+ c.Assert(err, IsNil)
+ _, err = i.Next()
+ c.Assert(err, Equals, io.EOF)
+}
+
func (s *IterSuite) TestNewIterFailsOnChildrenErrors(c *C) {
_, err := merkletrie.NewIter(&errorNoder{})
c.Assert(err, ErrorMatches, "mock error")
diff --git a/worktree_status.go b/worktree_status.go
index 728d7a0..a662516 100644
--- a/worktree_status.go
+++ b/worktree_status.go
@@ -24,16 +24,18 @@ var ErrDestinationExists = errors.New("destination exists")
// Status returns the working tree status.
func (w *Worktree) Status() (Status, error) {
+ var hash plumbing.Hash
+
ref, err := w.r.Head()
- if err == plumbing.ErrReferenceNotFound {
- return make(Status, 0), nil
+ if err != nil && err != plumbing.ErrReferenceNotFound {
+ return nil, err
}
- if err != nil {
- return nil, err
+ if err == nil {
+ hash = ref.Hash()
}
- return w.status(ref.Hash())
+ return w.status(hash)
}
func (w *Worktree) status(commit plumbing.Hash) (Status, error) {
@@ -182,19 +184,22 @@ func (w *Worktree) diffCommitWithStaging(commit plumbing.Hash, reverse bool) (me
return nil, err
}
- c, err := w.r.CommitObject(commit)
- if err != nil {
- return nil, err
- }
+ var from noder.Noder
+ if !commit.IsZero() {
+ c, err := w.r.CommitObject(commit)
+ if err != nil {
+ return nil, err
+ }
- t, err := c.Tree()
- if err != nil {
- return nil, err
+ t, err := c.Tree()
+ if err != nil {
+ return nil, err
+ }
+
+ from = object.NewTreeRootNode(t)
}
to := mindex.NewRootNode(idx)
- from := object.NewTreeRootNode(t)
-
if reverse {
return merkletrie.DiffTree(to, from, diffTreeIsEquals)
}
diff --git a/worktree_test.go b/worktree_test.go
index 864e19e..4c9907b 100644
--- a/worktree_test.go
+++ b/worktree_test.go
@@ -344,6 +344,25 @@ func (s *WorktreeSuite) TestStatusEmpty(c *C) {
c.Assert(status, NotNil)
}
+func (s *WorktreeSuite) TestStatusEmptyDirty(c *C) {
+ fs := memfs.New()
+ err := util.WriteFile(fs, "foo", []byte("foo"), 0755)
+ c.Assert(err, IsNil)
+
+ storage := memory.NewStorage()
+
+ r, err := Init(storage, fs)
+ c.Assert(err, IsNil)
+
+ w, err := r.Worktree()
+ c.Assert(err, IsNil)
+
+ status, err := w.Status()
+ c.Assert(err, IsNil)
+ c.Assert(status.IsClean(), Equals, false)
+ c.Assert(status, HasLen, 1)
+}
+
func (s *WorktreeSuite) TestReset(c *C) {
fs := memfs.New()
w := &Worktree{