diff mbox series

[bug#64708,3/8] gnu: commencement: Add git-fetch-from-tarball utility.

Message ID 161bab138845fe307ec92b8fea181e00ece86e58.1689685375.git.janneke@gnu.org
State New
Headers show
Series Fix cross build and native build for the Hurd. | expand

Commit Message

Janneke Nieuwenhuizen July 18, 2023, 1:14 p.m. UTC
From: Ludovic Courtès <ludo@gnu.org>

* gnu/packages/commencement.scm (git-fetch-from-tarball): New procedure.
---
 gnu/packages/commencement.scm | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

Comments

Ludovic Courtès July 18, 2023, 9:13 p.m. UTC | #1
Janneke Nieuwenhuizen <janneke@gnu.org> skribis:

> From: Ludovic Courtès <ludo@gnu.org>
>
> * gnu/packages/commencement.scm (git-fetch-from-tarball): New procedure.

I guess this one is very weird so it deserves an explanation.

The problems we’re trying to solve are:

  1. We cannot use ‘git-fetch’ at this point because that’d introduce a
     circular dependency: <https://issues.guix.gnu.org/63331>.

  2. Downloading a cgit-generated tarball is unsafe: the tarball might
     be modified when cgit is updated or whatever, leading to a hash
     mismatch that we wouldn’t be able to resolve (well,
     disarchive.guix.gnu.org might be able to add an entry for that
     tarball, but then there’s currently no fallback in case of hash
     mismatch: <https://issues.guix.gnu.org/28659>).

So we need to obtain our Git checkouts by some other mean.  There are
further complications:

  3. We could use (web client), but without (gnutls) since it’s
     unavailable at this stage.

  4. We cannot use (guix swh) as is because Guile-JSON doesn’t build
     with Guile 2.0, which is what we have here.

The trick below is the only way I could think of to reconcile these
issues: it essentially stacks two fixed-output derivation.  The first
one downloads that auto-generated tarball (bad!), and the second one
extracts the contents of that tarball using ‘tar’ from
‘%bootstrap-coreutils&co’.  The output of the second one is identical to
what ‘git-fetch’ would give us (or ‘swh-download’).

That makes it more robust.  It also allows ‘guix lint -c archival’ to do
its work and similarly (well, almost) for ‘build-package-metadata.scm’,
the program that builds <https://guix.gnu.org/sources.json>, which SWH
periodically ingests.

Pfeww, long story.

> +(define* (git-fetch-from-tarball tarball)

Maybe add this docstring:

    "Return an <origin> method equivalent to 'git-fetch', except that it
  fetches the checkout from TARBALL, a tarball containing said
  checkout.

  The purpose of this procedure is to work around bootstrapping issues:
  'git-fetch' depends on Git, which is much higher in the dependency
  graph."

> +             (setenv "PATH"
> +                     #+(file-append %bootstrap-coreutils&co "/bin"))
> +             (invoke (string-append #+tar "/bin/tar")
> +                     "xf" #$tarball)

This should be: (invoke "tar" "xf" #$tarball).
Otherwise we’d get a cyclic dependency with ‘tar’.

(I didn’t notice because there’s a bug where ‘-s’ is ignored here:

  ./pre-inst-env guix build -e '(@@ (gnu packages commencement) mig-boot0)' \
    -s i586-gnu -Sd

)

OK with these changes!

Ludo’.
Josselin Poiret July 19, 2023, 9:11 a.m. UTC | #2
Hi Ludo and Janneke.

Ludovic Courtès <ludo@gnu.org> writes:

> The trick below is the only way I could think of to reconcile these
> issues: it essentially stacks two fixed-output derivation.  The first
> one downloads that auto-generated tarball (bad!), and the second one
> extracts the contents of that tarball using ‘tar’ from
> ‘%bootstrap-coreutils&co’.  The output of the second one is identical to
> what ‘git-fetch’ would give us (or ‘swh-download’).
>
> That makes it more robust.  It also allows ‘guix lint -c archival’ to do
> its work and similarly (well, almost) for ‘build-package-metadata.scm’,
> the program that builds <https://guix.gnu.org/sources.json>, which SWH
> periodically ingests.

I don't 100% understand what this resolves though, since this still
depends on the unstable tarball in the end!  In both cases, we'd rely on
CI to have the stable copy, or SWH providing it, since we wouldn't be
able to rebuild it.

Best,
diff mbox series

Patch

diff --git a/gnu/packages/commencement.scm b/gnu/packages/commencement.scm
index d0603e62c8..1d69c2a80f 100644
--- a/gnu/packages/commencement.scm
+++ b/gnu/packages/commencement.scm
@@ -57,7 +57,10 @@  (define-module (gnu packages commencement)
   #:use-module (gnu packages xml)
   #:use-module (guix gexp)
   #:use-module (guix packages)
+  #:use-module ((guix store) #:select (%store-monad))
+  #:use-module (guix monads)
   #:use-module (guix download)
+  #:use-module ((guix git-download) #:select (git-reference git-file-name))
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system trivial)
   #:use-module ((guix licenses) #:prefix license:)
@@ -90,6 +93,34 @@  (define-module (gnu packages commencement)
 ;;;
 ;;; Code:
 
+(define* (git-fetch-from-tarball tarball)
+  (lambda* (url hash-algo hash
+                #:optional name
+                #:key (system (%current-system))
+                (guile %bootstrap-guile))
+    (mlet %store-monad ((guile (package->derivation guile system)))
+      (gexp->derivation
+       (or name "git-checkout")
+       (with-imported-modules '((guix build utils))
+         #~(begin
+             (use-modules (guix build utils)
+                          (ice-9 ftw)
+                          (ice-9 match))
+             (setenv "PATH"
+                     #+(file-append %bootstrap-coreutils&co "/bin"))
+             (invoke (string-append #+tar "/bin/tar")
+                     "xf" #$tarball)
+             (match (scandir ".")
+               (("." ".." directory)
+                (copy-recursively directory #$output)))))
+       #:recursive? #t
+       #:hash-algo hash-algo
+       #:hash hash
+       #:system system
+       #:guile-for-build guile
+       #:graft? #f
+       #:local-build? #t))))
+
 (define bootar
   (package
     (name "bootar")