Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 17cde59

Browse files
committed
repository: Resolve commit when cloning annotated tag, fixes #557
1 parent 2f58c82 commit 17cde59

File tree

2 files changed

+62
-12
lines changed

2 files changed

+62
-12
lines changed

repository.go

+41-12
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var (
3030
ErrRemoteExists = errors.New("remote already exists ")
3131
ErrWorktreeNotProvided = errors.New("worktree should be provided")
3232
ErrIsBareRepository = errors.New("worktree not available in a bare repository")
33+
ErrUnableToResolveCommit = errors.New("unable to resolve commit")
3334
)
3435

3536
// Repository represents a git repository
@@ -400,6 +401,25 @@ func (r *Repository) DeleteRemote(name string) error {
400401
return r.Storer.SetConfig(cfg)
401402
}
402403

404+
func (r *Repository) resolveToCommitHash(h plumbing.Hash) (plumbing.Hash, error) {
405+
obj, err := r.Storer.EncodedObject(plumbing.AnyObject, h)
406+
if err != nil {
407+
return plumbing.ZeroHash, err
408+
}
409+
switch obj.Type() {
410+
case plumbing.TagObject:
411+
t, err := object.DecodeTag(r.Storer, obj)
412+
if err != nil {
413+
return plumbing.ZeroHash, err
414+
}
415+
return r.resolveToCommitHash(t.Target)
416+
case plumbing.CommitObject:
417+
return h, nil
418+
default:
419+
return plumbing.ZeroHash, ErrUnableToResolveCommit
420+
}
421+
}
422+
403423
// Clone clones a remote repository
404424
func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
405425
if err := o.Validate(); err != nil {
@@ -415,7 +435,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
415435
return err
416436
}
417437

418-
head, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
438+
ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
419439
RefSpecs: r.cloneRefSpec(o, c),
420440
Depth: o.Depth,
421441
Auth: o.Auth,
@@ -431,6 +451,11 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
431451
return err
432452
}
433453

454+
head, err := r.Head()
455+
if err != nil {
456+
return err
457+
}
458+
434459
if err := w.Reset(&ResetOptions{Commit: head.Hash()}); err != nil {
435460
return err
436461
}
@@ -445,7 +470,7 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
445470
}
446471
}
447472

448-
return r.updateRemoteConfigIfNeeded(o, c, head)
473+
return r.updateRemoteConfigIfNeeded(o, c, ref)
449474
}
450475

451476
const (
@@ -520,12 +545,12 @@ func (r *Repository) fetchAndUpdateReferences(
520545
return nil, err
521546
}
522547

523-
head, err := storer.ResolveReference(remoteRefs, ref)
548+
resolvedRef, err := storer.ResolveReference(remoteRefs, ref)
524549
if err != nil {
525550
return nil, err
526551
}
527552

528-
refsUpdated, err := r.updateReferences(remote.c.Fetch, head)
553+
refsUpdated, err := r.updateReferences(remote.c.Fetch, resolvedRef)
529554
if err != nil {
530555
return nil, err
531556
}
@@ -534,26 +559,30 @@ func (r *Repository) fetchAndUpdateReferences(
534559
return nil, NoErrAlreadyUpToDate
535560
}
536561

537-
return head, nil
562+
return resolvedRef, nil
538563
}
539564

540565
func (r *Repository) updateReferences(spec []config.RefSpec,
541-
resolvedHead *plumbing.Reference) (updated bool, err error) {
566+
resolvedRef *plumbing.Reference) (updated bool, err error) {
542567

543-
if !resolvedHead.Name().IsBranch() {
568+
if !resolvedRef.Name().IsBranch() {
544569
// Detached HEAD mode
545-
head := plumbing.NewHashReference(plumbing.HEAD, resolvedHead.Hash())
570+
h, err := r.resolveToCommitHash(resolvedRef.Hash())
571+
if err != nil {
572+
return false, err
573+
}
574+
head := plumbing.NewHashReference(plumbing.HEAD, h)
546575
return updateReferenceStorerIfNeeded(r.Storer, head)
547576
}
548577

549578
refs := []*plumbing.Reference{
550-
// Create local reference for the resolved head
551-
resolvedHead,
579+
// Create local reference for the resolved ref
580+
resolvedRef,
552581
// Create local symbolic HEAD
553-
plumbing.NewSymbolicReference(plumbing.HEAD, resolvedHead.Name()),
582+
plumbing.NewSymbolicReference(plumbing.HEAD, resolvedRef.Name()),
554583
}
555584

556-
refs = append(refs, r.calculateRemoteHeadReference(spec, resolvedHead)...)
585+
refs = append(refs, r.calculateRemoteHeadReference(spec, resolvedRef)...)
557586

558587
for _, ref := range refs {
559588
u, err := updateReferenceStorerIfNeeded(r.Storer, ref)

repository_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,27 @@ func (s *RepositorySuite) TestCloneDetachedHEADAndShallow(c *C) {
651651
c.Assert(count, Equals, 15)
652652
}
653653

654+
func (s *RepositorySuite) TestCloneDetachedHEADAnnotatedTag(c *C) {
655+
r, _ := Init(memory.NewStorage(), nil)
656+
err := r.clone(context.Background(), &CloneOptions{
657+
URL: s.GetLocalRepositoryURL(fixtures.ByTag("tags").One()),
658+
ReferenceName: plumbing.ReferenceName("refs/tags/annotated-tag"),
659+
})
660+
c.Assert(err, IsNil)
661+
662+
head, err := r.Reference(plumbing.HEAD, false)
663+
c.Assert(err, IsNil)
664+
c.Assert(head, NotNil)
665+
c.Assert(head.Type(), Equals, plumbing.HashReference)
666+
c.Assert(head.Hash().String(), Equals, "f7b877701fbf855b44c0a9e86f3fdce2c298b07f")
667+
668+
count := 0
669+
objects, err := r.Objects()
670+
c.Assert(err, IsNil)
671+
objects.ForEach(func(object.Object) error { count++; return nil })
672+
c.Assert(count, Equals, 7)
673+
}
674+
654675
func (s *RepositorySuite) TestPush(c *C) {
655676
url := c.MkDir()
656677
server, err := PlainInit(url, true)

0 commit comments

Comments
 (0)