docs: add claude.md and avoid dashes
This commit is contained in:
1 parent
dbdbfe5cd5
commit
c40dfe0238
22 files changed
+205
-158
No files matched your search
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# cachy-auto-update - unattended updates for CachyOS
|
||||
# cachy-auto-update: unattended updates for CachyOS
|
||||
#
|
||||
# The command line front end. Everything it does is either flipping a switch in
|
||||
# /etc/cachy-auto-update/cachy-auto-update.conf, driving the systemd timer, or
|
||||
@@ -77,10 +77,10 @@ cau_do_enable() {
|
||||
|
||||
cau_config_load
|
||||
if [[ $CFG_AUR == yes ]] && ! cau_aur_detect_quiet; then
|
||||
cau_note "$(cau_msg "No AUR helper found - install paru or yay for AUR updates.")"
|
||||
cau_note "$(cau_msg "No AUR helper found. Install paru or yay for AUR updates.")"
|
||||
fi
|
||||
if [[ $CFG_AUR == yes ]] && ! cau_have makepkg; then
|
||||
cau_note "$(cau_msg "base-devel is missing - AUR packages cannot be built without it.")"
|
||||
cau_note "$(cau_msg "base-devel is missing, so AUR packages cannot be built.")"
|
||||
fi
|
||||
|
||||
cau_offer_disable_cachy_update
|
||||
@@ -89,7 +89,7 @@ cau_do_enable() {
|
||||
|
||||
# CachyOS ships a pacman hook that pops up "Reboot recommended!" the moment a
|
||||
# kernel, driver or systemd package is unpacked. During a manual upgrade that
|
||||
# is fine - the transaction is the last thing happening. During an unattended
|
||||
# is fine, because the transaction is the last thing happening. During an unattended
|
||||
# one it lands in the middle: the run still has AUR packages to build and
|
||||
# Flatpaks to pull, and a notification asking for a restart right then is an
|
||||
# invitation to cut the update in half.
|
||||
@@ -141,7 +141,7 @@ cau_aur_detect_quiet() {
|
||||
|
||||
# cachy-update ships an enabled user timer that only ever says "N updates
|
||||
# available". Once updates apply themselves that notification is pure noise,
|
||||
# so offer to silence it - but only ask, never decide.
|
||||
# so offer to silence it. But only ask, never decide.
|
||||
cau_offer_disable_cachy_update() {
|
||||
local user uid answer found=0
|
||||
|
||||
@@ -163,7 +163,7 @@ cau_offer_disable_cachy_update() {
|
||||
read -r answer || return 0
|
||||
|
||||
# Defaults to yes: once updates install themselves, cachy-update's "N
|
||||
# updates available" is purely noise. "j" is accepted too - the prompt is
|
||||
# updates available" is purely noise. "j" is accepted too: the prompt is
|
||||
# translated, so a German user types the German letter and used to have
|
||||
# that silently read as "no".
|
||||
case "${answer,,}" in
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# cachy-auto-update-progress - the update's progress bar on the desktop
|
||||
# cachy-auto-update-progress: the update's progress bar on the desktop
|
||||
#
|
||||
# Started by the update runner, once per logged-in user, inside that user's
|
||||
# session. Reads one instruction per line on stdin and turns it into the same
|
||||
@@ -16,7 +16,7 @@
|
||||
#
|
||||
# Why a separate process at all: the desktop ties the progress entry to the
|
||||
# D-Bus connection that asked for it and withdraws the entry the moment that
|
||||
# connection goes away. One-shot callers - gdbus, busctl, dbus-send - therefore
|
||||
# connection goes away. One-shot callers (gdbus, busctl, dbus-send) therefore
|
||||
# cannot drive one, because each invocation is its own connection that closes
|
||||
# again immediately. So something has to sit there and hold the connection open
|
||||
# for as long as the update takes, and read its orders from somewhere else.
|
||||
@@ -54,7 +54,7 @@ class Job:
|
||||
reply = self.bus.call_sync(
|
||||
JOB_SERVICE, JOB_PATH, "org.kde.JobViewServerV2", "requestView",
|
||||
# capabilities 0: no cancel and no pause button. Neither can be
|
||||
# honoured - pacman's commit phase is not interruptible - and a
|
||||
# honoured, because pacman's commit phase is not interruptible. A
|
||||
# button that does nothing is worse than no button.
|
||||
GLib.Variant("(sia{sv})", (DESKTOP_ENTRY, 0, {})),
|
||||
GLib.VariantType("(o)"), Gio.DBusCallFlags.NONE, -1, None)
|
||||
@@ -68,8 +68,8 @@ class Job:
|
||||
JOB_SERVICE, self.path, "org.kde.JobViewV2", method, variant,
|
||||
None, Gio.DBusCallFlags.NONE, -1, None)
|
||||
except GLib.Error:
|
||||
# The desktop went away mid-update - a logout, or a plasmashell
|
||||
# restart. The update carries on without a bar.
|
||||
# The desktop went away mid-update (a logout, or a plasmashell
|
||||
# restart). The update carries on without a bar.
|
||||
self.path = None
|
||||
|
||||
def close(self, message=""):
|
||||
@@ -96,7 +96,7 @@ def main():
|
||||
try:
|
||||
job.open()
|
||||
except GLib.Error:
|
||||
# No job server on this desktop - anything that is not Plasma. Same
|
||||
# No job server on this desktop (anything that is not Plasma). Same
|
||||
# deal as a missing binding: drain stdin, stay out of the way.
|
||||
for _ in sys.stdin:
|
||||
pass
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# cachy-auto-update-run - one unattended update pass
|
||||
# cachy-auto-update-run: one unattended update pass
|
||||
#
|
||||
# Started by cachy-auto-update.service as root. The timer fires hourly and this
|
||||
# decides whether anything should happen; that is what makes deferrals free.
|
||||
@@ -43,7 +43,7 @@ fi
|
||||
# Force a neutral locale here rather than relying on the unit's Environment=,
|
||||
# so a run started by hand behaves exactly like one started by the timer.
|
||||
# pacman failures are classified by matching its output, and on a German system
|
||||
# that output is German. Text aimed at a person does not come through here - a
|
||||
# that output is German. Text aimed at a person does not come through here: a
|
||||
# notification is rendered in the recipient's own locale by cau_msg_in.
|
||||
export LC_ALL=C LANGUAGE=
|
||||
|
||||
@@ -65,7 +65,7 @@ cau_log_open
|
||||
|
||||
# Record an interruption rather than leaving the previous run's verdict behind.
|
||||
# Without this, killing an interactive run leaves last_result at whatever it was
|
||||
# before - so the menu can keep reporting a problem from hours ago while the
|
||||
# before. Then the menu can keep reporting a problem from hours ago while the
|
||||
# machine is in fact fully up to date, which is worse than saying nothing.
|
||||
# pacman makes the commit phase itself uninterruptible, so the packages either
|
||||
# all landed or none did; only our own bookkeeping is at risk here.
|
||||
@@ -193,8 +193,8 @@ progress_steps+=(cleanup)
|
||||
cau_progress_begin "${progress_steps[@]}"
|
||||
|
||||
# And carry the run log's last lines along with it, so "Details" shows what the
|
||||
# update is doing during the stretches that have nothing to count - an AUR
|
||||
# package building for a quarter of an hour, most of all.
|
||||
# update is doing during the stretches that have nothing to count. Most of all
|
||||
# an AUR package building for a quarter of an hour.
|
||||
cau_progress_tail_start "$CAU_RUNLOG"
|
||||
|
||||
if ! cau_pacman_update; then
|
||||
@@ -273,7 +273,7 @@ fi
|
||||
|
||||
# Recorded, deliberately not announced. The running kernel loses its module
|
||||
# tree the moment pacman unpacks the new one, so this turns true partway
|
||||
# through a run that still has AUR builds and Flatpaks ahead of it - and a
|
||||
# through a run that still has AUR builds and Flatpaks ahead of it. A
|
||||
# "restart recommended" bubble arriving then reads as an invitation to restart
|
||||
# while the update is still going. `cachy-auto-update status` and the menu say
|
||||
# so instead, where nobody is being interrupted mid-transaction.
|
||||
|
||||
+7
-7
@@ -49,8 +49,8 @@ export TEXTDOMAINDIR="${CAU_LOCALEDIR}"
|
||||
#
|
||||
# Standard POSIX precedence, deliberately: LC_ALL wins outright, and LC_ALL=C
|
||||
# really does mean English. The service sets LC_ALL=C so that pacman and upower
|
||||
# stay parseable, which makes the log English - correct, since the log is a
|
||||
# technical artefact. Anything aimed at a person (a desktop notification) does
|
||||
# stay parseable, which makes the log English. That is correct, since the log
|
||||
# is a technical artefact. Anything aimed at a person (a desktop notification) does
|
||||
# not go through here at all; it names the recipient's own locale explicitly
|
||||
# via cau_msg_in and cau_user_locale.
|
||||
cau_ui_locale() {
|
||||
@@ -117,8 +117,8 @@ cau_msg_in() {
|
||||
fi
|
||||
|
||||
# With no arguments the message is plain text, not a format string. Feeding
|
||||
# it to printf anyway turns any literal percent sign in it - "Battery (%)",
|
||||
# "100 % done" - into an invalid conversion, and that is a trap every
|
||||
# it to printf anyway turns any literal percent sign in it (like
|
||||
# "Battery (%)" or "100 % done") into an invalid conversion, and that is a trap every
|
||||
# translator would eventually walk into.
|
||||
if (( $# == 0 )); then
|
||||
printf '%s' "$translated"
|
||||
@@ -184,7 +184,7 @@ cau_log_open() {
|
||||
# Runs a command, capturing its combined output in the run log. Returns the
|
||||
# command's exit status.
|
||||
#
|
||||
# When a person is watching - `cachy-auto-update run` from a terminal - the
|
||||
# When a person is watching (`cachy-auto-update run` from a terminal), the
|
||||
# output is shown as well. Building an AUR package or pulling a few hundred
|
||||
# megabytes of Flatpak can take minutes, and silence for that long is
|
||||
# indistinguishable from a hang.
|
||||
@@ -207,8 +207,8 @@ cau_run_logged() {
|
||||
# Set by cau_bad and cau_note. The menu redraws immediately after an action,
|
||||
# which would wipe the screen; this marks that something was printed that the
|
||||
# user still has to read, so only those cases wait for a keypress. A plain
|
||||
# success needs no acknowledgement - the status block at the top of the menu
|
||||
# already shows the new state.
|
||||
# success needs no acknowledgement, because the status block at the top of the
|
||||
# menu already shows the new state.
|
||||
CAU_UI_NEEDS_ACK=''
|
||||
|
||||
cau_say() { printf '%s\n' "$*"; }
|
||||
|
||||
@@ -16,7 +16,7 @@ CAU_SKIP_REASON=''
|
||||
# cau_on_ac
|
||||
# True when running on mains power. systemd-ac-power also returns success when
|
||||
# the machine has neither a battery nor an adapter, which is exactly right for
|
||||
# desktops - hand-rolled sysfs globbing gets that case wrong.
|
||||
# desktops. Hand-rolled sysfs globbing gets that case wrong.
|
||||
cau_on_ac() {
|
||||
if cau_have systemd-ac-power; then
|
||||
systemd-ac-power > /dev/null 2>&1
|
||||
@@ -41,8 +41,8 @@ cau_on_ac() {
|
||||
# cau_battery_percent
|
||||
# Average charge across the system batteries, or failure when the machine has
|
||||
# none. Peripheral batteries (mice, headsets) advertise type=Battery too and
|
||||
# are filtered out via the scope attribute; when scope is missing entirely -
|
||||
# as on many laptops - the device counts as a system battery.
|
||||
# are filtered out via the scope attribute. When scope is missing entirely (as
|
||||
# on many laptops), the device counts as a system battery.
|
||||
cau_battery_percent() {
|
||||
local ps sum=0 count=0 cap
|
||||
|
||||
@@ -139,7 +139,7 @@ cau_gamemode_active() {
|
||||
while read -r user uid; do
|
||||
[[ -n $user ]] || continue
|
||||
# timeout runs inside the runuser call because it has to be a real
|
||||
# binary there - it cannot wrap a shell function from out here.
|
||||
# binary there. It cannot wrap a shell function from out here.
|
||||
out="$(cau_as_user "$user" "$uid" timeout 5 busctl --user --json=short \
|
||||
get-property com.feralinteractive.GameMode \
|
||||
/com/feralinteractive/GameMode \
|
||||
|
||||
+6
-6
@@ -4,8 +4,8 @@
|
||||
#
|
||||
# The contract this file implements: the machine's owner may run any package
|
||||
# manager at any time and must never see a lock error caused by us. We can only
|
||||
# guarantee that in one direction - by never *starting* while somebody else is
|
||||
# mid-transaction - so the checks here run before anything is touched, and a
|
||||
# guarantee that in one direction: by never *starting* while somebody else is
|
||||
# mid-transaction. So the checks here run before anything is touched, and a
|
||||
# refusal simply defers the run to the next hourly tick.
|
||||
|
||||
# Package managers that take /var/lib/pacman/db.lck. checkupdates is absent on
|
||||
@@ -65,7 +65,7 @@ cau_package_manager_busy() {
|
||||
#
|
||||
# The rigorous test is the boot time: no process that existed before the
|
||||
# current boot can still be running, so a db.lck older than boot is abandoned
|
||||
# by definition - which is exactly what a power cut during an update leaves
|
||||
# by definition. That is exactly what a power cut during an update leaves
|
||||
# behind. A lock that is merely unheld *within* this boot is not provable in
|
||||
# the same way, so it is only reported (see cau_track_stale_lock) and never
|
||||
# removed; guessing wrong there would corrupt a live transaction.
|
||||
@@ -90,12 +90,12 @@ cau_pacman_lock_is_stale() {
|
||||
# cau_recover_stale_lock
|
||||
# Clears a provably abandoned lock so an interrupted update can be finished on
|
||||
# the next run. Without this, one power cut during an update stops every future
|
||||
# update permanently and silently - the worst possible outcome for a machine
|
||||
# nobody is watching.
|
||||
# update permanently and silently. That is the worst possible outcome for a
|
||||
# machine nobody is watching.
|
||||
cau_recover_stale_lock() {
|
||||
cau_pacman_lock_is_stale || return 1
|
||||
|
||||
cau_warn "Found a pacman lock older than this boot - an update was cut short"
|
||||
cau_warn "Found a pacman lock older than this boot. An update was cut short"
|
||||
rm -f "$CAU_PACMAN_LOCK" 2>/dev/null || {
|
||||
cau_error "Could not remove the stale pacman lock"
|
||||
return 1
|
||||
|
||||
+8
-8
@@ -32,7 +32,7 @@ cau_ui_term_restore() {
|
||||
}
|
||||
|
||||
# Runs an action with the terminal handed back to normal line mode, so anything
|
||||
# it prints - or prompts for - behaves the way a program expects.
|
||||
# it prints or prompts for behaves the way a program expects.
|
||||
cau_ui_cooked() {
|
||||
cau_ui_term_restore
|
||||
"$@"
|
||||
@@ -213,8 +213,8 @@ _cau_setting_cycle() {
|
||||
# A cursor list rather than a numbered menu: there are eighteen settings, and
|
||||
# numbering them would run out of digits and force paging.
|
||||
#
|
||||
# The frame is assembled in memory and written once. Everything constant - the
|
||||
# specs, the translated labels, the clear sequence - is resolved before the
|
||||
# The frame is assembled in memory and written once. Everything constant (the
|
||||
# specs, the translated labels, the clear sequence) is resolved before the
|
||||
# loop, and the values are re-read only after something actually changes.
|
||||
# Drawing the naive way cost a command substitution per label per frame, which
|
||||
# measured 435 ms per keypress: arrow keys felt like the console was reloading,
|
||||
@@ -239,7 +239,7 @@ cau_ui_settings() {
|
||||
|
||||
local title hint
|
||||
cau_msg_into "$locale" "Settings"; title="$CAU_MSG_RESULT"
|
||||
cau_msg_into "$locale" "Up/Down select - Space or Right changes - q goes back"
|
||||
cau_msg_into "$locale" "Up/Down: select, Space or Right: change, q: back"
|
||||
hint="$CAU_MSG_RESULT"
|
||||
|
||||
# the terminfo clear string, fetched once instead of forking per frame
|
||||
@@ -320,8 +320,8 @@ cau_ui_edit_text() {
|
||||
# _cau_row <label> <value>
|
||||
# printf's %-28s pads by bytes, so a label containing "ü" comes out one column
|
||||
# short. ${#s} counts characters in a UTF-8 locale, so the padding is computed
|
||||
# here instead - and applied inline, because command substitution would eat the
|
||||
# trailing spaces again.
|
||||
# here instead. It is applied inline, because command substitution would eat
|
||||
# the trailing spaces again.
|
||||
_cau_row() {
|
||||
local label="$1" value="$2" pad
|
||||
pad=$(( 28 - ${#label} ))
|
||||
@@ -389,7 +389,7 @@ cau_ui_status() {
|
||||
|
||||
if [[ $result == failed ]]; then
|
||||
printf '\n %s%s%s\n' "$CAU_C_YELLOW" \
|
||||
"$(cau_msg "The last run reported a problem - see 'cachy-auto-update log'.")" \
|
||||
"$(cau_msg "The last run reported a problem. See 'cachy-auto-update log'.")" \
|
||||
"$CAU_C_RESET"
|
||||
elif [[ $result == interrupted ]]; then
|
||||
printf '\n %s%s%s\n' "$CAU_C_YELLOW" \
|
||||
@@ -510,7 +510,7 @@ cau_ui_menu() {
|
||||
5) cau_ui_status_conditions; cau_pause ;;
|
||||
6) cau_ui_settings ;;
|
||||
q|Q) cau_ui_term_restore; trap - EXIT INT TERM; return 0 ;;
|
||||
# Anything else - Enter, arrow keys, stray characters - just
|
||||
# Anything else (Enter, arrow keys, stray characters) just
|
||||
# redraws. Escape is deliberately not a quit key, so a mistyped
|
||||
# arrow key cannot close the menu.
|
||||
*) ;;
|
||||
|
||||
+7
-7
@@ -3,10 +3,10 @@
|
||||
# Desktop notifications from a root system service.
|
||||
#
|
||||
# Two paths exist:
|
||||
# * live - somebody has a graphical session, so notify-send is run inside
|
||||
# it via runuser with the session bus address set;
|
||||
# * queued - nobody is logged in, so the message is appended to a spool that
|
||||
# the XDG autostart entry replays at the next login.
|
||||
# * live: somebody has a graphical session, so notify-send is run inside
|
||||
# it via runuser with the session bus address set;
|
||||
# * queued: nobody is logged in, so the message is appended to a spool that
|
||||
# the XDG autostart entry replays at the next login.
|
||||
#
|
||||
# Messages travel as a msgid plus printf arguments rather than as finished
|
||||
# text, so a notification queued at 04:00 is still rendered in whatever locale
|
||||
@@ -44,8 +44,8 @@ cau_notify_close() {
|
||||
# had to be skipped is only ever seen if it waits.
|
||||
#
|
||||
# Set explicitly rather than left to the server. Notification daemons do keep
|
||||
# critical-urgency messages up - the spec asks them to, and Plasma obliges -
|
||||
# but that is a "should", it says nothing about the normal-urgency messages
|
||||
# critical-urgency messages up (the spec asks them to, and Plasma obliges).
|
||||
# But that is a "should", it says nothing about the normal-urgency messages
|
||||
# here that still need somebody to act, and urgency separately controls sound
|
||||
# and whether do-not-disturb is overridden. Those are not the same question.
|
||||
#
|
||||
@@ -136,7 +136,7 @@ cau_notify_enqueue() {
|
||||
|
||||
printf '%s\n' "$record" >> "$CAU_NOTIFY_QUEUE" 2>/dev/null || return 0
|
||||
|
||||
# keep the spool bounded - nobody wants three weeks of backlog at login
|
||||
# keep the spool bounded: nobody wants three weeks of backlog at login
|
||||
if (( $(wc -l < "$CAU_NOTIFY_QUEUE" 2>/dev/null || echo 0) > CAU_NOTIFY_QUEUE_MAX )); then
|
||||
tmp="$(mktemp "${CAU_NOTIFY_QUEUE}.XXXXXX")" || return 0
|
||||
tail -n "$CAU_NOTIFY_QUEUE_MAX" "$CAU_NOTIFY_QUEUE" > "$tmp"
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
#
|
||||
# AppImages have no package manager of their own; Gear Lever is what tracks
|
||||
# where each one came from and how to fetch a new build. Its CLI is a first
|
||||
# class interface - `--update --all -y` is exactly the unattended entry point
|
||||
# class interface: `--update --all -y` is exactly the unattended entry point
|
||||
# we need, and it skips AppImages whose application is currently running rather
|
||||
# than pulling the file out from under it (we deliberately do not pass
|
||||
# --force).
|
||||
#
|
||||
# This only runs for users with a live graphical session: Gear Lever is a
|
||||
# Flatpak GTK application and needs the session's runtime directory. Nothing is
|
||||
# lost by waiting - the next hourly tick will catch it once they log in.
|
||||
# lost by waiting, because the next hourly tick will catch it once they log in.
|
||||
|
||||
CAU_APPIMAGE_ID="it.mijorus.gearlever"
|
||||
CAU_APPIMAGE_COUNT=0
|
||||
@@ -45,7 +45,7 @@ cau_appimage_update() {
|
||||
|
||||
# Is there a Gear Lever on this machine at all? Asked before the step is
|
||||
# announced rather than discovered inside the loop: on a machine without
|
||||
# one - the common case, it is an optional dependency - a step that exists
|
||||
# one (the common case, it is an optional dependency), a step that exists
|
||||
# only to hand its share of the bar straight to the next one is a jump the
|
||||
# bar does not need. Stops at the first user who has it, so the extra probe
|
||||
# costs anything only in the case it is there to remove.
|
||||
|
||||
+3
-3
@@ -2,15 +2,15 @@
|
||||
#
|
||||
# AUR packages.
|
||||
#
|
||||
# makepkg - and therefore paru and yay - refuse to run as root, so this is the
|
||||
# makepkg (and therefore paru and yay) refuse to run as root, so this is the
|
||||
# one part of the run that cannot happen in the service's own context. It is
|
||||
# executed as the locked "cachy-auto-update" system account instead, which
|
||||
# sysusers.d creates with no password and no shell. That account is granted
|
||||
# NOPASSWD access to /usr/bin/pacman through /etc/sudoers.d/cachy-auto-update,
|
||||
# which is what lets the helper install what it built without a human present.
|
||||
#
|
||||
# The alternative - stashing the user's password somewhere the daemon can read
|
||||
# it - buys nothing: whatever can decrypt it is exactly what an attacker would
|
||||
# The alternative (stashing the user's password somewhere the daemon can read
|
||||
# it) buys nothing: whatever can decrypt it is exactly what an attacker would
|
||||
# already have.
|
||||
|
||||
CAU_AUR_COUNT=0
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# System-wide installations are updated directly as root. That side-steps a
|
||||
# real obstacle: the shipped polkit rule for Flatpak only grants install and
|
||||
# uninstall, and only to a subject that is active, local and in the wheel
|
||||
# group - none of which is true for an unattended service. Being root means
|
||||
# group. None of that is true for an unattended service. Being root means
|
||||
# polkit is never consulted in the first place.
|
||||
#
|
||||
# Per-user installations live in the user's home and are updated inside their
|
||||
@@ -77,7 +77,7 @@ cau_flatpak_update() {
|
||||
fi
|
||||
done < <(cau_human_users)
|
||||
|
||||
# Unused runtimes are the Flatpak equivalent of orphaned packages - this is
|
||||
# Unused runtimes are the Flatpak equivalent of orphaned packages. This is
|
||||
# removal of installed software, not cache trimming, so it belongs behind
|
||||
# RemoveOrphans rather than CleanCache.
|
||||
if [[ $CFG_REMOVE_ORPHANS == yes ]]; then
|
||||
|
||||
+10
-10
@@ -39,7 +39,7 @@ CAU_PACMAN_OP_RE='^(\([[:space:]]*[0-9]+/[0-9]+\) )?(upgrading|installing|reinst
|
||||
#
|
||||
# glibc-2.44+r24+g16be1518495f-1-x86_64_v3 downloading...
|
||||
#
|
||||
# and nothing else - no counter, no total - so the position here is counted the
|
||||
# and nothing else: no counter, no total. So the position here is counted the
|
||||
# same way the transaction is.
|
||||
#
|
||||
# The database sync a few lines earlier prints the very same shape (" core
|
||||
@@ -55,7 +55,7 @@ CAU_PACMAN_DL_AWK='
|
||||
# Feeds the desktop's progress bar by watching pacman work, through the three
|
||||
# phases a pacman run has: first it works out what the upgrade consists of,
|
||||
# then everything is fetched, then everything is unpacked. Three steps on the
|
||||
# bar rather than one, because they are three stretches to sit through - and
|
||||
# bar rather than one, because they are three stretches to sit through. And
|
||||
# each one is silent in its own way.
|
||||
#
|
||||
# The first is the one that used to look like a hang. Between "starting full
|
||||
@@ -73,7 +73,7 @@ CAU_PACMAN_DL_AWK='
|
||||
#
|
||||
# Only the second carries a counter, and the unattended runs that this bar
|
||||
# exists for are exactly the ones that do not get it. So the position is
|
||||
# counted here instead - one line per package - and the total taken from the
|
||||
# counted here instead (one line per package), and the total taken from the
|
||||
# "Package (218)" header pacman prints before it starts. That header is the
|
||||
# better number anyway: checkupdates counts packages with an update available
|
||||
# and knows nothing about the new dependencies pulled in alongside them.
|
||||
@@ -104,9 +104,9 @@ _cau_pacman_progress_watch() {
|
||||
|
||||
if [[ -n $line ]]; then
|
||||
# Unpacking has started, so whatever came before it is over. If
|
||||
# nothing was ever retrieved - every package already sitting in the
|
||||
# cache, which is the ordinary state of affairs after a run that was
|
||||
# interrupted once already - then the download step never happened,
|
||||
# nothing was ever retrieved (every package already sitting in the
|
||||
# cache, which is normal after a run that was interrupted once
|
||||
# already), then the download step never happened,
|
||||
# and it is dropped rather than handed its whole share of the bar in
|
||||
# exchange for no work at all.
|
||||
if [[ $phase != install ]]; then
|
||||
@@ -189,7 +189,7 @@ _cau_pacman_exec() {
|
||||
fi
|
||||
|
||||
# Line-buffered on purpose. pacman writes to a file or through a pipe here,
|
||||
# never to a terminal, so libc buffers it in 4KB blocks - and 4KB of
|
||||
# never to a terminal, so libc buffers it in 4KB blocks. And 4KB of
|
||||
# "upgrading foo..." is on the order of a hundred and sixty packages. The
|
||||
# watcher would see nothing at all, then a hundred and sixty lines at once,
|
||||
# which is exactly how a bar comes to sit still and then leap to the end.
|
||||
@@ -321,7 +321,7 @@ cau_pacman_update() {
|
||||
#
|
||||
# While an upgrade runs, a shutdown request is refused by logind and the
|
||||
# desktop answers with a polkit password prompt reading "Power off the
|
||||
# system while an application is inhibiting this" - which never mentions
|
||||
# system while an application is inhibiting this". That never mentions
|
||||
# updates and, on a German system, is not even translated. Somebody who was
|
||||
# simply told beforehand does not end up staring at that.
|
||||
if [[ $CFG_NOTIFY_START == yes ]]; then
|
||||
@@ -393,7 +393,7 @@ cau_pacman_update() {
|
||||
|
||||
dependency)
|
||||
# Something installed still depends on a package the repos want
|
||||
# to drop or replace - almost always an AUR package that has not
|
||||
# to drop or replace, almost always an AUR package that has not
|
||||
# caught up yet. Nothing here can fix that, and it is not worth
|
||||
# failing over: letting one stuck package block every other
|
||||
# update indefinitely is far worse on an unattended machine.
|
||||
@@ -468,7 +468,7 @@ cau_pacman_cleanup() {
|
||||
reclaim="$( { paccache -d --nocolor -k"$CFG_KEEP_OLD"; paccache -du --nocolor -k0; } 2>&1 \
|
||||
| grep -oE 'disk space saved: [^)]*' | paste -sd', ' -)"
|
||||
|
||||
cau_info "Trimming the package cache (keeping $CFG_KEEP_OLD old version(s))${reclaim:+ - $reclaim}"
|
||||
cau_info "Trimming the package cache (keeping $CFG_KEEP_OLD old version(s))${reclaim:+: $reclaim}"
|
||||
cau_run_logged paccache -r --nocolor -k"$CFG_KEEP_OLD" || cau_warn "paccache -r failed"
|
||||
cau_run_logged paccache -ru --nocolor -k0 || cau_warn "paccache -ru failed"
|
||||
fi
|
||||
|
||||
+24
-24
@@ -3,8 +3,8 @@
|
||||
# The update's progress bar on the desktop.
|
||||
#
|
||||
# An unattended upgrade can take twenty minutes, and for most of that a user is
|
||||
# told only that "an update is running". This drives the desktop's job list -
|
||||
# the same widget that shows a bar while Dolphin copies files - so how far
|
||||
# told only that "an update is running". This drives the desktop's job list
|
||||
# (the same widget that shows a bar while Dolphin copies files), so how far
|
||||
# along the run is stays visible the whole time.
|
||||
#
|
||||
# The desktop ends the progress entry as soon as the D-Bus connection that
|
||||
@@ -14,8 +14,8 @@
|
||||
# of those pipes, plus the arithmetic that turns "package 120 of 260 in the
|
||||
# repository step" into one number for the bar.
|
||||
#
|
||||
# Absent anywhere along the way - no session, no Plasma, no Python bindings -
|
||||
# this does nothing at all and the update proceeds exactly as before.
|
||||
# If anything is missing along the way (no session, no Plasma, no Python
|
||||
# bindings), this does nothing at all and the update proceeds exactly as before.
|
||||
|
||||
CAU_PROGRESS_HELPER="${CAU_LIBEXECDIR}/cachy-auto-update-progress"
|
||||
|
||||
@@ -26,14 +26,14 @@ CAU_PROGRESS_FIFOS=()
|
||||
CAU_PROGRESS_LOCALES=()
|
||||
|
||||
# What each step is worth on the bar. Rough shares of a typical run rather than
|
||||
# anything measured: the repositories dominate - fetching them and unpacking
|
||||
# them about equally, on a domestic line - and the cleanup is a rounding error.
|
||||
# They do not have to add up to 100 - only the steps a given run will actually
|
||||
# anything measured: the repositories dominate (fetching them and unpacking
|
||||
# them about equally, on a domestic line), and the cleanup is a rounding error.
|
||||
# They do not have to add up to 100. Only the steps a given run will actually
|
||||
# perform are counted, and the total is normalised against those.
|
||||
#
|
||||
# "resolve" is everything pacman does before it has a transaction: syncing the
|
||||
# databases and working out what the upgrade actually consists of. It is
|
||||
# usually seconds, which is why it is worth so little - but on a large backlog
|
||||
# usually seconds, which is why it is worth so little. But on a large backlog
|
||||
# it is minutes, and those minutes used to be spent looking at a bar that had
|
||||
# not moved yet.
|
||||
declare -A CAU_PROGRESS_WEIGHTS=(
|
||||
@@ -147,7 +147,7 @@ cau_progress_active() {
|
||||
# turns up while it runs: nothing to download because every package was already
|
||||
# in the cache, no AUR updates pending, no Flatpaks installed. A step like that
|
||||
# keeps its whole share of the bar and then hands it over in a single jump the
|
||||
# moment the next one starts - which is precisely the stutter this is here to
|
||||
# moment the next one starts. That is precisely the stutter this is here to
|
||||
# remove. Dropping it hands its share to the steps that do have work instead,
|
||||
# so the bar advances at a steady pace rather than leaping across the gaps.
|
||||
#
|
||||
@@ -243,7 +243,7 @@ _cau_progress_pct() {
|
||||
|
||||
# Never backwards. Two honest things can ask for that: dropping a step
|
||||
# rescales the run against a smaller total, and the conflict-recovery loop
|
||||
# restarts pacman - and with it the item tally - from the top. Both are
|
||||
# restarts pacman (and with it the item tally) from the top. Both are
|
||||
# real, neither is a reason to show somebody a bar that retreats.
|
||||
(( pct < CAU_PROGRESS_SHOWN )) && pct=$CAU_PROGRESS_SHOWN
|
||||
|
||||
@@ -282,16 +282,16 @@ cau_progress_item() {
|
||||
# whatsoever between "starting full system upgrade" and the transaction it
|
||||
# eventually prepares; an AUR helper compiling a package prints plenty, none of
|
||||
# it countable. On a large backlog either is minutes. There is no honest number
|
||||
# to show for that - but a bar that has not moved since it appeared is read as
|
||||
# to show for that. But a bar that has not moved since it appeared is read as
|
||||
# a hang, and somebody who reads it that way reaches for the power button in
|
||||
# the middle of an update. That is the failure this is here to prevent.
|
||||
#
|
||||
# So it creeps, along a curve that approaches the end of the step without ever
|
||||
# reaching it: half the step's share after HALFLIFE seconds, three quarters
|
||||
# after three times that, the whole of it never. Nothing is claimed that is not
|
||||
# known - the item counter stays empty throughout, which is the field that
|
||||
# would be lying if it moved - and the step still finishes the instant real
|
||||
# work reports in, because every real report is further along than the creep.
|
||||
# known: the item counter stays empty throughout, and it is the field that
|
||||
# would be lying if it moved. The step still finishes the instant real work
|
||||
# reports in, because every real report is further along than the creep.
|
||||
#
|
||||
# Confined to the step's own span, so a creep can never overtake the step that
|
||||
# comes after it however long it is left running.
|
||||
@@ -324,8 +324,8 @@ cau_progress_creep_start() {
|
||||
# reason cau_progress_begin opens its fifo read-write: a pipe held open
|
||||
# at both ends never reports end-of-file, so a timed read on it blocks
|
||||
# for exactly the timeout and nothing else. A forked sleep would also
|
||||
# survive the kill below - it is a child of this subshell, not this
|
||||
# subshell - and inherit the fifo's write end, which would keep the
|
||||
# survive the kill below (it is a child of this subshell, not this
|
||||
# subshell) and inherit the fifo's write end, which would keep the
|
||||
# helper from seeing the end of its input until the sleep ran out.
|
||||
local nap
|
||||
exec {nap}<> <(:)
|
||||
@@ -345,15 +345,15 @@ cau_progress_creep_stop() {
|
||||
|
||||
# The ticker moved the bar from inside a subshell, so this side never saw
|
||||
# it happen and still believes the bar is where it was left. Catching up
|
||||
# costs one recomputation - the curve is a function of elapsed time and
|
||||
# nothing else - and without it the next ordinary report from here would be
|
||||
# costs one recomputation, since the curve is a function of elapsed time and
|
||||
# nothing else. Without it the next ordinary report from here would be
|
||||
# measured against a stale percentage and send the bar backwards.
|
||||
cau_progress_creep $(( SECONDS - CAU_PROGRESS_CREEP_T0 ))
|
||||
}
|
||||
|
||||
# cau_progress_detail <label-msgid> <value>
|
||||
# A labelled line under the entry's "Details" - which package is being unpacked
|
||||
# right now, say.
|
||||
# A labelled line under the entry's "Details", for example which package is
|
||||
# being unpacked right now.
|
||||
cau_progress_detail() {
|
||||
local label="$1" value="$2" i fd
|
||||
|
||||
@@ -383,7 +383,7 @@ CAU_PROGRESS_TAIL_PID=0
|
||||
#
|
||||
# The protocol is one instruction per line, so the tail travels tab separated
|
||||
# and is put back together on the other side. Tabs inside a log line would
|
||||
# split it in two on the way, so they become spaces first - the job view
|
||||
# split it in two on the way, so they become spaces first. The job view
|
||||
# renders either as whitespace, and a line broken in half renders as nonsense.
|
||||
cau_progress_log() {
|
||||
local label="$1" text="$2" i fd
|
||||
@@ -465,12 +465,12 @@ cau_progress_end() {
|
||||
|
||||
# Before the descriptors go: anything still running in the background holds
|
||||
# its own copy of them, so the helper would not see the end of its input
|
||||
# until it exited - and it is about to be waited on.
|
||||
# until it exited. And it is about to be waited on.
|
||||
cau_progress_creep_stop
|
||||
cau_progress_tail_stop
|
||||
|
||||
# The last step never consumes its own share - nothing reports items for
|
||||
# the cleanup - so the bar would stop a few percent short of the end and
|
||||
# The last step never consumes its own share (nothing reports items for
|
||||
# the cleanup), so the bar would stop a few percent short of the end and
|
||||
# vanish there. Only on the way out of a run that actually worked, though:
|
||||
# filling the bar for a failed update says the opposite of what happened.
|
||||
[[ $outcome == ok ]] && _cau_progress_line 'percent\t100'
|
||||
|
||||
Reference in new issue
Block a user