The retired omarchy-update-user-notify.path stays loaded in sessions that started before the update removing it, and pacman writes the migrations directory mid-transaction, so it fired a critical toast for migrations that omarchy-migrate was about to apply a step later. Migration 1785095882 stops that watcher, but migrations run after pacman, so it lands 11 seconds too late to prevent the toast it exists to retire. Check the lock omarchy-update holds for its whole pipeline instead of trusting that no trigger exists. That covers the stale watcher and anything added later: during an update every pending migration is by definition already being applied. The check repeats after waiting for the notification server, which is long enough for an update to start underneath it. Only this user's runtime directory is read, never the /tmp path the updater falls back to without XDG_RUNTIME_DIR. A shared lock file belongs to whoever created it first, so honouring it would let one user silence another user's notification; a redundant toast is the better failure. The sleep inhibitor now starts with the lock descriptor closed. It outlives the step that starts it, so an update killed before restore_update_inhibitors left it holding the flock indefinitely. That already blocked later updates, and now that the notifier reads the same lock it would have silenced migration notices at every login. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
61 lines
2.0 KiB
Bash
Executable File
61 lines
2.0 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:summary=Notify the user when Omarchy has pending migrations
|
|
|
|
set -euo pipefail
|
|
|
|
update_in_progress() {
|
|
local lock="${XDG_RUNTIME_DIR:-}/omarchy-update.lock"
|
|
|
|
[[ -n ${XDG_RUNTIME_DIR:-} && -f $lock ]] || return 1
|
|
|
|
# flock -n only fails here when the lock is held, since the file is ours.
|
|
! flock -n "$lock" true 2>/dev/null
|
|
}
|
|
|
|
if update_in_progress; then
|
|
exit 0
|
|
fi
|
|
|
|
pending_migrations=$(omarchy-migrate --pending 2>/dev/null) || exit 0
|
|
pending_count=$(printf '%s\n' "$pending_migrations" | sed '/^[[:space:]]*$/d' | wc -l)
|
|
|
|
if (( pending_count == 1 )); then
|
|
message="Click to run 1 pending migration."
|
|
else
|
|
message="Click to run $pending_count pending migrations."
|
|
fi
|
|
|
|
notify_command=$(printf 'if [[ -n $(omarchy-notification-send -u critical -g "Pending Omarchy Migrations" %q -a) ]]; then omarchy-launch-floating-terminal-with-presentation omarchy-migrate; fi' "$message")
|
|
|
|
# This runs from omarchy-migrate-notify.service after graphical-session.target,
|
|
# but the target can be reached before the shell has claimed
|
|
# org.freedesktop.Notifications. Without the wait the toast is sent into the
|
|
# void and the user never learns about their pending migrations.
|
|
omarchy-notification-wait || true
|
|
|
|
# That wait is long enough for an update to start underneath us, and the count
|
|
# above is already stale by then, so re-check before spending the toast.
|
|
if update_in_progress; then
|
|
exit 0
|
|
fi
|
|
|
|
unit="omarchy-migrations-notification-$(date +%Y%m%d%H%M%S)"
|
|
systemd-run --user --scope --unit="$unit" bash -lc "$notify_command" >/dev/null 2>&1 && exit 0
|
|
|
|
# Reached when there is no user manager to run the scope under, such as a
|
|
# non-graphical shell, so fall back to telling the user in the terminal.
|
|
print_pending_migrations() {
|
|
echo "Omarchy has pending migrations. Run omarchy-migrate in a terminal to apply them:"
|
|
while IFS= read -r migration; do
|
|
[[ -n $migration ]] || continue
|
|
printf ' %s\n' "$migration"
|
|
done <<<"$pending_migrations"
|
|
}
|
|
|
|
if [[ -t 1 ]]; then
|
|
print_pending_migrations
|
|
else
|
|
print_pending_migrations >&2
|
|
fi
|