pacman: seed the installed (local) db so pacman -Syu upgrades the base

The image rootfs is a squashfs, not a pacman install, so /var/lib/pacman
(-> /storage/.pacman/db) ships empty: on every device `pacman -Q` returns 0
and `pacman -Qu` finds nothing, so archr-update / `pacman -Syu` reports "No
updates available" even when the repo carries newer base packages. The
headline 2.0 update path therefore only ever installed user addons, never
upgraded the base system (confirmed live: local/ holds only ALPM_DB_VERSION).

Fix in two self-contained parts (no image-build wiring, so the seed always
matches the build that produced it):

- gen-pacman-repo: after building the sync db, register every just-built
  package as installed (`pacman -U --dbonly`, files already in the squashfs)
  and publish the resulting local/ tree as <repo>-localdb.tar.gz alongside
  the packages.
- autostart/004-seed-pacmandb: on first boot, if the local db is still empty
  (only ALPM_DB_VERSION) and the network is up, pull <repo>-localdb.tar.gz
  from the configured release channel and extract it into
  /storage/.pacman/db. Idempotent and skipped once the db is populated, so a
  user's own pacman activity is never clobbered.

PENDING VALIDATION: needs a full build + repo publish to confirm the seed is
produced and that `pacman -Syu` then sees base upgrades. Best-effort on the
generator side (logs a warning rather than failing the repo build).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Douglas Teles
2026-06-25 22:04:29 -03:00
parent 6a5781e4a4
commit 3d18661bf8
2 changed files with 69 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2026 ArchR (https://github.com/archr-linux/Arch-R)
#
# Seed the pacman *installed* (local) db on first boot so archr-update /
# `pacman -Syu` can upgrade the BASE system, not just user-installed addons.
#
# The image rootfs is a squashfs, not a pacman install, so /var/lib/pacman
# (-> /storage/.pacman/db) starts empty: `pacman -Q` returns nothing and
# `pacman -Qu` finds no upgrades even when the repo carries newer base
# packages. scripts/repo/gen-pacman-repo publishes a matching seed
# (<repo>-localdb.tar.gz) alongside the packages for every build, so we pull
# it from the same release channel and extract it once. Only seed when the
# local db is still empty, so a user who has installed/removed packages with
# pacman is never clobbered.
. /etc/profile.d/001-functions 2>/dev/null
DB=/storage/.pacman/db
REPO_NAME=archr-core
BRANCH="$(get_setting updates.branch 2>/dev/null)"
BRANCH="${BRANCH:-stable}"
SEED_URL="https://github.com/archr-linux/archr-repo/releases/download/repo-${BRANCH}/${REPO_NAME}-localdb.tar.gz"
LOG=/var/log/pacman-seed.log
mkdir -p "${DB}"
# Already seeded? Anything beyond ALPM_DB_VERSION means the local db is
# populated (by this hook earlier, or by the user's own pacman activity).
if [ -d "${DB}/local" ] &&
[ "$(ls -1 "${DB}/local" 2>/dev/null | grep -vc '^ALPM_DB_VERSION$')" -gt 0 ]; then
exit 0
fi
# Needs network; if it is not up yet we silently retry on the next boot.
ping -c 1 -W 3 8.8.8.8 >/dev/null 2>&1 || exit 0
tmp=/tmp/archr-localdb.tar.gz
if curl -fsSL "${SEED_URL}" -o "${tmp}" 2>>"${LOG}" ||
wget -q -O "${tmp}" "${SEED_URL}" 2>>"${LOG}"; then
if tar -C "${DB}" -xzf "${tmp}" 2>>"${LOG}"; then
echo "$(date): seeded pacman local db from ${SEED_URL}" >>"${LOG}"
fi
rm -f "${tmp}"
fi
+24
View File
@@ -167,6 +167,30 @@ fi
ln -sf "${REPO_NAME}.db.tar.gz" "${REPO_NAME}.db" && \
ln -sf "${REPO_NAME}.files.tar.gz" "${REPO_NAME}.files" )
# Seed an installed (local) db. Without it the shipped image's
# /var/lib/pacman/local is empty: `pacman -Q` returns nothing and
# `pacman -Syu` (archr-update) can only install user addons, never upgrade
# the base. We register every just-built package as installed (db entry
# only; the files already live in the image squashfs) into a staging dbpath
# and tar the resulting local/ tree. It is published as a repo asset and
# pulled in on first boot by the 004-seed-pacmandb autostart hook (so no
# image-build wiring is needed; the seed always matches this build).
echo "gen-pacman-repo: seeding installed (local) db..."
seed_dbpath="${OUT_DIR}/.seed-dbpath"
rm -rf "${seed_dbpath}" "${OUT_DIR}/.seed-root"
mkdir -p "${seed_dbpath}/local" "${seed_dbpath}/sync"
cp "${local_db}" "${seed_dbpath}/sync/${REPO_NAME}.db"
if fakeroot pacman -U --dbonly --noconfirm \
--root "${OUT_DIR}/.seed-root" --dbpath "${seed_dbpath}" \
--cachedir "${OUT_DIR}" \
"${OUT_DIR}"/*.pkg.tar.zst >/dev/null 2>&1; then
tar -C "${seed_dbpath}" -czf "${OUT_DIR}/${REPO_NAME}-localdb.tar.gz" local
echo " wrote ${REPO_NAME}-localdb.tar.gz ($(ls -1 "${seed_dbpath}/local" | wc -l) entries)"
else
echo " WARNING: local-db seed failed; base will not be pacman-upgradable" >&2
fi
rm -rf "${seed_dbpath}" "${OUT_DIR}/.seed-root"
echo ""
echo "gen-pacman-repo: ready at ${OUT_DIR}"
ls -1sh "${OUT_DIR}" | head -20