@@ -1306,16 +1306,6 @@ func (r *Repository) Worktree() (*Worktree, error) {
1306
1306
return & Worktree {r : r , Filesystem : r .wt }, nil
1307
1307
}
1308
1308
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
-
1319
1309
// ResolveRevision resolves revision to corresponding hash. It will always
1320
1310
// resolve to a commit hash, not a tree or annotated tag.
1321
1311
//
@@ -1336,54 +1326,57 @@ func (r *Repository) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, err
1336
1326
switch item .(type ) {
1337
1327
case revision.Ref :
1338
1328
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
+ }
1342
1337
1343
1338
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 )))
1345
1340
1346
1341
if err == nil {
1342
+ tryHashes = append (tryHashes , ref .Hash ())
1347
1343
break
1348
1344
}
1349
1345
}
1350
1346
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
1357
1359
}
1358
- refCommit , rErr = r .CommitObject (ref .Hash ())
1359
- } else {
1360
- rErr = plumbing .ErrReferenceNotFound
1361
- tErr = plumbing .ErrReferenceNotFound
1362
- }
1363
1360
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
+ }
1369
1374
}
1370
1375
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 {
1385
1377
return & plumbing .ZeroHash , plumbing .ErrReferenceNotFound
1386
1378
}
1379
+
1387
1380
case revision.CaretPath :
1388
1381
depth := item .(revision.CaretPath ).Depth
1389
1382
0 commit comments