mirror of
https://github.com/arthur-pbty/arthur-os.git
synced 2026-08-01 20:28:16 +02:00
Harden Omarchy 4 live upgrade cutover
This commit is contained in:
@@ -3,9 +3,21 @@
|
|||||||
# omarchy:summary=Restart the Omarchy shell
|
# omarchy:summary=Restart the Omarchy shell
|
||||||
# omarchy:examples=omarchy restart shell
|
# omarchy:examples=omarchy restart shell
|
||||||
|
|
||||||
CONFIG_DIR="$OMARCHY_PATH/shell"
|
omarchy_root="${OMARCHY_PATH:-/usr/share/omarchy}"
|
||||||
|
if [[ ! -f $omarchy_root/shell/shell.qml && -f /usr/share/omarchy/shell/shell.qml ]]; then
|
||||||
|
omarchy_root=/usr/share/omarchy
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ $(omarchy-shell lock isLocked 2>/dev/null || true) == "true" ]]; then
|
CONFIG_DIR="$omarchy_root/shell"
|
||||||
|
[[ -f $CONFIG_DIR/shell.qml ]] || { echo "Omarchy shell config not found: $CONFIG_DIR" >&2; exit 1; }
|
||||||
|
|
||||||
|
export OMARCHY_PATH="$omarchy_root"
|
||||||
|
export PATH="$omarchy_root/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
|
||||||
|
|
||||||
|
omarchy_shell_bin=/usr/bin/omarchy-shell
|
||||||
|
[[ -x $omarchy_shell_bin ]] || omarchy_shell_bin=omarchy-shell
|
||||||
|
|
||||||
|
if [[ $("$omarchy_shell_bin" lock isLocked 2>/dev/null || true) == "true" ]]; then
|
||||||
echo "Refusing to restart Omarchy shell while the session is locked." >&2
|
echo "Refusing to restart Omarchy shell while the session is locked." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
+155
-26
@@ -111,6 +111,7 @@ target_home=$(getent passwd "$target_user" | cut -d: -f6)
|
|||||||
[[ -n $target_home && -d $target_home ]] || fail "Home directory for '$target_user' was not found."
|
[[ -n $target_home && -d $target_home ]] || fail "Home directory for '$target_user' was not found."
|
||||||
target_uid=$(id -u "$target_user")
|
target_uid=$(id -u "$target_user")
|
||||||
target_runtime_dir="/run/user/$target_uid"
|
target_runtime_dir="/run/user/$target_uid"
|
||||||
|
package_path="/usr/share/omarchy/bin:/usr/local/bin:/usr/bin:/bin:$target_home/.local/bin"
|
||||||
|
|
||||||
as_root() {
|
as_root() {
|
||||||
if (( EUID == 0 )); then
|
if (( EUID == 0 )); then
|
||||||
@@ -306,11 +307,28 @@ EOF
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sudo_keepalive_pid=""
|
||||||
|
hyprland_config_reload_suppressed=0
|
||||||
|
|
||||||
|
cleanup_on_exit() {
|
||||||
|
local exit_status=$?
|
||||||
|
|
||||||
|
if (( hyprland_config_reload_suppressed )) && declare -F restore_hyprland_config_reload >/dev/null; then
|
||||||
|
restore_hyprland_config_reload >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n ${sudo_keepalive_pid:-} ]]; then
|
||||||
|
kill "$sudo_keepalive_pid" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$exit_status"
|
||||||
|
}
|
||||||
|
trap cleanup_on_exit EXIT
|
||||||
|
|
||||||
if (( EUID != 0 )); then
|
if (( EUID != 0 )); then
|
||||||
sudo -v
|
sudo -v
|
||||||
while true; do sudo -n true; sleep 60; done 2>/dev/null &
|
while true; do sudo -n true; sleep 60; done 2>/dev/null &
|
||||||
sudo_keepalive_pid=$!
|
sudo_keepalive_pid=$!
|
||||||
trap 'kill "$sudo_keepalive_pid" 2>/dev/null || true' EXIT
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
backup_suffix=$(date +%Y%m%d%H%M%S)
|
backup_suffix=$(date +%Y%m%d%H%M%S)
|
||||||
@@ -539,21 +557,40 @@ remove_retired_default_packages() {
|
|||||||
|
|
||||||
cleanup_legacy_user_paths() {
|
cleanup_legacy_user_paths() {
|
||||||
log "Cleaning legacy user command shims"
|
log "Cleaning legacy user command shims"
|
||||||
run_as_user env TARGET_HOME="$target_home" bash <<'USER_CLEANUP'
|
run_as_user env TARGET_HOME="$target_home" BACKUP_SUFFIX="$backup_suffix" bash <<'USER_CLEANUP'
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
local_bin="$TARGET_HOME/.local/bin"
|
local_bin="$TARGET_HOME/.local/bin"
|
||||||
legacy_root="$TARGET_HOME/.local/share/omarchy/bin/"
|
legacy_root="$TARGET_HOME/.local/share/omarchy"
|
||||||
[[ -d $local_bin ]] || exit 0
|
legacy_bin="$legacy_root/bin/"
|
||||||
shopt -s nullglob
|
if [[ -d $local_bin ]]; then
|
||||||
for link in "$local_bin"/omarchy*; do
|
shopt -s nullglob
|
||||||
[[ -L $link ]] || continue
|
for link in "$local_bin"/omarchy*; do
|
||||||
target=$(readlink "$link" || true)
|
[[ -L $link ]] || continue
|
||||||
case "$target" in
|
target=$(readlink "$link" || true)
|
||||||
"$legacy_root"*|../share/omarchy/bin/*|*.local/share/omarchy/bin/*)
|
case "$target" in
|
||||||
rm -f "$link"
|
"$legacy_bin"*|../share/omarchy/bin/*|*.local/share/omarchy/bin/*)
|
||||||
;;
|
rm -f "$link"
|
||||||
esac
|
;;
|
||||||
done
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Existing terminals still have OMARCHY_PATH=$HOME/.local/share/omarchy and
|
||||||
|
# often have $OMARCHY_PATH/bin early in PATH. Make that stale path resolve to
|
||||||
|
# the package-backed tree for the rest of the live session, while backing up
|
||||||
|
# the old git checkout for inspection/rollback.
|
||||||
|
if [[ -e /usr/share/omarchy ]]; then
|
||||||
|
mkdir -p "$TARGET_HOME/.local/share"
|
||||||
|
if [[ -L $legacy_root ]]; then
|
||||||
|
ln -sfn /usr/share/omarchy "$legacy_root"
|
||||||
|
elif [[ -e $legacy_root ]]; then
|
||||||
|
backup="$legacy_root.omarchy-upgrade-to-4.$BACKUP_SUFFIX.bak"
|
||||||
|
mv "$legacy_root" "$backup"
|
||||||
|
ln -sfn /usr/share/omarchy "$legacy_root"
|
||||||
|
else
|
||||||
|
ln -sfn /usr/share/omarchy "$legacy_root"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
USER_CLEANUP
|
USER_CLEANUP
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,10 +675,18 @@ start_omarchy_shell_session() {
|
|||||||
# Reboot is still the real cutover, but start the new shell in the current
|
# Reboot is still the real cutover, but start the new shell in the current
|
||||||
# Wayland session when possible so users do not sit without a bar after the
|
# Wayland session when possible so users do not sit without a bar after the
|
||||||
# retired waybar/walker/elephant processes are stopped.
|
# retired waybar/walker/elephant processes are stopped.
|
||||||
command -v quickshell >/dev/null 2>&1 || { warn "quickshell is not available; Omarchy shell will start after reboot."; return 1; }
|
local quickshell_bin omarchy_shell_bin shell_log
|
||||||
[[ -d /usr/share/omarchy/shell ]] || { warn "/usr/share/omarchy/shell is missing; Omarchy shell will start after reboot."; return 1; }
|
quickshell_bin=$(command -v quickshell || true)
|
||||||
|
[[ -n $quickshell_bin ]] || { warn "quickshell is not available; Omarchy shell will start after reboot."; return 1; }
|
||||||
|
omarchy_shell_bin=/usr/bin/omarchy-shell
|
||||||
|
[[ -x $omarchy_shell_bin ]] || omarchy_shell_bin=$(command -v omarchy-shell || true)
|
||||||
|
[[ -n $omarchy_shell_bin ]] || { warn "omarchy-shell is not available; Omarchy shell will start after reboot."; return 1; }
|
||||||
|
[[ -f /usr/share/omarchy/shell/shell.qml ]] || { warn "/usr/share/omarchy/shell is missing; Omarchy shell will start after reboot."; return 1; }
|
||||||
[[ -d $target_runtime_dir ]] || { warn "No running user session found; Omarchy shell will start after reboot."; return 1; }
|
[[ -d $target_runtime_dir ]] || { warn "No running user session found; Omarchy shell will start after reboot."; return 1; }
|
||||||
|
|
||||||
|
shell_log="$target_home/.local/state/omarchy/omarchy-shell-upgrade.log"
|
||||||
|
run_as_user mkdir -p "$target_home/.local/state/omarchy" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
local wayland_display hyprland_signature
|
local wayland_display hyprland_signature
|
||||||
wayland_display=$(discover_wayland_display || true)
|
wayland_display=$(discover_wayland_display || true)
|
||||||
[[ -n $wayland_display ]] || { warn "No Wayland display found; Omarchy shell will start after reboot."; return 1; }
|
[[ -n $wayland_display ]] || { warn "No Wayland display found; Omarchy shell will start after reboot."; return 1; }
|
||||||
@@ -661,20 +706,27 @@ start_omarchy_shell_session() {
|
|||||||
XDG_CURRENT_DESKTOP=Hyprland \
|
XDG_CURRENT_DESKTOP=Hyprland \
|
||||||
XDG_SESSION_DESKTOP=Hyprland \
|
XDG_SESSION_DESKTOP=Hyprland \
|
||||||
XDG_SESSION_TYPE=wayland \
|
XDG_SESSION_TYPE=wayland \
|
||||||
|
QT_QPA_PLATFORM=wayland \
|
||||||
|
GDK_BACKEND=wayland,x11,* \
|
||||||
DESKTOP_SESSION=hyprland \
|
DESKTOP_SESSION=hyprland \
|
||||||
OMARCHY_PATH=/usr/share/omarchy \
|
OMARCHY_PATH=/usr/share/omarchy \
|
||||||
PATH="/usr/share/omarchy/bin:$PATH" \
|
PATH="$package_path" \
|
||||||
bash -c '
|
bash -c '
|
||||||
if [[ $(omarchy-shell lock isLocked 2>/dev/null || true) == "true" ]]; then
|
omarchy_shell_bin=$1
|
||||||
|
quickshell_bin=$2
|
||||||
|
shell_log=$3
|
||||||
|
if [[ $("$omarchy_shell_bin" lock isLocked 2>/dev/null || true) == "true" ]]; then
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
pkill -x quickshell 2>/dev/null || true
|
pkill -x quickshell 2>/dev/null || true
|
||||||
sleep 0.2
|
sleep 0.2
|
||||||
setsid quickshell -n -p /usr/share/omarchy/shell >/dev/null 2>&1 &
|
: >"$shell_log"
|
||||||
' || { warn "Could not start Omarchy shell in the current session; it will start after reboot."; return 1; }
|
setsid "$quickshell_bin" -n -p /usr/share/omarchy/shell >>"$shell_log" 2>&1 &
|
||||||
|
' bash "$omarchy_shell_bin" "$quickshell_bin" "$shell_log" \
|
||||||
|
|| { warn "Could not start Omarchy shell in the current session; it will start after reboot. See $shell_log"; return 1; }
|
||||||
|
|
||||||
local attempt
|
local attempt
|
||||||
for attempt in {1..20}; do
|
for attempt in {1..60}; do
|
||||||
if run_as_user env \
|
if run_as_user env \
|
||||||
HOME="$target_home" \
|
HOME="$target_home" \
|
||||||
USER="$target_user" \
|
USER="$target_user" \
|
||||||
@@ -682,17 +734,92 @@ start_omarchy_shell_session() {
|
|||||||
XDG_RUNTIME_DIR="$target_runtime_dir" \
|
XDG_RUNTIME_DIR="$target_runtime_dir" \
|
||||||
DBUS_SESSION_BUS_ADDRESS="unix:path=$target_runtime_dir/bus" \
|
DBUS_SESSION_BUS_ADDRESS="unix:path=$target_runtime_dir/bus" \
|
||||||
OMARCHY_PATH=/usr/share/omarchy \
|
OMARCHY_PATH=/usr/share/omarchy \
|
||||||
PATH="/usr/share/omarchy/bin:$PATH" \
|
PATH="$package_path" \
|
||||||
omarchy-shell shell ping >/dev/null 2>&1; then
|
"$omarchy_shell_bin" shell ping >/dev/null 2>&1; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
sleep 0.25
|
sleep 0.25
|
||||||
done
|
done
|
||||||
|
|
||||||
warn "Omarchy shell did not respond in the current session; it will start after reboot."
|
warn "Omarchy shell did not respond in the current session; it will start after reboot. See $shell_log"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run_hyprctl_session() {
|
||||||
|
local wayland_display hyprland_signature hyprctl_bin
|
||||||
|
[[ -d $target_runtime_dir ]] || return 1
|
||||||
|
|
||||||
|
hyprctl_bin=/usr/bin/hyprctl
|
||||||
|
[[ -x $hyprctl_bin ]] || hyprctl_bin=$(command -v hyprctl || true)
|
||||||
|
[[ -n $hyprctl_bin ]] || return 1
|
||||||
|
|
||||||
|
wayland_display=$(discover_wayland_display || true)
|
||||||
|
[[ -n $wayland_display ]] || return 1
|
||||||
|
|
||||||
|
hyprland_signature=$(discover_hyprland_signature || true)
|
||||||
|
[[ -n $hyprland_signature ]] || return 1
|
||||||
|
|
||||||
|
run_as_user env \
|
||||||
|
HOME="$target_home" \
|
||||||
|
USER="$target_user" \
|
||||||
|
LOGNAME="$target_user" \
|
||||||
|
XDG_RUNTIME_DIR="$target_runtime_dir" \
|
||||||
|
WAYLAND_DISPLAY="$wayland_display" \
|
||||||
|
HYPRLAND_INSTANCE_SIGNATURE="$hyprland_signature" \
|
||||||
|
DBUS_SESSION_BUS_ADDRESS="unix:path=$target_runtime_dir/bus" \
|
||||||
|
XDG_CURRENT_DESKTOP=Hyprland \
|
||||||
|
XDG_SESSION_DESKTOP=Hyprland \
|
||||||
|
XDG_SESSION_TYPE=wayland \
|
||||||
|
DESKTOP_SESSION=hyprland \
|
||||||
|
OMARCHY_PATH=/usr/share/omarchy \
|
||||||
|
PATH="$package_path" \
|
||||||
|
"$hyprctl_bin" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
suppress_hyprland_config_reload() {
|
||||||
|
log "Suppressing live Hyprland reloads during the config swap"
|
||||||
|
|
||||||
|
local changed=0
|
||||||
|
if run_hyprctl_session keyword misc:disable_autoreload true >/dev/null 2>&1; then
|
||||||
|
changed=1
|
||||||
|
fi
|
||||||
|
if run_hyprctl_session eval 'hl.config({ misc = { disable_autoreload = true }, debug = { suppress_errors = true } })' >/dev/null 2>&1; then
|
||||||
|
changed=1
|
||||||
|
fi
|
||||||
|
run_hyprctl_session keyword debug:suppress_errors true >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
if (( changed )); then
|
||||||
|
hyprland_config_reload_suppressed=1
|
||||||
|
else
|
||||||
|
warn "Could not disable Hyprland auto-reload; the live session may briefly report config errors."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_hyprland_config_reload() {
|
||||||
|
(( hyprland_config_reload_suppressed )) || return 0
|
||||||
|
|
||||||
|
run_hyprctl_session keyword misc:disable_autoreload false >/dev/null 2>&1 || true
|
||||||
|
run_hyprctl_session eval 'hl.config({ misc = { disable_autoreload = false } })' >/dev/null 2>&1 || true
|
||||||
|
run_hyprctl_session keyword debug:suppress_errors false >/dev/null 2>&1 || true
|
||||||
|
run_hyprctl_session eval 'hl.config({ debug = { suppress_errors = false } })' >/dev/null 2>&1 || true
|
||||||
|
hyprland_config_reload_suppressed=0
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_hyprland_config_after_upgrade() {
|
||||||
|
log "Reloading Hyprland config with a full reset"
|
||||||
|
|
||||||
|
if run_hyprctl_session reload full-reset >/dev/null 2>&1; then
|
||||||
|
restore_hyprland_config_reload
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
warn "hyprctl reload full-reset failed; trying a regular Hyprland reload. If this session is still running an older Hyprland, reboot will complete the cutover."
|
||||||
|
if ! run_hyprctl_session reload >/dev/null 2>&1; then
|
||||||
|
warn "Could not reload the live Hyprland session; the new config will load after reboot."
|
||||||
|
fi
|
||||||
|
restore_hyprland_config_reload
|
||||||
|
}
|
||||||
|
|
||||||
enable_system_service() {
|
enable_system_service() {
|
||||||
local unit="$1"
|
local unit="$1"
|
||||||
as_root systemctl enable "$unit" >/dev/null 2>&1 || warn "Could not enable $unit; it may not be installed on this system."
|
as_root systemctl enable "$unit" >/dev/null 2>&1 || warn "Could not enable $unit; it may not be installed on this system."
|
||||||
@@ -1089,9 +1216,11 @@ remove_conflicting_legacy_packages
|
|||||||
install_omarchy_4_packages
|
install_omarchy_4_packages
|
||||||
cleanup_legacy_user_paths
|
cleanup_legacy_user_paths
|
||||||
apply_system_transition
|
apply_system_transition
|
||||||
|
suppress_hyprland_config_reload
|
||||||
apply_user_transition
|
apply_user_transition
|
||||||
cleanup_retired_services
|
cleanup_retired_services
|
||||||
remove_retired_default_packages
|
remove_retired_default_packages
|
||||||
|
reload_hyprland_config_after_upgrade
|
||||||
if start_omarchy_shell_session; then
|
if start_omarchy_shell_session; then
|
||||||
stop_retired_session_processes
|
stop_retired_session_processes
|
||||||
else
|
else
|
||||||
@@ -1102,8 +1231,8 @@ cat <<EOF
|
|||||||
|
|
||||||
Omarchy 4 upgrade complete.
|
Omarchy 4 upgrade complete.
|
||||||
|
|
||||||
IMPORTANT: Review the output above before rebooting. If there are ANY errors
|
IMPORTANT: Review the output above before rebooting.
|
||||||
above, do not reboot yet; fix the errors or ask for help first.
|
DO NOT REBOOT IF THERE ARE ERRORS above; fix the errors or ask for help first.
|
||||||
|
|
||||||
A reboot is required to finish switching to the package-backed Omarchy 4 session.
|
A reboot is required to finish switching to the package-backed Omarchy 4 session.
|
||||||
EOF
|
EOF
|
||||||
|
|||||||
Reference in New Issue
Block a user