| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
| |
configure_grub replaced the whole GRUB_CMDLINE_LINUX_DEFAULT line with a fixed string. A base install that had set cryptdevice=, resume=, zfs=, or any other boot-critical parameter lost it, and the grub-mkconfig that follows baked an unbootable config.
update_grub_cmdline now reads the current value and merges: every existing token survives, archsetup's tokens are added, and where both set the same key archsetup's value wins. A safety check refuses to write when any existing token's key would vanish from the merge, and the write goes through awk + mv so paths with slashes can't break the substitution. The block also backs up /etc/default/grub before editing, which the other system-file edits already did.
|
| |
|
|
|
|
| |
The ordering asserts compared two string literals to each other ("05..." < "60..."), which is constant-true and never read the file. The invariant it claims to guard is boot-critical: pacman runs hooks in filename order, and a guard hook renamed past 60-mkinitcpio-remove would let a blocked transaction remove the current initramfs with this test still green.
The test now extracts the hook filenames the installer actually writes and compares those against the stock mkinitcpio hook name, so a rename flows into the assertion. Verified by mutation: renaming 05-zfs-snapshot to 70- in a source copy fails the new extraction compare where the old literal compare stayed true. Also added: every written hook must carry a two-digit ordering prefix.
|
| |
|
|
|
|
| |
The nvme early-load edit landed in mkinitcpio.conf, but the only nearby mkinitcpio -P ran behind an is-not-zfs-root gate. On ZFS-root machines (all of mine) the hardening was never compiled into the initramfs, which is exactly the case the early load exists for. The extracted ensure_nvme_early_module now rebuilds whenever it changed the file, and skips the rebuild on an unchanged conf so a resume stays idempotent.
The already-present check also grepped the whole file for "nvme", so a comment or nvme_tcp anywhere skipped the edit. It now checks for the nvme word on the MODULES line only.
|
| |
|
|
|
|
|
|
| |
Four near-identical blocks validated that AUTOLOGIN, NO_GPU_DRIVERS, INSTALL_CLAUDE_CODE, and INSTALL_DEVICE_UDEV_RULES were empty or exactly yes/no. They collapse into a validate_yesno helper the callers guard with `|| exit 1`.
The NVIDIA driver floor of 535 was a magic literal in the comparison and three prose lines. It now lives in a NVIDIA_MIN_DRIVER constant, and the nvidia-preflight test sources that constant alongside the function it extracts.
This is the safe, purely-testable slice of the refactor rollup. The structural extractions that touch the installer's system-mutation paths -- the GPU modalias scan, the stow and retry loops, the display-server/window-manager dispatch, and the snapper/fsck/GRUB/waybar sed blocks -- are split into a follow-up so they get characterization coverage first rather than a blind rewrite.
|
| |
|
|
|
|
| |
With `set -e` off, the installer copied its zfs-replicate, zfs-pre-snapshot, and hypr-live-update-guard scripts into place with bare cp/chmod. A missing or partial source failed silently, leaving a systemd service with a dead ExecStart or a pacman hook pointing at a script that never landed.
The two zfs scripts now install through install_executable, which guards the copy, warns on failure, and skips the chmod when the copy did not land. The two live-update-guard chmods (the guard binary and its hook) are guarded inline with error_warn.
|
| |
|
|
|
|
|
|
|
|
| |
Each of these steps misbehaves on a resume re-run or under unexpected system state, so I pulled the logic into small testable helpers and fixed the behavior.
The log-cleanup cron line was appended unconditionally. essential_services is one resume step, so a failure past that point plus a re-run stacked a second identical cron line every time. crontab_append_once now appends only when no existing line matches.
The weekly ZFS scrub timer used `zpool list | head -1`, which picks an arbitrary pool when several exist and builds the malformed unit `zfs-scrub-weekly@.timer` when none do. zfs_scrub_timer_units emits one timer per pool and nothing for no pools, so every pool is scrubbed and an absent pool warns instead of enabling a broken unit.
gamemode was enabled through `systemctl --user enable`, which the script itself documents fails at install time with no user session bus -- so gamemoded was likely left un-enabled behind a silent warning. It now wires the wants symlink by hand through enable_user_service, the same helper syncthing's block folds into.
|
| |
|
|
|
|
| |
The installer copied /etc/sudoers.pacnew over /etc/sudoers with no validation. A malformed pacnew that sudo refuses to parse would replace a working sudoers with an unparseable one, locking out privilege escalation right before the NOPASSWD rule gets appended. replace_sudoers_pacnew now runs `visudo -cf` on the pacnew first and only copies a file that validates; a failure warns and leaves the current sudoers in place.
Extracted the logic into a function taking the pacnew and target as positional args defaulting to the system paths, so the guard can run against fixtures.
|
| |
|
|
|
|
| |
run_step marked a step complete only when its function returned 0. But error_fatal exits the script outright, so a step function that returns at all has already cleared every fatal check -- a non-zero return can only be a trailing non-fatal warning, since error_warn returns 1. The old code read that as a failure and withheld the state marker, so the step re-ran on every resume even though its body had finished. run_step now records the marker whenever the function returns and logs a warning line when the return was non-zero.
Two smaller fixes alongside it. run_step's step_name/step_func and show_status's step/timestamp now use local so they stop leaking to global scope. The package-cache refresh loop captures pacman's real exit code instead of reading `$?` off the `$refresh_ok` test, which always read 1 and made error_fatal report "error code: 0" -- the same trap retry_install already documents.
|
| |
|
|
|
|
|
|
| |
`df /` wraps to two lines when the root device name is long -- a device-mapper or live-ISO root -- so `awk 'NR==2 {print $4}'` read the wrapped device line, found an empty Available field, and aborted a valid install with "Insufficient disk space." `df -P` forces POSIX single-line output.
The gate now compares available KB against the minimum in KB rather than truncating to GB first, which rejected a disk sitting just under a whole-GB boundary. Non-numeric df output falls back to zero so a malformed read aborts loudly instead of crashing the arithmetic test.
Extracted the logic into check_disk_space so it can be exercised directly.
|
| |
|
|
| |
set -e is off, so a chpasswd failure silently left the primary user with no password and no log entry, leaving an unloggable account on a fresh install. I extracted set_user_password, which aborts via error_fatal on a chpasswd failure. A fake-chpasswd test pins that the guard fires.
|
| |
|
|
| |
TRAMP's /ftp: method shells out to a command-line ftp client, and Arch ships none by default. inetutils provides /usr/bin/ftp, so I added it to install_required_software. A static test asserts it stays in the base set.
|
| |
|
|
| |
Install snapshot and live-update hooks before mkinitcpio removal, migrate legacy paths, and cover the ordering invariant.
|
| |
|
|
|
|
| |
pacman --needed skips a package that is already on the system as a dependency and leaves its install reason alone. A declared package can then sit as asdeps, surface as an orphan once its accidental dependent leaves, and get swept away by an orphan cleanup. expac and lm_sensors, both maintenance-console runtime deps, nearly went this way: they were asdeps on both hosts and only survived today's orphan sweep because something still depended on them.
pacman_install now marks the package explicit after a successful install. The mark never runs on a failed install, and a mark failure never fails the install. I flipped expac and lm_sensors to explicit on ratio and velox by hand since the installer only runs on fresh systems.
|
| |
|
|
|
|
|
|
| |
The maint console and the system-health-check workflow grade against ~/.config/archsetup/maintenance-thresholds.toml, but nothing installed it. A fresh install got a working maint CLI and no thresholds file.
user_customizations now installs the shipped TOML from the cloned repo. A re-run refreshes it, and the user layer in ~/.config/maint/ is never touched, so a reinstall can't eat curation. It also enables maint-scan.timer and maint-net-scan.timer through wants-symlinks (systemctl --user has no session bus during install, the syncthing idiom). Timer enablement is hyprland-only because the units live in that stow tier.
The install lists gain the runtime tools the probes call but nothing carried: expac, lm_sensors, fwupd.
|
| |
|
|
|
|
| |
archsetup took sanoid from install-archzfs but never ported the pre-pacman snapshot hook, so a ZFS-root install had no transaction-triggered rollback point — the working setup only existed as a hand-placed script on velox, lost on reinstall. Add configure_pre_pacman_snapshots(): a PreTransaction pacman hook plus a self-pruning script that keeps the 10 most recent pre-pacman snapshots (sanoid ignores them — they aren't autosnap_ names). It's gated to ZFS-root and runs late in boot_ux, so the hook doesn't fire during the install's own package operations and the first snapshot is the fresh system.
The script ships as scripts/zfs-pre-snapshot, made ZFS_PRE_* env-overridable so the pruning logic is unit-testable. Unit tests drive it against a fake zfs (creates a snapshot, prunes the oldest past KEEP, ignores non-pre-pacman snapshots, honors the lockfile interval, warns on failure); a Testinfra test asserts the hook and script land on a ZFS install; the orchestrator test pins the new boot_ux substep.
|
|
|
The decomposition left each big step function as a thin list of sub-step
calls with no runtime coverage. These tests sed-extract each orchestrator,
stub its sub-functions as recorders, and assert the exact call order, so a
dropped or reordered step fails the suite. configure_snapshots also gets a
per-filesystem dispatch check (zfs / btrfs / other).
|