diff options
author | Alberto Cortés <alberto@sourced.tech> | 2016-08-02 10:49:06 +0200 |
---|---|---|
committer | Alberto Cortés <alberto@sourced.tech> | 2016-08-02 10:49:06 +0200 |
commit | 7dffd7c467af7c7c79398e7997837b6e8c37e14f (patch) | |
tree | 535b7310da790ef1070bc60fd2ec617d1e423b74 | |
parent | b5613047f0d1fc6f53d5a8ad1a05415ca9c6a92a (diff) | |
download | go-git-7dffd7c467af7c7c79398e7997837b6e8c37e14f.tar.gz |
add head support for local repos
-rw-r--r-- | repository.go | 12 | ||||
-rw-r--r-- | repository_test.go | 4 | ||||
-rw-r--r-- | storage/seekable/internal/gitdir/gitdir.go | 5 | ||||
-rw-r--r-- | storage/seekable/storage.go | 46 |
4 files changed, 65 insertions, 2 deletions
diff --git a/repository.go b/repository.go index 0cda947..866f9ff 100644 --- a/repository.go +++ b/repository.go @@ -226,6 +226,10 @@ func (r *Repository) Head(remote string) (core.Hash, error) { return r.localHead() } + return r.remoteHead(remote) +} + +func (r *Repository) remoteHead(remote string) (core.Hash, error) { rem, ok := r.Remotes[remote] if !ok { return core.ZeroHash, fmt.Errorf("unable to find remote %q", remote) @@ -235,5 +239,11 @@ func (r *Repository) Head(remote string) (core.Hash, error) { } func (r *Repository) localHead() (core.Hash, error) { - return core.ZeroHash, nil + storage, ok := r.Storage.(*seekable.ObjectStorage) + if !ok { + return core.ZeroHash, + fmt.Errorf("cannot retrieve local head: no local data found") + } + + return storage.Head() } diff --git a/repository_test.go b/repository_test.go index da02a4d..eafbdf7 100644 --- a/repository_test.go +++ b/repository_test.go @@ -260,4 +260,8 @@ func (s *SuiteRepository) TestHeadFromRemoteError(c *C) { remote := "not found" _, err = r.Head(remote) c.Assert(err, ErrorMatches, fmt.Sprintf("unable to find remote %q", remote)) + + remote = "" + _, err = r.Head(remote) + c.Assert(err, ErrorMatches, "cannot retrieve local head: no local data found") } diff --git a/storage/seekable/internal/gitdir/gitdir.go b/storage/seekable/internal/gitdir/gitdir.go index bfdf030..eea980b 100644 --- a/storage/seekable/internal/gitdir/gitdir.go +++ b/storage/seekable/internal/gitdir/gitdir.go @@ -25,6 +25,9 @@ var ( // ErrPackfileNotFound is returned by Packfile when the packfile is not found // on the repository. ErrPackfileNotFound = errors.New("packfile not found") + // ErrHeadfileNotFound is returned by Headfile when the HEAD file is not found + // on the repository. + ErrHeadfileNotFound = errors.New("headfile not found") ) // The GitDir type represents a local git repository on disk. This @@ -126,7 +129,7 @@ func (d *GitDir) Packfile() (fs.FS, string, error) { return nil, "", ErrPackfileNotFound } -// Packfile returns the path of the idx file (really, it returns the +// Idxfile returns the path of the idx file (really, it returns the // path of the first file in the "objects/pack/" directory with an // ".idx" extension. func (d *GitDir) Idxfile() (fs.FS, string, error) { diff --git a/storage/seekable/storage.go b/storage/seekable/storage.go index 8d75700..db436c8 100644 --- a/storage/seekable/storage.go +++ b/storage/seekable/storage.go @@ -3,6 +3,7 @@ package seekable import ( "fmt" "os" + "strings" "gopkg.in/src-d/go-git.v3/core" "gopkg.in/src-d/go-git.v3/formats/packfile" @@ -150,3 +151,48 @@ func (s *ObjectStorage) Iter(t core.ObjectType) (core.ObjectIter, error) { return core.NewObjectSliceIter(objects), nil } + +const ( + headErrPrefix = "cannot get HEAD reference:" + symrefCapability = "symref" + headRefPrefix = "HEAD:" +) + +// Head returns the hash of the HEAD reference +func (s *ObjectStorage) Head() (core.Hash, error) { + cap, err := s.dir.Capabilities() + if err != nil { + return core.ZeroHash, fmt.Errorf("%s %s", headErrPrefix, err) + } + + ok := cap.Supports(symrefCapability) + if !ok { + return core.ZeroHash, + fmt.Errorf("%s symref capability not supported", headErrPrefix) + } + + symrefs := cap.Get(symrefCapability) + var headRef string + for _, ref := range symrefs.Values { + if strings.HasPrefix(ref, headRefPrefix) { + headRef = strings.TrimPrefix(ref, headRefPrefix) + } + } + if headRef == "" { + return core.ZeroHash, fmt.Errorf("%s HEAD reference not found", + headErrPrefix) + } + + refs, err := s.dir.Refs() + if err != nil { + return core.ZeroHash, fmt.Errorf("%s %s", headErrPrefix, err) + } + + head, ok := refs[headRef] + if !ok { + return core.ZeroHash, fmt.Errorf("%s reference %q not found", + headErrPrefix, headRef) + } + + return head, nil +} |