Compare commits

...
5 Commits
Author SHA1 Message Date
yuri 8fb78651c9 Merge pull request 'Post-install tailoring (PeaZip variants, starship+preset, RobotoMono, services)' (#13) from feat/post-install-tailoring into main 2026-11-02 17:50:02 +01:00
Pathfinder c9a127a07e Advanced-menu installs go quiet: fix stdin theft + silent wiring
YuKu on the VM: menu installs were not quiet — the ONE place dnf's
full output still scrolled.

Root cause: the per-item install loop read picks with
'while read ... <<< "$sel"' — a herestring REPLACES stdin for its
whole body, so ui_quiet_run's tty gate saw 'piped' inside the loop
and every menu install ran in plain mode. Picks are now read into an
array first (herestring fills ONLY that); installs run in a for-loop
that never touches stdin.

Also silenced the remaining raw output in the menu path:
- Chrome repo wiring -> install_optional (quiet) + setopt silenced,
  direct-rpm fallback via ui_quiet_run
- Brave addrepo -> ui_quiet_run
- flatpak installs -> ui_quiet_run; ui_quiet_run now also matches
  flatpak's 'Installing...' progress (Unicode ellipsis) for the live
  line and count, sanitized to printable ASCII (tr -cd) so a
  non-UTF8 console never sees garbage bytes.

Pty-verified: live block lines + green summaries for chrome/gimp/
vscodium picks, flatpak progress only in the log, zero raw dnf or
flatpak text on screen.
2026-11-02 17:40:42 +01:00
Pathfinder 86358466e1 SilentSDDM theme, workstation-repos, Editors/Graphics/DevTools menus, flatpak support
Ported from the old fedora-full script:

- SilentSDDM SDDM theme in the tailoring section, gated on sddm
  being installed (skipped on gdm setups), idempotent via the
  ~/git/SilentSDDM checkout (pull --rebase when present), pipefail
  suspended around 'yes | ./install.sh' for the SIGPIPE trap.
- fedora-workstation-repositories added in base alongside the other
  repos (it ships the google-chrome repo the Browsers option enables).
- Advanced menu: Editors (VSCodium flatpak), Graphics and Multimedia
  (gimp/inkscape/obs/lollypop via dnf, spotify via flatpak), Development
  Tools (single option: @development-tools wget cmake ninja-build
  pkgconf-pkg-config). All names verified on F44.
- install_category_pkgs splits flatpak:<id> entries to Flathub so mixed
  picks cannot fail each other's transactions.

Harness: sddm->theme installs, gnome->skipped, vscodium+spotify via
flatpak, lollypop via dnf in the same multi-pick, devtools as one
transaction, all five categories listed, unattended+piped green.
2026-11-02 17:25:16 +01:00
Pathfinder 35c1939f28 Tailoring: wire starship into .bashrc only when dotfiles are absent
Per YuKu: after the starship install, append
  export STARSHIP_CONFIG=$HOME/.config/starship.toml
  eval "$(starship init bash)"
to ~/.bashrc — but ONLY when fedora-dots was NOT cloned (on dots
machines .bashrc belongs to the dots). Also gated on starship actually
being present (no dead eval in every shell) and idempotent (grep
guard). Harness: appended once with dots=no, never with dots=yes
(clean-home re-test; the first test was invalid because rm -rf home/*
left the previous .bashrc — the known dotfile-cleanup pitfall), and
not duplicated on re-run.
2026-11-02 16:58:34 +01:00
Pathfinder a8796467df Post-install tailoring section (ported from starburst minimal-fedora)
Section 8, after the advanced menu (summary renumbered to 9):

- PeaZip variant by environment: peazip-common + peazip-qt6 for
  plasma/hyprland, peazip-common + peazip-gtk3 otherwise (all verified
  on F44; peazip-qt6-10.9.0-1.fc44). Resilient: warns red, continues.
- Starship prompt via the official installer (command -v guarded), then
  the tokyo-night preset ONLY when no starship.toml exists yet —
  dotfiles checkouts always win over the preset.
- RobotoMono Nerd Font via the existing install_nerd_font helper
  (modules keep installing JetBrainsMono; both are small).
- Services: fstrim.timer, chronyd, NetworkManager globally-managed
  config (write + restart + 15s settle ONLY when the conf is absent —
  no needless NM restarts on re-runs, and no SSH self-drop when the
  config already exists), pipewire user units best-effort.

Polkit agent deliberately NOT ported: solved properly by the
polkit-kde user unit (VM-proven), the old polkit-kde-agent-1 line is
superseded.
2026-11-02 16:45:21 +01:00
2 changed files with 205 additions and 12 deletions
+7 -3
View File
@@ -140,9 +140,13 @@ ui_quiet_run() {
local pid=$! local pid=$!
local f=0 cur local f=0 cur
while kill -0 "$pid" 2>/dev/null; do while kill -0 "$pid" 2>/dev/null; do
# Match dnf ('Installing: pkg') AND flatpak ('Installing... id', a
# Unicode ellipsis) progress lines; sanitize to printable ASCII so a
# non-UTF8 console never sees garbage bytes in the live line.
cur=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null \ cur=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null \
| grep -E '^(Installing|Upgrading|Downgrading|Removing|Verifying|Preparing|Cleanup):' \ | grep -aE '^Installing|^Upgrading|^Downgrading|^Removing|^Verifying|^Preparing|^Cleanup' \
| tail -n 1 || true) | tail -n 1 \
| tr -cd '\11\12\40-\176' || true)
# Compose ONCE, then clamp to the terminal width: a live line longer # Compose ONCE, then clamp to the terminal width: a live line longer
# than the screen wraps on every redraw and floods the screen with # than the screen wraps on every redraw and floods the screen with
# duplicate partial lines (VM-proven on the 80-col TTY). # duplicate partial lines (VM-proven on the 80-col TTY).
@@ -172,7 +176,7 @@ ui_quiet_run() {
printf '\r%*s\r' 100 '' >&2 printf '\r%*s\r' 100 '' >&2
if (( rc == 0 )); then if (( rc == 0 )); then
n=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null | grep -c '^Installing:' || true) n=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null | grep -ac '^Installing' || true)
local plural="s" local plural="s"
(( n == 1 )) && plural="" (( n == 1 )) && plural=""
if (( depth == 256 )); then if (( depth == 256 )); then
+196 -7
View File
@@ -192,6 +192,9 @@ add_rpmfusion_repo
# Terra up front: it carries mangowc (noctalia moved into Fedora proper in # Terra up front: it carries mangowc (noctalia moved into Fedora proper in
# F44). Idempotent; also kept for the standalone-mango-module case. # F44). Idempotent; also kept for the standalone-mango-module case.
add_terra_repo add_terra_repo
# Fedora's third-party repo set (ships the google-chrome repo, disabled by
# default — the Browsers menu option enables it via config-manager setopt).
install_optional fedora-workstation-repositories
pause_if_debug pause_if_debug
if ! command -v flatpak >/dev/null 2>&1; then if ! command -v flatpak >/dev/null 2>&1; then
@@ -421,6 +424,9 @@ pause_if_debug
ADV_CATEGORIES=( ADV_CATEGORIES=(
"Virtualisation" "Virtualisation"
"Browsers" "Browsers"
"Editors"
"Graphics and Multimedia"
"Development Tools"
) )
# shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES # shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES
ADV_Virtualisation=( ADV_Virtualisation=(
@@ -434,6 +440,22 @@ ADV_Browsers=(
"google-chrome:Google Chrome (adds repo):google-chrome-stable" "google-chrome:Google Chrome (adds repo):google-chrome-stable"
"brave:Brave (adds repo):brave-browser" "brave:Brave (adds repo):brave-browser"
) )
# shellcheck disable=SC2034 # arrays are read via nameref from ADV_CATEGORIES
ADV_Editors=(
"vscodium:VSCodium (flatpak):flatpak:com.vscodium.codium"
)
# shellcheck disable=SC2034
ADV_Graphics_and_Multimedia=(
"gimp:GIMP:gimp"
"inkscape:Inkscape:inkscape"
"obs:OBS Studio:obs-studio"
"lollypop:Lollypop (music):lollypop"
"spotify:Spotify (flatpak):flatpak:com.spotify.Client"
)
# shellcheck disable=SC2034
ADV_Development_Tools=(
"devtools:Development Tools (dnf group + build tools):@development-tools wget cmake ninja-build pkgconf-pkg-config"
)
run_advanced_menu() { run_advanced_menu() {
local done_any=false local done_any=false
@@ -472,9 +494,18 @@ run_advanced_menu() {
# transaction (VM: brave's no-match took chromium down with it). # transaction (VM: brave's no-match took chromium down with it).
# Repo wiring inside install_category_pkgs runs per item; failures # Repo wiring inside install_category_pkgs runs per item; failures
# warn in red and the remaining picks still install. # warn in red and the remaining picks still install.
local picked lbl it # Read the picks into an ARRAY first, install in a for-loop.
# A `while read ... <<< "$sel"` herestring REPLACES stdin for its whole
# body — inside it stdin is no longer a TTY, ui_quiet_run saw "piped"
# and menu installs ran in plain mode (VM-proven: the advanced menu
# was the one place dnf's full output still scrolled).
local -a picked_items=()
while IFS= read -r picked; do while IFS= read -r picked; do
[[ -z "$picked" ]] && continue [[ -n "$picked" ]] && picked_items+=("$picked")
done <<< "$sel"
local picked lbl it
for picked in "${picked_items[@]}"; do
for entry in "${entries[@]}"; do for entry in "${entries[@]}"; do
rest="${entry#*:}" rest="${entry#*:}"
lbl="${rest%%:*}" lbl="${rest%%:*}"
@@ -494,7 +525,7 @@ run_advanced_menu() {
pause_if_debug pause_if_debug
fi fi
done done
done <<< "$sel" done
done done
# not `&& ok` — a false done_any would return 1 and kill the script under set -e # not `&& ok` — a false done_any would return 1 and kill the script under set -e
if [[ "$done_any" == "true" ]]; then if [[ "$done_any" == "true" ]]; then
@@ -506,6 +537,35 @@ run_advanced_menu() {
# app that needs one; packages alone stay generic. # app that needs one; packages alone stay generic.
install_category_pkgs() { install_category_pkgs() {
local cat="$1"; shift local cat="$1"; shift
# flatpak:<id> entries install from Flathub; the rest go to dnf. Split so
# a flatpak in a mixed pick cannot fail the dnf transaction (and vice
# versa — same per-item resilience as the rest of the menu).
local -a fp=() dp=()
local item
for item in "$@"; do
if [[ "$item" == flatpak:* ]]; then
fp+=("${item#flatpak:}")
else
dp+=("$item")
fi
done
if (( ${#dp[@]} > 0 )); then
# existing per-category wiring + dnf install (unchanged)
install_category_pkgs_dnf "$cat" "${dp[@]}" || return 1
fi
if (( ${#fp[@]} > 0 )); then
# quiet like dnf: live block line, full output in the log, red + tail
# on failure (ui_quiet_run matches flatpak's 'Installing...' lines)
ui_quiet_run "Installing flatpak: ${fp[*]}" \
flatpak install -y flathub "${fp[@]}" || return 1
fi
return 0
}
install_category_pkgs_dnf() {
local cat="$1"; shift
case "$cat" in case "$cat" in
Virtualisation) Virtualisation)
# qemu:///system without password prompts: libvirt group + enabled # qemu:///system without password prompts: libvirt group + enabled
@@ -530,10 +590,13 @@ install_category_pkgs() {
done done
if $needs_chrome && ! pkg_installed google-chrome-stable; then if $needs_chrome && ! pkg_installed google-chrome-stable; then
info "Adding Google Chrome repo..." info "Adding Google Chrome repo..."
sudo dnf install -y fedora-workstation-repositories 2>/dev/null || true install_optional fedora-workstation-repositories
sudo dnf config-manager setopt google-chrome.enabled=1 2>/dev/null || \ if ! sudo dnf config-manager setopt google-chrome.enabled=1 >/dev/null 2>&1; then
# repo enable failed: install straight from Google's rpm
ui_quiet_run "Installing Google Chrome (direct rpm)" \
sudo dnf install -y "https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm" sudo dnf install -y "https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm"
fi fi
fi
if $needs_brave && ! pkg_installed brave-browser; then if $needs_brave && ! pkg_installed brave-browser; then
# dnf5 (Fedora 41+) has no 'config-manager add' subcommand — # dnf5 (Fedora 41+) has no 'config-manager add' subcommand —
# the VM showed 'Unknown argument "add"', so the repo never # the VM showed 'Unknown argument "add"', so the repo never
@@ -543,7 +606,7 @@ install_category_pkgs() {
if [[ -f /etc/yum.repos.d/brave-browser.repo ]]; then if [[ -f /etc/yum.repos.d/brave-browser.repo ]]; then
ok "Brave repo already present." ok "Brave repo already present."
else else
info "Adding Brave repo (dnf5 addrepo)..." ui_quiet_run "Adding Brave repo (dnf5 addrepo)" \
sudo dnf config-manager addrepo \ sudo dnf config-manager addrepo \
--from-repofile=https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo --from-repofile=https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo
fi fi
@@ -563,7 +626,133 @@ if [[ "$ASSUME_YES" != "true" ]]; then
fi fi
pause_if_debug pause_if_debug
step "8 Summary" #------------------------------------------
# 8 Post-install tailoring
#------------------------------------------
# Ported from the old starburst minimal-fedora script, adapted:
# - polkit agent handled elsewhere (polkit-kde user unit, VM-proven)
# - resilient: each part warns red and continues (one missing package
# must not abort a finished install)
step "8 Post-install tailoring"
rule
# --- 8.1 PeaZip: toolkit variant follows the session (Qt6 for Qt-ish
# environments, GTK3 for the rest) ---
info "Tailoring toolkits for DE=$DE / TWM=$TWM..."
if [[ "$DE" == "plasma" || "$TWM" == "hyprland" ]]; then
peazip_pkgs="peazip-common peazip-qt6"
else
# XFCE, GNOME, Niri, MangoWC, chadwm: lightweight/generic toolkits
peazip_pkgs="peazip-common peazip-gtk3"
fi
# shellcheck disable=SC2086
if ! install_packages $peazip_pkgs; then
color_red " Failed: $peazip_pkgs"
color_red " (continuing — PeaZip is a convenience, not a dependency)"
fi
pause_if_debug
# --- 8.2 Starship prompt + Tokyo Night preset ---
if ! command -v starship >/dev/null 2>&1; then
info "Installing Starship shell prompt..."
# starship's official installer; -y skips its confirmation
if ! curl -sS https://starship.rs/install.sh | sh -s -- -y; then
color_red " Failed: starship installer"
color_red " (continuing)"
fi
fi
# Preset only when the user has no config yet — never clobber existing
# configuration (which may arrive via the dotfiles checkout).
if command -v starship >/dev/null 2>&1 && [[ ! -f "$HOME/.config/starship.toml" ]]; then
info "Applying starship tokyo-night preset..."
mkdir -p "$HOME/.config"
starship preset tokyo-night -o "$HOME/.config/starship.toml" \
|| warn "Could not apply the preset (starship still installed)."
fi
# bashrc wiring — ONLY when dotfiles were not cloned: on machines that
# use fedora-dots, .bashrc is owned by the dots and must not be edited
# here. Also requires starship to actually be present (a missing binary
# would make every shell print an error from the eval line).
if [[ "$DOTFILES" != "true" ]] \
&& command -v starship >/dev/null 2>&1 \
&& ! grep -q "starship init" "$HOME/.bashrc" 2>/dev/null; then
info "Wiring starship into ~/.bashrc..."
cat >> "$HOME/.bashrc" <<'EOF'
# starship
export STARSHIP_CONFIG="$HOME/.config/starship.toml"
eval "$(starship init bash)"
EOF
fi
pause_if_debug
# --- 8.3 RobotoMono Nerd Font (the modules install JetBrainsMono) ---
install_nerd_font RobotoMono
pause_if_debug
# --- 8.4 Services ---
info "Enabling services..."
sudo systemctl enable --now fstrim.timer
sudo systemctl enable --now chronyd || true
info "Ensuring NetworkManager manages all devices..."
NM_CONF="/etc/NetworkManager/conf.d/10-globally-managed-devices.conf"
if [[ ! -f "$NM_CONF" ]]; then
sudo mkdir -p "$(dirname "$NM_CONF")"
printf '[ifupdown]\nmanaged=true\n\n[keyfile]\nunmanaged-devices=\n' \
| sudo tee "$NM_CONF" >/dev/null
sudo systemctl enable --now NetworkManager
sudo systemctl restart NetworkManager
warn "NetworkManager restarted; giving it 15s to settle..."
sleep 15
else
ok "NetworkManager already globally-managed (config present)."
fi
# pipewire user units: preset-enabled on install; enable explicitly for
# robustness (fails harmlessly in odd session contexts, hence || true)
systemctl --user enable pipewire pipewire-pulse wireplumber >/dev/null 2>&1 || true
pause_if_debug
# --- 8.5 SDDM theme (SilentSDDM) — only when SDDM is the greeter ---
# Requires SDDM >= 0.21 (Fedora 44 ships 0.24+). Skipped on GNOME (gdm) and
# any setup where sddm is not installed.
if pkg_installed sddm; then
info "Installing SDDM theme: SilentSDDM..."
GIT_DIR="$HOME/git"
REPO_DIR="$GIT_DIR/SilentSDDM"
REPO_URL="https://github.com/uiriansan/SilentSDDM"
mkdir -p "$GIT_DIR"
if [[ -d "$REPO_DIR/.git" ]]; then
ok "SilentSDDM checkout exists. Updating..."
git -C "$REPO_DIR" pull --rebase --quiet || warn "git pull failed; using existing checkout."
else
info "Cloning SilentSDDM..."
git clone -b main --depth 1 --quiet "$REPO_URL" "$REPO_DIR" \
|| { color_red " Failed: git clone SilentSDDM (continuing)"; }
fi
if [[ -f "$REPO_DIR/install.sh" ]]; then
# yes | install.sh: the installer prompts; SIGPIPE from 'yes' would
# read as a crash under pipefail, so suspend it for this one command
set +o pipefail
if ( cd "$REPO_DIR" && yes | ./install.sh ); then
ok "SilentSDDM theme installed."
else
color_red " Failed: SilentSDDM installer (continuing; SDDM keeps its default theme)"
fi
set -o pipefail
else
color_red " SilentSDDM install.sh not found; skipping theme."
fi
else
info "SDDM not installed (gdm/none setup) - skipping SDDM theme."
fi
pause_if_debug
step "9 Summary"
rule rule
# Post-install wiring that must see the FINAL package state. The libvirt # Post-install wiring that must see the FINAL package state. The libvirt