make aroot builds a SchFS root from Alpine's minirootfs, the packages ports/alpine/world lists, and SchOS itself as the signed apk package schos-base, in its own repository inside the root. apk add installs from Alpine; apk upgrade updates both. Booted: zsh is Alpine's, apk update sees 28669 packages, apk add htop works, and so does xorg-server. world.lock pins every package with its sha256; a build fetches only what dist/alpine/ lacks and never looks for newer versions. make alpine-lock is the one step that does. Alpine's zsh, busybox commands and hwdata replace SchOS's copies; SchOS keeps its own tools, toybox's other commands, and static mksh, which schinit's recovery shell now tries first. Also: the dependency-file include matched Alpine's usr/lib/sysctl.d, a directory, and stopped every make. See docs/plan/alpine.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
62 lines
2.6 KiB
Shell
62 lines
2.6 KiB
Shell
#!/bin/sh
|
|
# Resolve ports/alpine/world into world.lock.
|
|
#
|
|
# tools/posix/alpine-lock.sh APK_STATIC MINIROOTFS WORLD LOCK DISTDIR
|
|
#
|
|
# Asks Alpine's mirror, so it needs the network; nothing else in the build
|
|
# does. Every package in the dependency closure is fetched into DISTDIR and
|
|
# recorded as
|
|
#
|
|
# <file> <sha256> <repository>
|
|
#
|
|
# which is all a build needs to download it again and know it got the same
|
|
# bytes. apk checks Alpine's signature on top of that when it installs.
|
|
|
|
set -eu
|
|
[ $# -eq 5 ] || { echo "usage: $0 APK_STATIC MINIROOTFS WORLD LOCK DISTDIR" >&2; exit 2; }
|
|
abs() { case "$1" in /*) echo "$1" ;; *) echo "$(pwd)/$1" ;; esac; }
|
|
APK=$(abs "$1"); MINI=$(abs "$2"); WORLD=$(abs "$3"); LOCK=$(abs "$4"); DIST=$(abs "$5")
|
|
|
|
T=$(mktemp -d)
|
|
trap 'rm -rf "$T"' EXIT
|
|
mkdir -p "$T/root" "$DIST"
|
|
tar -xzf "$MINI" -C "$T/root"
|
|
# apk.static looks for CA certificates on the host, where a NixOS or a macOS
|
|
# keeps them somewhere else; Alpine's own bundle is right here.
|
|
export SSL_CERT_FILE="$T/root/etc/ssl/certs/ca-certificates.crt"
|
|
|
|
PKGS=$(sed 's/#.*//' "$WORLD" | tr -s ' \t' '\n' | grep . || true)
|
|
[ -n "$PKGS" ] || { echo "alpine-lock: $WORLD lists nothing" >&2; exit 1; }
|
|
|
|
"$APK" --root "$T/root" --no-cache update -q
|
|
# shellcheck disable=SC2086
|
|
"$APK" --root "$T/root" --no-cache fetch --recursive --output "$DIST" $PKGS
|
|
|
|
# Which repository each one came from, read from the indexes apk just used.
|
|
MIRROR=$(grep -m1 '^http' "$T/root/etc/apk/repositories" | sed 's|/[^/]*$||')
|
|
for r in main community; do
|
|
curl -fsSL "$MIRROR/$r/x86_64/APKINDEX.tar.gz" | tar -xzO APKINDEX |
|
|
awk -v r="$r" '/^P:/{p=substr($0,3)} /^V:/{print p "-" substr($0,3) ".apk", r}'
|
|
done > "$T/where"
|
|
|
|
# The closure, as apk resolved it: install it into the scratch root and read
|
|
# back what is there.
|
|
# shellcheck disable=SC2086
|
|
"$APK" --root "$T/root" --no-cache --no-scripts --no-chown add -q $PKGS
|
|
"$APK" --root "$T/root" info -v 2>/dev/null | sort > "$T/closure"
|
|
|
|
{
|
|
echo "# Generated by tools/posix/alpine-lock.sh from world. Do not edit;"
|
|
echo "# change world and run \`make alpine-lock\`."
|
|
echo "# file sha256 repository"
|
|
while read -r nv; do
|
|
f=$nv.apk
|
|
[ -f "$DIST/$f" ] || continue # in the minirootfs, not needed by world
|
|
repo=$(awk -v f="$f" '$1 == f { print $2; exit }' "$T/where")
|
|
[ -n "$repo" ] || { echo "alpine-lock: $f is in no repository" >&2; exit 1; }
|
|
sum=$(sha256sum "$DIST/$f" | cut -d' ' -f1)
|
|
echo "$f $sum $repo"
|
|
done < "$T/closure"
|
|
} > "$LOCK.new"
|
|
mv "$LOCK.new" "$LOCK"
|
|
echo "alpine-lock: $(grep -vc '^#' "$LOCK") packages in $LOCK"
|