Compare commits

..
5 Commits
Author SHA1 Message Date
yuri d1031277bf Merge pull request 'Repo guards (repolist) + PeaZip flavor guard' (#14) from fix/repo-and-peazip-guards into main 2026-11-11 15:48:11 +01:00
Pathfinder ee10829452 Cosmetic: ANSI line wipe; hide (0 packages) on idempotent re-runs
Two nits from YuKu's laptop paste: the 100-space line wipe left a
visible gap before short summaries (now ANSI EL: \r\033[K, no
residue), and '(0 packages)' printed when nothing new was installed
(idempotent re-run / theme deps all present) — the count parenthetical
is now omitted when zero.
2026-11-11 15:46:45 +01:00
Pathfinder 1586e10df1 SilentSDDM install: quiet like everything else
The theme's own install.sh runs dnf for its dependencies and its
output flooded the screen raw (laptop-proven: the last wall of text
left in the run). Now wrapped in ui_quiet_run: live block line with
the current dependency, summary count after, full output in the
setup log, red + tail on failure. Unattended/piped runs keep plain
output. pipefail still suspended around the yes| pipe (inherited at
subshell fork).
2026-11-11 15:42:49 +01:00
Pathfinder 4e0dad3483 PeaZip: swap to the wanted flavor when an incompatible one is detected
Per YuKu: instead of skipping when an older flavor is present, SWAP it
to the environment-appropriate one (dnf swap -y old new). Atomic —
if the swap fails, the existing flavor stays and the run continues
with a warning (the safe outcome). Right flavor already present ->
no-op; fresh machine -> plain install.

Verified: qt5+niri -> swap to gtk3 (your laptop scenario); qt6+hyprland
-> no-op; forced swap failure -> warn + keep qt5; fresh -> gtk3.
2026-11-11 15:38:57 +01:00
Pathfinder b79735d82e Repo guards check repolist, not just RPMs; PeaZip skips when any flavor exists
Laptop run (YuKu, existing machine) exposed two fresh-install blind
spots:

1. Terra add failed on a machine that already HAD the repo but not a
   queryable terra-release RPM — bootstrapping --repofrompath over an
   existing repo id collides. New repo_enabled() checks dnf repolist
   (the source of truth); add_terra_repo and add_rpmfusion_repo now
   skip when the repo is configured OR the release RPM present.

2. PeaZip tailoring tried gtk3 over an existing peazip-qt5: all UI
   flavors ship /usr/bin/peazip and file-conflict, transaction died.
   Any installed flavor (qt5/qt6/gtk3/gtk2) now wins and the section
   skips with the flavor named.

Harness: laptop sim (repo configured, peazip-qt5 present) -> zero
bootstrap calls, PeaZip skipped; fresh machine -> terra bootstraps +
gtk3 installs; re-run -> skip via repolist; peazip-qt6 + hyprland ->
skip; unattended/piped green.
2026-11-11 15:35:15 +01:00
2 changed files with 65 additions and 18 deletions
+27 -10
View File
@@ -173,18 +173,26 @@ ui_quiet_run() {
local rc=0 local rc=0
wait "$pid" || rc=$? wait "$pid" || rc=$?
printf '\r%*s\r' 100 '' >&2 # ANSI erase-line: wipes the live line without leaving trailing spaces
# (a 100-space wipe left a visible gap when the summary was shorter)
printf '\r\033[K' >&2
if (( rc == 0 )); then if (( rc == 0 )); then
n=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null | grep -ac '^Installing' || true) n=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null | grep -ac '^Installing' || true)
local plural="s" local count_txt=""
(( n == 1 )) && plural="" if (( n > 0 )); then
local plural="s"
(( n == 1 )) && plural=""
count_txt=" (${n} package${plural})"
fi
# n == 0 means nothing new was installed (idempotent re-run /
# deps already present): print the message without a count.
if (( depth == 256 )); then if (( depth == 256 )); then
printf '\033[48;5;34m \033[0m %s (%s package%s)\n' "$msg" "$n" "$plural" >&2 printf '\033[48;5;34m \033[0m %s%s\n' "$msg" "$count_txt" >&2
elif (( depth == 16 )); then elif (( depth == 16 )); then
printf '\033[42m \033[0m %s (%s package%s)\n' "$msg" "$n" "$plural" >&2 printf '\033[42m \033[0m %s%s\n' "$msg" "$count_txt" >&2
else else
ok "$msg (${n} package${plural})" ok "$msg${count_txt}"
fi fi
return 0 return 0
else else
@@ -283,9 +291,17 @@ install_group_any() {
#------------------------------------------ #------------------------------------------
# Third-party repos # Third-party repos
#------------------------------------------ #------------------------------------------
# True when a repo id is CONFIGURED, whatever installed it. This is the
# reliable source of truth: a machine can have the repo without the
# -release RPM (hand-added .repo file) — and bootstrapping over an existing
# repo id via --repofrompath collides and fails (laptop-proven).
repo_enabled() {
dnf repolist --all 2>/dev/null | awk '{print $1}' | grep -qx "$1"
}
add_terra_repo() { add_terra_repo() {
if pkg_installed terra-release; then if pkg_installed terra-release || repo_enabled terra; then
ok "Terra repository already installed." ok "Terra repository already present."
return 0 return 0
fi fi
info "Adding Terra repository (Fyra Labs)..." info "Adding Terra repository (Fyra Labs)..."
@@ -299,8 +315,9 @@ add_terra_repo() {
add_rpmfusion_repo() { add_rpmfusion_repo() {
local rel local rel
rel=$(rpm -E %fedora) rel=$(rpm -E %fedora)
if pkg_installed rpmfusion-free-release rpmfusion-nonfree-release; then if pkg_installed rpmfusion-free-release rpmfusion-nonfree-release \
ok "RPM Fusion already installed." || { repo_enabled rpmfusion-free && repo_enabled rpmfusion-nonfree; }; then
ok "RPM Fusion already present."
return 0 return 0
fi fi
info "Enabling RPM Fusion (free + nonfree) for Fedora ${rel}..." info "Enabling RPM Fusion (free + nonfree) for Fedora ${rel}..."
+38 -8
View File
@@ -639,16 +639,42 @@ rule
# --- 8.1 PeaZip: toolkit variant follows the session (Qt6 for Qt-ish # --- 8.1 PeaZip: toolkit variant follows the session (Qt6 for Qt-ish
# environments, GTK3 for the rest) --- # environments, GTK3 for the rest) ---
info "Tailoring toolkits for DE=$DE / TWM=$TWM..." info "Tailoring toolkits for DE=$DE / TWM=$TWM..."
# The UI flavors all ship /usr/bin/peazip and file-conflict with each
# other — installing gtk3 over an existing qt5 dies mid-transaction
# (laptop-proven). Behaviors:
# no flavor -> install the environment-appropriate one
# right flavor -> nothing to do
# OTHER flavor -> dnf SWAP to the wanted one (atomic: on failure the
# existing flavor stays, which is the safe outcome)
if [[ "$DE" == "plasma" || "$TWM" == "hyprland" ]]; then if [[ "$DE" == "plasma" || "$TWM" == "hyprland" ]]; then
peazip_pkgs="peazip-common peazip-qt6" peazip_wanted="peazip-qt6"
else else
# XFCE, GNOME, Niri, MangoWC, chadwm: lightweight/generic toolkits # XFCE, GNOME, Niri, MangoWC, chadwm: lightweight/generic toolkits
peazip_pkgs="peazip-common peazip-gtk3" peazip_wanted="peazip-gtk3"
fi fi
# shellcheck disable=SC2086 peazip_existing=""
if ! install_packages $peazip_pkgs; then local_v=""
color_red " Failed: $peazip_pkgs" for local_v in peazip-qt5 peazip-qt6 peazip-gtk3 peazip-gtk2; do
color_red " (continuing — PeaZip is a convenience, not a dependency)" pkg_installed "$local_v" && peazip_existing="$local_v"
done
if [[ -z "$peazip_existing" ]]; then
# shellcheck disable=SC2086
if ! install_packages peazip-common "$peazip_wanted"; then
color_red " Failed: peazip-common $peazip_wanted"
color_red " (continuing — PeaZip is a convenience, not a dependency)"
fi
elif [[ "$peazip_existing" == "$peazip_wanted" ]]; then
ok "PeaZip already present ($peazip_existing)."
else
info "PeaZip $peazip_existing does not match this environment — swapping to $peazip_wanted..."
if ui_quiet_run "Swapping PeaZip: $peazip_existing -> $peazip_wanted" \
sudo dnf swap -y "$peazip_existing" "$peazip_wanted"; then
ok "PeaZip swapped to $peazip_wanted."
else
warn "Swap failed — keeping the existing $peazip_existing (fully functional)."
fi
fi fi
pause_if_debug pause_if_debug
@@ -736,9 +762,13 @@ if pkg_installed sddm; then
if [[ -f "$REPO_DIR/install.sh" ]]; then if [[ -f "$REPO_DIR/install.sh" ]]; then
# yes | install.sh: the installer prompts; SIGPIPE from 'yes' would # yes | install.sh: the installer prompts; SIGPIPE from 'yes' would
# read as a crash under pipefail, so suspend it for this one command # read as a crash under pipefail, so suspend it for this one command.
# pipefail state is inherited by the ui_quiet_run subshell at fork.
# The theme's own dnf dependency flood goes to the log like every
# other transaction (laptop-proven it was the last raw wall left).
set +o pipefail set +o pipefail
if ( cd "$REPO_DIR" && yes | ./install.sh ); then if ui_quiet_run "Installing SilentSDDM theme" \
bash -c 'cd "$1" && yes | ./install.sh' _ "$REPO_DIR"; then
ok "SilentSDDM theme installed." ok "SilentSDDM theme installed."
else else
color_red " Failed: SilentSDDM installer (continuing; SDDM keeps its default theme)" color_red " Failed: SilentSDDM installer (continuing; SDDM keeps its default theme)"