@@ -836,10 +836,7 @@ func main() {
836836 os .Exit (exitCode )
837837 }
838838
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 {
843840 log .V (0 ).Info ("ref appears to be a git hash, no further sync needed" , "ref" , git .ref )
844841 log .DeleteErrorFile ()
845842 sleepForever ()
@@ -1493,49 +1490,6 @@ func (m multiError) Error() string {
14931490 return strings .Join (strs , "; " )
14941491}
14951492
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-
15391493// worktree represents a git worktree (which may or may not exist on disk).
15401494type worktree absPath
15411495
@@ -1592,26 +1546,6 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
15921546 return false , "" , err
15931547 }
15941548
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-
16151549 // Find out what we currently have synced, if anything.
16161550 var currentWorktree worktree
16171551 if wt , err := git .currentWorktree (); err != nil {
@@ -1622,6 +1556,22 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
16221556 currentHash := currentWorktree .Hash ()
16231557 git .log .V (3 ).Info ("current state" , "hash" , currentHash , "worktree" , currentWorktree )
16241558
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+
16251575 if currentHash == remoteHash {
16261576 // We seem to have the right hash already. Let's be sure it's good.
16271577 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
16431593 // are set properly. This is cheap when we already have the target hash.
16441594 if changed || git .syncCount == 0 {
16451595 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- }
16511596 metricFetchCount .Inc ()
16521597
16531598 // Reset the repo (note: not the worktree - that happens later) to the new
16541599 // ref. This makes subsequent fetches much less expensive. It uses --soft
16551600 // 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 {
16571602 return false , "" , err
16581603 }
16591604
@@ -1715,7 +1660,7 @@ func (git *repoSync) SyncRepo(ctx context.Context, refreshCreds func(context.Con
17151660
17161661// fetch retrieves the specified ref from the upstream repo.
17171662func (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 )
17191664
17201665 // Fetch the ref and do some cleanup, setting or un-setting the repo's
17211666 // shallow flag as appropriate.
0 commit comments