From bc9e3d13010d866a8d78e73dd3c8d697bfc1e85b Mon Sep 17 00:00:00 2001 From: vxtls <187420201+vxtls@users.noreply.github.com> Date: Wed, 15 Apr 2026 08:33:34 -0400 Subject: [PATCH] fix(guix): split local self-source into base and final snapshots --- .../inject-local-bootstrap-source-patch.patch | 135 ------------------ .../patches/use-local-self-source.patch.in | 17 +++ steps-guix/improve/guix-daemon-and-pull.sh | 66 +++++++++ 3 files changed, 83 insertions(+), 135 deletions(-) delete mode 100644 steps-guix/guix-1.5.0/patches/inject-local-bootstrap-source-patch.patch create mode 100644 steps-guix/guix-1.5.0/patches/use-local-self-source.patch.in diff --git a/steps-guix/guix-1.5.0/patches/inject-local-bootstrap-source-patch.patch b/steps-guix/guix-1.5.0/patches/inject-local-bootstrap-source-patch.patch deleted file mode 100644 index 672e6428..00000000 --- a/steps-guix/guix-1.5.0/patches/inject-local-bootstrap-source-patch.patch +++ /dev/null @@ -1,135 +0,0 @@ -diff --git guix-1.5.0/gnu/packages/package-management.scm guix-1.5.0/gnu/packages/package-management.scm -index 21a9217..d1c8a62 100644 ---- guix-1.5.0/gnu/packages/package-management.scm -+++ guix-1.5.0/gnu/packages/package-management.scm -@@ -155,6 +155,7 @@ - #:autoload (guix channels) (channel? - guix-channel? - repository->guix-channel) -+ #:autoload (guix base32) (bytevector->nix-base32-string) - #:use-module ((guix licenses) #:prefix license:) - #:use-module (guix packages) - #:use-module (guix utils) -@@ -177,6 +178,112 @@ - (string-append "http://alpha.gnu.org/gnu/guix/bootstrap/" - arch "-linux" - "/20131110/guile-2.0.9.tar.xz")))) -+ -+(define %local-bootstrap-base-url -+ "http://127.0.0.1:38445") -+ -+(define (origin-base32-string origin) -+ (bytevector->nix-base32-string -+ (content-hash-value (origin-hash origin)))) -+ -+(define (origin-uri-string origin) -+ (match (origin-uri origin) -+ ((head . _) head) -+ (uri uri))) -+ -+(define (local-bootstrap-uri-path origin) -+ (let* ((uri (origin-uri-string origin)) -+ (base-length (string-length %local-bootstrap-base-url))) -+ (if (and (<= base-length (string-length uri)) -+ (string=? %local-bootstrap-base-url -+ (substring uri 0 base-length))) -+ (substring uri base-length) -+ uri))) -+ -+(define %guix-local-bootstrap-source-patch -+ (plain-file -+ "guix-local-bootstrap-source.patch" -+ (format #f "\ -+diff --git a/gnu/packages/bootstrap.scm b/gnu/packages/bootstrap.scm -+--- a/gnu/packages/bootstrap.scm -++++ b/gnu/packages/bootstrap.scm -+@@ -164,15 +164,12 @@ -+ (define %bootstrap-executable-base-urls -+ ;; This is where the bootstrap executables come from. -+- '(\"https://ftpmirror.gnu.org/guix/bootstrap/\" -+- \"https://git.savannah.gnu.org/cgit/guix.git/plain/gnu/packages/bootstrap/\" -+- \"https://alpha.gnu.org/gnu/guix/bootstrap/\" -+- \"http://flashner.co.il/guix/bootstrap/\" -+- \"http://lilypond.org/janneke/guix/\")) -++ '(\"~a/\")) -+ -+ (define (bootstrap-executable-file-name system program) -+ \"Return the FILE-NAME part of url where PROGRAM can be found for SYSTEM.\" -+ (match system -++ (\"i686-linux\" (string-append \"i686-linux/bootstrap-exec-\" program \"-i686-linux\")) -+ (\"powerpc64le-linux\" (string-append system \"/20210106/\" program)) -+ (\"i586-gnu\" (string-append system \"/20200326/\" program)) -+ (\"x86_64-gnu\" (string-append system \"/20241122/\" program)) -+@@ -357,8 +354,9 @@ -+-(define %bootstrap-base-urls -+- ;; This is where the initial binaries come from. -++(define %bootstrap-linux-headers-base-urls -++ ;; Keep linux headers as an explicit exception: text headers can still come -++ ;; from the historical bootstrap mirrors. -+ '(\"https://ftpmirror.gnu.org/guix/bootstrap/\" -+ \"https://ftp.gnu.org/gnu/guix/bootstrap\" -+ \"https://alpha.gnu.org/gnu/guix/bootstrap\" -+@@ -369,6 +367,10 @@ -+ \"http://flashner.co.il/guix/bootstrap\" -+ \"http://lilypond.org/janneke/guix/\")) -+ -++(define %bootstrap-base-urls -++ ;; All bootstrap binaries must come from the local bootstrap mirror. -++ '(\"~a\")) -++ -+ (define (bootstrap-guile-url-path system) -+ \"Return the URI for FILE.\" -+ (string-append \"/\" system -+@@ -387,6 +389,10 @@ -+ \"/20210106/guile-static-stripped-2.0.14-powerpc64le-linux-gnu.tar.xz\") -+ (\"riscv64-linux\" -+ \"/20210725/guile-3.0.2.tar.xz\") -++ (\"x86_64-linux\" -++ \"~a\") -++ (\"i686-linux\" -++ \"~a\") -+ (_ -+ \"/20131110/guile-2.0.9.tar.xz\")))) -+ -+@@ -395,9 +401,9 @@ -+ (match system -+ (\"x86_64-linux\" -+- (base32 \"1w2p5zyrglzzniqgvyn1b55vprfzhgk8vzbzkkbdgl5248si0yq3\")) -++ (base32 \"~a\")) -+ (\"i686-linux\" -+- (base32 \"0im800m30abgh7msh331pcbjvb4n02smz5cfzf1srv0kpx3csmxp\")) -++ (base32 \"~a\")) -+ (\"mips64el-linux\" -+ (base32 \"0fzp93lvi0hn54acc0fpvhc7bvl0yc853k62l958cihk03q80ilr\")) -+ (\"armhf-linux\" -+@@ -684,7 +690,7 @@ -+ (uri (map (cute string-append <> -+ \"/i686-linux/20190815/\" -+ \"linux-libre-headers-stripped-4.14.67-i686-linux.tar.xz\") -+- %bootstrap-base-urls)) -++ %bootstrap-linux-headers-base-urls)) -+ (sha256 -+ (base32 -+ \"0sm2z9x4wk45bh6qfs94p0w1d6hsy6dqx9sw38qsqbvxwa1qzk8s\")))) -+" -+ %local-bootstrap-base-url -+ %local-bootstrap-base-url -+ (local-bootstrap-uri-path -+ (bootstrap-guile-origin "x86_64-linux")) -+ (local-bootstrap-uri-path -+ (bootstrap-guile-origin "i686-linux")) -+ (origin-base32-string (bootstrap-guile-origin "x86_64-linux")) -+ (origin-base32-string (bootstrap-guile-origin "i686-linux"))))) - - ;; NOTE: The commit IDs used here form a linked list threaded through the git - ;; history. In a phenomenon known as boot-stripping, not only the head of this -@@ -214,7 +282,8 @@ - (sha256 - (base32 - "0z1ixlkzsaj978nh57179871xkzbf8zsf10xkcfs2647iznkx7az")) -- (file-name (string-append "guix-" version "-checkout")))) -+ (file-name (string-append "guix-" version "-checkout")) -+ (patches (list %guix-local-bootstrap-source-patch)))) - (build-system gnu-build-system) - (arguments - `(;; For reproducibility, see . diff --git a/steps-guix/guix-1.5.0/patches/use-local-self-source.patch.in b/steps-guix/guix-1.5.0/patches/use-local-self-source.patch.in new file mode 100644 index 00000000..39bc725b --- /dev/null +++ b/steps-guix/guix-1.5.0/patches/use-local-self-source.patch.in @@ -0,0 +1,17 @@ +--- a/gnu/packages/package-management.scm ++++ b/gnu/packages/package-management.scm +@@ -211,11 +211,11 @@ + (source (origin + (method git-fetch) + (uri (git-reference +- (url "https://git.guix.gnu.org/guix.git") +- (commit commit))) ++ (url "@LOCAL_GUIX_CHECKOUT_URL@") ++ (commit "@LOCAL_GUIX_CHECKOUT_COMMIT@"))) + (sha256 + (base32 +- "0z1ixlkzsaj978nh57179871xkzbf8zsf10xkcfs2647iznkx7az")) ++ "@LOCAL_GUIX_CHECKOUT_HASH@")) + (file-name (string-append "guix-" version "-checkout")))) + (build-system gnu-build-system) + (arguments diff --git a/steps-guix/improve/guix-daemon-and-pull.sh b/steps-guix/improve/guix-daemon-and-pull.sh index d6b56933..61b56b8f 100644 --- a/steps-guix/improve/guix-daemon-and-pull.sh +++ b/steps-guix/improve/guix-daemon-and-pull.sh @@ -34,6 +34,41 @@ export GNUTLS_GUILE_EXTENSION_DIR="${guile_ext_path}" trap stop_distfiles_http_server EXIT INT TERM HUP +hash_git_checkout_as_guix() { + repo="$1" + commit="$2" + tmp_checkout="$(mktemp -d /tmp/guix-source-hash.XXXXXX)" + hash="" + + if ! git -C "${tmp_checkout}" init --initial-branch=main >/dev/null 2>&1; then + rm -rf "${tmp_checkout}" + return 1 + fi + if ! git -C "${tmp_checkout}" remote add origin "${repo}"; then + rm -rf "${tmp_checkout}" + return 1 + fi + if ! git -C "${tmp_checkout}" fetch --depth 1 -- origin "${commit}" >/dev/null 2>&1; then + if ! git -C "${tmp_checkout}" fetch -- origin "${commit}" >/dev/null 2>&1; then + rm -rf "${tmp_checkout}" + return 1 + fi + fi + if ! git -C "${tmp_checkout}" checkout --quiet FETCH_HEAD; then + rm -rf "${tmp_checkout}" + return 1 + fi + + rm -rf "${tmp_checkout}/.git" + if ! hash="$(/usr/bin/guix-hash-compat -r "${tmp_checkout}")"; then + rm -rf "${tmp_checkout}" + return 1 + fi + + rm -rf "${tmp_checkout}" + printf '%s\n' "${hash}" +} + have_group() { if command -v getent >/dev/null 2>&1; then getent group "$1" >/dev/null 2>&1 @@ -70,8 +105,13 @@ verify_terminal_devices() { prepare_local_channel_checkout() { rendered_patch="/tmp/guix-bootstrap-local-seeds.patch" rendered_mes_patch="/tmp/guix-bootstrap-local-mes-extra.patch" + self_source_patch_template="${guix_patch_dir}/use-local-self-source.patch.in" + rendered_self_source_patch="/tmp/guix-use-local-self-source.patch" static_patch="" channel_patch_link="" + base_commit="" + base_hash="" + channel_url="" if [ ! -x "${guix_seed_helper}" ]; then echo "Missing Guix seed helper: ${guix_seed_helper}" >&2 @@ -81,6 +121,10 @@ prepare_local_channel_checkout() { echo "Missing Guix patch directory: ${guix_patch_dir}" >&2 exit 1 fi + if [ ! -f "${self_source_patch_template}" ]; then + echo "Missing Guix self-source patch template: ${self_source_patch_template}" >&2 + exit 1 + fi "${guix_seed_helper}" if [ ! -f /tmp/guix-bootstrap-seeds.env ]; then @@ -142,6 +186,28 @@ prepare_local_channel_checkout() { doc/images/shepherd-graph.png git init -q git add -A + # Commit the bootstrap-patched tree first, then hash that exact checkout + # as Guix would fetch it. The follow-up self-source patch points the + # final channel snapshot back to this base commit to avoid a hash cycle. + git -c user.name='guix-local' -c user.email='guix-local@example.invalid' commit -q -m 'local guix channel base snapshot' + + base_commit="$(git rev-parse HEAD)" + channel_url="file://${channel_repo}" + base_hash="$(hash_git_checkout_as_guix "${channel_repo}" "${base_commit}")" + + sed \ + -e "s|@LOCAL_GUIX_CHECKOUT_URL@|${channel_url}|g" \ + -e "s|@LOCAL_GUIX_CHECKOUT_COMMIT@|${base_commit}|g" \ + -e "s|@LOCAL_GUIX_CHECKOUT_HASH@|${base_hash}|g" \ + "${self_source_patch_template}" > "${rendered_self_source_patch}" + + if grep -Eq '@[A-Z0-9_]+@' "${rendered_self_source_patch}"; then + echo "Unexpanded placeholder found while rendering Guix self-source patch." >&2 + exit 1 + fi + + patch -p1 < "${rendered_self_source_patch}" + git add -A git -c user.name='guix-local' -c user.email='guix-local@example.invalid' commit -q -m 'local guix channel snapshot' ) }