fix(installer): Survive copytoram, keep ISO repos, default to fish

- install_pacstrap: fall back to the live system's pacman -Q when the
  medium's pkglist is gone (copytoram unmounts bootmnt), and die on an
  empty list instead of pacstrapping only the essentials.
- screen_disk: find the live medium via archisosearchuuid when bootmnt
  is unmounted, and hide whole-disk sources (empty PKNAME).
- install_cachyos_repo: put [cachyos] ahead of [core] like the ISO build
  and add [chaotic-aur], so chaotic packages keep updating.
- install_user: create the user with fish; the 'none' login manager now
  autostarts Hyprland via ~/.config/fish/conf.d/alvin-hyprland.fish.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
alvinlollo
2026-10-11 17:38:11 +11:00
co-authored by Claude Opus 5.5
parent 504a568570
commit 55b66a1373
+93 -41
View File
@@ -320,11 +320,20 @@ screen_disk() {
header "Select Installation Disk" header "Select Installation Disk"
echo "" echo ""
local live_dev="" # The boot medium: the bootmnt source, or - when copytoram unmounted it -
# the device carrying the archisosearchuuid= volume. A whole-disk source
# (hybrid ISO, sr0) has no PKNAME and is itself the disk to hide.
local live_dev="" src="" pk="" search_uuid=""
if [[ -d /run/archiso/bootmnt ]]; then if [[ -d /run/archiso/bootmnt ]]; then
local src
src=$(findmnt -no SOURCE /run/archiso/bootmnt 2>/dev/null || true) src=$(findmnt -no SOURCE /run/archiso/bootmnt 2>/dev/null || true)
[[ -n "$src" ]] && live_dev="/dev/$(lsblk -no PKNAME "$src" 2>/dev/null | head -n1)" fi
if [[ -z "$src" ]]; then
search_uuid=$(sed -n 's/.*archisosearchuuid=\([^[:space:]]*\).*/\1/p' /proc/cmdline)
[[ -n "$search_uuid" ]] && src=$(blkid -U "$search_uuid" 2>/dev/null || true)
fi
if [[ -n "$src" ]]; then
pk=$(lsblk -no PKNAME "$src" 2>/dev/null | head -n1 || true)
live_dev="/dev/${pk:-$(basename "$src")}"
fi fi
local disks=() local disks=()
@@ -650,36 +659,47 @@ install_pacstrap() {
local pkgs=() local pkgs=()
local dropped=() local dropped=()
local filter_ok=false local filter_ok=false
local -a src_lines=()
# The medium's pkglist comes from `pacman -Q` at build time: lines are
# "name version". With copytoram the boot medium is unmounted and the
# file is gone - the live system's own `pacman -Q` is the same data.
if [[ -f "$pkglist" ]]; then if [[ -f "$pkglist" ]]; then
# The medium's pkglist comes from `pacman -Q`: lines are "name version". mapfile -t src_lines < "$pkglist"
# Parse only the first field, then drop names not resolvable in the live else
# session's repos (e.g. local-aur packages are not configured there). warn "${pkglist} not found (copytoram?) - using the live system's package list."
info "Syncing package databases for resolvability check..." log "Pacstrap: ${pkglist} missing, falling back to pacman -Q"
if run_logged -s dot "pacman -Syy failed (resolvability check)" \ mapfile -t src_lines < <(pacman -Q 2>>"$LOG" || true)
pacman -Syy --noconfirm; then
declare -A available=()
local db_line
while IFS= read -r db_line; do
[[ -n "$db_line" ]] && available["$db_line"]=1
done < <(pacman -Slq 2>>"$LOG" || true)
(( ${#available[@]} > 0 )) && filter_ok=true
else
warn "pacman -Syy failed (output above) — installing without resolvability filter."
fi
local line pkg
while IFS= read -r line; do
[[ -z "$line" ]] && continue
pkg=${line%% *}
skip "$pkg" && continue
if $filter_ok && [[ -z "${available[$pkg]:-}" ]]; then
dropped+=("$pkg")
continue
fi
pkgs+=("$pkg")
done < "$pkglist"
fi fi
(( ${#src_lines[@]} > 0 )) \
|| die "No package list: ${pkglist} is missing and pacman -Q returned nothing."
# Parse only the first field, then drop names not resolvable in the
# live session's repos (incl. [local-aur] = /opt/localrepo).
info "Syncing package databases for resolvability check..."
if run_logged -s dot "pacman -Syy failed (resolvability check)" \
pacman -Syy --noconfirm; then
declare -A available=()
local db_line
while IFS= read -r db_line; do
[[ -n "$db_line" ]] && available["$db_line"]=1
done < <(pacman -Slq 2>>"$LOG" || true)
(( ${#available[@]} > 0 )) && filter_ok=true
else
warn "pacman -Syy failed (output above) — installing without resolvability filter."
fi
local line pkg
while IFS= read -r line; do
[[ -z "$line" ]] && continue
pkg=${line%% *}
skip "$pkg" && continue
if $filter_ok && [[ -z "${available[$pkg]:-}" ]]; then
dropped+=("$pkg")
continue
fi
pkgs+=("$pkg")
done < <(printf '%s\n' "${src_lines[@]}")
if (( ${#dropped[@]} > 0 )); then if (( ${#dropped[@]} > 0 )); then
warn "Skipped ${#dropped[@]} pkglist package(s) not found in configured repos:" warn "Skipped ${#dropped[@]} pkglist package(s) not found in configured repos:"
@@ -729,14 +749,24 @@ install_fstab() {
} }
install_cachyos_repo() { install_cachyos_repo() {
info "Configuring CachyOS repository..." info "Configuring CachyOS and chaotic-aur repositories..."
local conf="${TARGET}/etc/pacman.conf"
if ! grep -q '\[cachyos\]' "${TARGET}/etc/pacman.conf" 2>/dev/null; then # Same order as the ISO build (pacman.conf): cachyos ahead of [core], so
cat >> "${TARGET}/etc/pacman.conf" <<'REPO' # packages in both keep resolving to the cachyos builds pacstrap
# installed instead of flipping to extra on the first -Syu.
[cachyos] if ! grep -q '^\[cachyos\]' "$conf" 2>/dev/null; then
Include = /etc/pacman.d/cachyos-mirrorlist if grep -q '^\[core\]' "$conf"; then
REPO sed -i '0,/^\[core\]/s//[cachyos]\nInclude = \/etc\/pacman.d\/cachyos-mirrorlist\n\n[core]/' "$conf"
else
printf '\n[cachyos]\nInclude = /etc/pacman.d/cachyos-mirrorlist\n' >> "$conf"
fi
fi
# chaotic-aur packages (yay, ...) came from the ISO - without the repo
# they turn foreign and never update.
if ! grep -q '^\[chaotic-aur\]' "$conf" 2>/dev/null \
&& [[ -f "${TARGET}/etc/pacman.d/chaotic-mirrorlist" ]]; then
printf '\n[chaotic-aur]\nInclude = /etc/pacman.d/chaotic-mirrorlist\n' >> "$conf"
fi fi
# [local-aur] lives only on the live medium (file:///opt/localrepo). The # [local-aur] lives only on the live medium (file:///opt/localrepo). The
@@ -745,7 +775,7 @@ REPO
# but drop it anyway in case that ever changes. # but drop it anyway in case that ever changes.
sed -i '/^\[local-aur\]$/,/^$/d' "${TARGET}/etc/pacman.conf" 2>/dev/null || true sed -i '/^\[local-aur\]$/,/^$/d' "${TARGET}/etc/pacman.conf" 2>/dev/null || true
ok "CachyOS repo configured." ok "CachyOS + chaotic-aur repos configured."
} }
install_timezone() { install_timezone() {
@@ -819,7 +849,12 @@ install_user() {
cp -rT /etc/skel "${TARGET}/etc/skel" cp -rT /etc/skel "${TARGET}/etc/skel"
arch-chroot "$TARGET" useradd -m -G wheel -s /bin/bash "$USERNAME" # fish is the default shell (skel ships its config); bash only if the
# target somehow lacks it, so the account is never left without a shell.
local user_shell="/usr/bin/fish"
[[ -x "${TARGET}${user_shell}" ]] || user_shell="/bin/bash"
arch-chroot "$TARGET" useradd -m -G wheel -s "$user_shell" "$USERNAME"
log "User shell: ${user_shell}"
printf '%s:%s\n' "$USERNAME" "$PASS" | arch-chroot "$TARGET" chpasswd printf '%s:%s\n' "$USERNAME" "$PASS" | arch-chroot "$TARGET" chpasswd
@@ -1770,8 +1805,25 @@ install_none_profile() {
profile="${home_in_target}/.zprofile" profile="${home_in_target}/.zprofile"
;; ;;
*fish) *fish)
warn "fish is the login shell - skipping tty autostart; run 'Hyprland' after login." # conf.d is sourced automatically on every start. This runs after
log "tty profile: skipped (fish shell)" # install_end4_dots, so end-4's rsync --delete of ~/.config/fish
# cannot remove it.
local fish_cfg="${TARGET}${home_in_target}/.config/fish"
if grep -rqsE 'start-hyprland|exec Hyprland|auto-Hypr' \
"${fish_cfg}/config.fish" "${fish_cfg}/conf.d"; then
log "tty profile: fish config already launches Hyprland - skipped"
return 0
fi
mkdir -p "${fish_cfg}/conf.d"
cat > "${fish_cfg}/conf.d/alvin-hyprland.fish" <<'FISH'
# alvin-install: start Hyprland on tty1 (pam_systemd sets XDG_VTNR).
if status is-login; and test -z "$WAYLAND_DISPLAY"; and test "$XDG_VTNR" = 1
exec Hyprland
end
FISH
chown -R "$owner" "${fish_cfg}/conf.d" 2>/dev/null || true
ok "tty login will start Hyprland via ~/.config/fish/conf.d/alvin-hyprland.fish."
log "tty profile: fish conf.d/alvin-hyprland.fish (exec Hyprland on VT1)"
return 0 return 0
;; ;;
*) *)