aboutsummaryrefslogtreecommitdiffstats
path: root/repository.go
diff options
context:
space:
mode:
Diffstat (limited to 'repository.go')
-rw-r--r--repository.go56
1 files changed, 41 insertions, 15 deletions
diff --git a/repository.go b/repository.go
index 62e22a6..651425d 100644
--- a/repository.go
+++ b/repository.go
@@ -654,11 +654,12 @@ func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
}
ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
- RefSpecs: r.cloneRefSpec(o, c),
- Depth: o.Depth,
- Auth: o.Auth,
- Progress: o.Progress,
- Tags: o.Tags,
+ RefSpecs: r.cloneRefSpec(o, c),
+ Depth: o.Depth,
+ Auth: o.Auth,
+ Progress: o.Progress,
+ Tags: o.Tags,
+ RemoteName: o.RemoteName,
}, o.ReferenceName)
if err != nil {
return err
@@ -1170,7 +1171,18 @@ func (r *Repository) Worktree() (*Worktree, error) {
return &Worktree{r: r, Filesystem: r.wt}, nil
}
-// ResolveRevision resolves revision to corresponding hash.
+func countTrue(vals ...bool) int {
+ sum := 0
+ for _, v := range vals {
+ if v {
+ sum++
+ }
+ }
+ return sum
+}
+
+// ResolveRevision resolves revision to corresponding hash. It will always
+// resolve to a commit hash, not a tree or annotated tag.
//
// Implemented resolvers : HEAD, branch, tag, heads/branch, refs/heads/branch,
// refs/tags/tag, refs/remotes/origin/branch, refs/remotes/origin/HEAD, tilde and caret (HEAD~1, master~^, tag~2, ref/heads/master~1, ...), selection by text (HEAD^{/fix nasty bug})
@@ -1190,8 +1202,8 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
case revision.Ref:
revisionRef := item.(revision.Ref)
var ref *plumbing.Reference
- var hashCommit, refCommit *object.Commit
- var rErr, hErr error
+ var hashCommit, refCommit, tagCommit *object.Commit
+ var rErr, hErr, tErr error
for _, rule := range append([]string{"%s"}, plumbing.RefRevParseRules...) {
ref, err = storer.ResolveReference(r.Storer, plumbing.ReferenceName(fmt.Sprintf(rule, revisionRef)))
@@ -1202,24 +1214,38 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
}
if ref != nil {
+ tag, tObjErr := r.TagObject(ref.Hash())
+ if tObjErr != nil {
+ tErr = tObjErr
+ } else {
+ tagCommit, tErr = tag.Commit()
+ }
refCommit, rErr = r.CommitObject(ref.Hash())
} else {
rErr = plumbing.ErrReferenceNotFound
+ tErr = plumbing.ErrReferenceNotFound
}
- isHash := plumbing.NewHash(string(revisionRef)).String() == string(revisionRef)
-
- if isHash {
+ maybeHash := plumbing.NewHash(string(revisionRef)).String() == string(revisionRef)
+ if maybeHash {
hashCommit, hErr = r.CommitObject(plumbing.NewHash(string(revisionRef)))
+ } else {
+ hErr = plumbing.ErrReferenceNotFound
}
+ isTag := tErr == nil
+ isCommit := rErr == nil
+ isHash := hErr == nil
+
switch {
- case rErr == nil && !isHash:
+ case countTrue(isTag, isCommit, isHash) > 1:
+ return &plumbing.ZeroHash, fmt.Errorf(`refname "%s" is ambiguous`, revisionRef)
+ case isTag:
+ commit = tagCommit
+ case isCommit:
commit = refCommit
- case rErr != nil && isHash && hErr == nil:
+ case isHash:
commit = hashCommit
- case rErr == nil && isHash && hErr == nil:
- return &plumbing.ZeroHash, fmt.Errorf(`refname "%s" is ambiguous`, revisionRef)
default:
return &plumbing.ZeroHash, plumbing.ErrReferenceNotFound
}