Subject: bug#45187: [PATCH] git: Update cached checkout to the remote HEAD by default.

From: Kyle Meyer <[email-masked]>
Date: Fri, 09 Apr 2021 01:10:22 -0400

Ricardo Wurmus writes:

> I’m a bit lost: is there something we need to decide on to move this
> forward?

I guess the main open question is whether to rework things to use
revparse-single as Marius suggested.

And if we don't, another question (raised by me) is whether there's a
better approach than adding the additional symref key/field.  As I said
upthread, "without the introduction of something like `symref', I'm not
spotting a straightforward way to deal with refs/remotes/origin/HEAD in
resolve-reference".

> (The issue has become a bit more pressing as origin/main is the new
> default on Github since a while.)

Right, thanks for bumping this.  Here's my attempt to put together a
complete patch.  I've tested this with

  $ guix import cran -r -a git https://github.com/immunogenomics/scpost

as well as a few `guix build --with-(branch|commit)=...' invocations.

Running `make check', I don't see any new failures, though I see the
same two failures ("channel-news, one entry" and
"tests/guix-git-authenticate.sh") on master and with this patch.  I
haven't yet looked more closely at those.

-- >8 --
Subject: [PATCH] git: Update cached checkout to the remote HEAD by default.

Fixes <https://bugs.gnu.org/45187>.
Reported by Ricardo Wurmus <[email-masked]>.

update-cached-checkout hard codes "master" as the default branch, leading to a
failure when the clone doesn't have a "master" branch.  Instead use the remote
HEAD symref as an indicator of what the primary branch is.

* guix/git.scm (resolve-reference): Support resolving symrefs.
(update-cached-checkout, latest-repository-commit): Default to the remote HEAD
symref.
(<git-checkout>): Add symref field that defaults to "HEAD", and change branch
field's default to #f.
(git-checkout-compiler): Handle symref field of <git-checkout>.
---
 guix/git.scm | 35 ++++++++++++++++++++++++-----------
 1 file changed, 24 insertions(+), 11 deletions(-)

diff --git a/guix/git.scm b/guix/git.scm
index 1820036f25..6b410ed42f 100644
--- a/guix/git.scm
+++ b/guix/git.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2017, 2020 Mathieu Othacehe <[email-masked]>
 ;;; Copyright © 2018, 2019, 2020, 2021 Ludovic Courtès <[email-masked]>
+;;; Copyright © 2021 Kyle Meyer <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -209,6 +210,9 @@ (define (resolve-reference repository ref)
        (let ((oid (reference-target
                    (branch-lookup repository branch BRANCH-REMOTE))))
          (object-lookup repository oid)))
+      (('symref . symref)
+       (let ((oid (reference-name->oid repository symref)))
+         (object-lookup repository oid)))
       (('commit . commit)
        (let ((len (string-length commit)))
          ;; 'object-lookup-prefix' appeared in Guile-Git in Mar. 2018, so we
@@ -340,7 +344,7 @@ (define (delete-checkout directory)
 
 (define* (update-cached-checkout url
                                  #:key
-                                 (ref '(branch . "master"))
+                                 (ref '(symref . "HEAD"))
                                  recursive?
                                  (check-out? #t)
                                  starting-commit
@@ -354,8 +358,9 @@ (define* (update-cached-checkout url
 to REF, and the relation of the new commit relative to STARTING-COMMIT (if
 provided) as returned by 'commit-relation'.
 
-REF is pair whose key is [branch | commit | tag | tag-or-commit ] and value
-the associated data: [<branch name> | <sha1> | <tag name> | <string>].
+REF is pair whose key is [branch | commit | tag | tag-or-commit | symref] and
+value the associated data:
+[<branch name> | <sha1> | <tag name> | <string> | <symref>].
 
 When RECURSIVE? is true, check out submodules as well, if any.
 
@@ -378,6 +383,10 @@ (define* (update-cached-checkout url
        `(branch . ,(if (string-prefix? "origin/" branch)
                        branch
                        (string-append "origin/" branch))))
+      (('symref . symref)
+       `(symref . ,(if (string-prefix? "refs/remotes/origin/" symref)
+                       symref
+                       (string-append "refs/remotes/origin/" symref))))
       (_ ref)))
 
   (with-libgit2
@@ -433,12 +442,12 @@ (define* (latest-repository-commit store url
                                    (log-port (%make-void-port "w"))
                                    (cache-directory
                                     (%repository-cache-directory))
-                                   (ref '(branch . "master")))
+                                   (ref '(symref . "HEAD")))
   "Return two values: the content of the git repository at URL copied into a
 store directory and the sha1 of the top level commit in this directory.  The
 reference to be checkout, once the repository is fetched, is specified by REF.
-REF is pair whose key is [branch | commit | tag] and value the associated
-data, respectively [<branch name> | <sha1> | <tag name>].
+REF is pair whose key is [branch | commit | tag | symref] and value the
+associated data, respectively [<branch name> | <sha1> | <tag name> | <symref>].
 
 When RECURSIVE? is true, check out submodules as well, if any.
 
@@ -548,7 +557,8 @@ (define-record-type* <git-checkout>
   git-checkout make-git-checkout
   git-checkout?
   (url     git-checkout-url)
-  (branch  git-checkout-branch (default "master"))
+  (branch  git-checkout-branch (default #f))
+  (symref  git-checkout-symref (default "HEAD"))
   (commit  git-checkout-commit (default #f))      ;#f | tag | commit
   (recursive? git-checkout-recursive? (default #f)))
 
@@ -585,11 +595,14 @@ (define-gexp-compiler (git-checkout-compiler (checkout <git-checkout>)
   ;; "Compile" CHECKOUT by updating the local checkout and adding it to the
   ;; store.
   (match checkout
-    (($ <git-checkout> url branch commit recursive?)
+    (($ <git-checkout> url branch symref commit recursive?)
      (latest-repository-commit* url
-                                #:ref (if commit
-                                          `(tag-or-commit . ,commit)
-                                          `(branch . ,branch))
+                                #:ref (cond (commit
+                                             `(tag-or-commit . ,commit))
+                                            (branch
+                                             `(branch . ,branch))
+                                            (else
+                                             `(symref . ,symref)))
                                 #:recursive? recursive?
                                 #:log-port (current-error-port)))))

base-commit: 43c55856c876c76200cdccc1211868b92352c4ae
-- 
2.31.1