From 4183c846e3b3b7eee2bfa7b2f20b3de6fe1896e7 Mon Sep 17 00:00:00 2001 From: Antoine GIRARD Date: Wed, 17 Apr 2019 04:04:23 +0200 Subject: [PATCH] [mod]: Bump gopkg.in/src-d/go-git.v4 from 4.8.0 to 4.10.0 (#6662) Bumps [gopkg.in/src-d/go-git.v4](https://github.com/src-d/go-git) from 4.8.0 to 4.10.0. - [Release notes](https://github.com/src-d/go-git/releases) - [Commits](https://github.com/src-d/go-git/compare/v4.8.0...v4.10.0) --- go.mod | 2 +- go.sum | 2 + .../gopkg.in/src-d/go-git.v4/config/config.go | 5 + .../src-d/go-git.v4/internal/url/url.go | 37 +++++ vendor/gopkg.in/src-d/go-git.v4/options.go | 5 + .../plumbing/format/packfile/common.go | 8 +- .../plumbing/format/packfile/fsobject.go | 2 +- .../plumbing/format/packfile/packfile.go | 53 ++++--- .../plumbing/format/packfile/parser.go | 6 +- .../plumbing/format/packfile/scanner.go | 46 +++++- .../plumbing/object/commit_walker.go | 144 ++++++++++++++++++ .../plumbing/object/commit_walker_file.go | 50 ++++-- .../go-git.v4/plumbing/revlist/revlist.go | 16 +- .../src-d/go-git.v4/plumbing/storer/object.go | 2 +- .../go-git.v4/plumbing/storer/reference.go | 70 ++++++++- .../go-git.v4/plumbing/transport/common.go | 22 +-- vendor/gopkg.in/src-d/go-git.v4/remote.go | 15 +- vendor/gopkg.in/src-d/go-git.v4/repository.go | 103 +++++++++---- .../storage/filesystem/dotgit/dotgit.go | 3 +- .../filesystem/dotgit/dotgit_setref.go | 51 ++++++- .../filesystem/dotgit/dotgit_setref_norwfs.go | 47 ------ .../go-git.v4/storage/filesystem/object.go | 60 +++++--- .../go-git.v4/storage/filesystem/storage.go | 6 +- .../src-d/go-git.v4/storage/memory/storage.go | 3 +- .../src-d/go-git.v4/storage/storer.go | 4 + .../go-git.v4/utils/merkletrie/noder/path.go | 10 +- vendor/gopkg.in/src-d/go-git.v4/worktree.go | 11 +- vendor/modules.txt | 3 +- 28 files changed, 597 insertions(+), 189 deletions(-) create mode 100644 vendor/gopkg.in/src-d/go-git.v4/internal/url/url.go delete mode 100644 vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref_norwfs.go diff --git a/go.mod b/go.mod index 177b76a0ae2..7c682cc1e40 100644 --- a/go.mod +++ b/go.mod @@ -128,7 +128,7 @@ require ( gopkg.in/macaron.v1 v1.3.2 gopkg.in/redis.v2 v2.3.2 // indirect gopkg.in/src-d/go-billy.v4 v4.3.0 // indirect - gopkg.in/src-d/go-git.v4 v4.8.0 + gopkg.in/src-d/go-git.v4 v4.10.0 gopkg.in/testfixtures.v2 v2.5.0 mvdan.cc/xurls/v2 v2.0.0 strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a diff --git a/go.sum b/go.sum index c1ea8474789..4746f42bbdf 100644 --- a/go.sum +++ b/go.sum @@ -354,6 +354,8 @@ gopkg.in/src-d/go-git-fixtures.v3 v3.1.1 h1:XWW/s5W18RaJpmo1l0IYGqXKuJITWRFuA45i gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.8.0 h1:dDEbgvfNG9vUDM54uhCYPExiGa8uYgXpQ/MR8YvxcAM= gopkg.in/src-d/go-git.v4 v4.8.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= +gopkg.in/src-d/go-git.v4 v4.10.0 h1:NWjTJTQnk8UpIGlssuefyDZ6JruEjo5s88vm88uASbw= +gopkg.in/src-d/go-git.v4 v4.10.0/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk= gopkg.in/stretchr/testify.v1 v1.2.2 h1:yhQC6Uy5CqibAIlk1wlusa/MJ3iAN49/BsR/dCCKz3M= gopkg.in/stretchr/testify.v1 v1.2.2/go.mod h1:QI5V/q6UbPmuhtm10CaFZxED9NreB8PnFYN9JcR6TxU= gopkg.in/testfixtures.v2 v2.5.0 h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw= diff --git a/vendor/gopkg.in/src-d/go-git.v4/config/config.go b/vendor/gopkg.in/src-d/go-git.v4/config/config.go index a637f6d7096..2c3b8b9683b 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/config/config.go +++ b/vendor/gopkg.in/src-d/go-git.v4/config/config.go @@ -8,6 +8,7 @@ import ( "sort" "strconv" + "gopkg.in/src-d/go-git.v4/internal/url" format "gopkg.in/src-d/go-git.v4/plumbing/format/config" ) @@ -399,3 +400,7 @@ func (c *RemoteConfig) marshal() *format.Subsection { return c.raw } + +func (c *RemoteConfig) IsFirstURLLocal() bool { + return url.IsLocalEndpoint(c.URLs[0]) +} diff --git a/vendor/gopkg.in/src-d/go-git.v4/internal/url/url.go b/vendor/gopkg.in/src-d/go-git.v4/internal/url/url.go new file mode 100644 index 00000000000..0f0d709d93b --- /dev/null +++ b/vendor/gopkg.in/src-d/go-git.v4/internal/url/url.go @@ -0,0 +1,37 @@ +package url + +import ( + "regexp" +) + +var ( + isSchemeRegExp = regexp.MustCompile(`^[^:]+://`) + scpLikeUrlRegExp = regexp.MustCompile(`^(?:(?P[^@]+)@)?(?P[^:\s]+):(?:(?P[0-9]{1,5})/)?(?P[^\\].*)$`) +) + +// MatchesScheme returns true if the given string matches a URL-like +// format scheme. +func MatchesScheme(url string) bool { + return isSchemeRegExp.MatchString(url) +} + +// MatchesScpLike returns true if the given string matches an SCP-like +// format scheme. +func MatchesScpLike(url string) bool { + return scpLikeUrlRegExp.MatchString(url) +} + +// FindScpLikeComponents returns the user, host, port and path of the +// given SCP-like URL. +func FindScpLikeComponents(url string) (user, host, port, path string) { + m := scpLikeUrlRegExp.FindStringSubmatch(url) + return m[1], m[2], m[3], m[4] +} + +// IsLocalEndpoint returns true if the given URL string specifies a +// local file endpoint. For example, on a Linux machine, +// `/home/user/src/go-git` would match as a local endpoint, but +// `https://github.com/src-d/go-git` would not. +func IsLocalEndpoint(url string) bool { + return !MatchesScheme(url) && !MatchesScpLike(url) +} diff --git a/vendor/gopkg.in/src-d/go-git.v4/options.go b/vendor/gopkg.in/src-d/go-git.v4/options.go index 5d10a88c359..ed7689ab3f8 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/options.go +++ b/vendor/gopkg.in/src-d/go-git.v4/options.go @@ -335,6 +335,11 @@ type LogOptions struct { // Show only those commits in which the specified file was inserted/updated. // It is equivalent to running `git log -- `. FileName *string + + // Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as . + // It is equivalent to running `git log --all`. + // If set on true, the From option will be ignored. + All bool } var ( diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go index 2b4acebdeb3..0d9ed5447dd 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/common.go @@ -51,7 +51,13 @@ func WritePackfileToObjectStorage( } defer ioutil.CheckClose(w, &err) - _, err = io.Copy(w, packfile) + + var n int64 + n, err = io.Copy(w, packfile) + if err == nil && n == 0 { + return ErrEmptyPackfile + } + return err } diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go index 330cb73c983..a268bce7ed0 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/fsobject.go @@ -48,7 +48,7 @@ func NewFSObject( // Reader implements the plumbing.EncodedObject interface. func (o *FSObject) Reader() (io.ReadCloser, error) { obj, ok := o.cache.Get(o.hash) - if ok { + if ok && obj != o { reader, err := obj.Reader() if err != nil { return nil, err diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go index 2166e0aa20e..69b6e85d0cb 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/packfile.go @@ -21,6 +21,16 @@ var ( ErrZLib = NewError("zlib reading error") ) +// When reading small objects from packfile it is beneficial to do so at +// once to exploit the buffered I/O. In many cases the objects are so small +// that they were already loaded to memory when the object header was +// loaded from the packfile. Wrapping in FSObject would cause this buffered +// data to be thrown away and then re-read later, with the additional +// seeking causing reloads from disk. Objects smaller than this threshold +// are now always read into memory and stored in cache instead of being +// wrapped in FSObject. +const smallObjectThreshold = 16 * 1024 + // Packfile allows retrieving information from inside a packfile. type Packfile struct { idxfile.Index @@ -79,15 +89,7 @@ func (p *Packfile) GetByOffset(o int64) (plumbing.EncodedObject, error) { } } - if _, err := p.s.SeekFromStart(o); err != nil { - if err == io.EOF || isInvalid(err) { - return nil, plumbing.ErrObjectNotFound - } - - return nil, err - } - - return p.nextObject() + return p.objectAtOffset(o) } // GetSizeByOffset retrieves the size of the encoded object from the @@ -105,7 +107,13 @@ func (p *Packfile) GetSizeByOffset(o int64) (size int64, err error) { if err != nil { return 0, err } - return h.Length, nil + return p.getObjectSize(h) +} + +func (p *Packfile) objectHeaderAtOffset(offset int64) (*ObjectHeader, error) { + h, err := p.s.SeekObjectHeader(offset) + p.s.pendingObject = nil + return h, err } func (p *Packfile) nextObjectHeader() (*ObjectHeader, error) { @@ -154,11 +162,7 @@ func (p *Packfile) getObjectType(h *ObjectHeader) (typ plumbing.ObjectType, err if baseType, ok := p.offsetToType[offset]; ok { typ = baseType } else { - if _, err = p.s.SeekFromStart(offset); err != nil { - return - } - - h, err = p.nextObjectHeader() + h, err = p.objectHeaderAtOffset(offset) if err != nil { return } @@ -175,8 +179,8 @@ func (p *Packfile) getObjectType(h *ObjectHeader) (typ plumbing.ObjectType, err return } -func (p *Packfile) nextObject() (plumbing.EncodedObject, error) { - h, err := p.nextObjectHeader() +func (p *Packfile) objectAtOffset(offset int64) (plumbing.EncodedObject, error) { + h, err := p.objectHeaderAtOffset(offset) if err != nil { if err == io.EOF || isInvalid(err) { return nil, plumbing.ErrObjectNotFound @@ -190,6 +194,13 @@ func (p *Packfile) nextObject() (plumbing.EncodedObject, error) { return p.getNextObject(h) } + // If the object is not a delta and it's small enough then read it + // completely into memory now since it is already read from disk + // into buffer anyway. + if h.Length <= smallObjectThreshold && h.Type != plumbing.OFSDeltaObject && h.Type != plumbing.REFDeltaObject { + return p.getNextObject(h) + } + hash, err := p.FindHash(h.Offset) if err != nil { return nil, err @@ -233,11 +244,7 @@ func (p *Packfile) getObjectContent(offset int64) (io.ReadCloser, error) { } } - if _, err := p.s.SeekFromStart(offset); err != nil { - return nil, err - } - - h, err := p.nextObjectHeader() + h, err := p.objectHeaderAtOffset(offset) if err != nil { return nil, err } @@ -329,8 +336,6 @@ func (p *Packfile) fillOFSDeltaObjectContent(obj plumbing.EncodedObject, offset if err != nil { return err } - - p.cachePut(base) } obj.SetType(base.Type()) diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go index 5a62d63bb09..71cbba9838b 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/parser.go @@ -398,11 +398,7 @@ func (p *Parser) readData(o *objectInfo) ([]byte, error) { return data, nil } - if _, err := p.scanner.SeekFromStart(o.Offset); err != nil { - return nil, err - } - - if _, err := p.scanner.NextObjectHeader(); err != nil { + if _, err := p.scanner.SeekObjectHeader(o.Offset); err != nil { return nil, err } diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go index 6fc183b94f7..614b0d1a8b6 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/format/packfile/scanner.go @@ -138,14 +138,52 @@ func (s *Scanner) readCount() (uint32, error) { return binary.ReadUint32(s.r) } +// SeekObjectHeader seeks to specified offset and returns the ObjectHeader +// for the next object in the reader +func (s *Scanner) SeekObjectHeader(offset int64) (*ObjectHeader, error) { + // if seeking we assume that you are not interested in the header + if s.version == 0 { + s.version = VersionSupported + } + + if _, err := s.r.Seek(offset, io.SeekStart); err != nil { + return nil, err + } + + h, err := s.nextObjectHeader() + if err != nil { + return nil, err + } + + h.Offset = offset + return h, nil +} + // NextObjectHeader returns the ObjectHeader for the next object in the reader func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) { - defer s.Flush() - if err := s.doPending(); err != nil { return nil, err } + offset, err := s.r.Seek(0, io.SeekCurrent) + if err != nil { + return nil, err + } + + h, err := s.nextObjectHeader() + if err != nil { + return nil, err + } + + h.Offset = offset + return h, nil +} + +// nextObjectHeader returns the ObjectHeader for the next object in the reader +// without the Offset field +func (s *Scanner) nextObjectHeader() (*ObjectHeader, error) { + defer s.Flush() + s.crc.Reset() h := &ObjectHeader{} @@ -308,7 +346,7 @@ var byteSlicePool = sync.Pool{ // SeekFromStart sets a new offset from start, returns the old position before // the change. func (s *Scanner) SeekFromStart(offset int64) (previous int64, err error) { - // if seeking we assume that you are not interested on the header + // if seeking we assume that you are not interested in the header if s.version == 0 { s.version = VersionSupported } @@ -385,7 +423,7 @@ type bufferedSeeker struct { } func (r *bufferedSeeker) Seek(offset int64, whence int) (int64, error) { - if whence == io.SeekCurrent { + if whence == io.SeekCurrent && offset == 0 { current, err := r.r.Seek(offset, whence) if err != nil { return current, err diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go index 40ad2582bc0..0eff0591277 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker.go @@ -1,10 +1,12 @@ package object import ( + "container/list" "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/storage" ) type commitPreIterator struct { @@ -181,3 +183,145 @@ func (w *commitPostIterator) ForEach(cb func(*Commit) error) error { } func (w *commitPostIterator) Close() {} + +// commitAllIterator stands for commit iterator for all refs. +type commitAllIterator struct { + // currCommit points to the current commit. + currCommit *list.Element +} + +// NewCommitAllIter returns a new commit iterator for all refs. +// repoStorer is a repo Storer used to get commits and references. +// commitIterFunc is a commit iterator function, used to iterate through ref commits in chosen order +func NewCommitAllIter(repoStorer storage.Storer, commitIterFunc func(*Commit) CommitIter) (CommitIter, error) { + commitsPath := list.New() + commitsLookup := make(map[plumbing.Hash]*list.Element) + head, err := storer.ResolveReference(repoStorer, plumbing.HEAD) + if err == nil { + err = addReference(repoStorer, commitIterFunc, head, commitsPath, commitsLookup) + } + + if err != nil && err != plumbing.ErrReferenceNotFound { + return nil, err + } + + // add all references along with the HEAD + refIter, err := repoStorer.IterReferences() + if err != nil { + return nil, err + } + defer refIter.Close() + + for { + ref, err := refIter.Next() + if err == io.EOF { + break + } + + if err == plumbing.ErrReferenceNotFound { + continue + } + + if err != nil { + return nil, err + } + + if err = addReference(repoStorer, commitIterFunc, ref, commitsPath, commitsLookup); err != nil { + return nil, err + } + } + + return &commitAllIterator{commitsPath.Front()}, nil +} + +func addReference( + repoStorer storage.Storer, + commitIterFunc func(*Commit) CommitIter, + ref *plumbing.Reference, + commitsPath *list.List, + commitsLookup map[plumbing.Hash]*list.Element) error { + + _, exists := commitsLookup[ref.Hash()] + if exists { + // we already have it - skip the reference. + return nil + } + + refCommit, _ := GetCommit(repoStorer, ref.Hash()) + if refCommit == nil { + // if it's not a commit - skip it. + return nil + } + + var ( + refCommits []*Commit + parent *list.Element + ) + // collect all ref commits to add + commitIter := commitIterFunc(refCommit) + for c, e := commitIter.Next(); e == nil; { + parent, exists = commitsLookup[c.Hash] + if exists { + break + } + refCommits = append(refCommits, c) + c, e = commitIter.Next() + } + commitIter.Close() + + if parent == nil { + // common parent - not found + // add all commits to the path from this ref (maybe it's a HEAD and we don't have anything, yet) + for _, c := range refCommits { + parent = commitsPath.PushBack(c) + commitsLookup[c.Hash] = parent + } + } else { + // add ref's commits to the path in reverse order (from the latest) + for i := len(refCommits) - 1; i >= 0; i-- { + c := refCommits[i] + // insert before found common parent + parent = commitsPath.InsertBefore(c, parent) + commitsLookup[c.Hash] = parent + } + } + + return nil +} + +func (it *commitAllIterator) Next() (*Commit, error) { + if it.currCommit == nil { + return nil, io.EOF + } + + c := it.currCommit.Value.(*Commit) + it.currCommit = it.currCommit.Next() + + return c, nil +} + +func (it *commitAllIterator) ForEach(cb func(*Commit) error) error { + for { + c, err := it.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + + err = cb(c) + if err == storer.ErrStop { + break + } + if err != nil { + return err + } + } + + return nil +} + +func (it *commitAllIterator) Close() { + it.currCommit = nil +} diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go index 84e738ac6c4..6f16e611f17 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/object/commit_walker_file.go @@ -1,23 +1,30 @@ package object import ( - "gopkg.in/src-d/go-git.v4/plumbing/storer" "io" + + "gopkg.in/src-d/go-git.v4/plumbing" + + "gopkg.in/src-d/go-git.v4/plumbing/storer" ) type commitFileIter struct { fileName string sourceIter CommitIter currentCommit *Commit + checkParent bool } // NewCommitFileIterFromIter returns a commit iterator which performs diffTree between // successive trees returned from the commit iterator from the argument. The purpose of this is // to find the commits that explain how the files that match the path came to be. -func NewCommitFileIterFromIter(fileName string, commitIter CommitIter) CommitIter { +// If checkParent is true then the function double checks if potential parent (next commit in a path) +// is one of the parents in the tree (it's used by `git log --all`). +func NewCommitFileIterFromIter(fileName string, commitIter CommitIter, checkParent bool) CommitIter { iterator := new(commitFileIter) iterator.sourceIter = commitIter iterator.fileName = fileName + iterator.checkParent = checkParent return iterator } @@ -71,20 +78,14 @@ func (c *commitFileIter) getNextFileCommit() (*Commit, error) { return nil, diffErr } - foundChangeForFile := false - for _, change := range changes { - if change.name() == c.fileName { - foundChangeForFile = true - break - } - } + found := c.hasFileChange(changes, parentCommit) // Storing the current-commit in-case a change is found, and // Updating the current-commit for the next-iteration prevCommit := c.currentCommit c.currentCommit = parentCommit - if foundChangeForFile == true { + if found { return prevCommit, nil } @@ -95,6 +96,35 @@ func (c *commitFileIter) getNextFileCommit() (*Commit, error) { } } +func (c *commitFileIter) hasFileChange(changes Changes, parent *Commit) bool { + for _, change := range changes { + if change.name() != c.fileName { + continue + } + + // filename matches, now check if source iterator contains all commits (from all refs) + if c.checkParent { + if parent != nil && isParentHash(parent.Hash, c.currentCommit) { + return true + } + continue + } + + return true + } + + return false +} + +func isParentHash(hash plumbing.Hash, commit *Commit) bool { + for _, h := range commit.ParentHashes { + if h == hash { + return true + } + } + return false +} + func (c *commitFileIter) ForEach(cb func(*Commit) error) error { for { commit, nextErr := c.Next() diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/revlist/revlist.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/revlist/revlist.go index 0a9d1e8120e..7ad71ac044d 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/revlist/revlist.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/revlist/revlist.go @@ -21,7 +21,20 @@ func Objects( objs, ignore []plumbing.Hash, ) ([]plumbing.Hash, error) { - ignore, err := objects(s, ignore, nil, true) + return ObjectsWithStorageForIgnores(s, s, objs, ignore) +} + +// ObjectsWithStorageForIgnores is the same as Objects, but a +// secondary storage layer can be provided, to be used to finding the +// full set of objects to be ignored while finding the reachable +// objects. This is useful when the main `s` storage layer is slow +// and/or remote, while the ignore list is available somewhere local. +func ObjectsWithStorageForIgnores( + s, ignoreStore storer.EncodedObjectStorer, + objs, + ignore []plumbing.Hash, +) ([]plumbing.Hash, error) { + ignore, err := objects(ignoreStore, ignore, nil, true) if err != nil { return nil, err } @@ -114,7 +127,6 @@ func reachableObjects( i := object.NewCommitPreorderIter(commit, seen, ignore) pending := make(map[plumbing.Hash]bool) addPendingParents(pending, visited, commit) - for { commit, err := i.Next() if err == io.EOF { diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/object.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/object.go index 2ac9b091ef8..98d1ec3fecc 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/object.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/object.go @@ -222,7 +222,7 @@ type MultiEncodedObjectIter struct { } // NewMultiEncodedObjectIter returns an object iterator for the given slice of -// objects. +// EncodedObjectIters. func NewMultiEncodedObjectIter(iters []EncodedObjectIter) EncodedObjectIter { return &MultiEncodedObjectIter{iters: iters} } diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/reference.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/reference.go index 5e85a3be4db..cce72b4aa33 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/reference.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/storer/reference.go @@ -131,9 +131,27 @@ func (iter *ReferenceSliceIter) Next() (*plumbing.Reference, 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 *ReferenceSliceIter) ForEach(cb func(*plumbing.Reference) error) error { + return forEachReferenceIter(iter, cb) +} + +type bareReferenceIterator interface { + Next() (*plumbing.Reference, error) + Close() +} + +func forEachReferenceIter(iter bareReferenceIterator, cb func(*plumbing.Reference) error) error { defer iter.Close() - for _, r := range iter.series { - if err := cb(r); err != nil { + for { + obj, err := iter.Next() + if err != nil { + if err == io.EOF { + return nil + } + + return err + } + + if err := cb(obj); err != nil { if err == ErrStop { return nil } @@ -141,8 +159,6 @@ func (iter *ReferenceSliceIter) ForEach(cb func(*plumbing.Reference) error) erro return err } } - - return nil } // Close releases any resources used by the iterator. @@ -150,6 +166,52 @@ func (iter *ReferenceSliceIter) Close() { iter.pos = len(iter.series) } +// MultiReferenceIter implements ReferenceIter. It iterates over several +// ReferenceIter, +// +// The MultiReferenceIter must be closed with a call to Close() when it is no +// longer needed. +type MultiReferenceIter struct { + iters []ReferenceIter +} + +// NewMultiReferenceIter returns an reference iterator for the given slice of +// EncodedObjectIters. +func NewMultiReferenceIter(iters []ReferenceIter) ReferenceIter { + return &MultiReferenceIter{iters: iters} +} + +// Next returns the next reference from the iterator, if one iterator reach +// io.EOF is removed and the next one is used. +func (iter *MultiReferenceIter) Next() (*plumbing.Reference, error) { + if len(iter.iters) == 0 { + return nil, io.EOF + } + + obj, err := iter.iters[0].Next() + if err == io.EOF { + iter.iters[0].Close() + iter.iters = iter.iters[1:] + return iter.Next() + } + + return obj, err +} + +// ForEach call the cb function for each reference contained on this iter until +// 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 *MultiReferenceIter) ForEach(cb func(*plumbing.Reference) error) error { + return forEachReferenceIter(iter, cb) +} + +// Close releases any resources used by the iterator. +func (iter *MultiReferenceIter) Close() { + for _, i := range iter.iters { + i.Close() + } +} + // ResolveReference resolves a SymbolicReference to a HashReference. func ResolveReference(s ReferenceStorer, n plumbing.ReferenceName) (*plumbing.Reference, error) { r, err := s.Reference(n) diff --git a/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/common.go b/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/common.go index f7b882b8b6a..dcf9391d59a 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/common.go +++ b/vendor/gopkg.in/src-d/go-git.v4/plumbing/transport/common.go @@ -19,10 +19,10 @@ import ( "fmt" "io" "net/url" - "regexp" "strconv" "strings" + giturl "gopkg.in/src-d/go-git.v4/internal/url" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp" "gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability" @@ -224,34 +224,28 @@ func getPath(u *url.URL) string { return res } -var ( - isSchemeRegExp = regexp.MustCompile(`^[^:]+://`) - scpLikeUrlRegExp = regexp.MustCompile(`^(?:(?P[^@]+)@)?(?P[^:\s]+):(?:(?P[0-9]{1,5})/)?(?P[^\\].*)$`) -) - func parseSCPLike(endpoint string) (*Endpoint, bool) { - if isSchemeRegExp.MatchString(endpoint) || !scpLikeUrlRegExp.MatchString(endpoint) { + if giturl.MatchesScheme(endpoint) || !giturl.MatchesScpLike(endpoint) { return nil, false } - m := scpLikeUrlRegExp.FindStringSubmatch(endpoint) - - port, err := strconv.Atoi(m[3]) + user, host, portStr, path := giturl.FindScpLikeComponents(endpoint) + port, err := strconv.Atoi(portStr) if err != nil { port = 22 } return &Endpoint{ Protocol: "ssh", - User: m[1], - Host: m[2], + User: user, + Host: host, Port: port, - Path: m[4], + Path: path, }, true } func parseFile(endpoint string) (*Endpoint, bool) { - if isSchemeRegExp.MatchString(endpoint) { + if giturl.MatchesScheme(endpoint) { return nil, false } diff --git a/vendor/gopkg.in/src-d/go-git.v4/remote.go b/vendor/gopkg.in/src-d/go-git.v4/remote.go index 8f4e41d725a..de537ce8e8b 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/remote.go +++ b/vendor/gopkg.in/src-d/go-git.v4/remote.go @@ -6,8 +6,10 @@ import ( "fmt" "io" + "gopkg.in/src-d/go-billy.v4/osfs" "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/cache" "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/protocol/packp" @@ -18,6 +20,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" + "gopkg.in/src-d/go-git.v4/storage/filesystem" "gopkg.in/src-d/go-git.v4/storage/memory" "gopkg.in/src-d/go-git.v4/utils/ioutil" ) @@ -149,7 +152,17 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) { var hashesToPush []plumbing.Hash // Avoid the expensive revlist operation if we're only doing deletes. if !allDelete { - hashesToPush, err = revlist.Objects(r.s, objects, haves) + if r.c.IsFirstURLLocal() { + // If we're are pushing to a local repo, it might be much + // faster to use a local storage layer to get the commits + // to ignore, when calculating the object revlist. + localStorer := filesystem.NewStorage( + osfs.New(r.c.URLs[0]), cache.NewObjectLRUDefault()) + hashesToPush, err = revlist.ObjectsWithStorageForIgnores( + r.s, localStorer, objects, haves) + } else { + hashesToPush, err = revlist.Objects(r.s, objects, haves) + } if err != nil { return err } diff --git a/vendor/gopkg.in/src-d/go-git.v4/repository.go b/vendor/gopkg.in/src-d/go-git.v4/repository.go index f548e9a8334..de92d647099 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/repository.go +++ b/vendor/gopkg.in/src-d/go-git.v4/repository.go @@ -41,6 +41,8 @@ var ( ErrTagExists = errors.New("tag already exists") // ErrTagNotFound an error stating the specified tag does not exist ErrTagNotFound = errors.New("tag not found") + // ErrFetching is returned when the packfile could not be downloaded + ErrFetching = errors.New("unable to fetch packfile") ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch") ErrRepositoryNotExists = errors.New("repository does not exist") @@ -342,8 +344,9 @@ func PlainClone(path string, isBare bool, o *CloneOptions) (*Repository, error) // transport operations. // // TODO(mcuadros): move isBare to CloneOptions in v5 +// TODO(smola): refuse upfront to clone on a non-empty directory in v5, see #1027 func PlainCloneContext(ctx context.Context, path string, isBare bool, o *CloneOptions) (*Repository, error) { - dirExists, err := checkExistsAndIsEmptyDir(path) + cleanup, cleanupParent, err := checkIfCleanupIsNeeded(path) if err != nil { return nil, err } @@ -355,7 +358,9 @@ func PlainCloneContext(ctx context.Context, path string, isBare bool, o *CloneOp err = r.clone(ctx, o) if err != nil && err != ErrRepositoryAlreadyExists { - cleanUpDir(path, !dirExists) + if cleanup { + cleanUpDir(path, cleanupParent) + } } return r, err @@ -369,37 +374,37 @@ func newRepository(s storage.Storer, worktree billy.Filesystem) *Repository { } } -func checkExistsAndIsEmptyDir(path string) (exists bool, err error) { +func checkIfCleanupIsNeeded(path string) (cleanup bool, cleanParent bool, err error) { fi, err := os.Stat(path) if err != nil { if os.IsNotExist(err) { - return false, nil + return true, true, nil } - return false, err + return false, false, err } if !fi.IsDir() { - return false, fmt.Errorf("path is not a directory: %s", path) + return false, false, fmt.Errorf("path is not a directory: %s", path) } f, err := os.Open(path) if err != nil { - return false, err + return false, false, err } defer ioutil.CheckClose(f, &err) _, err = f.Readdirnames(1) if err == io.EOF { - return true, nil + return true, false, nil } if err != nil { - return true, err + return false, false, err } - return true, fmt.Errorf("directory is not empty: %s", path) + return false, false, nil } func cleanUpDir(path string, all bool) error { @@ -425,7 +430,7 @@ func cleanUpDir(path string, all bool) error { } } - return nil + return err } // Config return the repository config @@ -855,6 +860,8 @@ func (r *Repository) fetchAndUpdateReferences( remoteRefs, err := remote.fetch(ctx, o) if err == NoErrAlreadyUpToDate { objsUpdated = false + } else if err == packfile.ErrEmptyPackfile { + return nil, ErrFetching } else if err != nil { return nil, err } @@ -1020,8 +1027,36 @@ func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error { // Log returns the commit history from the given LogOptions. func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) { - h := o.From - if o.From == plumbing.ZeroHash { + fn := commitIterFunc(o.Order) + if fn == nil { + return nil, fmt.Errorf("invalid Order=%v", o.Order) + } + + var ( + it object.CommitIter + err error + ) + if o.All { + it, err = r.logAll(fn) + } else { + it, err = r.log(o.From, fn) + } + + if err != nil { + return nil, err + } + + if o.FileName != nil { + // for `git log --all` also check parent (if the next commit comes from the real parent) + it = r.logWithFile(*o.FileName, it, o.All) + } + + return it, nil +} + +func (r *Repository) log(from plumbing.Hash, commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) { + h := from + if from == plumbing.ZeroHash { head, err := r.Head() if err != nil { return nil, err @@ -1034,27 +1069,41 @@ func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) { if err != nil { return nil, err } + return commitIterFunc(commit), nil +} + +func (r *Repository) logAll(commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) { + return object.NewCommitAllIter(r.Storer, commitIterFunc) +} - var commitIter object.CommitIter - switch o.Order { +func (*Repository) logWithFile(fileName string, commitIter object.CommitIter, checkParent bool) object.CommitIter { + return object.NewCommitFileIterFromIter(fileName, commitIter, checkParent) +} + +func commitIterFunc(order LogOrder) func(c *object.Commit) object.CommitIter { + switch order { case LogOrderDefault: - commitIter = object.NewCommitPreorderIter(commit, nil, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitPreorderIter(c, nil, nil) + } case LogOrderDFS: - commitIter = object.NewCommitPreorderIter(commit, nil, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitPreorderIter(c, nil, nil) + } case LogOrderDFSPost: - commitIter = object.NewCommitPostorderIter(commit, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitPostorderIter(c, nil) + } case LogOrderBSF: - commitIter = object.NewCommitIterBSF(commit, nil, nil) + return func(c *object.Commit) object.CommitIter { + return object.NewCommitIterBSF(c, nil, nil) + } case LogOrderCommitterTime: - commitIter = object.NewCommitIterCTime(commit, nil, nil) - default: - return nil, fmt.Errorf("invalid Order=%v", o.Order) - } - - if o.FileName == nil { - return commitIter, nil + return func(c *object.Commit) object.CommitIter { + return object.NewCommitIterCTime(c, nil, nil) + } } - return object.NewCommitFileIterFromIter(*o.FileName, commitIter), nil + return nil } // Tags returns all the tag References in a repository. diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit.go index a58c2482a22..ba9667e65e2 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit.go @@ -14,6 +14,7 @@ import ( "gopkg.in/src-d/go-billy.v4/osfs" "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/storage" "gopkg.in/src-d/go-git.v4/utils/ioutil" "gopkg.in/src-d/go-billy.v4" @@ -596,7 +597,7 @@ func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference return err } if ref.Hash() != old.Hash() { - return fmt.Errorf("reference has changed concurrently") + return storage.ErrReferenceHasChanged } _, err = f.Seek(0, io.SeekStart) if err != nil { diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go index d27c1a30397..9da2f31e892 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref.go @@ -1,15 +1,24 @@ -// +build !norwfs - package dotgit import ( + "fmt" "os" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/utils/ioutil" + + "gopkg.in/src-d/go-billy.v4" ) func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err error) { + if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) { + return d.setRefRwfs(fileName, content, old) + } + + return d.setRefNorwfs(fileName, content, old) +} + +func (d *DotGit) setRefRwfs(fileName, content string, old *plumbing.Reference) (err error) { // If we are not checking an old ref, just truncate the file. mode := os.O_RDWR | os.O_CREATE if old == nil { @@ -41,3 +50,41 @@ func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err _, err = f.Write([]byte(content)) return err } + +// There are some filesystems that don't support opening files in RDWD mode. +// In these filesystems the standard SetRef function can not be used as it +// reads the reference file to check that it's not modified before updating it. +// +// This version of the function writes the reference without extra checks +// making it compatible with these simple filesystems. This is usually not +// a problem as they should be accessed by only one process at a time. +func (d *DotGit) setRefNorwfs(fileName, content string, old *plumbing.Reference) error { + _, err := d.fs.Stat(fileName) + if err == nil && old != nil { + fRead, err := d.fs.Open(fileName) + if err != nil { + return err + } + + ref, err := d.readReferenceFrom(fRead, old.Name().String()) + fRead.Close() + + if err != nil { + return err + } + + if ref.Hash() != old.Hash() { + return fmt.Errorf("reference has changed concurrently") + } + } + + f, err := d.fs.Create(fileName) + if err != nil { + return err + } + + defer f.Close() + + _, err = f.Write([]byte(content)) + return err +} diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref_norwfs.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref_norwfs.go deleted file mode 100644 index 5695bd3b612..00000000000 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/dotgit/dotgit_setref_norwfs.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build norwfs - -package dotgit - -import ( - "fmt" - - "gopkg.in/src-d/go-git.v4/plumbing" -) - -// There are some filesystems that don't support opening files in RDWD mode. -// In these filesystems the standard SetRef function can not be used as i -// reads the reference file to check that it's not modified before updating it. -// -// This version of the function writes the reference without extra checks -// making it compatible with these simple filesystems. This is usually not -// a problem as they should be accessed by only one process at a time. -func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) error { - _, err := d.fs.Stat(fileName) - if err == nil && old != nil { - fRead, err := d.fs.Open(fileName) - if err != nil { - return err - } - - ref, err := d.readReferenceFrom(fRead, old.Name().String()) - fRead.Close() - - if err != nil { - return err - } - - if ref.Hash() != old.Hash() { - return fmt.Errorf("reference has changed concurrently") - } - } - - f, err := d.fs.Create(fileName) - if err != nil { - return err - } - - defer f.Close() - - _, err = f.Write([]byte(content)) - return err -} diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go index 57dcbb43f92..3eb62a22f41 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/object.go @@ -20,24 +20,25 @@ import ( type ObjectStorage struct { options Options - // deltaBaseCache is an object cache uses to cache delta's bases when - deltaBaseCache cache.Object + // objectCache is an object cache uses to cache delta's bases and also recently + // loaded loose objects + objectCache cache.Object dir *dotgit.DotGit index map[plumbing.Hash]idxfile.Index } // NewObjectStorage creates a new ObjectStorage with the given .git directory and cache. -func NewObjectStorage(dir *dotgit.DotGit, cache cache.Object) *ObjectStorage { - return NewObjectStorageWithOptions(dir, cache, Options{}) +func NewObjectStorage(dir *dotgit.DotGit, objectCache cache.Object) *ObjectStorage { + return NewObjectStorageWithOptions(dir, objectCache, Options{}) } // NewObjectStorageWithOptions creates a new ObjectStorage with the given .git directory, cache and extra options -func NewObjectStorageWithOptions(dir *dotgit.DotGit, cache cache.Object, ops Options) *ObjectStorage { +func NewObjectStorageWithOptions(dir *dotgit.DotGit, objectCache cache.Object, ops Options) *ObjectStorage { return &ObjectStorage{ - options: ops, - deltaBaseCache: cache, - dir: dir, + options: ops, + objectCache: objectCache, + dir: dir, } } @@ -206,7 +207,7 @@ func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) ( idx := s.index[pack] hash, err := idx.FindHash(offset) if err == nil { - obj, ok := s.deltaBaseCache.Get(hash) + obj, ok := s.objectCache.Get(hash) if ok { return obj.Size(), nil } @@ -215,8 +216,8 @@ func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) ( } var p *packfile.Packfile - if s.deltaBaseCache != nil { - p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.deltaBaseCache) + if s.objectCache != nil { + p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.objectCache) } else { p = packfile.NewPackfile(idx, s.dir.Fs(), f) } @@ -241,9 +242,19 @@ func (s *ObjectStorage) EncodedObjectSize(h plumbing.Hash) ( // EncodedObject returns the object with the given hash, by searching for it in // the packfile and the git object directories. func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) { - obj, err := s.getFromUnpacked(h) - if err == plumbing.ErrObjectNotFound { + var obj plumbing.EncodedObject + var err error + + if s.index != nil { obj, err = s.getFromPackfile(h, false) + if err == plumbing.ErrObjectNotFound { + obj, err = s.getFromUnpacked(h) + } + } else { + obj, err = s.getFromUnpacked(h) + if err == plumbing.ErrObjectNotFound { + obj, err = s.getFromPackfile(h, false) + } } // If the error is still object not found, check if it's a shared object @@ -254,7 +265,7 @@ func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (p // Create a new object storage with the DotGit(s) and check for the // required hash object. Skip when not found. for _, dg := range dotgits { - o := NewObjectStorage(dg, s.deltaBaseCache) + o := NewObjectStorage(dg, s.objectCache) enobj, enerr := o.EncodedObject(t, h) if enerr != nil { continue @@ -304,9 +315,12 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb return nil, err } - defer ioutil.CheckClose(f, &err) + if cacheObj, found := s.objectCache.Get(h); found { + return cacheObj, nil + } + obj = s.NewEncodedObject() r, err := objfile.NewReader(f) if err != nil { @@ -327,6 +341,8 @@ func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedOb return nil, err } + s.objectCache.Put(obj) + _, err = io.Copy(w, r) return obj, err } @@ -369,7 +385,7 @@ func (s *ObjectStorage) decodeObjectAt( ) (plumbing.EncodedObject, error) { hash, err := idx.FindHash(offset) if err == nil { - obj, ok := s.deltaBaseCache.Get(hash) + obj, ok := s.objectCache.Get(hash) if ok { return obj, nil } @@ -380,8 +396,8 @@ func (s *ObjectStorage) decodeObjectAt( } var p *packfile.Packfile - if s.deltaBaseCache != nil { - p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.deltaBaseCache) + if s.objectCache != nil { + p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.objectCache) } else { p = packfile.NewPackfile(idx, s.dir.Fs(), f) } @@ -400,11 +416,7 @@ func (s *ObjectStorage) decodeDeltaObjectAt( } p := packfile.NewScanner(f) - if _, err := p.SeekFromStart(offset); err != nil { - return nil, err - } - - header, err := p.NextObjectHeader() + header, err := p.SeekObjectHeader(offset) if err != nil { return nil, err } @@ -495,7 +507,7 @@ func (s *ObjectStorage) buildPackfileIters( } return newPackfileIter( s.dir.Fs(), pack, t, seen, s.index[h], - s.deltaBaseCache, s.options.KeepDescriptors, + s.objectCache, s.options.KeepDescriptors, ) }, }, nil diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go index 14a772abe0c..370f7bd34a7 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/filesystem/storage.go @@ -51,11 +51,7 @@ func NewStorageWithOptions(fs billy.Filesystem, cache cache.Object, ops Options) fs: fs, dir: dir, - ObjectStorage: ObjectStorage{ - options: ops, - deltaBaseCache: cache, - dir: dir, - }, + ObjectStorage: *NewObjectStorageWithOptions(dir, cache, ops), ReferenceStorage: ReferenceStorage{dir: dir}, IndexStorage: IndexStorage{dir: dir}, ShallowStorage: ShallowStorage{dir: dir}, diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/memory/storage.go b/vendor/gopkg.in/src-d/go-git.v4/storage/memory/storage.go index 6e1174240fa..f240f2a1f93 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/memory/storage.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/memory/storage.go @@ -13,7 +13,6 @@ import ( ) var ErrUnsupportedObjectType = fmt.Errorf("unsupported object type") -var ErrRefHasChanged = fmt.Errorf("reference has changed concurrently") // Storage is an implementation of git.Storer that stores data on memory, being // ephemeral. The use of this storage should be done in controlled envoriments, @@ -258,7 +257,7 @@ func (r ReferenceStorage) CheckAndSetReference(ref, old *plumbing.Reference) err if old != nil { tmp := r[ref.Name()] if tmp != nil && tmp.Hash() != old.Hash() { - return ErrRefHasChanged + return storage.ErrReferenceHasChanged } } r[ref.Name()] = ref diff --git a/vendor/gopkg.in/src-d/go-git.v4/storage/storer.go b/vendor/gopkg.in/src-d/go-git.v4/storage/storer.go index d1a94f2a7ce..5de0cfb96c5 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/storage/storer.go +++ b/vendor/gopkg.in/src-d/go-git.v4/storage/storer.go @@ -1,10 +1,14 @@ package storage import ( + "errors" + "gopkg.in/src-d/go-git.v4/config" "gopkg.in/src-d/go-git.v4/plumbing/storer" ) +var ErrReferenceHasChanged = errors.New("reference has changed concurrently") + // Storer is a generic storage of objects, references and any information // related to a particular repository. The package gopkg.in/src-d/go-git.v4/storage // contains two implementation a filesystem base implementation (such as `.git`) diff --git a/vendor/gopkg.in/src-d/go-git.v4/utils/merkletrie/noder/path.go b/vendor/gopkg.in/src-d/go-git.v4/utils/merkletrie/noder/path.go index e9c905c96bc..1c7ef54eebc 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/utils/merkletrie/noder/path.go +++ b/vendor/gopkg.in/src-d/go-git.v4/utils/merkletrie/noder/path.go @@ -3,8 +3,6 @@ package noder import ( "bytes" "strings" - - "golang.org/x/text/unicode/norm" ) // Path values represent a noder and its ancestors. The root goes first @@ -80,11 +78,9 @@ func (p Path) Compare(other Path) int { case i == len(p): return -1 default: - form := norm.Form(norm.NFC) - this := form.String(p[i].Name()) - that := form.String(other[i].Name()) - - cmp := strings.Compare(this, that) + // We do *not* normalize Unicode here. CGit doesn't. + // https://github.com/src-d/go-git/issues/1057 + cmp := strings.Compare(p[i].Name(), other[i].Name()) if cmp != 0 { return cmp } diff --git a/vendor/gopkg.in/src-d/go-git.v4/worktree.go b/vendor/gopkg.in/src-d/go-git.v4/worktree.go index e45d815484c..a14fd8d6c34 100644 --- a/vendor/gopkg.in/src-d/go-git.v4/worktree.go +++ b/vendor/gopkg.in/src-d/go-git.v4/worktree.go @@ -25,10 +25,11 @@ import ( ) var ( - ErrWorktreeNotClean = errors.New("worktree is not clean") - ErrSubmoduleNotFound = errors.New("submodule not found") - ErrUnstagedChanges = errors.New("worktree contains unstaged changes") - ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink") + ErrWorktreeNotClean = errors.New("worktree is not clean") + ErrSubmoduleNotFound = errors.New("submodule not found") + ErrUnstagedChanges = errors.New("worktree contains unstaged changes") + ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink") + ErrNonFastForwardUpdate = errors.New("non-fast-forward update") ) // Worktree represents a git worktree. @@ -101,7 +102,7 @@ func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error { } if !ff { - return fmt.Errorf("non-fast-forward update") + return ErrNonFastForwardUpdate } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 899965af4e2..929353e3e6f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -415,7 +415,7 @@ gopkg.in/src-d/go-billy.v4/osfs gopkg.in/src-d/go-billy.v4/util gopkg.in/src-d/go-billy.v4/helper/chroot gopkg.in/src-d/go-billy.v4/helper/polyfill -# gopkg.in/src-d/go-git.v4 v4.8.0 +# gopkg.in/src-d/go-git.v4 v4.10.0 gopkg.in/src-d/go-git.v4 gopkg.in/src-d/go-git.v4/config gopkg.in/src-d/go-git.v4/plumbing @@ -442,6 +442,7 @@ gopkg.in/src-d/go-git.v4/utils/merkletrie gopkg.in/src-d/go-git.v4/utils/merkletrie/filesystem gopkg.in/src-d/go-git.v4/utils/merkletrie/index gopkg.in/src-d/go-git.v4/utils/merkletrie/noder +gopkg.in/src-d/go-git.v4/internal/url gopkg.in/src-d/go-git.v4/plumbing/format/config gopkg.in/src-d/go-git.v4/utils/binary gopkg.in/src-d/go-git.v4/plumbing/format/idxfile