fix: disk picker fd0 (#112), menu Back guard (#106), offline theme (#113)
Some checks failed
Check / eval (push) Has been cancelled

- #112: list_installable_disks drops fd/loop/sr/zram/<8GiB, largest-first
  so OVMF no longer offers /dev/fd0 as the default wipe target
- #106: tools/check-menu-back.py + checks.menu-back (proved to fail)
- #113: offline theme-switch contract documented (default/pinned only);
  theme-sync run_switch adds offline-oriented hint when no network

Verified: V0 flake check; installer-safety; menu-back; py_compile.
This commit is contained in:
2026-07-15 10:02:19 +01:00
parent 748d4af414
commit e6be5a5770
10 changed files with 202 additions and 49 deletions

View File

@@ -224,13 +224,43 @@ live_disk=""
live_src=$(findmnt -no SOURCE /iso 2>/dev/null || true)
[[ -n "$live_src" ]] && live_disk=$(lsblk -no PKNAME "$live_src" 2>/dev/null || true)
mapfile -t disks < <(lsblk -dpno NAME,SIZE,MODEL,TYPE \
| awk -v skip="/dev/${live_disk:-NONE}" \
'$NF == "disk" && $1 != skip && $1 !~ /loop|zram|sr[0-9]/ {NF--; print}')
[[ ${#disks[@]} -gt 0 ]] || fail "No installable disks found."
# Installable whole disks only (#112): drop floppy/pseudo/tiny devices that
# OVMF and some firmwares expose as TYPE=disk (e.g. /dev/fd0 first in the
# list — a blind Enter would erase nothing useful and break the install).
# Bytes via lsblk -b; 8 GiB floor catches fd0/USB crumbs; REQUIREMENTS still
# recommend ≥40 GiB for a real install.
# NOMARCHY_MIN_DISK_BYTES overrides the floor (tests / expert installs).
MIN_DISK_BYTES="${NOMARCHY_MIN_DISK_BYTES:-$((8 * 1024 * 1024 * 1024))}"
list_installable_disks() {
local skip="/dev/${live_disk:-NONE}"
local name size type model hsize
# NAME SIZE TYPE in bytes (-b); MODEL looked up separately (may contain spaces).
{
while read -r name size type; do
[[ "$type" == "disk" ]] || continue
[[ "$name" == "$skip" ]] && continue
case "$name" in
/dev/loop*|/dev/zram*|/dev/sr*|/dev/fd*|/dev/ram*|/dev/nbd*|/dev/md*)
continue ;;
esac
[[ "$size" =~ ^[0-9]+$ ]] || continue
(( size >= MIN_DISK_BYTES )) || continue
hsize=$(lsblk -dno SIZE "$name" 2>/dev/null || echo "?")
model=$(lsblk -dno MODEL "$name" 2>/dev/null | tr -s '[:space:]' ' ' | sed 's/^ //;s/ $//')
printf '%s %s %s\n' "$name" "$hsize" "${model:-}"
done < <(lsblk -dpbno NAME,SIZE,TYPE 2>/dev/null)
} | sort -k2 -h -r # largest first — never default to a tiny leftover
}
mapfile -t disks < <(list_installable_disks)
[[ ${#disks[@]} -gt 0 ]] || fail "No installable disks found (need a whole disk ≥ $(( MIN_DISK_BYTES / 1024 / 1024 / 1024 )) GiB; floppy/loop/optical excluded)."
if [[ "$UNATTENDED" == "1" ]]; then
TARGET_DISK="${NOMARCHY_DISK:?NOMARCHY_DISK required in unattended mode}"
# Unattended still rejects non-installable targets (CI footgun).
if ! printf '%s\n' "${disks[@]}" | grep -q "^${TARGET_DISK} "; then
fail "$TARGET_DISK is not an installable disk (missing, live medium, or below size floor)."
fi
else
choice=$(printf '%s\n' "${disks[@]}" \
| gum choose --header "Install Nomarchy on which disk? (EVERYTHING on it will be erased)")