Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6f00018d4
|
||
|
|
e377f9313a
|
@@ -74,7 +74,7 @@ The airootfs overlay ships it as `/usr/local/bin/alvin-install` (mode `0755` for
|
|||||||
locale, login manager, sshd, summary) then a fixed order of `install_*` steps
|
locale, login manager, sshd, summary) then a fixed order of `install_*` steps
|
||||||
(partition → LUKS → format/mount → pacstrap → fstab → repos → timezone → locale →
|
(partition → LUKS → format/mount → pacstrap → fstab → repos → timezone → locale →
|
||||||
hostname → network → sshd → user → git/SSH → end-4 dots → mkinitcpio → bootloader →
|
hostname → network → sshd → user → git/SSH → end-4 dots → mkinitcpio → bootloader →
|
||||||
TPM/unl0kr → login manager (none if unl0kr succeeded; with unl0kr selected the login screen only asks for a fallback) → autologin → update (reflector + keyrings + `pacman -Syu`, warn-only) → cleanup). Screens and install steps are
|
TPM/unl0kr → login manager (none if unl0kr succeeded; with unl0kr selected the login screen only asks for a fallback) → autologin → update (reflector + keyrings + `pacman -Syu`, warn-only) → cleanup, which offers an optional `arch-chroot` shell into the target before unmounting; the `EXIT` trap offers the same shell when a step after pacstrap fails or the install is interrupted (INT/TERM re-exit with 128+N so signals count as failure). Screens and install steps are
|
||||||
independent — edit one without
|
independent — edit one without
|
||||||
touching the other. An `EXIT` trap unmounts `$TARGET` and closes `cryptroot` on any exit.
|
touching the other. An `EXIT` trap unmounts `$TARGET` and closes `cryptroot` on any exit.
|
||||||
- **Package list**: `install_pacstrap` builds the *installed* system's list from the medium's
|
- **Package list**: `install_pacstrap` builds the *installed* system's list from the medium's
|
||||||
@@ -116,7 +116,7 @@ commit; CI remains the enforcer. Bypass it with `git commit --no-verify`.
|
|||||||
- The **image** ships its own `[local-aur]` at `file:///opt/localrepo` (see `.live-pacman.conf`). It holds `localrepo/` (copied by CI/`update.sh`) plus everything `install-deps` built. pacstrap runs without `-P`, so the target keeps the stock `/etc/pacman.conf`; `alvin-install` strips `[local-aur]` from it anyway as a safety net, because `/opt/localrepo` exists only on the medium.
|
- The **image** ships its own `[local-aur]` at `file:///opt/localrepo` (see `.live-pacman.conf`). It holds `localrepo/` (copied by CI/`update.sh`) plus everything `install-deps` built. pacstrap runs without `-P`, so the target keeps the stock `/etc/pacman.conf`; `alvin-install` strips `[local-aur]` from it anyway as a safety net, because `/opt/localrepo` exists only on the medium.
|
||||||
- `alvin-install` runs end-4 with `--skip-alldeps` — dependencies must come from the ISO. It feeds `yes i` to end-4's failure prompt: inside the installer chroot the medium's `/run` is bind-mounted in, so end-4's `systemctl --machine=…@.host --user enable … --now` lines can never work (and `--now` would start services on the live medium). `install_end4_dots` re-applies the enable-only part (bluetooth, ydotool, i2c module) outside the chroot and reports every step end-4 had to skip. If the end-4 step reports "incomplete", check that `hyprctl`/`quickshell`/the venv were resolvable (harvest) before re-running anything.
|
- `alvin-install` runs end-4 with `--skip-alldeps` — dependencies must come from the ISO. It feeds `yes i` to end-4's failure prompt: inside the installer chroot the medium's `/run` is bind-mounted in, so end-4's `systemctl --machine=…@.host --user enable … --now` lines can never work (and `--now` would start services on the live medium). `install_end4_dots` re-applies the enable-only part (bluetooth, ydotool, i2c module) outside the chroot and reports every step end-4 had to skip. If the end-4 step reports "incomplete", check that `hyprctl`/`quickshell`/the venv were resolvable (harvest) before re-running anything.
|
||||||
- `/etc/skel/.cache/uv` + `/etc/skel/.local/share/uv/python` are pre-warmed by the build (~460 MB: CPython 3.12 and the pinned wheel cache) so end-4's `uv venv`/`uv pip install` at install time needs no network.
|
- `/etc/skel/.cache/uv` + `/etc/skel/.local/share/uv/python` are pre-warmed by the build (~460 MB: CPython 3.12 and the pinned wheel cache) so end-4's `uv venv`/`uv pip install` at install time needs no network.
|
||||||
- **end4-pC** (`pctrade/end4-pC`) is the default quickshell config: cloned into `/etc/skel/.config/quickshell/end4-pC` at build time, selected by patching `hl.env("qsConfig", "ii")` → `"end4-pC"` in the **staged** `/opt/dots-hyprland/dots/.config/hypr/hyprland/variables.lua` (there is no `hypr/hyprland/` in this repo — `./setup install` copies it to the installed system). `alvin-install` re-copies end4-pC into the user's home *after* `./setup install`, because end-4's installer `rsync --delete`s all of `~/.config/quickshell`.
|
- **end4-pC** (`pctrade/end4-pC`) is the default quickshell config: cloned into `/etc/skel/.config/quickshell/end4-pC` at build time, selected by patching `hl.env("qsConfig", "ii")` → `"end4-pC"` in the **staged** `/opt/dots-hyprland/dots/.config/hypr/hyprland/variables.lua` (there is no `hypr/hyprland/` in this repo — `./setup install` copies it to the installed system). `alvin-install` re-copies end4-pC into the user's home *after* `./setup install`, because end-4's installer `rsync --delete`s all of `~/.config/quickshell`. The build also rewrites the fork's hard-coded `QUICKSHELL_CONFIG_NAME="ii"` in its colour/wallpaper/kvantum scripts to `end4-pC` (otherwise they act on `~/.config/quickshell/ii`), and overwrites its `assets/images/default_wallpaper.png` (applied by `FirstRunExperience.qml` on first login) with `airootfs/etc/skel/Pictures/Wallpapers/Dynamic-Wallpapers/Dark/japan-street-Dark.png`.
|
||||||
- `airootfs/etc/skel/.config/illogical-impulse/presets/` carries the user's presets (`Laptop.json`, `Personal-Performance.json`, `Personal-Performance.zip`). They embed `/home/alvin/...` paths, so wallpapers/screenshots need fixing up after install.
|
- `airootfs/etc/skel/.config/illogical-impulse/presets/` carries the user's presets (`Laptop.json`, `Personal-Performance.json`, `Personal-Performance.zip`). They embed `/home/alvin/...` paths, so wallpapers/screenshots need fixing up after install.
|
||||||
- End-4 metapackages are built from `localrepo/end4-pkgbuilds/` (quickshell-git, bibata-modern-classic-bin, microtex-git).
|
- End-4 metapackages are built from `localrepo/end4-pkgbuilds/` (quickshell-git, bibata-modern-classic-bin, microtex-git).
|
||||||
- **quickshell pin / Qt 6.12**: end-4 pins quickshell to `41651d7` (Sep 25), which predates upstream fix `5d5d498` (Oct 3, *"use MOC includes instead of opaque pointer definitions — … Qt 6.12 compatibility"*). Arch shipped qt6 6.12.0 on Oct 8 and the old pin died with `Meta Types must be fully defined` in the moc build of quickshell-hyprland-ipc (failed CI run 137). `customize_airootfs.sh` therefore rewrites end-4's `_commit` to `11ca60be` after cloning — but **only** while it still matches `^_commit='41651d7`, so once end-4 bumps their own pin the guard goes inert and theirs wins. `localrepo/check-quickshell-pin.sh` (weekly `pin-check.yaml` job) fails CI if either pin goes stale or loses the fix; it warns instead of failing when end-4's known-stale pin is covered by the override.
|
- **quickshell pin / Qt 6.12**: end-4 pins quickshell to `41651d7` (Sep 25), which predates upstream fix `5d5d498` (Oct 3, *"use MOC includes instead of opaque pointer definitions — … Qt 6.12 compatibility"*). Arch shipped qt6 6.12.0 on Oct 8 and the old pin died with `Meta Types must be fully defined` in the moc build of quickshell-hyprland-ipc (failed CI run 137). `customize_airootfs.sh` therefore rewrites end-4's `_commit` to `11ca60be` after cloning — but **only** while it still matches `^_commit='41651d7`, so once end-4 bumps their own pin the guard goes inert and theirs wins. `localrepo/check-quickshell-pin.sh` (weekly `pin-check.yaml` job) fails CI if either pin goes stale or loses the fix; it warns instead of failing when end-4's known-stale pin is covered by the override.
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 9.4 MiB |
@@ -134,6 +134,29 @@ if [[ ! -d "${SKEL}/.config/quickshell/end4-pC" ]]; then
|
|||||||
git clone --depth=1 https://github.com/pctrade/end4-pC.git \
|
git clone --depth=1 https://github.com/pctrade/end4-pC.git \
|
||||||
"${SKEL}/.config/quickshell/end4-pC"
|
"${SKEL}/.config/quickshell/end4-pC"
|
||||||
fi
|
fi
|
||||||
|
# The fork's colour/wallpaper/kvantum scripts still hard-code
|
||||||
|
# QUICKSHELL_CONFIG_NAME="ii", so they'd read and write ~/.config/quickshell/ii
|
||||||
|
# instead of end4-pC. Point them at the fork. Re-running is a no-op.
|
||||||
|
mapfile -t PC_II_SCRIPTS < <(grep -rl --exclude-dir=.git \
|
||||||
|
'^QUICKSHELL_CONFIG_NAME="ii"$' "${SKEL}/.config/quickshell/end4-pC" || true)
|
||||||
|
if (( ${#PC_II_SCRIPTS[@]} )); then
|
||||||
|
echo "[customize] Pointing ${#PC_II_SCRIPTS[@]} end4-pC scripts at end4-pC..."
|
||||||
|
sed -i 's/^QUICKSHELL_CONFIG_NAME="ii"$/QUICKSHELL_CONFIG_NAME="end4-pC"/' \
|
||||||
|
"${PC_II_SCRIPTS[@]}"
|
||||||
|
fi
|
||||||
|
# Default wallpaper: end4-pC's first run (services/FirstRunExperience.qml)
|
||||||
|
# feeds assets/images/default_wallpaper.png to switchwall.sh, so replace that
|
||||||
|
# image with the one shipped in skel's ~/Pictures/Wallpapers.
|
||||||
|
DEFAULT_WALL="${SKEL}/Pictures/Wallpapers/Dynamic-Wallpapers/Dark/japan-street-Dark.png"
|
||||||
|
PC_DEFAULT_WALL="${SKEL}/.config/quickshell/end4-pC/assets/images/default_wallpaper.png"
|
||||||
|
if [[ ! -f "${DEFAULT_WALL}" ]]; then
|
||||||
|
echo "[customize] Default wallpaper ${DEFAULT_WALL} is missing" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! cmp -s "${DEFAULT_WALL}" "${PC_DEFAULT_WALL}"; then
|
||||||
|
echo "[customize] Setting end4-pC default wallpaper to ${DEFAULT_WALL##*/}..."
|
||||||
|
install -Dm644 "${DEFAULT_WALL}" "${PC_DEFAULT_WALL}"
|
||||||
|
fi
|
||||||
|
|
||||||
# ── Default quickshell config: ii -> end4-pC ─────────────────────────────────
|
# ── Default quickshell config: ii -> end4-pC ─────────────────────────────────
|
||||||
# alvin-install copies this staged repo onto the target and runs `./setup
|
# alvin-install copies this staged repo onto the target and runs `./setup
|
||||||
|
|||||||
@@ -43,20 +43,74 @@ SSHD_APPLIED="false"
|
|||||||
TPM_DISCLAIMER=""
|
TPM_DISCLAIMER=""
|
||||||
TARGET_DB_SYNCED="false"
|
TARGET_DB_SYNCED="false"
|
||||||
UPDATE_STATUS="not run"
|
UPDATE_STATUS="not run"
|
||||||
|
# Flipped once pacstrap succeeds: from then on a failed step still leaves a
|
||||||
|
# chroot-able system, so the EXIT trap offers a repair shell into it.
|
||||||
|
TARGET_INSTALLED="false"
|
||||||
|
# Teardown state: a signal arriving while cleanup() runs must not skip the
|
||||||
|
# unmount - the first one only aborts what is on screen, a second forces exit.
|
||||||
|
CLEANUP_RUNNING="false"
|
||||||
|
SIGNALS_SEEN="0"
|
||||||
|
|
||||||
log() { echo "[$(date '+%H:%M:%S')] $*" >>"$LOG"; }
|
log() { echo "[$(date '+%H:%M:%S')] $*" >>"$LOG"; }
|
||||||
|
|
||||||
cleanup() {
|
# Temporary NOPASSWD drop-ins some install steps create; never leave them
|
||||||
set +e
|
# behind (EXIT) or expose them to the user's post-install chroot shell.
|
||||||
|
remove_temp_sudoers() {
|
||||||
rm -f "${TARGET}/etc/sudoers.d/99-end4-install" \
|
rm -f "${TARGET}/etc/sudoers.d/99-end4-install" \
|
||||||
"${TARGET}/etc/sudoers.d/99-ssh-import-id" \
|
"${TARGET}/etc/sudoers.d/99-ssh-import-id" \
|
||||||
"${TARGET}/etc/sudoers.d/99-unl0kr-install" 2>/dev/null
|
"${TARGET}/etc/sudoers.d/99-unl0kr-install" 2>/dev/null || true
|
||||||
umount -R "$TARGET" 2>/dev/null
|
}
|
||||||
cryptsetup close cryptroot 2>/dev/null
|
|
||||||
|
cleanup() {
|
||||||
|
local rc=$?
|
||||||
|
CLEANUP_RUNNING="true"
|
||||||
|
set +e
|
||||||
|
trap - ERR
|
||||||
|
# A later step failed but the base system is on disk: let the user fix
|
||||||
|
# it from inside before everything is unmounted.
|
||||||
|
if ((rc != 0)) && [[ "$TARGET_INSTALLED" == "true" && -t 0 ]]; then
|
||||||
|
echo ""
|
||||||
|
warn "Installation failed after the base system was installed."
|
||||||
|
offer_chroot "The installed system is still mounted. Chroot into it to fix things?"
|
||||||
|
fi
|
||||||
|
remove_temp_sudoers
|
||||||
|
# A repair shell can leave mounts behind, and the LUKS mapping may still
|
||||||
|
# be open - report a failure instead of hiding it, so the user knows the
|
||||||
|
# target was not cleanly torn down before rebooting.
|
||||||
|
if mountpoint -q "$TARGET" 2>/dev/null; then
|
||||||
|
if ! umount -R "$TARGET"; then
|
||||||
|
log "Cleanup: umount -R $TARGET failed"
|
||||||
|
warn "Some mounts under ${TARGET} are busy - unmounting failed (released at reboot)."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -e /dev/mapper/cryptroot ]] && ! cryptsetup close cryptroot 2>/dev/null; then
|
||||||
|
log "Cleanup: cryptsetup close cryptroot failed"
|
||||||
|
warn "cryptroot is still open - it is released at reboot."
|
||||||
|
fi
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Signal handler. Without one, bash runs the EXIT trap with $? = 0 when the
|
||||||
|
# shell itself is killed (SIGINT between commands, SIGTERM from a shutdown),
|
||||||
|
# and cleanup()'s rc != 0 test would read that as success and skip the repair
|
||||||
|
# shell. Re-exit with the conventional 128+N status so an interrupted install
|
||||||
|
# takes the same path as a failed step. Note: a SIGINT delivered while a
|
||||||
|
# foreground command is running is consumed together with that command (bash
|
||||||
|
# then suppresses both errexit and this handler) - that case is unchanged.
|
||||||
|
on_signal() {
|
||||||
|
local status="$1"
|
||||||
|
if [[ "$CLEANUP_RUNNING" == "true" && "$SIGNALS_SEEN" == "0" ]]; then
|
||||||
|
SIGNALS_SEEN="1"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "" >&2
|
||||||
|
echo "Interrupted." >&2
|
||||||
|
exit "$status"
|
||||||
|
}
|
||||||
|
trap 'on_signal 130' INT
|
||||||
|
trap 'on_signal 143' TERM
|
||||||
|
|
||||||
# ── error surfacing ───────────────────────────────────────────────────────────
|
# ── error surfacing ───────────────────────────────────────────────────────────
|
||||||
# Step output normally ends up in $LOG only. These helpers make sure a failure
|
# Step output normally ends up in $LOG only. These helpers make sure a failure
|
||||||
# is ALSO shown on screen, paged through `gum pager` so long outputs stay
|
# is ALSO shown on screen, paged through `gum pager` so long outputs stay
|
||||||
@@ -811,6 +865,7 @@ install_pacstrap() {
|
|||||||
>>"$LOG" 2>&1 || warn "cert-sync failed - mono apps may reject TLS certificates."
|
>>"$LOG" 2>&1 || warn "cert-sync failed - mono apps may reject TLS certificates."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
TARGET_INSTALLED="true"
|
||||||
ok "Packages installed."
|
ok "Packages installed."
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2337,11 +2392,33 @@ install_cleanup() {
|
|||||||
gum pager <"$LOG" || true
|
gum pager <"$LOG" || true
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
|
offer_chroot
|
||||||
# Last line on screen after the optional log view - the instruction to
|
# Last line on screen after the optional log view - the instruction to
|
||||||
# reboot must be the final thing the user reads.
|
# reboot must be the final thing the user reads.
|
||||||
echo "Run 'reboot' to boot into your new system."
|
echo "Run 'reboot' to boot into your new system."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Optional shell inside the installed system. $TARGET (and cryptroot) are
|
||||||
|
# still mounted here - cleanup() only tears them down afterwards.
|
||||||
|
# Also called from the EXIT trap when a step after pacstrap failed ($1 then
|
||||||
|
# carries the failure prompt).
|
||||||
|
offer_chroot() {
|
||||||
|
gum confirm --affirmative "Open chroot" --negative "No thanks" \
|
||||||
|
"${1:-Chroot into the installed system to make changes before rebooting?}" ||
|
||||||
|
return 0
|
||||||
|
remove_temp_sudoers
|
||||||
|
# Copy first so the log is readable from inside (/var/log/alvin-install.log).
|
||||||
|
cp "$LOG" "${TARGET}/var/log/alvin-install.log" 2>/dev/null || true
|
||||||
|
info "Entering ${TARGET} - type 'exit' to leave and finish."
|
||||||
|
log "Chroot: interactive shell opened"
|
||||||
|
# The user's last command may fail; that must not trip errexit/ERR.
|
||||||
|
arch-chroot "$TARGET" /bin/bash || true
|
||||||
|
log "Chroot: shell closed"
|
||||||
|
# Keep the copy in the target current with the lines logged above.
|
||||||
|
cp "$LOG" "${TARGET}/var/log/alvin-install.log" 2>/dev/null || true
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
# ── Main ──────────────────────────────────────────────────────────────────────
|
# ── Main ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
|||||||
Reference in New Issue
Block a user