feat(aur/install-hook): proactive legacy-cruft detection
Common upgrade snags from pre-v2 setups that the 2.0.0 hook didn't
catch in time. Both detected read-only and reported with precise
remediation; the hook never modifies user files.
1. Stale ~/.config/systemd/user/owlry{,d}.{service,socket} overrides.
systemd-user gives precedence to ~/.config/systemd/user/* over
/usr/lib/systemd/user/*. A leftover dev-time override (e.g. from
'just install-local' in a 1.x tree) silently masks the AUR-shipped
unit. We classify them:
- references the deleted owlryd binary
- points at a dev-time target/debug or target/release path
- redundant override of the canonical /usr/bin/owlry
- non-standard ExecStart (flagged for review)
2. Compositor autostart referencing 'owlryd':
~/.config/hypr/hyprland.conf and any *.conf / *.hyprlang in hypr/
~/.config/sway/config
~/.config/i3/config
~/.config/river/init
~/.config/niri/config.kdl
Each affected user gets a banner with the exact rm + systemctl --user
commands to run (and what to replace 'owlryd' with in compositor
configs). The hook reads only — it never executes the cleanup itself.
Runs on:
- 1.x -> 2.x upgrades (alongside the existing rename banner)
- 2.0.0 -> 2.0.1 upgrade (re-runs the detection idempotently for
users who missed cleanup the first time around)
The 1.x banner copy is touched lightly: bookmarks now appears in the
'deferred' line alongside the widgets (D22).
This commit is contained in:
+131
-21
@@ -1,8 +1,127 @@
|
||||
## owlry .install hook
|
||||
##
|
||||
## v2.0 renamed the systemd user units (owlryd.{service,socket} → owlry.{service,socket})
|
||||
## and consolidated 14 separate packages into one. Handle the unit migration so users
|
||||
## upgrading from 1.x don't end up with an enabled-but-missing owlryd.service.
|
||||
## and consolidated 14 separate packages into one.
|
||||
##
|
||||
## 2.0.1 extends this hook with proactive detection of two common upgrade snags:
|
||||
## 1. Stale ~/.config/systemd/user/owlry{,d}.{service,socket} overrides pointing
|
||||
## at a deleted dev-time build path or the removed `owlryd` binary. systemd-user
|
||||
## gives precedence to user-level units over /usr/lib/systemd/user/*, so a
|
||||
## stale override silently breaks the AUR-shipped unit.
|
||||
## 2. Compositor configs (Hyprland, Sway, i3, river, niri) with `exec owlryd` /
|
||||
## `exec-once = owlryd` lines that won't resolve anymore.
|
||||
##
|
||||
## The hook only DETECTS and REPORTS — it never touches user homedirs from a root
|
||||
## pacman context. Each affected user gets a precise remediation command.
|
||||
|
||||
_owlry_for_each_user() {
|
||||
# Apply $1 (function name) to each logged-in user's home directory.
|
||||
# Falls back silently if loginctl/getent aren't available.
|
||||
local fn="$1"
|
||||
command -v loginctl >/dev/null 2>&1 || return 0
|
||||
command -v getent >/dev/null 2>&1 || return 0
|
||||
local user home
|
||||
while read -r user; do
|
||||
[ -n "$user" ] || continue
|
||||
home="$(getent passwd "$user" 2>/dev/null | awk -F: '{print $6}')"
|
||||
[ -d "$home" ] || continue
|
||||
"$fn" "$user" "$home"
|
||||
done < <(loginctl list-users --no-legend 2>/dev/null | awk '{print $2}')
|
||||
}
|
||||
|
||||
_owlry_check_unit() {
|
||||
# Inspect a user-level systemd unit; emit a remediation hint if it's stale.
|
||||
# Args: $1=user, $2=home, $3=unit-filename (e.g. owlry.service)
|
||||
local user="$1" home="$2" unit="$3"
|
||||
local svc="$home/.config/systemd/user/$unit"
|
||||
[ -f "$svc" ] || return 1
|
||||
local exec_line
|
||||
exec_line="$(grep -E '^ExecStart=' "$svc" 2>/dev/null | head -1 | sed 's/^ExecStart=//')"
|
||||
case "$exec_line" in
|
||||
*/owlryd|*/owlryd\ *)
|
||||
printf ' %s -> references deleted owlryd binary: %s\n' "$svc" "$exec_line"
|
||||
return 0
|
||||
;;
|
||||
*/target/debug/*|*/target/release/*)
|
||||
printf ' %s -> points at a dev-time build path: %s\n' "$svc" "$exec_line"
|
||||
return 0
|
||||
;;
|
||||
*/owlry|*/owlry\ *|/usr/bin/owlry|/usr/bin/owlry\ *)
|
||||
# If the override matches the canonical /usr/bin/owlry, it's harmless
|
||||
# but redundant. Flag it gently.
|
||||
printf ' %s -> user-level override (redundant; AUR ships this unit)\n' "$svc"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
# Unknown ExecStart — flag it so the user can review.
|
||||
printf ' %s -> non-standard ExecStart: %s\n' "$svc" "$exec_line"
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
_owlry_check_compositors() {
|
||||
# Args: $1=user, $2=home
|
||||
local user="$1" home="$2"
|
||||
local found=0 f
|
||||
# Single-file configs
|
||||
for f in \
|
||||
"$home/.config/sway/config" \
|
||||
"$home/.config/i3/config" \
|
||||
"$home/.config/river/init" \
|
||||
"$home/.config/niri/config.kdl"; do
|
||||
if [ -f "$f" ] && grep -qE '\bowlryd\b' "$f" 2>/dev/null; then
|
||||
printf ' %s -> contains `owlryd` reference\n' "$f"
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
# Hyprland — main file + include directory
|
||||
if [ -d "$home/.config/hypr" ]; then
|
||||
while IFS= read -r f; do
|
||||
if grep -qE '\bowlryd\b' "$f" 2>/dev/null; then
|
||||
printf ' %s -> contains `owlryd` reference\n' "$f"
|
||||
found=1
|
||||
fi
|
||||
done < <(find "$home/.config/hypr" -type f \( -name '*.conf' -o -name '*.hyprlang' \) 2>/dev/null)
|
||||
fi
|
||||
return $((1 - found))
|
||||
}
|
||||
|
||||
_owlry_per_user_migration_check() {
|
||||
local user="$1" home="$2"
|
||||
# Collect all check output in one subshell so internal newlines are
|
||||
# preserved (only the trailing newline gets stripped by $()).
|
||||
local out
|
||||
out="$({
|
||||
_owlry_check_unit "$user" "$home" owlry.service
|
||||
_owlry_check_unit "$user" "$home" owlry.socket
|
||||
_owlry_check_unit "$user" "$home" owlryd.service
|
||||
_owlry_check_unit "$user" "$home" owlryd.socket
|
||||
_owlry_check_compositors "$user" "$home"
|
||||
})"
|
||||
|
||||
[ -z "$out" ] && return 0
|
||||
|
||||
echo
|
||||
echo " ── user '$user' ─────────────────────────────────────────────"
|
||||
echo "$out"
|
||||
echo
|
||||
echo " Suggested cleanup (run as '$user'):"
|
||||
echo
|
||||
cat <<EOF
|
||||
# 1. Drop any user-level systemd overrides:
|
||||
rm -f ~/.config/systemd/user/owlry.service ~/.config/systemd/user/owlry.socket
|
||||
rm -f ~/.config/systemd/user/owlryd.service ~/.config/systemd/user/owlryd.socket
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user reenable --now owlry.service
|
||||
systemctl --user reset-failed owlry.service 2>/dev/null || true
|
||||
|
||||
# 2. Replace any \`owlryd\` autostart line in your compositor config:
|
||||
# exec-once = owlryd -> exec-once = owlry -d
|
||||
# exec owlryd -> exec owlry -d
|
||||
# (Usually unnecessary now — owlry.service / owlry.socket replace autostart.)
|
||||
EOF
|
||||
}
|
||||
|
||||
post_upgrade() {
|
||||
local old_pkgver="$2"
|
||||
@@ -20,31 +139,22 @@ post_upgrade() {
|
||||
│ owlryd.service -> owlry.service │
|
||||
│ owlryd.socket -> owlry.socket │
|
||||
│ │
|
||||
│ If you had the old service enabled, run: │
|
||||
│ systemctl --user disable --now owlryd.service │
|
||||
│ systemctl --user enable --now owlry.service │
|
||||
│ │
|
||||
│ Plugin packages (bookmarks, systemd, clipboard, …) are now │
|
||||
│ built into owlry by default — they were dropped from AUR and │
|
||||
│ replaced via this package. │
|
||||
│ │
|
||||
│ Widget providers (weather, media, pomodoro) are not in 2.0; │
|
||||
│ they return in a later 2.x release. See: │
|
||||
│ docs/RESTRUCTURE-V2.md (decisions D20, section 8) │
|
||||
│ Widget providers (weather, media, pomodoro) and bookmarks │
|
||||
│ are not in 2.0; they return in a later 2.x release. See: │
|
||||
│ docs/RESTRUCTURE-V2.md (decisions D20, D22) │
|
||||
╰─────────────────────────────────────────────────────────────────╯
|
||||
|
||||
EOF
|
||||
# Best-effort transition: if the old owlryd.service is enabled or
|
||||
# active for the invoking user, stop it and disable it so the new
|
||||
# owlry.service can take over. Errors are non-fatal — pacman runs
|
||||
# as root, so we can only inspect, not toggle user units here.
|
||||
if command -v loginctl >/dev/null 2>&1; then
|
||||
local invoking_user
|
||||
invoking_user="$(loginctl list-users --no-legend 2>/dev/null | awk 'NR==1 {print $2}')"
|
||||
if [ -n "$invoking_user" ]; then
|
||||
echo " (Run the systemctl --user commands above as user '$invoking_user'.)"
|
||||
fi
|
||||
fi
|
||||
_owlry_for_each_user _owlry_per_user_migration_check
|
||||
;;
|
||||
2.0|2.0.0)
|
||||
# 2.0.0 → 2.0.1: re-run the migration check; some users may have
|
||||
# missed cleanup the first time. Idempotent — only prints when
|
||||
# there's still something to flag.
|
||||
_owlry_for_each_user _owlry_per_user_migration_check
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user