diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2017-08-27 23:51:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-27 23:51:24 +0200 |
commit | 631a45f55b397090ad7d817a3c72041cfc3729f3 (patch) | |
tree | 955d20a91cc0b4753f9b7aedc7517601a9b51228 | |
parent | 334923a20db4c8bd89e6197f99051839eac1731b (diff) | |
parent | 17cde59e5ced61adece4741b3a4da947f08fd9dc (diff) | |
download | go-git-631a45f55b397090ad7d817a3c72041cfc3729f3.tar.gz |
Merge pull request #558 from orirawlings/cloneAnnotatedTag
repository: Resolve commit when cloning annotated tag, fixes #557
-rw-r--r-- | repository.go | 53 | ||||
-rw-r--r-- | repository_test.go | 21 |
2 files changed, 62 insertions, 12 deletions
diff --git a/repository.go b/repository.go index 8110cf1..932b8d4 100644 --- a/repository.go +++ b/repository.go @@ -30,6 +30,7 @@ var ( ErrRemoteExists = errors.New("remote already exists ") ErrWorktreeNotProvided = errors.New("worktree should be provided") ErrIsBareRepository = errors.New("worktree not available in a bare repository") + ErrUnableToResolveCommit = errors.New("unable to resolve commit") ) // Repository represents a git repository @@ -400,6 +401,25 @@ func (r *Repository) DeleteRemote(name string) error { return r.Storer.SetConfig(cfg) } +func (r *Repository) resolveToCommitHash(h plumbing.Hash) (plumbing.Hash, error) { + obj, err := r.Storer.EncodedObject(plumbing.AnyObject, h) + if err != nil { + return plumbing.ZeroHash, err + } + switch obj.Type() { + case plumbing.TagObject: + t, err := object.DecodeTag(r.Storer, obj) + if err != nil { + return plumbing.ZeroHash, err + } + return r.resolveToCommitHash(t.Target) + case plumbing.CommitObject: + return h, nil + default: + return plumbing.ZeroHash, ErrUnableToResolveCommit + } +} + // Clone clones a remote repository func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { if err := o.Validate(); err != nil { @@ -415,7 +435,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { return err } - head, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{ + ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{ RefSpecs: r.cloneRefSpec(o, c), Depth: o.Depth, Auth: o.Auth, @@ -431,6 +451,11 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { return err } + head, err := r.Head() + if err != nil { + return err + } + if err := w.Reset(&ResetOptions{Commit: head.Hash()}); err != nil { return err } @@ -445,7 +470,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error { } } - return r.updateRemoteConfigIfNeeded(o, c, head) + return r.updateRemoteConfigIfNeeded(o, c, ref) } const ( @@ -520,12 +545,12 @@ func (r *Repository) fetchAndUpdateReferences( return nil, err } - head, err := storer.ResolveReference(remoteRefs, ref) + resolvedRef, err := storer.ResolveReference(remoteRefs, ref) if err != nil { return nil, err } - refsUpdated, err := r.updateReferences(remote.c.Fetch, head) + refsUpdated, err := r.updateReferences(remote.c.Fetch, resolvedRef) if err != nil { return nil, err } @@ -534,26 +559,30 @@ func (r *Repository) fetchAndUpdateReferences( return nil, NoErrAlreadyUpToDate } - return head, nil + return resolvedRef, nil } func (r *Repository) updateReferences(spec []config.RefSpec, - resolvedHead *plumbing.Reference) (updated bool, err error) { + resolvedRef *plumbing.Reference) (updated bool, err error) { - if !resolvedHead.Name().IsBranch() { + if !resolvedRef.Name().IsBranch() { // Detached HEAD mode - head := plumbing.NewHashReference(plumbing.HEAD, resolvedHead.Hash()) + h, err := r.resolveToCommitHash(resolvedRef.Hash()) + if err != nil { + return false, err + } + head := plumbing.NewHashReference(plumbing.HEAD, h) return updateReferenceStorerIfNeeded(r.Storer, head) } refs := []*plumbing.Reference{ - // Create local reference for the resolved head - resolvedHead, + // Create local reference for the resolved ref + resolvedRef, // Create local symbolic HEAD - plumbing.NewSymbolicReference(plumbing.HEAD, resolvedHead.Name()), + plumbing.NewSymbolicReference(plumbing.HEAD, resolvedRef.Name()), } - refs = append(refs, r.calculateRemoteHeadReference(spec, resolvedHead)...) + refs = append(refs, r.calculateRemoteHeadReference(spec, resolvedRef)...) for _, ref := range refs { u, err := updateReferenceStorerIfNeeded(r.Storer, ref) diff --git a/repository_test.go b/repository_test.go index 3da11f6..e944251 100644 --- a/repository_test.go +++ b/repository_test.go @@ -651,6 +651,27 @@ func (s *RepositorySuite) TestCloneDetachedHEADAndShallow(c *C) { c.Assert(count, Equals, 15) } +func (s *RepositorySuite) TestCloneDetachedHEADAnnotatedTag(c *C) { + r, _ := Init(memory.NewStorage(), nil) + err := r.clone(context.Background(), &CloneOptions{ + URL: s.GetLocalRepositoryURL(fixtures.ByTag("tags").One()), + ReferenceName: plumbing.ReferenceName("refs/tags/annotated-tag"), + }) + c.Assert(err, IsNil) + + head, err := r.Reference(plumbing.HEAD, false) + c.Assert(err, IsNil) + c.Assert(head, NotNil) + c.Assert(head.Type(), Equals, plumbing.HashReference) + c.Assert(head.Hash().String(), Equals, "f7b877701fbf855b44c0a9e86f3fdce2c298b07f") + + count := 0 + objects, err := r.Objects() + c.Assert(err, IsNil) + objects.ForEach(func(object.Object) error { count++; return nil }) + c.Assert(count, Equals, 7) +} + func (s *RepositorySuite) TestPush(c *C) { url := c.MkDir() server, err := PlainInit(url, true) |