diff --git a/lib/common.sh b/lib/common.sh index adb408d..554fac8 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -91,21 +91,49 @@ ui_quiet_run() { local log="${SETUP_DNF_LOG:-/tmp/fedora-setup-dnf.log}" local before n - if ! have_gum; then + # Live-quiet mode needs only an interactive terminal (stdin tty + writable + # /dev/tty), NOT gum — the progress line is pure bash. Unattended runs and + # pipes keep plain full output (logs/cron contract). + if [[ "${ASSUME_YES:-false}" == "true" ]] || [ ! -t 0 ] || [ ! -w /dev/tty ]; then "$@" return $? fi before=$(wc -l < "$log" 2>/dev/null || echo 0) - if LOGFILE="$log" gum spin --title "$msg" -- \ - bash -c 'exec "$@" >>"$LOGFILE" 2>&1' _ "$@"; then + + # Child writes to the log; we draw a LIVE line: spinner frame + the package + # dnf is currently working on. gum spin was tried here first but rendered + # as a frozen block on the real VM ("looks like it hangs") — this variant + # animates independently of gum and shows real progress, not just motion. + "$@" >>"$log" 2>&1 & + local pid=$! + local frames=( '⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏' ) + local f=0 cur + while kill -0 "$pid" 2>/dev/null; do + cur=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null \ + | grep -E '^(Installing|Upgrading|Downgrading|Removing|Verifying|Preparing|Cleanup):' \ + | tail -n 1 || true) + if [[ -n "$cur" ]]; then + printf '\r %s %s — %s' "${frames[$f]}" "$msg" "$cur" >&2 + else + printf '\r %s %s' "${frames[$f]}" "$msg" >&2 + fi + f=$(( (f + 1) % ${#frames[@]} )) + sleep 0.15 + done + + local rc=0 + wait "$pid" || rc=$? + # wipe the progress line before printing the result + printf '\r%*s\r' 100 '' >&2 + + if (( rc == 0 )); then n=$(sed -n "$((before+1)),\$p" "$log" 2>/dev/null | grep -c '^Installing:' || true) local plural="s" (( n == 1 )) && plural="" ok "$msg (${n} package${plural})" return 0 else - local rc=$? color_red " Failed: $msg" color_red " Last lines from $log:" sed -n "$((before+1)),\$p" "$log" 2>/dev/null | tail -n 20 | sed 's/^/ /' >&2