@@ -1306,16 +1306,6 @@ func (r *Repository) Worktree() (*Worktree, error) {
13061306 return & Worktree {r : r , Filesystem : r .wt }, nil
13071307}
13081308
1309- func countTrue (vals ... bool ) int {
1310- sum := 0
1311- for _ , v := range vals {
1312- if v {
1313- sum ++
1314- }
1315- }
1316- return sum
1317- }
1318-
13191309// ResolveRevision resolves revision to corresponding hash. It will always
13201310// resolve to a commit hash, not a tree or annotated tag.
13211311//
@@ -1336,54 +1326,57 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
13361326 switch item .(type ) {
13371327 case revision.Ref :
13381328 revisionRef := item .(revision.Ref )
1339- var ref * plumbing.Reference
1340- var hashCommit , refCommit , tagCommit * object.Commit
1341- var rErr , hErr , tErr error
1329+
1330+ var tryHashes []plumbing.Hash
1331+
1332+ maybeHash := plumbing .NewHash (string (revisionRef ))
1333+
1334+ if ! maybeHash .IsZero () {
1335+ tryHashes = append (tryHashes , maybeHash )
1336+ }
13421337
13431338 for _ , rule := range append ([]string {"%s" }, plumbing .RefRevParseRules ... ) {
1344- ref , err = storer .ResolveReference (r .Storer , plumbing .ReferenceName (fmt .Sprintf (rule , revisionRef )))
1339+ ref , err : = storer .ResolveReference (r .Storer , plumbing .ReferenceName (fmt .Sprintf (rule , revisionRef )))
13451340
13461341 if err == nil {
1342+ tryHashes = append (tryHashes , ref .Hash ())
13471343 break
13481344 }
13491345 }
13501346
1351- if ref != nil {
1352- tag , tObjErr := r .TagObject (ref .Hash ())
1353- if tObjErr != nil {
1354- tErr = tObjErr
1355- } else {
1356- tagCommit , tErr = tag .Commit ()
1347+ // in ambiguous cases, `git rev-parse` will emit a warning, but
1348+ // will always return the oid in preference to a ref; we don't have
1349+ // the ability to emit a warning here, so (for speed purposes)
1350+ // don't bother to detect the ambiguity either, just return in the
1351+ // priority that git would.
1352+ gotOne := false
1353+ for _ , hash := range tryHashes {
1354+ commitObj , err := r .CommitObject (hash )
1355+ if err == nil {
1356+ commit = commitObj
1357+ gotOne = true
1358+ break
13571359 }
1358- refCommit , rErr = r .CommitObject (ref .Hash ())
1359- } else {
1360- rErr = plumbing .ErrReferenceNotFound
1361- tErr = plumbing .ErrReferenceNotFound
1362- }
13631360
1364- maybeHash := plumbing .NewHash (string (revisionRef )).String () == string (revisionRef )
1365- if maybeHash {
1366- hashCommit , hErr = r .CommitObject (plumbing .NewHash (string (revisionRef )))
1367- } else {
1368- hErr = plumbing .ErrReferenceNotFound
1361+ tagObj , err := r .TagObject (hash )
1362+ if err == nil {
1363+ // If the tag target lookup fails here, this most likely
1364+ // represents some sort of repo corruption, so let the
1365+ // error bubble up.
1366+ tagCommit , err := tagObj .Commit ()
1367+ if err != nil {
1368+ return & plumbing .ZeroHash , err
1369+ }
1370+ commit = tagCommit
1371+ gotOne = true
1372+ break
1373+ }
13691374 }
13701375
1371- isTag := tErr == nil
1372- isCommit := rErr == nil
1373- isHash := hErr == nil
1374-
1375- switch {
1376- case countTrue (isTag , isCommit , isHash ) > 1 :
1377- return & plumbing .ZeroHash , fmt .Errorf (`refname "%s" is ambiguous` , revisionRef )
1378- case isTag :
1379- commit = tagCommit
1380- case isCommit :
1381- commit = refCommit
1382- case isHash :
1383- commit = hashCommit
1384- default :
1376+ if ! gotOne {
13851377 return & plumbing .ZeroHash , plumbing .ErrReferenceNotFound
13861378 }
1379+
13871380 case revision.CaretPath :
13881381 depth := item .(revision.CaretPath ).Depth
13891382
0 commit comments