161 lines
6.1 KiB
Bash
Executable File
161 lines
6.1 KiB
Bash
Executable File
#!/bin/bash -p
|
|
|
|
# omarchy:summary=Update Omarchy and system packages
|
|
# omarchy:alias=omarchy up
|
|
# omarchy:args=[-y]
|
|
# omarchy:examples=omarchy update | omarchy update -y
|
|
# omarchy:requires-sudo=true
|
|
|
|
if [[ $- != *p* ]]; then
|
|
echo "Refusing an unsafe Bash startup." >&2
|
|
exit 126
|
|
fi
|
|
|
|
security_entrypoint=$(/usr/bin/readlink -e -- "${BASH_SOURCE[0]}") || exit 126
|
|
source "${security_entrypoint%/*}/omarchy-security-functions" || exit 126
|
|
omarchy_security_require_privileged_bash_startup || exit 126
|
|
set -e
|
|
omarchy_security_sanitize_bash_environment "$0" "$@"
|
|
omarchy_security_require_source_root "$0"
|
|
# Logging and lock acquisition re-exec this command with a sanitized PATH.
|
|
# Preserve the caller's path only for the later hook/mise phases.
|
|
user_path=${OMARCHY_UPDATE_USER_PATH:-$PATH}
|
|
unset OMARCHY_UPDATE_USER_PATH
|
|
# Traps first, so a signal or failure during the entry revocation still
|
|
# exits through the cleanup path. Starting cold means the single password
|
|
# prompt below always belongs to this update, never to an earlier session.
|
|
omarchy_security_install_sudo_cleanup_traps
|
|
omarchy_security_revoke_sudo_timestamp || exit 1
|
|
# Validate the no-update wrapper up front: the AUR phase depends on it. Every
|
|
# other phase shares the one authorization, so it stays off PATH until then.
|
|
omarchy_security_enable_no_update_sudo
|
|
PATH="$OMARCHY_PATH/bin:/usr/bin:/usr/sbin:/bin:/sbin"
|
|
unset OMARCHY_SUDO_NO_UPDATE
|
|
# Helpers that manage their own sudo boundary leave this authorization to us.
|
|
export PATH OMARCHY_UPDATE_SUDO_SESSION=1
|
|
|
|
update_stay_awake_stopped=0
|
|
sudo_keepalive_pid=""
|
|
|
|
# Ask for the password once, then keep sudo's timestamp fresh so long package
|
|
# downloads, migrations, hooks, and mise never outlast it and prompt again.
|
|
# Authorize by running a command rather than sudo -v: under the default
|
|
# verifypw=all, -v prompts even when passwordless sudo is enabled.
|
|
authorize_update() {
|
|
/usr/bin/sudo /usr/bin/true || return 1
|
|
|
|
local update_pid=$$
|
|
(
|
|
[[ -z ${OMARCHY_UPDATE_LOCK_FD:-} ]] || exec {OMARCHY_UPDATE_LOCK_FD}>&-
|
|
sleep_pid=""
|
|
trap - EXIT HUP INT
|
|
trap '[[ -z $sleep_pid ]] || kill "$sleep_pid" 2>/dev/null; exit 0' TERM
|
|
while :; do
|
|
sleep 60 &
|
|
sleep_pid=$!
|
|
wait "$sleep_pid"
|
|
kill -0 "$update_pid" 2>/dev/null || exit 0
|
|
/usr/bin/sudo -n /usr/bin/true 2>/dev/null || exit 0
|
|
done
|
|
) &
|
|
sudo_keepalive_pid=$!
|
|
}
|
|
|
|
end_update_authorization() {
|
|
if [[ -n $sudo_keepalive_pid ]]; then
|
|
kill "$sudo_keepalive_pid" 2>/dev/null || true
|
|
wait "$sudo_keepalive_pid" 2>/dev/null || true
|
|
sudo_keepalive_pid=""
|
|
fi
|
|
omarchy_security_revoke_sudo_timestamp
|
|
}
|
|
|
|
cleanup_update() {
|
|
local status=$?
|
|
trap - EXIT HUP INT TERM
|
|
if ! end_update_authorization; then
|
|
echo "Could not invalidate sudo before update cleanup." >&2
|
|
omarchy_security_exit_with_revoked_sudo 1
|
|
fi
|
|
if (( update_stay_awake_stopped == 0 )); then
|
|
omarchy-update-stay-awake stop || status=1
|
|
fi
|
|
omarchy_security_exit_with_revoked_sudo "$status"
|
|
}
|
|
|
|
if [[ -z ${OMARCHY_UPDATE_LOGGED:-} ]]; then
|
|
script_command=$(printf '%q ' "$0" "$@")
|
|
exec env OMARCHY_UPDATE_LOGGED=1 OMARCHY_UPDATE_USER_PATH="$user_path" script -qefc "$script_command" "/tmp/omarchy-update.log"
|
|
fi
|
|
|
|
if ! omarchy-update-lock held; then
|
|
exec env OMARCHY_UPDATE_USER_PATH="$user_path" omarchy-update-lock run "$0" "$@"
|
|
fi
|
|
|
|
trap 'echo ""; echo -e "\033[0;31mSomething went wrong during the update!\n\nPlease review the output above carefully, correct the error, and retry the update.\n\nIf you need assistance, get help from the community at https://omarchy.org/discord\033[0m"' ERR
|
|
trap cleanup_update EXIT
|
|
omarchy_security_install_signal_exit_traps
|
|
|
|
omarchy-update-requires-free-space
|
|
|
|
# -y suppresses Omarchy confirmation prompts; sudo authorization is still
|
|
# required. Interactive review steps report and move on instead of waiting.
|
|
[[ ${1:-} != "-y" ]] || export OMARCHY_UPDATE_UNATTENDED=1
|
|
|
|
if [[ ${1:-} == "-y" ]] || omarchy-update-confirm; then
|
|
authorize_update
|
|
|
|
# Before the snapshot: the cache is on the snapshotted subvolume, so pruning
|
|
# after it frees nothing until that snapshot ages out.
|
|
omarchy-update-pkg-prune
|
|
|
|
# 127 means Snapper is deliberately absent. Any other failure already said
|
|
# what went wrong, and a missing snapshot is not worth blocking an update
|
|
# over, but it must not pass for one either.
|
|
omarchy-snapshot create || (($? == 127)) ||
|
|
echo -e "\e[33mContinuing the update without a snapshot.\e[0m" >&2
|
|
|
|
omarchy-update-stay-awake start
|
|
|
|
# Preserve the established development-checkout update ordering.
|
|
omarchy-update-dev
|
|
omarchy-update-keyring
|
|
|
|
# Migrations ship with the packages installed here and are written against
|
|
# them, so everything below waits on this finishing. An upgrade that stopped
|
|
# takes the update with it rather than migrating against what is still on disk.
|
|
omarchy-update-system-pkgs
|
|
|
|
omarchy-migrate
|
|
omarchy-update-orphan-pkgs -y
|
|
|
|
omarchy-update-analyze-logs
|
|
omarchy-update-status
|
|
|
|
# Service restart helpers can need sudo. The reboot-only phase below
|
|
# performs no privileged work.
|
|
omarchy-update-restart --services-only
|
|
|
|
# Hooks and mise run with the caller's PATH so user-installed tools resolve.
|
|
PATH="$user_path" "$OMARCHY_PATH/bin/omarchy-hook" post-update
|
|
PATH="$user_path" "$OMARCHY_PATH/bin/omarchy-update-mise"
|
|
|
|
# AUR builds run third-party PKGBUILD code, so they go last and never see the
|
|
# update's authorization: revoke it, then authenticate each sudo call with
|
|
# the no-update wrapper, for yay and any bare sudo a PKGBUILD runs, so an AUR
|
|
# install prompts without caching anything.
|
|
end_update_authorization
|
|
PATH="$OMARCHY_PATH/default/omarchy/sudo-no-update:$PATH" OMARCHY_SUDO_NO_UPDATE=1 omarchy-update-aur-pkgs
|
|
omarchy_security_revoke_sudo_timestamp
|
|
|
|
# The sleep inhibitor covers AUR builds, hooks and mise as well; releasing it
|
|
# needs no privilege because the held command already dropped to this user.
|
|
# Release it before offering a reboot: a confirmed reboot can terminate this
|
|
# process before its EXIT trap gets a chance to remove the persistent Stay
|
|
# Awake marker.
|
|
omarchy-update-stay-awake stop
|
|
update_stay_awake_stopped=1
|
|
|
|
"$OMARCHY_PATH/bin/omarchy-update-restart" --reboot-only
|
|
fi
|