aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2017-08-27 23:51:24 +0200
committerGitHub <noreply@github.com>2017-08-27 23:51:24 +0200
commit631a45f55b397090ad7d817a3c72041cfc3729f3 (patch)
tree955d20a91cc0b4753f9b7aedc7517601a9b51228
parent334923a20db4c8bd89e6197f99051839eac1731b (diff)
parent17cde59e5ced61adece4741b3a4da947f08fd9dc (diff)
downloadgo-git-631a45f55b397090ad7d817a3c72041cfc3729f3.tar.gz
Merge pull request #558 from orirawlings/cloneAnnotatedTag
repository: Resolve commit when cloning annotated tag, fixes #557
-rw-r--r--repository.go53
-rw-r--r--repository_test.go21
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)