feat(iso): build end-4 deps in-image, ship end4-pC as default shell
Tests / tests (push) Successful in 2m35s
Tests / tests (push) Successful in 2m35s
- customize_airootfs.sh stages dots-hyprland at /opt, runs ./setup install-deps as a throwaway builder, harvests the built packages into /opt/localrepo so pacstrap resolves them offline - image ships its own [local-aur] (file:///opt/localrepo); CI and localrepo/update.sh keep that copy in sync; .gitignore covers work/, out/ and airootfs/opt/localrepo/ - alvin-install runs ./setup install --skip-alldeps on the target - clone pctrade/end4-pC into /etc/skel/.config/quickshell, patch qsConfig ii -> end4-pC in the staged variables.lua (guarded + idempotent), and restore the fork after setup rsync --delete's ~/.config/quickshell - ship user presets in skel, point fish `q` alias at end4-pC - AGENTS.md: document the fourth package source and new gotchas
This commit is contained in:
@@ -28,6 +28,7 @@ log() { echo "[$(date '+%H:%M:%S')] $*" >> "$LOG"; }
|
||||
|
||||
cleanup() {
|
||||
set +e
|
||||
rm -f "${TARGET}/etc/sudoers.d/99-end4-install" 2>/dev/null
|
||||
umount -R "$TARGET" 2>/dev/null
|
||||
cryptsetup close cryptroot 2>/dev/null
|
||||
true
|
||||
@@ -443,7 +444,11 @@ Include = /etc/pacman.d/cachyos-mirrorlist
|
||||
REPO
|
||||
fi
|
||||
|
||||
sed -i '/\[local-aur\]/,/Include/d' "${TARGET}/etc/pacman.conf" 2>/dev/null || true
|
||||
# [local-aur] lives only on the live medium (file:///opt/localrepo). The
|
||||
# target's pacman.conf does not normally contain it - pacstrap is run
|
||||
# without -P, so it keeps the stock file shipped by the pacman package -
|
||||
# but drop it anyway in case that ever changes.
|
||||
sed -i '/^\[local-aur\]$/,/^$/d' "${TARGET}/etc/pacman.conf" 2>/dev/null || true
|
||||
|
||||
ok "CachyOS repo configured."
|
||||
}
|
||||
@@ -520,6 +525,183 @@ install_git() {
|
||||
ok "Git configured for ${USERNAME}."
|
||||
}
|
||||
|
||||
install_end4_dots() {
|
||||
if [[ ! -d /opt/dots-hyprland ]]; then
|
||||
warn "No staged dots-hyprland at /opt/dots-hyprland — skipping end-4 dotfiles."
|
||||
return
|
||||
fi
|
||||
|
||||
info "Installing end-4 dotfiles (this may take a while)..."
|
||||
|
||||
local home_in_target="/home/${USERNAME}"
|
||||
local repo_in_target="${home_in_target}/.dots-hyprland"
|
||||
local repo_on_host="${TARGET}${repo_in_target}"
|
||||
local dots_ok=true
|
||||
local setups_done=true
|
||||
|
||||
cp -a /opt/dots-hyprland "$repo_on_host"
|
||||
chown -R "${USERNAME}:${USERNAME}" "$repo_on_host"
|
||||
|
||||
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" > "${TARGET}/etc/sudoers.d/99-end4-install"
|
||||
chmod 440 "${TARGET}/etc/sudoers.d/99-end4-install"
|
||||
|
||||
# Everything appended to $LOG from here belongs to this attempt; used
|
||||
# further down to report which steps end-4 had to skip.
|
||||
local log_mark=0
|
||||
if [[ -f "$LOG" ]]; then
|
||||
log_mark=$(wc -l < "$LOG")
|
||||
fi
|
||||
|
||||
# stdin feeds "i" to end-4's x() [R/e:i] failure prompt, which otherwise
|
||||
# blocks forever on a TTY whose prompt text is redirected to $LOG.
|
||||
# Its systemd lines cannot work from inside this chroot: the medium's /run
|
||||
# is bind-mounted in, so `systemctl --machine=…@.host --user enable … --now`
|
||||
# has no target session (and --now would start services on the live medium
|
||||
# anyway) - they fail on every install. "i" lets the run carry on with the
|
||||
# venv, groups and config sync instead of aborting at the first such line;
|
||||
# the usable part of that step is re-applied below and every skip is
|
||||
# reported afterwards.
|
||||
# --skip-alldeps: every dependency was already installed at ISO build time
|
||||
# (customize_airootfs.sh runs ./setup install-deps), so this only copies
|
||||
# configs, sets up services and builds the python venv from the warm cache.
|
||||
if ! arch-chroot "$TARGET" runuser -u "$USERNAME" -- \
|
||||
env HOME="$home_in_target" bash -c \
|
||||
"cd ${repo_in_target} && ./setup install -f -s --skip-alldeps" \
|
||||
< <(yes i) >>"$LOG" 2>&1; then
|
||||
warn "end-4 setup failed, retrying files only (see $LOG)."
|
||||
setups_done=false
|
||||
arch-chroot "$TARGET" runuser -u "$USERNAME" -- \
|
||||
env HOME="$home_in_target" bash -c \
|
||||
"cd ${repo_in_target} && ./setup install -f -s --skip-alldeps --skip-allsetups" \
|
||||
< <(yes i) >>"$LOG" 2>&1 || dots_ok=false
|
||||
fi
|
||||
|
||||
rm -f "${TARGET}/etc/sudoers.d/99-end4-install"
|
||||
|
||||
if ! arch-chroot "$TARGET" id -nG "$USERNAME" | grep -qw input; then
|
||||
arch-chroot "$TARGET" groupadd -f i2c
|
||||
arch-chroot "$TARGET" usermod -aG video,i2c,input "$USERNAME"
|
||||
warn "end-4 group setup was missing and has been applied."
|
||||
fi
|
||||
|
||||
# ── steps end-4 cannot take from inside the chroot ───────────────────────
|
||||
# `enable` alone is a pure file operation and needs no running session, so
|
||||
# redo those here - without --now, since the target is not booted yet.
|
||||
local mods_conf="${TARGET}/etc/modules-load.d/i2c-dev.conf"
|
||||
if [[ ! -f "$mods_conf" ]]; then
|
||||
mkdir -p "$(dirname "$mods_conf")"
|
||||
echo i2c-dev > "$mods_conf"
|
||||
fi
|
||||
|
||||
if [[ -f "${TARGET}/usr/lib/systemd/system/bluetooth.service" ]]; then
|
||||
arch-chroot "$TARGET" systemctl enable bluetooth.service >>"$LOG" 2>&1 \
|
||||
|| warn "Could not enable bluetooth.service (see $LOG)."
|
||||
fi
|
||||
if [[ -f "${TARGET}/usr/lib/systemd/user/ydotool.service" ]]; then
|
||||
arch-chroot "$TARGET" runuser -u "$USERNAME" -- env HOME="$home_in_target" \
|
||||
systemctl --user enable ydotool.service >>"$LOG" 2>&1 \
|
||||
|| warn "Could not enable ydotool.service for ${USERNAME} (see $LOG)."
|
||||
fi
|
||||
|
||||
# Everything end-4 answered "i" to. systemctl/gsettings are the lines known
|
||||
# to be unusable in this chroot; anything else it had to skip is worth
|
||||
# telling the user about.
|
||||
local -a ignored=()
|
||||
if ((log_mark > 0)); then
|
||||
mapfile -t ignored < <(
|
||||
sed -n "$((log_mark + 1)),\$p" "$LOG" | sed $'s/\x1b\\[[0-9;]*m//g' |
|
||||
sed -n 's/^.*Command "\(.*\)" has failed but ignored by user\..*$/\1/p'
|
||||
)
|
||||
fi
|
||||
if ((${#ignored[@]} > 0)); then
|
||||
log "end-4 skipped ${#ignored[@]} step(s): ${ignored[*]}"
|
||||
local step
|
||||
local -a skipped=()
|
||||
for step in "${ignored[@]}"; do
|
||||
case "$step" in
|
||||
*systemctl* | *gsettings*) ;;
|
||||
*) skipped+=("$step") ;;
|
||||
esac
|
||||
done
|
||||
if ((${#skipped[@]} > 0)); then
|
||||
warn "end-4 had to skip: ${skipped[*]} (see $LOG)"
|
||||
fi
|
||||
fi
|
||||
if ! $setups_done; then
|
||||
warn "end-4 setup did not complete — rerun as ${USERNAME}: cd ~/.dots-hyprland && ./setup install-setups"
|
||||
fi
|
||||
|
||||
# end-4's install step rsync --delete's the whole ~/.config/quickshell
|
||||
# directory (sdata/subcmd-install/3.files-legacy.sh), which drops the
|
||||
# end4-pC fork skel put into the user's home - restore it afterwards.
|
||||
local fork_src="/etc/skel/.config/quickshell/end4-pC"
|
||||
local fork_dst="${TARGET}${home_in_target}/.config/quickshell/end4-pC"
|
||||
if [[ -d "$fork_src" ]]; then
|
||||
mkdir -p "$(dirname "$fork_dst")"
|
||||
rm -rf "$fork_dst"
|
||||
cp -a "$fork_src" "$fork_dst"
|
||||
chown -R "${USERNAME}:${USERNAME}" "$fork_dst"
|
||||
fi
|
||||
|
||||
# Same for fish: end-4 syncs ~/.config/fish with rsync --delete, keeping
|
||||
# only what upstream ships (auto-Hypr.fish, config.fish, fish_variables),
|
||||
# which drops skel's extras (fisher/nvm functions, completions,
|
||||
# fish_plugins) and restores its own `alias q 'qs -c ii'`. The default
|
||||
# quickshell config on this ISO is end4-pC, so put the extras back and
|
||||
# repoint that one alias.
|
||||
local fish_src="/etc/skel/.config/fish"
|
||||
local fish_dst="${TARGET}${home_in_target}/.config/fish"
|
||||
if [[ -d "$fish_src" && -d "$fish_dst" ]]; then
|
||||
rsync -a --exclude config.fish --exclude fish_variables \
|
||||
"$fish_src/" "$fish_dst/"
|
||||
if [[ -f "${fish_dst}/config.fish" ]]; then
|
||||
sed -i "s/alias q 'qs -c ii'/alias q 'qs -c end4-pC'/" "${fish_dst}/config.fish"
|
||||
grep -qF "alias q 'qs -c end4-pC'" "${fish_dst}/config.fish" \
|
||||
|| warn "fish 'q' alias still points at the upstream ii config (see $LOG)."
|
||||
fi
|
||||
chown -R "${USERNAME}:${USERNAME}" "$fish_dst"
|
||||
fi
|
||||
|
||||
local configs_ok=true
|
||||
[[ -e "${TARGET}${home_in_target}/.config/hypr/hyprland.lua" \
|
||||
&& -d "${TARGET}${home_in_target}/.config/quickshell/ii" \
|
||||
&& -d "${TARGET}${home_in_target}/.config/quickshell/end4-pC" ]] || configs_ok=false
|
||||
# Files alone are not enough: with --skip-alldeps the dependencies must
|
||||
# have come from the ISO. hyprland and quickshell are installed at ISO
|
||||
# build time, so their binaries missing here means pacstrap dropped them
|
||||
# (they were not resolvable in the live repos). The venv is created from
|
||||
# the image's uv cache at install time, so a missing python means the
|
||||
# python step of end-4's setup never got to run.
|
||||
if $configs_ok; then
|
||||
[[ -x "${TARGET}/usr/bin/hyprctl" && -x "${TARGET}/usr/bin/quickshell" ]] \
|
||||
|| configs_ok=false
|
||||
[[ -x "${TARGET}${home_in_target}/.local/state/quickshell/.venv/bin/python" ]] \
|
||||
|| configs_ok=false
|
||||
fi
|
||||
|
||||
if [[ -d /etc/skel/.config/hypr/custom ]]; then
|
||||
cp -rfT /etc/skel/.config/hypr/custom "${TARGET}${home_in_target}/.config/hypr/custom"
|
||||
chown -R "${USERNAME}:${USERNAME}" "${TARGET}${home_in_target}/.config/hypr/custom"
|
||||
fi
|
||||
|
||||
# Presets ship with absolute paths from the build machine; repoint them at
|
||||
# the home that was just created (the images they name are not shipped).
|
||||
local presets="${TARGET}${home_in_target}/.config/illogical-impulse/presets"
|
||||
local preset
|
||||
for preset in "$presets"/*.json; do
|
||||
[[ -f "$preset" ]] || continue
|
||||
sed -i "s|/home/alvin/|/home/${USERNAME}/|g" "$preset"
|
||||
done
|
||||
|
||||
if $dots_ok && $configs_ok; then
|
||||
log "end-4 dotfiles installed for ${USERNAME} (setups_done=${setups_done} skipped=${#ignored[@]})."
|
||||
ok "end-4 dotfiles installed."
|
||||
else
|
||||
log "end-4 dotfiles incomplete for ${USERNAME} (setup_exit_ok=${dots_ok} configs=${configs_ok} setups=${setups_done} skipped=${#ignored[@]})."
|
||||
warn "end-4 dotfiles incomplete (see $LOG) — as ${USERNAME}, run: cd ~/.dots-hyprland && ./setup install"
|
||||
fi
|
||||
}
|
||||
|
||||
install_mkinitcpio() {
|
||||
info "Generating initramfs..."
|
||||
|
||||
@@ -597,6 +779,7 @@ main() {
|
||||
install_network
|
||||
install_user
|
||||
install_git
|
||||
install_end4_dots
|
||||
install_mkinitcpio
|
||||
install_bootloader
|
||||
install_cleanup
|
||||
|
||||
Reference in New Issue
Block a user