@@ -836,10 +836,7 @@ func main() {
836
836
os .Exit (exitCode )
837
837
}
838
838
839
- if isHash , err := git .IsKnownHash (ctx , git .ref ); err != nil {
840
- log .Error (err , "can't tell if ref is a git hash, exiting" , "ref" , git .ref )
841
- os .Exit (1 )
842
- } else if isHash {
839
+ if hash == git .ref {
843
840
log .V (0 ).Info ("ref appears to be a git hash, no further sync needed" , "ref" , git .ref )
844
841
log .DeleteErrorFile ()
845
842
sleepForever ()
@@ -1493,49 +1490,6 @@ func (m multiError) Error() string {
1493
1490
return strings .Join (strs , "; " )
1494
1491
}
1495
1492
1496
- // remoteHashForRef returns the upstream hash for a given ref.
1497
- func (git * repoSync ) remoteHashForRef (ctx context.Context , ref string ) (string , error ) {
1498
- // Fetch both the bare and dereferenced ref. git sorts the results and
1499
- // prints the dereferenced result, if present, after the bare result, so we
1500
- // always want the last result it produces.
1501
- output , _ , err := git .Run (ctx , git .root , "ls-remote" , "-q" , git .repo , ref , ref + "^{}" )
1502
- if err != nil {
1503
- return "" , err
1504
- }
1505
- line := lastNonEmptyLine (output )
1506
- parts := strings .Split (line , "\t " ) // guaranteed to have at least 1 element
1507
- return parts [0 ], nil
1508
- }
1509
-
1510
- func lastNonEmptyLine (text string ) string {
1511
- lines := strings .Split (text , "\n " ) // guaranteed to have at least 1 element
1512
- for i := len (lines ) - 1 ; i >= 0 ; i -- {
1513
- line := strings .TrimSpace (lines [i ])
1514
- if line != "" {
1515
- return line
1516
- }
1517
- }
1518
- return ""
1519
- }
1520
-
1521
- // IsKnownHash returns true if ref is the hash of a commit which is known to this
1522
- // repo. In the event that ref is an abbreviated hash (e.g. "abcd" which
1523
- // resolves to "abcdef1234567890"), this will return true by prefix-matching.
1524
- // If ref is ambiguous, it will consider whatever result git returns. If ref
1525
- // is not a hash or is not known to this repo, even if it appears to be a hash,
1526
- // this will return false.
1527
- func (git * repoSync ) IsKnownHash (ctx context.Context , ref string ) (bool , error ) {
1528
- stdout , stderr , err := git .Run (ctx , git .root , "rev-parse" , ref + "^{commit}" )
1529
- if err != nil {
1530
- if strings .Contains (stderr , "unknown revision" ) {
1531
- return false , nil
1532
- }
1533
- return false , err
1534
- }
1535
- line := lastNonEmptyLine (stdout )
1536
- return strings .HasPrefix (line , ref ), nil
1537
- }
1538
-
1539
1493
// worktree represents a git worktree (which may or may not exist on disk).
1540
1494
type worktree absPath
1541
1495
@@ -1592,26 +1546,6 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
1592
1546
return false , "" , err
1593
1547
}
1594
1548
1595
- // Figure out what hash the remote resolves to.
1596
- remoteHash , err := git .remoteHashForRef (ctx , git .ref )
1597
- if err != nil {
1598
- return false , "" , err
1599
- }
1600
-
1601
- // If we couldn't find a remote commit, it might have been a hash literal.
1602
- if remoteHash == "" {
1603
- // If git thinks it tastes like a hash, we just use that and if it
1604
- // is wrong, we will fail later.
1605
- output , _ , err := git .Run (ctx , git .root , "rev-parse" , git .ref )
1606
- if err != nil {
1607
- return false , "" , err
1608
- }
1609
- result := strings .Trim (output , "\n " )
1610
- if result == git .ref {
1611
- remoteHash = git .ref
1612
- }
1613
- }
1614
-
1615
1549
// Find out what we currently have synced, if anything.
1616
1550
var currentWorktree worktree
1617
1551
if wt , err := git .currentWorktree (); err != nil {
@@ -1622,6 +1556,22 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
1622
1556
currentHash := currentWorktree .Hash ()
1623
1557
git .log .V (3 ).Info ("current state" , "hash" , currentHash , "worktree" , currentWorktree )
1624
1558
1559
+ // This should be very fast if we already have the hash we need. Parameters
1560
+ // like depth are set at fetch time.
1561
+ if err := git .fetch (ctx , git .ref ); err != nil {
1562
+ return false , "" , err
1563
+ }
1564
+
1565
+ // Figure out what we got. The ^{} syntax "peels" annotated tags to
1566
+ // their underlying commit hashes, but has no effect if we fetched a
1567
+ // branch, plain tag, or hash.
1568
+ remoteHash := ""
1569
+ if output , _ , err := git .Run (ctx , git .root , "rev-parse" , "FETCH_HEAD^{}" ); err != nil {
1570
+ return false , "" , err
1571
+ } else {
1572
+ remoteHash = strings .Trim (output , "\n " )
1573
+ }
1574
+
1625
1575
if currentHash == remoteHash {
1626
1576
// We seem to have the right hash already. Let's be sure it's good.
1627
1577
git .log .V (3 ).Info ("current hash is same as remote" , "hash" , currentHash )
@@ -1643,17 +1593,12 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
1643
1593
// are set properly. This is cheap when we already have the target hash.
1644
1594
if changed || git .syncCount == 0 {
1645
1595
git .log .V (0 ).Info ("update required" , "ref" , git .ref , "local" , currentHash , "remote" , remoteHash , "syncCount" , git .syncCount )
1646
-
1647
- // Parameters like depth are set at fetch time.
1648
- if err := git .fetch (ctx , remoteHash ); err != nil {
1649
- return false , "" , err
1650
- }
1651
1596
metricFetchCount .Inc ()
1652
1597
1653
1598
// Reset the repo (note: not the worktree - that happens later) to the new
1654
1599
// ref. This makes subsequent fetches much less expensive. It uses --soft
1655
1600
// so no files are checked out.
1656
- if _ , _ , err := git .Run (ctx , git .root , "reset" , "--soft" , "FETCH_HEAD" ); err != nil {
1601
+ if _ , _ , err := git .Run (ctx , git .root , "reset" , "--soft" , remoteHash ); err != nil {
1657
1602
return false , "" , err
1658
1603
}
1659
1604
@@ -1715,7 +1660,7 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
1715
1660
1716
1661
// fetch retrieves the specified ref from the upstream repo.
1717
1662
func (git * repoSync ) fetch (ctx context.Context , ref string ) error {
1718
- git .log .V (1 ).Info ("fetching" , "ref" , ref , "repo" , git .repo )
1663
+ git .log .V (2 ).Info ("fetching" , "ref" , ref , "repo" , git .repo )
1719
1664
1720
1665
// Fetch the ref and do some cleanup, setting or un-setting the repo's
1721
1666
// shallow flag as appropriate.
0 commit comments