diff options
-rw-r--r-- | options.go | 2 | ||||
-rw-r--r-- | plumbing/cache/object_lru.go | 5 | ||||
-rw-r--r-- | plumbing/cache/object_test.go | 15 | ||||
-rw-r--r-- | remote.go | 9 | ||||
-rw-r--r-- | remote_test.go | 9 | ||||
-rw-r--r-- | worktree_status.go | 6 | ||||
-rw-r--r-- | worktree_test.go | 28 |
7 files changed, 70 insertions, 4 deletions
@@ -229,7 +229,7 @@ var ( ErrCreateRequiresBranch = errors.New("Branch is mandatory when Create is used") ) -// CheckoutOptions describes how a checkout 31operation should be performed. +// CheckoutOptions describes how a checkout operation should be performed. type CheckoutOptions struct { // Hash is the hash of the commit to be checked out. If used, HEAD will be // in detached mode. If Create is not used, Branch and Hash are mutually diff --git a/plumbing/cache/object_lru.go b/plumbing/cache/object_lru.go index 53d8b02..cd3712b 100644 --- a/plumbing/cache/object_lru.go +++ b/plumbing/cache/object_lru.go @@ -61,6 +61,11 @@ func (c *ObjectLRU) Put(obj plumbing.EncodedObject) { c.actualSize += objSize for c.actualSize > c.MaxSize { last := c.ll.Back() + if last == nil { + c.actualSize = 0 + break + } + lastObj := last.Value.(plumbing.EncodedObject) lastSize := FileSize(lastObj.Size()) diff --git a/plumbing/cache/object_test.go b/plumbing/cache/object_test.go index b3e5f79..2e8fa7b 100644 --- a/plumbing/cache/object_test.go +++ b/plumbing/cache/object_test.go @@ -153,6 +153,19 @@ func (s *ObjectSuite) TestDefaultLRU(c *C) { c.Assert(defaultLRU.MaxSize, Equals, DefaultMaxSize) } +func (s *ObjectSuite) TestObjectUpdateOverflow(c *C) { + o := NewObjectLRU(9 * Byte) + + a1 := newObject(s.aObject.Hash().String(), 9*Byte) + a2 := newObject(s.aObject.Hash().String(), 1*Byte) + b := newObject(s.bObject.Hash().String(), 1*Byte) + + o.Put(a1) + a1.SetSize(-5) + o.Put(a2) + o.Put(b) +} + type dummyObject struct { hash plumbing.Hash size FileSize @@ -169,6 +182,6 @@ func (d *dummyObject) Hash() plumbing.Hash { return d.hash } func (*dummyObject) Type() plumbing.ObjectType { return plumbing.InvalidObject } func (*dummyObject) SetType(plumbing.ObjectType) {} func (d *dummyObject) Size() int64 { return int64(d.size) } -func (*dummyObject) SetSize(s int64) {} +func (d *dummyObject) SetSize(s int64) { d.size = FileSize(s) } func (*dummyObject) Reader() (io.ReadCloser, error) { return nil, nil } func (*dummyObject) Writer() (io.WriteCloser, error) { return nil, nil } @@ -1020,7 +1020,12 @@ func pushHashes( if err != nil { return nil, err } - done := make(chan error) + + // Set buffer size to 1 so the error message can be written when + // ReceivePack fails. Otherwise the goroutine will be blocked writing + // to the channel. + done := make(chan error, 1) + go func() { e := packfile.NewEncoder(wr, s, useRefDeltas) if _, err := e.Encode(hs, config.Pack.Window); err != nil { @@ -1033,6 +1038,8 @@ func pushHashes( rs, err := sess.ReceivePack(ctx, req) if err != nil { + // close the pipe to unlock encode write + _ = rd.Close() return nil, err } diff --git a/remote_test.go b/remote_test.go index 28b0a3a..58a0598 100644 --- a/remote_test.go +++ b/remote_test.go @@ -6,6 +6,8 @@ import ( "io" "io/ioutil" "os" + "runtime" + "time" "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/plumbing" @@ -448,10 +450,17 @@ func (s *RemoteSuite) TestPushContext(c *C) { ctx, cancel := context.WithCancel(context.Background()) cancel() + numGoroutines := runtime.NumGoroutine() + err = r.PushContext(ctx, &PushOptions{ RefSpecs: []config.RefSpec{"refs/tags/*:refs/tags/*"}, }) c.Assert(err, NotNil) + + // let the goroutine from pushHashes finish and check that the number of + // goroutines is the same as before + time.Sleep(100 * time.Millisecond) + c.Assert(runtime.NumGoroutine(), Equals, numGoroutines) } func (s *RemoteSuite) TestPushTags(c *C) { diff --git a/worktree_status.go b/worktree_status.go index 0e113d0..16ce937 100644 --- a/worktree_status.go +++ b/worktree_status.go @@ -142,12 +142,16 @@ func (w *Worktree) diffStagingWithWorktree(reverse bool) (merkletrie.Changes, er func (w *Worktree) excludeIgnoredChanges(changes merkletrie.Changes) merkletrie.Changes { patterns, err := gitignore.ReadPatterns(w.Filesystem, nil) - if err != nil || len(patterns) == 0 { + if err != nil { return changes } patterns = append(patterns, w.Excludes...) + if len(patterns) == 0 { + return changes + } + m := gitignore.NewMatcher(patterns) var res merkletrie.Changes diff --git a/worktree_test.go b/worktree_test.go index 872cd82..afedc91 100644 --- a/worktree_test.go +++ b/worktree_test.go @@ -1129,6 +1129,34 @@ func (s *WorktreeSuite) TestIgnored(c *C) { c.Assert(file.Worktree, Equals, Untracked) } +func (s *WorktreeSuite) TestExcludedNoGitignore(c *C) { + f := fixtures.ByTag("empty").One() + r := s.NewRepository(f) + + fs := memfs.New() + w := &Worktree{ + r: r, + Filesystem: fs, + } + + _, err := fs.Open(".gitignore") + c.Assert(err, Equals, os.ErrNotExist) + + w.Excludes = make([]gitignore.Pattern, 0) + w.Excludes = append(w.Excludes, gitignore.ParsePattern("foo", nil)) + + err = util.WriteFile(w.Filesystem, "foo", []byte("FOO"), 0755) + c.Assert(err, IsNil) + + status, err := w.Status() + c.Assert(err, IsNil) + c.Assert(status, HasLen, 0) + + file := status.File("foo") + c.Assert(file.Staging, Equals, Untracked) + c.Assert(file.Worktree, Equals, Untracked) +} + func (s *WorktreeSuite) TestAddModified(c *C) { fs := memfs.New() w := &Worktree{ |