@@ -1004,7 +1004,18 @@ func (r *Repository) Worktree() (*Worktree, error) {
10041004 return & Worktree {r : r , Filesystem : r .wt }, nil
10051005}
10061006
1007- // ResolveRevision resolves revision to corresponding hash.
1007+ func countTrue (vals ... bool ) int {
1008+ sum := 0
1009+ for _ , v := range vals {
1010+ if v {
1011+ sum ++
1012+ }
1013+ }
1014+ return sum
1015+ }
1016+
1017+ // ResolveRevision resolves revision to corresponding hash. It will always
1018+ // resolve to a commit hash, not a tree or annotated tag.
10081019//
10091020// Implemented resolvers : HEAD, branch, tag, heads/branch, refs/heads/branch,
10101021// 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})
@@ -1024,8 +1035,8 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
10241035 case revision.Ref :
10251036 revisionRef := item .(revision.Ref )
10261037 var ref * plumbing.Reference
1027- var hashCommit , refCommit * object.Commit
1028- var rErr , hErr error
1038+ var hashCommit , refCommit , tagCommit * object.Commit
1039+ var rErr , hErr , tErr error
10291040
10301041 for _ , rule := range append ([]string {"%s" }, plumbing .RefRevParseRules ... ) {
10311042 ref , err = storer .ResolveReference (r .Storer , plumbing .ReferenceName (fmt .Sprintf (rule , revisionRef )))
@@ -1036,24 +1047,38 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
10361047 }
10371048
10381049 if ref != nil {
1050+ tag , tObjErr := r .TagObject (ref .Hash ())
1051+ if tObjErr != nil {
1052+ tErr = tObjErr
1053+ } else {
1054+ tagCommit , tErr = tag .Commit ()
1055+ }
10391056 refCommit , rErr = r .CommitObject (ref .Hash ())
10401057 } else {
10411058 rErr = plumbing .ErrReferenceNotFound
1059+ tErr = plumbing .ErrReferenceNotFound
10421060 }
10431061
1044- isHash := plumbing .NewHash (string (revisionRef )).String () == string (revisionRef )
1045-
1046- if isHash {
1062+ maybeHash := plumbing .NewHash (string (revisionRef )).String () == string (revisionRef )
1063+ if maybeHash {
10471064 hashCommit , hErr = r .CommitObject (plumbing .NewHash (string (revisionRef )))
1065+ } else {
1066+ hErr = plumbing .ErrReferenceNotFound
10481067 }
10491068
1069+ isTag := tErr == nil
1070+ isCommit := rErr == nil
1071+ isHash := hErr == nil
1072+
10501073 switch {
1051- case rErr == nil && ! isHash :
1074+ case countTrue (isTag , isCommit , isHash ) > 1 :
1075+ return & plumbing .ZeroHash , fmt .Errorf (`refname "%s" is ambiguous` , revisionRef )
1076+ case isTag :
1077+ commit = tagCommit
1078+ case isCommit :
10521079 commit = refCommit
1053- case rErr != nil && isHash && hErr == nil :
1080+ case isHash :
10541081 commit = hashCommit
1055- case rErr == nil && isHash && hErr == nil :
1056- return & plumbing .ZeroHash , fmt .Errorf (`refname "%s" is ambiguous` , revisionRef )
10571082 default :
10581083 return & plumbing .ZeroHash , plumbing .ErrReferenceNotFound
10591084 }
0 commit comments