Improve the update script UI

This commit is contained in:
SirBlob committed 2026-09-24 02:53:27 +00:00
1 parent 4c60929aff
commit b05311d814
2 files changed
+216 -12

No files matched your search

+209 -10
View File
@@ -4,33 +4,232 @@
# blob:args=[--no-confirm] # blob:args=[--no-confirm]
# blob:requires-sudo=true # blob:requires-sudo=true
set -e set -eE
confirm=true confirm=true
[[ ${1-} == --no-confirm ]] && confirm=false [[ ${1-} == --no-confirm ]] && confirm=false
if [[ $confirm == true ]]; then accent_color=4
read -rp "Update system and AUR packages? [y/N] " answer muted_color=8
[[ $answer == [yY] ]] || exit 0 success_color=2
failure_color=1
total_steps=4
current_step=0
current_label="Checking for updates"
started_at=$SECONDS
repo_updates=""
aur_updates=""
counts_known=false
aur_reachable=false
reboot_needed=false
orphan_count=0
has_gum() {
command -v gum &>/dev/null
}
styled() {
local color="$1"
shift
if has_gum; then
gum style --foreground "$color" "$@"
else
local argument
for argument in "$@"; do
[[ $argument == --* ]] || printf '%s\n' "$argument"
done
fi
}
line_count() {
[[ -n $1 ]] || { echo 0; return; }
grep -c . <<<"$1"
}
show_header() {
if has_gum; then
gum style --border rounded --border-foreground "$accent_color" --padding "0 2" --margin "1 0" \
--bold "Blob Update" "$(date '+%A %-d %B, %H:%M')"
else
printf '\nBlob Update - %s\n\n' "$(date '+%A %-d %B, %H:%M')"
fi
}
begin_step() {
current_step=$((current_step + 1))
current_label="$1"
echo
styled "$accent_color" --bold "[$current_step/$total_steps] $1"
}
skip_step() {
begin_step "$1"
styled "$muted_color" " $2"
}
report_failure() {
trap - ERR
echo
styled "$failure_color" --bold "Update failed while: $current_label"
blob-notify-send -u critical "Update failed" "Stopped while: $current_label" || true
exit 1
}
trap report_failure ERR
print_update_list() {
local title="$1" updates="$2"
styled "$accent_color" --bold "$title ($(line_count "$updates"))"
if [[ -z $updates ]]; then
styled "$muted_color" " none"
return
fi
awk '{ printf " %-34s %s -> %s\n", $1, $2, $4 }' <<<"$updates"
}
gather_pending() {
if has_gum; then
gum spin --spinner dot --title "Checking the AUR..." -- blob-pkg-aur && aur_reachable=true || true
else
echo "Checking the AUR..."
blob-pkg-aur && aur_reachable=true || true
fi
blob-cmd-present checkupdates || return 0
counts_known=true
local check_status=0
if has_gum; then
repo_updates=$(gum spin --spinner dot --title "Checking for system updates..." --show-output -- checkupdates 2>/dev/null) || check_status=$?
else
echo "Checking for system updates..."
repo_updates=$(checkupdates 2>/dev/null) || check_status=$?
fi
if (( check_status == 1 )); then
counts_known=false
repo_updates=""
styled "$muted_color" "Could not check for system updates; updating anyway."
return 0
fi
if blob-cmd-present yay && [[ $aur_reachable == true ]]; then
aur_updates=$(yay -Qua 2>/dev/null || true)
fi
if grep -qE '^linux(-lts|-zen|-hardened)? ' <<<"$repo_updates"; then
reboot_needed=true
fi
}
show_pending() {
[[ $counts_known == true ]] || return 0
echo
print_update_list "System packages" "$repo_updates"
echo
if blob-cmd-present yay && [[ $aur_reachable == true ]]; then
print_update_list "AUR packages" "$aur_updates"
else
styled "$muted_color" "AUR packages: not checked"
fi
}
confirm_update() {
[[ $confirm == true ]] || return 0
echo
local question="Update system and AUR packages?"
if [[ $counts_known == true ]]; then
question="Install $(( $(line_count "$repo_updates") + $(line_count "$aur_updates") )) update(s)?"
fi
if has_gum; then
gum confirm "$question" || exit 0
else
local answer
read -rp "$question [y/N] " answer
[[ $answer == [yY] ]] || exit 0
fi
}
format_duration() {
local seconds=$1
if (( seconds >= 60 )); then
printf '%dm %ds' $((seconds / 60)) $((seconds % 60))
else
printf '%ds' "$seconds"
fi
}
show_summary() {
local elapsed
elapsed=$(format_duration $((SECONDS - started_at)))
echo
if has_gum; then
local summary_lines=()
if [[ $counts_known == true ]]; then
summary_lines+=("System packages $(line_count "$repo_updates")")
summary_lines+=("AUR packages $(line_count "$aur_updates")")
fi
summary_lines+=("Orphans removed $orphan_count")
summary_lines+=("Time $elapsed")
gum style --border rounded --border-foreground "$success_color" --padding "0 2" \
"$(gum style --foreground "$success_color" --bold "Update complete")" "" "${summary_lines[@]}"
else
echo "Update complete in $elapsed."
[[ $counts_known == true ]] && echo "System: $(line_count "$repo_updates"), AUR: $(line_count "$aur_updates"), orphans removed: $orphan_count"
fi
if [[ $reboot_needed == true ]]; then
echo
styled "$accent_color" --bold "A new kernel was installed. Reboot to start using it."
fi
}
show_header
gather_pending
if [[ $counts_known == true && -z $repo_updates && -z $aur_updates ]]; then
echo
styled "$success_color" --bold "Everything is up to date."
if blob-cmd-present yay && [[ $aur_reachable != true ]]; then
styled "$muted_color" "The AUR was not reachable, so AUR packages were not checked."
fi
exit 0
fi fi
show_pending
confirm_update
blob-sudo-keepalive blob-sudo-keepalive
echo "Refreshing the keyring..." begin_step "Refreshing the keyring"
sudo pacman -Sy --needed --noconfirm archlinux-keyring sudo pacman -Sy --needed --noconfirm archlinux-keyring
echo "Updating system packages..." begin_step "Updating system packages"
sudo pacman -Syu --noconfirm sudo pacman -Syu --noconfirm
if blob-cmd-present yay && blob-pkg-aur; then if ! blob-cmd-present yay; then
echo "Updating AUR packages..." skip_step "Updating AUR packages" "Skipped: yay is not installed"
elif [[ $aur_reachable != true ]]; then
skip_step "Updating AUR packages" "Skipped: the AUR is not reachable"
else
begin_step "Updating AUR packages"
yay -Sua --noconfirm yay -Sua --noconfirm
fi fi
begin_step "Removing orphaned packages"
orphans=$(pacman -Qtdq 2>/dev/null || true) orphans=$(pacman -Qtdq 2>/dev/null || true)
if [[ -n $orphans ]]; then if [[ -n $orphans ]]; then
echo "Removing orphaned packages..." orphan_count=$(line_count "$orphans")
printf '%s\n' "$orphans" | sudo pacman -Rns --noconfirm - printf '%s\n' "$orphans" | sudo pacman -Rns --noconfirm -
else
styled "$muted_color" " None to remove"
fi fi
blob-notify-send "Update complete" "System and AUR packages are up to date" show_summary
notify_body="System and AUR packages are up to date"
[[ $reboot_needed == true ]] && notify_body="$notify_body. Reboot to use the new kernel."
blob-notify-send "Update complete" "$notify_body"
+7 -2
View File
@@ -163,8 +163,13 @@ it will not rewrite for a bootloader other than GRUB.
blob update blob update
``` ```
Refreshes the keyring, runs `pacman -Syu`, runs `yay -Sua` when the AUR is Checks for updates first and lists every pending system and AUR package with
reachable, prunes orphans, and sends a notification. `blob update-available` its old and new version, then asks once with `gum confirm` (`--no-confirm`
skips it). When nothing is pending it says so and stops. The update itself runs
as four numbered steps: refresh the keyring, `pacman -Syu`, `yay -Sua` when the
AUR is reachable, and prune orphans. It ends with a summary of what changed and
how long it took, a reminder to reboot when a new kernel came in, and a
notification. A failed step is named on screen and in a critical notification. `blob update-available`
prints the pending count that the bar's update indicator reads. The indicator prints the pending count that the bar's update indicator reads. The indicator
rechecks every six hours and a few seconds after any pacman transaction, so it rechecks every six hours and a few seconds after any pacman transaction, so it
clears as soon as an update, from `blob update` or by hand, finishes. clears as soon as an update, from `blob update` or by hand, finishes.