fix(guix): split local self-source into base and final snapshots

This commit is contained in:
vxtls 2026-04-15 08:33:34 -04:00
parent 77eb912998
commit bc9e3d1301
3 changed files with 83 additions and 135 deletions

View file

@ -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 <https://issues.guix.gnu.org/74204>.

View file

@ -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

View file

@ -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'
)
}