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

repository: Resolve commit when cloning annotated tag, fixes #557 #558

Merged
merged 1 commit into from
Aug 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 41 additions & 12 deletions repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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,
Expand All @@ -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
}
Expand All @@ -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 (
Expand Down Expand Up @@ -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
}
Expand All @@ -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)
Expand Down
21 changes: 21 additions & 0 deletions repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down