Unify Omarchy migrations
This commit is contained in:
@@ -177,12 +177,9 @@ This copies `/etc/skel/.config/hypr/hyprlock.conf` to `~/.config/hypr/hyprlock.c
|
|||||||
|
|
||||||
Read `docs/migrations.md` before creating or changing migrations.
|
Read `docs/migrations.md` before creating or changing migrations.
|
||||||
|
|
||||||
Migrations are split by execution scope:
|
Migrations are per-user and run through `omarchy-migrate` during `omarchy update` or from the migration notification. Put migrations directly under `migrations/<timestamp>.sh`. Pending state is per-user under `~/.local/state/omarchy/migrations/`, so every user gets a chance to run every migration. Migrations run as the user; privileged work should invoke the appropriate helper or privilege prompt, and no-op when another user already applied it.
|
||||||
|
|
||||||
- `migrations/system/<timestamp>.sh` — root, noninteractive, safe to run from pacman via `omarchy-migrate-system` (`omarchy` `post_upgrade` calls it). Use for `/etc`, `/usr`, `/boot`, services, hardware quirks, and other system state. Do not prompt.
|
To create a new migration, run `omarchy-dev-add-migration --no-edit`.
|
||||||
- `migrations/user/<timestamp>.sh` — current user/session, may touch `~/.config`, `~/.local`, user systemd, browser prefs, DBus/session state, and may prompt if necessary. Runs through `omarchy-migrate` / `omarchy-migrate-user`; pending state is per-user based on missing files under `~/.local/state/omarchy/migrations/user/`.
|
|
||||||
|
|
||||||
To create a new migration, run `omarchy-dev-add-migration system --no-edit` or `omarchy-dev-add-migration user --no-edit` based on scope.
|
|
||||||
|
|
||||||
New migration format:
|
New migration format:
|
||||||
- File permissions must be `0644` (`-rw-r--r--`); migration runners execute them with `bash -euo pipefail`, not through executable bits
|
- File permissions must be `0644` (`-rw-r--r--`); migration runners execute them with `bash -euo pipefail`, not through executable bits
|
||||||
|
|||||||
@@ -1,32 +1,40 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# omarchy:summary=Create a new Omarchy migration in the current source tree.
|
# omarchy:summary=Create a new Omarchy migration in the current source tree.
|
||||||
# omarchy:args=<system|user> [--no-edit]
|
# omarchy:args=[--no-edit]
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
scope="${1:-}"
|
no_edit=0
|
||||||
case "$scope" in
|
|
||||||
system|user)
|
while (($#)); do
|
||||||
|
case "$1" in
|
||||||
|
--no-edit)
|
||||||
|
no_edit=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-h|--help|"")
|
system|user)
|
||||||
echo "Usage: omarchy-dev-add-migration <system|user> [--no-edit]"
|
echo "omarchy-dev-add-migration: migration scopes are no longer used; creating a regular migration." >&2
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
echo "Usage: omarchy-dev-add-migration [--no-edit]"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown migration scope: $scope" >&2
|
echo "Unknown option: $1" >&2
|
||||||
echo "Usage: omarchy-dev-add-migration <system|user> [--no-edit]" >&2
|
echo "Usage: omarchy-dev-add-migration [--no-edit]" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
cd "${OMARCHY_PATH:-$(pwd)}"
|
cd "${OMARCHY_PATH:-$(pwd)}"
|
||||||
mkdir -p "migrations/$scope"
|
mkdir -p migrations
|
||||||
migration_file="migrations/$scope/$(git log -1 --format=%cd --date=unix).sh"
|
migration_file="migrations/$(git log -1 --format=%cd --date=unix).sh"
|
||||||
touch "$migration_file"
|
touch "$migration_file"
|
||||||
|
|
||||||
if [[ ${1:-} != "--no-edit" ]]; then
|
if (( ! no_edit )); then
|
||||||
nvim "$migration_file"
|
nvim "$migration_file"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ For shipped configs see /etc/skel (new users) and omarchy-reinstall-configs
|
|||||||
(existing users explicitly resyncing).
|
(existing users explicitly resyncing).
|
||||||
|
|
||||||
--first-install is used by the ISO in the target chroot. It marks shipped
|
--first-install is used by the ISO in the target chroot. It marks shipped
|
||||||
user migrations complete for the freshly-created user.
|
migrations complete for the freshly-created user.
|
||||||
|
|
||||||
Idempotency marker: ~/.local/state/omarchy/finalize-user.done
|
Idempotency marker: ~/.local/state/omarchy/finalize-user.done
|
||||||
USAGE
|
USAGE
|
||||||
@@ -123,9 +123,9 @@ xdg-settings set default-web-browser chromium.desktop
|
|||||||
xdg-mime default HEY.desktop x-scheme-handler/mailto
|
xdg-mime default HEY.desktop x-scheme-handler/mailto
|
||||||
|
|
||||||
if (( first_install )); then
|
if (( first_install )); then
|
||||||
mkdir -p "$state_dir/migrations/user"
|
mkdir -p "$state_dir/migrations"
|
||||||
for migration in "$OMARCHY_PATH"/migrations/user/*.sh; do
|
for migration in "$OMARCHY_PATH"/migrations/*.sh; do
|
||||||
[[ -f $migration ]] && touch "$state_dir/migrations/user/$(basename "$migration")"
|
[[ -f $migration ]] && touch "$state_dir/migrations/$(basename "$migration")"
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ if [[ ! -f $MIGRATION_NOTIFY_WATCH_MARKER || $force -eq 1 ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
run_first_run_step "notify about pending user migrations" omarchy-migrate-notify
|
run_first_run_step "notify about pending migrations" omarchy-migrate-notify
|
||||||
|
|
||||||
USER_MARKER="$state_dir/first-run-user.done"
|
USER_MARKER="$state_dir/first-run-user.done"
|
||||||
if [[ ! -f $USER_MARKER || $force -eq 1 ]]; then
|
if [[ ! -f $USER_MARKER || $force -eq 1 ]]; then
|
||||||
|
|||||||
+40
-40
@@ -1,15 +1,14 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# omarchy:summary=Run pending Omarchy system and user migrations.
|
# omarchy:summary=Run pending Omarchy migrations.
|
||||||
# omarchy:args=[--pending [all|system|user]]
|
# omarchy:args=[--pending]
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
mode="run"
|
mode="run"
|
||||||
pending_scope="all"
|
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo "Usage: omarchy-migrate [--pending [all|system|user]]"
|
echo "Usage: omarchy-migrate [--pending]"
|
||||||
}
|
}
|
||||||
|
|
||||||
while (($#)); do
|
while (($#)); do
|
||||||
@@ -17,15 +16,6 @@ while (($#)); do
|
|||||||
--pending|--check)
|
--pending|--check)
|
||||||
mode="pending"
|
mode="pending"
|
||||||
shift
|
shift
|
||||||
if [[ ${1:-} == "all" || ${1:-} == "system" || ${1:-} == "user" ]]; then
|
|
||||||
pending_scope="$1"
|
|
||||||
shift
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
--pending=all|--pending=system|--pending=user)
|
|
||||||
mode="pending"
|
|
||||||
pending_scope="${1#--pending=}"
|
|
||||||
shift
|
|
||||||
;;
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
usage
|
usage
|
||||||
@@ -38,38 +28,37 @@ while (($#)); do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
pending_output=""
|
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
|
||||||
|
STATE_DIR="${OMARCHY_MIGRATION_STATE:-$HOME/.local/state/omarchy/migrations}"
|
||||||
|
MIGRATIONS_DIR="$OMARCHY_PATH/migrations"
|
||||||
|
|
||||||
append_pending() {
|
migration_entries() {
|
||||||
local scope="$1"
|
[[ -d $MIGRATIONS_DIR ]] || return 0
|
||||||
local command="$2"
|
|
||||||
local output=""
|
|
||||||
local migration=""
|
|
||||||
|
|
||||||
if output=$("$command" --pending 2>/dev/null); then
|
local file filename
|
||||||
while IFS= read -r migration; do
|
|
||||||
[[ -n $migration ]] || continue
|
for file in "$MIGRATIONS_DIR"/*.sh; do
|
||||||
pending_output+="$scope/$migration"$'\n'
|
[[ -f $file ]] || continue
|
||||||
done <<<"$output"
|
filename=$(basename "$file")
|
||||||
|
printf '%s\t%s\t%s\n' "$filename" "$file" "$STATE_DIR/$filename"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
pending_migrations() {
|
||||||
|
local name file marker
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r name file marker; do
|
||||||
|
[[ -n $name ]] || continue
|
||||||
|
if [[ ! -f $marker ]]; then
|
||||||
|
printf '%s\n' "$name"
|
||||||
fi
|
fi
|
||||||
|
done < <(migration_entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ $mode == "pending" ]]; then
|
if [[ $mode == "pending" ]]; then
|
||||||
case "$pending_scope" in
|
pending_output=$(pending_migrations)
|
||||||
all)
|
|
||||||
append_pending system omarchy-migrate-system
|
|
||||||
append_pending user omarchy-migrate-user
|
|
||||||
;;
|
|
||||||
system)
|
|
||||||
append_pending system omarchy-migrate-system
|
|
||||||
;;
|
|
||||||
user)
|
|
||||||
append_pending user omarchy-migrate-user
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [[ -n $pending_output ]]; then
|
if [[ -n $pending_output ]]; then
|
||||||
printf '%s' "$pending_output"
|
printf '%s\n' "$pending_output"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
exit 1
|
exit 1
|
||||||
@@ -93,5 +82,16 @@ wait_for_pacman_transaction() {
|
|||||||
|
|
||||||
wait_for_pacman_transaction
|
wait_for_pacman_transaction
|
||||||
|
|
||||||
omarchy-migrate-system
|
mkdir -p "$STATE_DIR"
|
||||||
omarchy-migrate-user
|
[[ -d $MIGRATIONS_DIR ]] || exit 0
|
||||||
|
|
||||||
|
while IFS=$'\t' read -r name file marker; do
|
||||||
|
[[ -n $name ]] || continue
|
||||||
|
|
||||||
|
if [[ ! -f $marker ]]; then
|
||||||
|
echo -e "\e[32m\nRunning migration (${name%.sh})\e[0m"
|
||||||
|
OMARCHY_PATH="$OMARCHY_PATH" bash -euo pipefail "$file"
|
||||||
|
mkdir -p "$(dirname "$marker")"
|
||||||
|
touch "$marker"
|
||||||
|
fi
|
||||||
|
done < <(migration_entries)
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# omarchy:summary=Notify the user when Omarchy has pending user migrations
|
# omarchy:summary=Notify the user when Omarchy has pending migrations
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
pending_migrations=$(omarchy-migrate --pending user 2>/dev/null) || exit 0
|
pending_migrations=$(omarchy-migrate --pending 2>/dev/null) || exit 0
|
||||||
pending_count=$(printf '%s\n' "$pending_migrations" | sed '/^[[:space:]]*$/d' | wc -l)
|
pending_count=$(printf '%s\n' "$pending_migrations" | sed '/^[[:space:]]*$/d' | wc -l)
|
||||||
|
|
||||||
if (( pending_count == 1 )); then
|
if (( pending_count == 1 )); then
|
||||||
message="1 new Omarchy user migration is available. Click to run it in a terminal."
|
message="1 new Omarchy migration is available. Click to run it in a terminal."
|
||||||
else
|
else
|
||||||
message="$pending_count new Omarchy user migrations are available. Click to run them in a terminal."
|
message="$pending_count new Omarchy migrations are available. Click to run them in a terminal."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
notify_command=$(printf 'if [[ -n $(omarchy-notification-send -u critical -g "Run Omarchy Migrations" %q -a) ]]; then omarchy-launch-floating-terminal-with-presentation omarchy-migrate; fi' "$message")
|
notify_command=$(printf 'if [[ -n $(omarchy-notification-send -u critical -g "Run Omarchy Migrations" %q -a) ]]; then omarchy-launch-floating-terminal-with-presentation omarchy-migrate; fi' "$message")
|
||||||
@@ -21,7 +21,7 @@ if command -v systemd-run >/dev/null 2>&1; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
print_pending_migrations() {
|
print_pending_migrations() {
|
||||||
echo "Omarchy has pending user migrations. Run omarchy-migrate in a terminal to apply them:"
|
echo "Omarchy has pending migrations. Run omarchy-migrate in a terminal to apply them:"
|
||||||
while IFS= read -r migration; do
|
while IFS= read -r migration; do
|
||||||
[[ -n $migration ]] || continue
|
[[ -n $migration ]] || continue
|
||||||
printf ' %s\n' "$migration"
|
printf ' %s\n' "$migration"
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# omarchy:summary=Run pending Omarchy system migrations as root.
|
|
||||||
# omarchy:args=[--pending]
|
|
||||||
# omarchy:requires-sudo=true
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
mode="run"
|
|
||||||
while (($#)); do
|
|
||||||
case "$1" in
|
|
||||||
--pending|--check)
|
|
||||||
mode="pending"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
echo "Usage: omarchy-migrate-system [--pending]"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown option: $1" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
|
|
||||||
STATE_DIR="${OMARCHY_SYSTEM_MIGRATION_STATE:-/var/lib/omarchy/migrations/system}"
|
|
||||||
MIGRATIONS_DIR="$OMARCHY_PATH/migrations/system"
|
|
||||||
|
|
||||||
pending_migrations() {
|
|
||||||
[[ -d $MIGRATIONS_DIR ]] || return 0
|
|
||||||
|
|
||||||
for file in "$MIGRATIONS_DIR"/*.sh; do
|
|
||||||
[[ -f $file ]] || continue
|
|
||||||
filename=$(basename "$file")
|
|
||||||
|
|
||||||
if [[ ! -f $STATE_DIR/$filename ]]; then
|
|
||||||
printf '%s\n' "$filename"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $mode == "pending" ]]; then
|
|
||||||
pending_output=$(pending_migrations)
|
|
||||||
if [[ -n $pending_output ]]; then
|
|
||||||
printf '%s\n' "$pending_output"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (( EUID != 0 )) && [[ -z ${OMARCHY_SYSTEM_MIGRATION_STATE:-} ]]; then
|
|
||||||
if ! "$0" --pending >/dev/null; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec sudo --preserve-env=OMARCHY_PATH "$0" "$@"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$STATE_DIR"
|
|
||||||
[[ -d $MIGRATIONS_DIR ]] || exit 0
|
|
||||||
|
|
||||||
for file in "$MIGRATIONS_DIR"/*.sh; do
|
|
||||||
[[ -f $file ]] || continue
|
|
||||||
filename=$(basename "$file")
|
|
||||||
|
|
||||||
if [[ ! -f $STATE_DIR/$filename ]]; then
|
|
||||||
echo -e "\e[32m\nRunning system migration (${filename%.sh})\e[0m"
|
|
||||||
OMARCHY_PATH="$OMARCHY_PATH" bash -euo pipefail "$file"
|
|
||||||
touch "$STATE_DIR/$filename"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# omarchy:summary=Run pending Omarchy migrations for the current user.
|
|
||||||
# omarchy:args=[--pending]
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
mode="run"
|
|
||||||
while (($#)); do
|
|
||||||
case "$1" in
|
|
||||||
--pending|--check)
|
|
||||||
mode="pending"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-h|--help)
|
|
||||||
echo "Usage: omarchy-migrate-user [--pending]"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unknown option: $1" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
|
|
||||||
STATE_DIR="${OMARCHY_USER_MIGRATION_STATE:-$HOME/.local/state/omarchy/migrations/user}"
|
|
||||||
MIGRATIONS_DIR="$OMARCHY_PATH/migrations/user"
|
|
||||||
|
|
||||||
pending_migrations() {
|
|
||||||
[[ -d $MIGRATIONS_DIR ]] || return 0
|
|
||||||
|
|
||||||
for file in "$MIGRATIONS_DIR"/*.sh; do
|
|
||||||
[[ -f $file ]] || continue
|
|
||||||
filename=$(basename "$file")
|
|
||||||
|
|
||||||
if [[ ! -f $STATE_DIR/$filename ]]; then
|
|
||||||
printf '%s\n' "$filename"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $mode == "pending" ]]; then
|
|
||||||
pending_output=$(pending_migrations)
|
|
||||||
if [[ -n $pending_output ]]; then
|
|
||||||
printf '%s\n' "$pending_output"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$STATE_DIR"
|
|
||||||
[[ -d $MIGRATIONS_DIR ]] || exit 0
|
|
||||||
|
|
||||||
for file in "$MIGRATIONS_DIR"/*.sh; do
|
|
||||||
[[ -f $file ]] || continue
|
|
||||||
filename=$(basename "$file")
|
|
||||||
|
|
||||||
if [[ ! -f $STATE_DIR/$filename ]]; then
|
|
||||||
echo -e "\e[32m\nRunning user migration (${filename%.sh})\e[0m"
|
|
||||||
OMARCHY_PATH="$OMARCHY_PATH" bash -euo pipefail "$file"
|
|
||||||
touch "$STATE_DIR/$filename"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Watch for Omarchy user migrations
|
Description=Watch for Omarchy migrations
|
||||||
|
|
||||||
[Path]
|
[Path]
|
||||||
PathExistsGlob=/usr/share/omarchy/migrations/user/*.sh
|
PathExistsGlob=/usr/share/omarchy/migrations/*.sh
|
||||||
PathModified=/usr/share/omarchy/migrations/user
|
PathModified=/usr/share/omarchy/migrations
|
||||||
Unit=omarchy-update-user-notify.service
|
Unit=omarchy-update-user-notify.service
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Notify about pending Omarchy user migrations
|
Description=Notify about pending Omarchy migrations
|
||||||
ConditionPathExistsGlob=/usr/share/omarchy/migrations/user/*.sh
|
ConditionPathIsDirectory=/usr/share/omarchy/migrations
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
|||||||
+18
-31
@@ -63,12 +63,11 @@ default/libalpm/hooks/*.hook
|
|||||||
──► omarchy /usr/share/libalpm/hooks/*.hook
|
──► omarchy /usr/share/libalpm/hooks/*.hook
|
||||||
|
|
||||||
install/** ──► omarchy /usr/share/omarchy/install/
|
install/** ──► omarchy /usr/share/omarchy/install/
|
||||||
migrations/system/** ──► omarchy /usr/share/omarchy/migrations/system/
|
migrations/** ──► omarchy /usr/share/omarchy/migrations/
|
||||||
migrations/user/** ──► omarchy /usr/share/omarchy/migrations/user/
|
|
||||||
themes/** ──► omarchy /usr/share/omarchy/themes/
|
themes/** ──► omarchy /usr/share/omarchy/themes/
|
||||||
shell/** ──► omarchy /usr/share/omarchy/shell/
|
shell/** ──► omarchy /usr/share/omarchy/shell/
|
||||||
version ──► omarchy /usr/share/omarchy/version
|
version ──► omarchy /usr/share/omarchy/version
|
||||||
+ /etc/skel/.local/state/omarchy/migrations/user/*
|
+ /etc/skel/.local/state/omarchy/migrations/*
|
||||||
|
|
||||||
config/** ──► omarchy-settings /etc/skel/.config/** (seeds new users)
|
config/** ──► omarchy-settings /etc/skel/.config/** (seeds new users)
|
||||||
/usr/share/omarchy/config/** (resync source)
|
/usr/share/omarchy/config/** (resync source)
|
||||||
@@ -185,37 +184,26 @@ the root-side work.
|
|||||||
See [`migrations.md`](migrations.md) for the full migration model, authoring
|
See [`migrations.md`](migrations.md) for the full migration model, authoring
|
||||||
guidelines, and troubleshooting notes.
|
guidelines, and troubleshooting notes.
|
||||||
|
|
||||||
Omarchy migrations are split by scope:
|
Omarchy migrations live in `migrations/*.sh` and run per-user through
|
||||||
|
`omarchy-migrate`. Completion state lives in
|
||||||
- `migrations/system/*.sh` — root, noninteractive, safe to run from pacman.
|
`~/.local/state/omarchy/migrations/`, so every user gets a chance to run every
|
||||||
The `omarchy` package `post_upgrade()` runs `omarchy-migrate-system` after an
|
migration. Migrations run as the user; privileged work should invoke the
|
||||||
`omarchy` package upgrade, so even explicit direct-pacman bypasses still get
|
appropriate helper or privilege prompt. Migrations must be idempotent;
|
||||||
system migrations applied. Completion state lives in
|
machine-wide repairs should no-op when another user already applied them.
|
||||||
`/var/lib/omarchy/migrations/system/`.
|
|
||||||
- `migrations/user/*.sh` — current user/session, may be interactive, and may
|
|
||||||
touch `~/.config`, `~/.local`, user systemd, DBus, browser prefs, etc.
|
|
||||||
Completion state lives in `~/.local/state/omarchy/migrations/user/`.
|
|
||||||
|
|
||||||
Package upgrades happen as root, but user migrations must run as each user and
|
|
||||||
may be interactive. There is no root-owned "user migration required" marker. A
|
|
||||||
user migration is pending only when a script exists in `migrations/user/` and
|
|
||||||
that user's matching state file is missing.
|
|
||||||
|
|
||||||
Each graphical user has `omarchy-update-user-notify.path` watching the packaged
|
Each graphical user has `omarchy-update-user-notify.path` watching the packaged
|
||||||
user migration directory. When that directory changes, or when the path unit is
|
migration directory. When that directory changes, or when the path unit is
|
||||||
started on login, `omarchy-update-user-notify.service` runs
|
started on login, `omarchy-update-user-notify.service` runs
|
||||||
`omarchy-migrate-notify` as that user. The notifier checks
|
`omarchy-migrate-notify` as that user. The notifier checks
|
||||||
`omarchy-migrate --pending user`. If this user has missing migration state, it
|
`omarchy-migrate --pending`. If this user has missing migration state, it shows a
|
||||||
shows a notification that opens a terminal for `omarchy-migrate`. The notifier
|
notification that opens a terminal for `omarchy-migrate`. The notifier never runs
|
||||||
never runs user migrations in the background.
|
migrations in the background.
|
||||||
|
|
||||||
`omarchy-migrate` waits for any active pacman transaction to finish, runs
|
`omarchy-migrate` waits for any active pacman transaction to finish, then runs
|
||||||
pending system migrations, then runs pending user migrations. It does not need
|
pending migrations. It does not need `--force`; migrations happen when state
|
||||||
`--force`; migrations happen when state files are missing. For watchers and
|
files are missing. `omarchy update` runs `omarchy-migrate` after the package
|
||||||
diagnostics, `omarchy-migrate --pending [all|system|user]` prints
|
transaction in the already-visible update terminal, then runs
|
||||||
scope-prefixed pending migration filenames and exits `0` when any are pending.
|
`omarchy-hook post-update`.
|
||||||
`omarchy update` runs `omarchy-migrate` after the package transaction in the
|
|
||||||
already-visible update terminal, then runs `omarchy-hook post-update`.
|
|
||||||
|
|
||||||
## First-run (`omarchy-first-run`)
|
## First-run (`omarchy-first-run`)
|
||||||
|
|
||||||
@@ -286,8 +274,7 @@ return to the packaged default.
|
|||||||
| Per-user file that's static but lives outside `~/.config` | `default/`, then add `install -Dm644 ... $pkgdir/etc/skel/...` in `omarchy-settings` PKGBUILD |
|
| Per-user file that's static but lives outside `~/.config` | `default/`, then add `install -Dm644 ... $pkgdir/etc/skel/...` in `omarchy-settings` PKGBUILD |
|
||||||
| Runtime tweak that needs `$HOME` or live system state | extend `omarchy-finalize-user`, or add a per-user leaf under `install/user/` and wire into `install/user/all.sh` |
|
| Runtime tweak that needs `$HOME` or live system state | extend `omarchy-finalize-user`, or add a per-user leaf under `install/user/` and wire into `install/user/all.sh` |
|
||||||
| One-time root-side setup step | `install/config/*.sh` or `install/hardware/*.sh`, wire into `omarchy-setup-system` or `install/hardware/all.sh` |
|
| One-time root-side setup step | `install/config/*.sh` or `install/hardware/*.sh`, wire into `omarchy-setup-system` or `install/hardware/all.sh` |
|
||||||
| Noninteractive root fix for existing installs | `migrations/system/<unix-timestamp>.sh` |
|
| One-time fix for existing installs | `migrations/<unix-timestamp>.sh` |
|
||||||
| User/session fix for existing installs | `migrations/user/<unix-timestamp>.sh` |
|
|
||||||
| User-facing `omarchy-*` command | `bin/omarchy-<group>-<verb>` — see `GROUP_DESCRIPTIONS` in `bin/omarchy` |
|
| User-facing `omarchy-*` command | `bin/omarchy-<group>-<verb>` — see `GROUP_DESCRIPTIONS` in `bin/omarchy` |
|
||||||
| New stock theme | `themes/<name>/` (+ matching templates under `default/themed/` if they need theme colors) |
|
| New stock theme | `themes/<name>/` (+ matching templates under `default/themed/` if they need theme colors) |
|
||||||
| User-installed theme | `~/.config/omarchy/themes/<name>/` |
|
| User-installed theme | `~/.config/omarchy/themes/<name>/` |
|
||||||
|
|||||||
+58
-208
@@ -4,59 +4,30 @@ Omarchy migrations are one-time repair scripts for existing installs. They are
|
|||||||
used when a package update needs to change state that pacman cannot safely own by
|
used when a package update needs to change state that pacman cannot safely own by
|
||||||
itself.
|
itself.
|
||||||
|
|
||||||
## The two migration scopes
|
## Migration model
|
||||||
|
|
||||||
Omarchy migrations are split by execution context:
|
Migrations live in:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
migrations/system/*.sh
|
migrations/*.sh
|
||||||
migrations/user/*.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### System migrations
|
They run as the current Omarchy user through `omarchy-migrate`, normally during
|
||||||
|
`omarchy update`. A migration may touch user/session state (`~/.config`,
|
||||||
|
`~/.local`, user systemd, browser/editor prefs, DBus/session state), and may also
|
||||||
|
perform machine-wide repairs when needed.
|
||||||
|
|
||||||
System migrations run as root and must be noninteractive.
|
Completion state is per-user:
|
||||||
|
|
||||||
Use system migrations for machine-wide state, for example:
|
|
||||||
|
|
||||||
- `/etc` drop-ins or legacy config cleanup
|
|
||||||
- `/boot` / bootloader cleanup
|
|
||||||
- systemd system units or service state
|
|
||||||
- hardware quirks
|
|
||||||
- package-owned layout transitions
|
|
||||||
|
|
||||||
Note that it's not necessary to write a migration for any file that will be package-owned.
|
|
||||||
|
|
||||||
State lives in:
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
/var/lib/omarchy/migrations/system/<migration filename>
|
~/.local/state/omarchy/migrations/<migration filename>
|
||||||
```
|
```
|
||||||
|
|
||||||
### User migrations
|
That means every user gets a chance to run every migration. Migrations run as the
|
||||||
|
user; privileged operations should invoke the appropriate helper or privilege
|
||||||
User migrations run as the current graphical/login user and may be interactive.
|
prompt themselves. Migrations must be idempotent: if one user already applied a
|
||||||
|
machine-wide repair, the same migration running for another user should detect
|
||||||
Use user migrations for per-user or session-aware state, for example:
|
that and no-op.
|
||||||
|
|
||||||
- `~/.config` changes
|
|
||||||
- `~/.local` state
|
|
||||||
- user systemd units
|
|
||||||
- browser/editor preferences
|
|
||||||
- DBus/session-dependent updates
|
|
||||||
- prompts that need to happen in a visible terminal
|
|
||||||
|
|
||||||
State lives in:
|
|
||||||
|
|
||||||
```text
|
|
||||||
~/.local/state/omarchy/migrations/user/<migration filename>
|
|
||||||
```
|
|
||||||
|
|
||||||
A user migration is pending for a given user only when the script exists under
|
|
||||||
`/usr/share/omarchy/migrations/user/` and that user's matching state file is
|
|
||||||
missing.
|
|
||||||
|
|
||||||
There is no global root-owned “user migrations required” queue.
|
|
||||||
|
|
||||||
## When migrations run
|
## When migrations run
|
||||||
|
|
||||||
@@ -69,15 +40,8 @@ omarchy-migrate
|
|||||||
omarchy-hook post-update
|
omarchy-hook post-update
|
||||||
```
|
```
|
||||||
|
|
||||||
`omarchy-migrate`:
|
`omarchy-migrate` waits for any active pacman transaction to finish, then runs
|
||||||
|
all pending migrations for the current user in the visible update terminal.
|
||||||
1. waits for any active pacman transaction to finish
|
|
||||||
2. runs pending system migrations
|
|
||||||
3. runs pending user migrations for the current user
|
|
||||||
|
|
||||||
System migrations usually already ran during the pacman transaction via the
|
|
||||||
`omarchy` package `post_upgrade()`, but the second check is intentional and
|
|
||||||
idempotent.
|
|
||||||
|
|
||||||
### During direct pacman updates
|
### During direct pacman updates
|
||||||
|
|
||||||
@@ -87,28 +51,21 @@ Raw `sudo pacman -Syu` is guarded. Users should normally run:
|
|||||||
omarchy update
|
omarchy update
|
||||||
```
|
```
|
||||||
|
|
||||||
If a user explicitly bypasses the guard, the `omarchy` package still runs system
|
If a user explicitly bypasses the guard, user sessions watch the packaged
|
||||||
migrations from `post_upgrade()`:
|
migration directory and run a notifier. The notifier checks:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
omarchy-migrate-system
|
omarchy-migrate --pending
|
||||||
```
|
```
|
||||||
|
|
||||||
User migrations are never run by pacman. Instead, the user session watches the
|
If that user has pending migrations, it shows a notification that opens a
|
||||||
packaged user migration directory and runs a notifier. The notifier checks:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
omarchy-migrate --pending user
|
|
||||||
```
|
|
||||||
|
|
||||||
If that user has pending user migrations, it shows a notification that opens a
|
|
||||||
terminal for:
|
terminal for:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
omarchy-migrate
|
omarchy-migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
The notifier never runs user migrations silently in the background.
|
The notifier never runs migrations silently in the background.
|
||||||
|
|
||||||
### Manually
|
### Manually
|
||||||
|
|
||||||
@@ -126,179 +83,72 @@ Use:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
omarchy-migrate --pending
|
omarchy-migrate --pending
|
||||||
omarchy-migrate --pending system
|
|
||||||
omarchy-migrate --pending user
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Exit behavior:
|
Exit behavior:
|
||||||
|
|
||||||
- `0` — one or more matching migrations are pending
|
- `0` — one or more migrations are pending
|
||||||
- non-zero — no matching migrations are pending
|
- non-zero — no migrations are pending
|
||||||
|
|
||||||
Output is scope-prefixed:
|
Output is one pending migration per line:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
system/100-system.sh
|
1781158082.sh
|
||||||
user/200-user.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The lower-level runners also support `--pending` and print filenames without the
|
## Creating a migration
|
||||||
scope prefix:
|
|
||||||
|
Use the helper:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
omarchy-migrate-system --pending
|
omarchy-dev-add-migration --no-edit
|
||||||
omarchy-migrate-user --pending
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Prefer `omarchy-migrate --pending ...` in user-facing tools and watchers.
|
This creates:
|
||||||
|
|
||||||
## Writing migrations
|
```text
|
||||||
|
migrations/<unix timestamp>.sh
|
||||||
Create a migration with:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
omarchy-dev-add-migration system --no-edit
|
|
||||||
omarchy-dev-add-migration user --no-edit
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Choose the scope based on the state being changed, not on convenience.
|
New migration format:
|
||||||
|
|
||||||
### File format
|
- File permissions must be `0644` (`-rw-r--r--`). Migration runners execute them
|
||||||
|
with `bash -euo pipefail`, not through executable bits.
|
||||||
|
- No shebang line.
|
||||||
|
- Start with an `echo` describing what the migration does.
|
||||||
|
- Use `$OMARCHY_PATH` to reference the Omarchy directory.
|
||||||
|
- Be idempotent. Check existing state before changing it.
|
||||||
|
- Use helper commands such as `omarchy-cmd-present`, `omarchy-cmd-missing`,
|
||||||
|
`omarchy-pkg-add`, `omarchy-pkg-drop`, `omarchy-pkg-present`, and
|
||||||
|
`omarchy-pkg-missing` when appropriate.
|
||||||
|
|
||||||
Migrations are plain shell files:
|
Example:
|
||||||
|
|
||||||
- filename: unix timestamp, generated by `omarchy-dev-add-migration`
|
|
||||||
- mode: `0644`
|
|
||||||
- no shebang
|
|
||||||
- start with an `echo` describing the migration
|
|
||||||
- use `$OMARCHY_PATH` for Omarchy-owned files
|
|
||||||
- should be idempotent
|
|
||||||
- should be as simple as possible to accomplish the task
|
|
||||||
|
|
||||||
Example system migration:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo "Remove legacy Limine config"
|
echo "Relink Neovim theme to Omarchy current state"
|
||||||
|
|
||||||
rm -f /boot/EFI/limine/limine.conf
|
theme_link="$HOME/.config/nvim/lua/plugins/theme.lua"
|
||||||
|
current_relative_target="../../../../.local/state/omarchy/current/theme/neovim.lua"
|
||||||
|
|
||||||
|
[[ -L $theme_link ]] || exit 0
|
||||||
|
ln -sfn "$current_relative_target" "$theme_link"
|
||||||
```
|
```
|
||||||
|
|
||||||
Example user migration:
|
## Testing migrations
|
||||||
|
|
||||||
|
Run a migration against a temporary home when possible:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo "Refresh user app launchers"
|
HOME=$(mktemp -d) bash -euo pipefail migrations/<timestamp>.sh
|
||||||
|
|
||||||
omarchy-refresh-applications
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Execution model
|
To rerun a migration locally, remove its marker and run the migrator:
|
||||||
|
|
||||||
Migration runners execute scripts with strict shell settings:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bash -euo pipefail <migration>
|
|
||||||
```
|
|
||||||
|
|
||||||
`$OMARCHY_PATH` is exported into the migration process.
|
|
||||||
|
|
||||||
A migration is marked complete only after the script exits successfully. If it
|
|
||||||
fails, the marker is not written and the migration will be retried later.
|
|
||||||
|
|
||||||
Because failed migrations can be retried after doing partial work, migrations
|
|
||||||
must be idempotent. Prefer operations that are safe to run more than once:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p ~/.config/example
|
|
||||||
rm -f ~/.config/example/legacy.conf
|
|
||||||
install -Dm644 "$OMARCHY_PATH/default/example.conf" ~/.config/example/example.conf
|
|
||||||
systemctl --user enable --now some-unit.service || true
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `|| true` only when a failure is genuinely acceptable.
|
|
||||||
|
|
||||||
## What belongs in a migration?
|
|
||||||
|
|
||||||
Good migration uses:
|
|
||||||
|
|
||||||
- deleting or moving legacy files that block the packaged layout
|
|
||||||
- marking or enabling new service state
|
|
||||||
- migrating old config paths to new config paths
|
|
||||||
- repairing known bad state from an earlier Omarchy release
|
|
||||||
- one-time compatibility for existing installs
|
|
||||||
|
|
||||||
Bad migration uses:
|
|
||||||
|
|
||||||
- fresh-install setup that belongs in `install/` or `/etc/skel`
|
|
||||||
- package installation that belongs in package dependencies or package lists
|
|
||||||
- recurring maintenance
|
|
||||||
- arbitrary cleanup that should be a user command
|
|
||||||
- pre-4 upgrade work that belongs in `omarchy-upgrade-to-4`
|
|
||||||
- hidden user/session work from pacman
|
|
||||||
|
|
||||||
## Fresh installs and new users
|
|
||||||
|
|
||||||
Fresh users created from the packaged layout should not have to run historical
|
|
||||||
user migrations. The package seeds user migration markers into `/etc/skel` so
|
|
||||||
new users start with shipped user migrations marked complete.
|
|
||||||
|
|
||||||
The ISO/finalization path also marks shipped user migrations complete for the
|
|
||||||
freshly-created install user when running:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
omarchy-finalize-user --first-install
|
|
||||||
```
|
|
||||||
|
|
||||||
Existing users keep their own migration state and run only migrations whose
|
|
||||||
state files are missing.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### See what is pending
|
|
||||||
|
|
||||||
```bash
|
|
||||||
omarchy-migrate --pending
|
|
||||||
```
|
|
||||||
|
|
||||||
### Retry failed migrations
|
|
||||||
|
|
||||||
Fix the underlying problem, then run:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
rm ~/.local/state/omarchy/migrations/<migration>.sh
|
||||||
omarchy-migrate
|
omarchy-migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
A failed migration is not marked complete, so it will retry.
|
Omarchy 4.0 is upgraded through `bin/omarchy-upgrade-to-4`, not through the
|
||||||
|
normal migration runner. Do not add compatibility migrations for old installer
|
||||||
### Re-run a completed migration manually
|
layouts; put pre-4 package-layout transition work in the upgrade command instead.
|
||||||
|
|
||||||
Remove its marker, then run the migration command again:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
rm ~/.local/state/omarchy/migrations/user/<migration>.sh
|
|
||||||
omarchy-migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
For system migrations:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo rm /var/lib/omarchy/migrations/system/<migration>.sh
|
|
||||||
omarchy-migrate
|
|
||||||
```
|
|
||||||
|
|
||||||
Be careful: migrations should be idempotent, but manually removing markers is an
|
|
||||||
advanced troubleshooting step.
|
|
||||||
|
|
||||||
## Agent checklist
|
|
||||||
|
|
||||||
Before adding a migration:
|
|
||||||
|
|
||||||
1. Is this a one-time repair for existing installs?
|
|
||||||
2. Is it system state or user/session state?
|
|
||||||
3. Can it run safely more than once?
|
|
||||||
4. Will it fail loudly if the important work fails?
|
|
||||||
5. Does it avoid hidden interactive work from pacman?
|
|
||||||
6. Does it belong in `omarchy-upgrade-to-4` instead?
|
|
||||||
7. Did you add or update tests if behavior changed?
|
|
||||||
|
|
||||||
If the answer to any of these is unclear, stop and ask before adding the
|
|
||||||
migration.
|
|
||||||
|
|||||||
+40
-104
@@ -10,13 +10,12 @@ bypass it:
|
|||||||
|
|
||||||
The design goal is:
|
The design goal is:
|
||||||
|
|
||||||
- System/root migrations should run automatically from package transactions when
|
- `omarchy update` owns the visible update pipeline: package transaction,
|
||||||
safe.
|
migrations, post-update hooks, update-state refresh, and restart checks.
|
||||||
- User/session migrations should never run invisibly from pacman because they may
|
- Migrations run per-user after pacman finishes, because they may need `$HOME`,
|
||||||
need `$HOME`, DBus/session state, a graphical session, or user interaction.
|
DBus/session state, a graphical session, sudo, or user interaction.
|
||||||
- Users who bypass `omarchy update` should still get system migrations from
|
- Users who bypass `omarchy update` are nudged back by the pacman guard; if they
|
||||||
pacman and should be notified only when their own user migration state is
|
explicitly bypass it, their session is notified when migrations are pending.
|
||||||
missing a shipped user migration.
|
|
||||||
|
|
||||||
## State and coordination files
|
## State and coordination files
|
||||||
|
|
||||||
@@ -26,8 +25,7 @@ The design goal is:
|
|||||||
| `/tmp/omarchy-update.log` | user | Transcript of `omarchy update`, used by `omarchy-update-analyze-logs`. |
|
| `/tmp/omarchy-update.log` | user | Transcript of `omarchy update`, used by `omarchy-update-analyze-logs`. |
|
||||||
| `~/.local/state/omarchy/updates/` | user | Update-check state for the shell widget (`packages`, `aur`, `available`, `checked-at`, `error`). |
|
| `~/.local/state/omarchy/updates/` | user | Update-check state for the shell widget (`packages`, `aur`, `available`, `checked-at`, `error`). |
|
||||||
| `~/.local/state/omarchy/current/` | user | Generated active theme, selected theme name, and current background symlink. |
|
| `~/.local/state/omarchy/current/` | user | Generated active theme, selected theme name, and current background symlink. |
|
||||||
| `/var/lib/omarchy/migrations/system/` | root | System migration markers. |
|
| `~/.local/state/omarchy/migrations/` | user | Per-user migration markers. |
|
||||||
| `~/.local/state/omarchy/migrations/user/` | user | User migration markers. |
|
|
||||||
| `~/.local/state/omarchy/reboot-required` | user | Optional reboot marker checked by `omarchy-update-restart`. |
|
| `~/.local/state/omarchy/reboot-required` | user | Optional reboot marker checked by `omarchy-update-restart`. |
|
||||||
| `~/.local/state/omarchy/restart-*-required` | user | Optional service/app restart markers checked by `omarchy-update-restart`. |
|
| `~/.local/state/omarchy/restart-*-required` | user | Optional service/app restart markers checked by `omarchy-update-restart`. |
|
||||||
|
|
||||||
@@ -36,83 +34,32 @@ The design goal is:
|
|||||||
See [`migrations.md`](migrations.md) for the full migration model, authoring
|
See [`migrations.md`](migrations.md) for the full migration model, authoring
|
||||||
guidelines, and troubleshooting notes.
|
guidelines, and troubleshooting notes.
|
||||||
|
|
||||||
Migrations are scoped by directory:
|
Migrations live in:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
migrations/system/*.sh
|
migrations/*.sh
|
||||||
migrations/user/*.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### System migrations
|
They run as the current user through:
|
||||||
|
|
||||||
System migrations are root-owned, noninteractive fixes for existing installs.
|
|
||||||
They may touch `/etc`, `/usr`, `/boot`, system services, hardware configuration,
|
|
||||||
and other machine-wide state.
|
|
||||||
|
|
||||||
Runner:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
omarchy-migrate-system
|
|
||||||
```
|
|
||||||
|
|
||||||
Completion state:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/var/lib/omarchy/migrations/system/<migration filename>
|
|
||||||
```
|
|
||||||
|
|
||||||
Pacman integration:
|
|
||||||
|
|
||||||
```text
|
|
||||||
pkgbuilds/omarchy/omarchy.install post_upgrade()
|
|
||||||
```
|
|
||||||
|
|
||||||
The `omarchy` package calls `omarchy-migrate-system` from `post_upgrade()`.
|
|
||||||
The runner is idempotent, so repeated calls only check the state files.
|
|
||||||
|
|
||||||
### User migrations
|
|
||||||
|
|
||||||
User migrations are current-user/session fixes. They may touch `~/.config`,
|
|
||||||
`~/.local`, user systemd units, browser/editor preferences, DBus/session state,
|
|
||||||
or ask questions.
|
|
||||||
|
|
||||||
Runner:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
omarchy-migrate-user
|
|
||||||
```
|
|
||||||
|
|
||||||
Public command:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
omarchy-migrate
|
omarchy-migrate
|
||||||
```
|
```
|
||||||
|
|
||||||
Completion state:
|
Completion state is per-user:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
~/.local/state/omarchy/migrations/user/<migration filename>
|
~/.local/state/omarchy/migrations/<migration filename>
|
||||||
```
|
```
|
||||||
|
|
||||||
A user migration is pending only when a script exists in `migrations/user/` and
|
Every user gets a chance to run every migration. Migrations run as the user;
|
||||||
that user's matching state file is missing. There is no global root-owned queue
|
privileged work should invoke the appropriate helper or privilege prompt.
|
||||||
for user migrations.
|
Migrations must be idempotent; if one user already applied a machine-wide repair,
|
||||||
|
the migration should no-op for other users.
|
||||||
|
|
||||||
`omarchy-migrate` is the public command. It waits for any active pacman
|
For watchers and diagnostics, `omarchy-migrate --pending` prints pending
|
||||||
transaction to finish, runs pending system migrations, then runs pending user
|
migration names and exits `0` when any are pending. When no migrations are
|
||||||
migrations. It does not need `--force`; migrations should happen when they are
|
pending, it prints nothing and exits non-zero.
|
||||||
pending.
|
|
||||||
|
|
||||||
For watchers and diagnostics, `omarchy-migrate --pending [all|system|user]`
|
|
||||||
prints pending migration names and exits `0` when any are pending. Output is
|
|
||||||
scope-prefixed, for example:
|
|
||||||
|
|
||||||
```text
|
|
||||||
system/100-system.sh
|
|
||||||
user/200-user.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
When no matching migrations are pending, it prints nothing and exits non-zero.
|
|
||||||
|
|
||||||
## Raw pacman guard
|
## Raw pacman guard
|
||||||
|
|
||||||
@@ -187,10 +134,8 @@ omarchy-update
|
|||||||
|
|
||||||
Important behavior:
|
Important behavior:
|
||||||
|
|
||||||
- `omarchy update` checks/runs system and user migrations in the same visible
|
- `omarchy update` checks/runs migrations in the same visible terminal via
|
||||||
terminal via `omarchy-migrate`.
|
`omarchy-migrate` after pacman finishes.
|
||||||
- `omarchy update` still benefits from pacman-triggered system migrations
|
|
||||||
because the system migration hook runs as part of the pacman transaction.
|
|
||||||
- A failure should leave enough output in `/tmp/omarchy-update.log` and the
|
- A failure should leave enough output in `/tmp/omarchy-update.log` and the
|
||||||
terminal transcript to debug.
|
terminal transcript to debug.
|
||||||
|
|
||||||
@@ -202,10 +147,9 @@ High-level flow:
|
|||||||
sudo pacman -Syu
|
sudo pacman -Syu
|
||||||
├─ pre-transaction guard aborts and tells the user to run omarchy update
|
├─ pre-transaction guard aborts and tells the user to run omarchy update
|
||||||
└─ if explicitly bypassed, upgrades omarchy and related packages
|
└─ if explicitly bypassed, upgrades omarchy and related packages
|
||||||
├─ omarchy post_upgrade runs omarchy-migrate-system as root
|
|
||||||
└─ user session notices migration directory changes
|
└─ user session notices migration directory changes
|
||||||
├─ omarchy-update-user-notify.path triggers, if enabled
|
├─ omarchy-update-user-notify.path triggers, if enabled
|
||||||
├─ omarchy-migrate-notify checks omarchy-migrate --pending user
|
├─ omarchy-migrate-notify checks omarchy-migrate --pending
|
||||||
├─ if this user has missing migration state, show notification
|
├─ if this user has missing migration state, show notification
|
||||||
└─ click opens terminal: omarchy-migrate
|
└─ click opens terminal: omarchy-migrate
|
||||||
```
|
```
|
||||||
@@ -215,12 +159,11 @@ Fallbacks:
|
|||||||
- `omarchy-first-run` enables the user notification path unit.
|
- `omarchy-first-run` enables the user notification path unit.
|
||||||
- `omarchy-first-run` also invokes `omarchy-migrate-notify` on graphical
|
- `omarchy-first-run` also invokes `omarchy-migrate-notify` on graphical
|
||||||
startup, so users who updated before the path unit existed still get prompted
|
startup, so users who updated before the path unit existed still get prompted
|
||||||
if they have missing user migration state.
|
if they have missing migration state.
|
||||||
- The notifier is only a prompt. It does not run user migrations in the
|
- The notifier is only a prompt. It does not run migrations in the background.
|
||||||
background.
|
|
||||||
- Direct pacman updates do not run `omarchy-hook post-update` unless the user
|
- Direct pacman updates do not run `omarchy-hook post-update` unless the user
|
||||||
explicitly runs that hook; without a package-update marker, the only user-side
|
explicitly runs that hook; without a package-update marker, the only pending
|
||||||
pending state we can derive is missing user migration markers.
|
state we can derive is missing per-user migration markers.
|
||||||
|
|
||||||
## Shell update indicator
|
## Shell update indicator
|
||||||
|
|
||||||
@@ -265,11 +208,9 @@ scripts.
|
|||||||
| `omarchy-update-confirm` | Gum confirmation copy for `omarchy update`. | **Question.** Could be inlined into `omarchy-update`; separate file only helps keep copy isolated. |
|
| `omarchy-update-confirm` | Gum confirmation copy for `omarchy update`. | **Question.** Could be inlined into `omarchy-update`; separate file only helps keep copy isolated. |
|
||||||
| `omarchy-update-keyring` | Ensures Omarchy keyring and Arch keyring are current before the main transaction. | **Keep, but review.** It uses targeted `pacman -Sy` for keyring bootstrapping; acceptable for this special case but should remain tightly scoped. |
|
| `omarchy-update-keyring` | Ensures Omarchy keyring and Arch keyring are current before the main transaction. | **Keep, but review.** It uses targeted `pacman -Sy` for keyring bootstrapping; acceptable for this special case but should remain tightly scoped. |
|
||||||
| `omarchy-update-system-pkgs` | Runs `sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syu --noconfirm` with targeted transition `--overwrite` entries so the ALPM guard allows the transaction and early package-layout conflicts are handled. | **Keep for now.** Small leaf command, clear/testable. |
|
| `omarchy-update-system-pkgs` | Runs `sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syu --noconfirm` with targeted transition `--overwrite` entries so the ALPM guard allows the transaction and early package-layout conflicts are handled. | **Keep for now.** Small leaf command, clear/testable. |
|
||||||
| `omarchy-migrate-system` | Runs root/system migrations from `migrations/system`. Called by `omarchy` package `post_upgrade()` and by `omarchy-migrate` when system migration state is missing. | **Keep.** This is the important direct-`pacman -Syu` integration. |
|
| `omarchy-migrate` | Public migration command. Waits for pacman, then runs all pending migrations for the current user. Supports `--pending`. | **Keep.** This replaces the discarded `omarchy-update-user-finalize` name and no longer needs `--force`. |
|
||||||
| `omarchy-migrate-user` | Checks `migrations/user` against this user's state and runs only missing user migrations. Supports `--pending` and prints pending filenames. | **Keep internal.** Public users should generally run `omarchy-migrate`. |
|
|
||||||
| `omarchy-migrate` | Public migration command. Waits for pacman, then runs pending system and user migrations. Supports `--pending [all|system|user]` and prints scope-prefixed pending filenames. | **Keep.** This replaces the discarded `omarchy-update-user-finalize` name and no longer needs `--force`. |
|
|
||||||
| `omarchy-update-pacman-guard` | ALPM pre-transaction guard that aborts direct `pacman -Syu` style upgrades unless Omarchy set `OMARCHY_UPDATE_PACMAN=1` or the user explicitly set `OMARCHY_ALLOW_DIRECT_PACMAN=1`. | **Keep internal/hidden.** This is what nudges users back to `omarchy update`. |
|
| `omarchy-update-pacman-guard` | ALPM pre-transaction guard that aborts direct `pacman -Syu` style upgrades unless Omarchy set `OMARCHY_UPDATE_PACMAN=1` or the user explicitly set `OMARCHY_ALLOW_DIRECT_PACMAN=1`. | **Keep internal/hidden.** This is what nudges users back to `omarchy update`. |
|
||||||
| `omarchy-migrate-notify` | Internal notification helper for direct pacman updates. Uses `omarchy-migrate --pending user` and shows notification only when this user has pending migrations. | **Keep internal/hidden.** Clear name now that the public command is `omarchy-migrate`. |
|
| `omarchy-migrate-notify` | Internal notification helper for direct pacman updates. Uses `omarchy-migrate --pending` and shows notification only when this user has pending migrations. | **Keep internal/hidden.** Clear name now that the public command is `omarchy-migrate`. |
|
||||||
| `omarchy-update-user-notify` | Hidden compatibility wrapper for `omarchy-migrate-notify`. | **Temporary.** Keep only for old callers. |
|
| `omarchy-update-user-notify` | Hidden compatibility wrapper for `omarchy-migrate-notify`. | **Temporary.** Keep only for old callers. |
|
||||||
| `omarchy-update-available` | Update checker for shell widget and post-update refresh. Writes update state. | **Keep.** Could eventually be renamed `omarchy-update-check`, but current name matches widget semantics. |
|
| `omarchy-update-available` | Update checker for shell widget and post-update refresh. Writes update state. | **Keep.** Could eventually be renamed `omarchy-update-check`, but current name matches widget semantics. |
|
||||||
| `omarchy-update-aur-pkgs` | Updates AUR packages with `yay -Sua` if foreign packages exist and AUR is reachable. | **Question.** Omarchy is package-backed now, but users may still install AUR packages. Keep for now. |
|
| `omarchy-update-aur-pkgs` | Updates AUR packages with `yay -Sua` if foreign packages exist and AUR is reachable. | **Question.** Omarchy is package-backed now, but users may still install AUR packages. Keep for now. |
|
||||||
@@ -282,36 +223,31 @@ scripts.
|
|||||||
|
|
||||||
## Closed decisions
|
## Closed decisions
|
||||||
|
|
||||||
1. **System migrations run from the `omarchy` package**
|
1. **Migrations run per-user from the update pipeline**
|
||||||
- `omarchy.install post_upgrade()` calls `omarchy-migrate-system`.
|
- `omarchy update` runs `omarchy-migrate` after pacman finishes.
|
||||||
- We do not need a separate system-migration ALPM hook from
|
- Package-time migration runners do not apply migrations inside pacman.
|
||||||
`omarchy-settings`.
|
- Every user has per-user migration markers, and migrations must be
|
||||||
|
idempotent when they repair machine-wide state.
|
||||||
|
|
||||||
2. **Root vs user migrations stay separate**
|
2. **Migration notification naming**
|
||||||
- Do not use `su {user}` from pacman to run user migrations.
|
|
||||||
- User migrations need the user's real session and should be visible.
|
|
||||||
- Pending user work is determined only by comparing `migrations/user/*.sh`
|
|
||||||
against `~/.local/state/omarchy/migrations/user/`.
|
|
||||||
|
|
||||||
3. **Migration notification naming**
|
|
||||||
- The real helper is `omarchy-migrate-notify`.
|
- The real helper is `omarchy-migrate-notify`.
|
||||||
- `omarchy-update-user-notify` remains only as a hidden compatibility wrapper.
|
- `omarchy-update-user-notify` remains only as a hidden compatibility wrapper.
|
||||||
|
|
||||||
4. **Update pipeline ownership**
|
3. **Update pipeline ownership**
|
||||||
- `omarchy-update` owns the full update pipeline now.
|
- `omarchy-update` owns the full update pipeline now.
|
||||||
- `omarchy-update-perform` is only a hidden compatibility wrapper for
|
- `omarchy-update-perform` is only a hidden compatibility wrapper for
|
||||||
`omarchy-update -y`.
|
`omarchy-update -y`.
|
||||||
|
|
||||||
5. **Mise remains in the blessed update path**
|
4. **Mise remains in the blessed update path**
|
||||||
- `omarchy-update-mise` intentionally runs as part of `omarchy update`.
|
- `omarchy-update-mise` intentionally runs as part of `omarchy update`.
|
||||||
|
|
||||||
6. **Orphan cleanup stays in the update path for now**
|
5. **Orphan cleanup stays in the update path for now**
|
||||||
- It is prompt-only and never removes packages noninteractively.
|
- It is prompt-only and never removes packages noninteractively.
|
||||||
|
|
||||||
7. **Direct pacman user follow-up is based on actual migration state**
|
6. **Direct pacman user follow-up is based on actual migration state**
|
||||||
- Direct `sudo pacman -Syu` no longer uses a fake user-update marker.
|
- Direct `sudo pacman -Syu` no longer uses a fake user-update marker.
|
||||||
- User notifications are shown only when `omarchy-migrate --pending user`
|
- User notifications are shown only when `omarchy-migrate --pending` finds
|
||||||
finds missing per-user migration state.
|
missing per-user migration state.
|
||||||
|
|
||||||
## Remaining concerns
|
## Remaining concerns
|
||||||
|
|
||||||
|
|||||||
@@ -393,7 +393,7 @@ package.path = os.getenv("HOME")
|
|||||||
.. package.path
|
.. package.path
|
||||||
LUA
|
LUA
|
||||||
ln -s "$MIGRATION_TMPDIR/.config/omarchy/current/theme/btop.theme" "$MIGRATION_TMPDIR/.config/btop/themes/current.theme"
|
ln -s "$MIGRATION_TMPDIR/.config/omarchy/current/theme/btop.theme" "$MIGRATION_TMPDIR/.config/btop/themes/current.theme"
|
||||||
HOME="$MIGRATION_TMPDIR" bash -euo pipefail "$ROOT/migrations/user/1781043107.sh" >/dev/null
|
HOME="$MIGRATION_TMPDIR" bash -euo pipefail "$ROOT/migrations/1781043107.sh" >/dev/null
|
||||||
[[ -f $MIGRATION_TMPDIR/.local/state/omarchy/current/theme.name ]] || fail "current theme migration moves theme name"
|
[[ -f $MIGRATION_TMPDIR/.local/state/omarchy/current/theme.name ]] || fail "current theme migration moves theme name"
|
||||||
[[ ! -e $MIGRATION_TMPDIR/.config/omarchy/current ]] || fail "current theme migration removes legacy config state"
|
[[ ! -e $MIGRATION_TMPDIR/.config/omarchy/current ]] || fail "current theme migration removes legacy config state"
|
||||||
grep -Fq '~/.local/state/omarchy/current/theme/alacritty.toml' "$MIGRATION_TMPDIR/.config/alacritty/alacritty.toml" || fail "current theme migration updates alacritty import"
|
grep -Fq '~/.local/state/omarchy/current/theme/alacritty.toml' "$MIGRATION_TMPDIR/.config/alacritty/alacritty.toml" || fail "current theme migration updates alacritty import"
|
||||||
@@ -415,7 +415,7 @@ for nvim_legacy_target in \
|
|||||||
"../../../omarchy/current/theme/neovim.lua" \
|
"../../../omarchy/current/theme/neovim.lua" \
|
||||||
"$NVIM_MIGRATION_TMPDIR/.config/omarchy/current/theme/neovim.lua"; do
|
"$NVIM_MIGRATION_TMPDIR/.config/omarchy/current/theme/neovim.lua"; do
|
||||||
ln -sfn "$nvim_legacy_target" "$nvim_theme_link"
|
ln -sfn "$nvim_legacy_target" "$nvim_theme_link"
|
||||||
HOME="$NVIM_MIGRATION_TMPDIR" bash -euo pipefail "$ROOT/migrations/user/1781158082.sh" >/dev/null
|
HOME="$NVIM_MIGRATION_TMPDIR" bash -euo pipefail "$ROOT/migrations/1781158082.sh" >/dev/null
|
||||||
nvim_actual_target=$(readlink "$nvim_theme_link")
|
nvim_actual_target=$(readlink "$nvim_theme_link")
|
||||||
nvim_resolved_target=$(readlink -f "$nvim_theme_link")
|
nvim_resolved_target=$(readlink -f "$nvim_theme_link")
|
||||||
[[ $nvim_actual_target == $nvim_expected_target ]] || fail "nvim theme migration updates theme symlink"
|
[[ $nvim_actual_target == $nvim_expected_target ]] || fail "nvim theme migration updates theme symlink"
|
||||||
|
|||||||
@@ -276,11 +276,12 @@ jq -e '
|
|||||||
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
|
' "$TMPDIR/home/.config/omarchy/shell.json" >/dev/null
|
||||||
pass "shell config removes widgets with remove alias"
|
pass "shell config removes widgets with remove alias"
|
||||||
|
|
||||||
mapfile -t migrations < <(find "$ROOT/migrations" -maxdepth 1 -type f -name '*.sh' -printf '%f\n' | sort)
|
if grep -RIl 'upgrade-to-4\|Omarchy 4\.0 is upgraded' "$ROOT/migrations" >/dev/null; then
|
||||||
[[ ${#migrations[@]} -eq 0 ]] || fail "4.0 upgrade is not modeled as a migration"
|
fail "4.0 upgrade is not modeled as a migration"
|
||||||
|
fi
|
||||||
pass "4.0 upgrade is handled outside the migration runner"
|
pass "4.0 upgrade is handled outside the migration runner"
|
||||||
|
|
||||||
clock_migration=$(grep -rl 'Remove leading zero from bar clock date' "$ROOT/migrations/user" | head -n 1 || true)
|
clock_migration=$(grep -rl 'Remove leading zero from bar clock date' "$ROOT/migrations" | head -n 1 || true)
|
||||||
[[ -n $clock_migration ]] || fail "clock date format user migration exists"
|
[[ -n $clock_migration ]] || fail "clock date format user migration exists"
|
||||||
|
|
||||||
cat >"$TMPDIR/home/.config/omarchy/shell.json" <<'JSON'
|
cat >"$TMPDIR/home/.config/omarchy/shell.json" <<'JSON'
|
||||||
|
|||||||
@@ -11,16 +11,16 @@ stub_bin="$test_tmp/bin"
|
|||||||
test_home="$test_tmp/home"
|
test_home="$test_tmp/home"
|
||||||
mkdir -p "$stub_bin" "$test_home"
|
mkdir -p "$stub_bin" "$test_home"
|
||||||
|
|
||||||
cat >"$stub_bin/omarchy-migrate-user" <<'SH'
|
cat >"$stub_bin/omarchy-migrate" <<'SH'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
if [[ ${1:-} == "--pending" && ${OMARCHY_TEST_PENDING_MIGRATIONS:-0} == 1 ]]; then
|
if [[ ${1:-} == "--pending" && ${OMARCHY_TEST_PENDING_MIGRATIONS:-0} == 1 ]]; then
|
||||||
echo 200-user.sh
|
echo 200-migration.sh
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
SH
|
SH
|
||||||
chmod +x "$stub_bin/omarchy-migrate-user"
|
chmod +x "$stub_bin/omarchy-migrate"
|
||||||
|
|
||||||
cat >"$stub_bin/systemd-run" <<'SH'
|
cat >"$stub_bin/systemd-run" <<'SH'
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
@@ -41,6 +41,6 @@ run_notify 0 >"$test_tmp/not-pending.out" 2>"$test_tmp/not-pending.err"
|
|||||||
pass "migration notifier ignores users with no pending migrations"
|
pass "migration notifier ignores users with no pending migrations"
|
||||||
|
|
||||||
run_notify 1 >"$test_tmp/pending.out" 2>"$test_tmp/pending.err"
|
run_notify 1 >"$test_tmp/pending.out" 2>"$test_tmp/pending.err"
|
||||||
grep -q 'Omarchy has pending user migrations' "$test_tmp/pending.err" || fail "migration notifier explains pending migrations without notification system"
|
grep -q 'Omarchy has pending migrations' "$test_tmp/pending.err" || fail "migration notifier explains pending migrations without notification system"
|
||||||
grep -q 'user/200-user.sh' "$test_tmp/pending.err" || fail "migration notifier lists pending migration names"
|
grep -q '200-migration.sh' "$test_tmp/pending.err" || fail "migration notifier lists pending migration names"
|
||||||
pass "migration notifier reports pending user migrations"
|
pass "migration notifier reports pending migrations"
|
||||||
|
|||||||
@@ -9,107 +9,69 @@ trap 'rm -rf "$test_tmp"' EXIT
|
|||||||
|
|
||||||
test_root="$test_tmp/omarchy"
|
test_root="$test_tmp/omarchy"
|
||||||
test_home="$test_tmp/home"
|
test_home="$test_tmp/home"
|
||||||
system_state="$test_tmp/system-state"
|
mkdir -p "$test_root/migrations" "$test_home"
|
||||||
mkdir -p "$test_root/migrations/system" "$test_root/migrations/user" "$test_home" "$system_state"
|
|
||||||
|
|
||||||
cat >"$test_root/migrations/system/100-system.sh" <<'SH'
|
cat >"$test_root/migrations/100-first.sh" <<'SH'
|
||||||
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
|
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
|
||||||
echo system >>"$TEST_CALLS"
|
echo first >>"$TEST_CALLS"
|
||||||
SH
|
SH
|
||||||
cat >"$test_root/migrations/user/200-user.sh" <<'SH'
|
cat >"$test_root/migrations/200-second.sh" <<'SH'
|
||||||
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
|
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
|
||||||
echo user >>"$TEST_CALLS"
|
echo second >>"$TEST_CALLS"
|
||||||
SH
|
SH
|
||||||
|
|
||||||
calls="$test_tmp/calls"
|
calls="$test_tmp/calls"
|
||||||
|
|
||||||
if ! HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate-user" --pending >"$test_tmp/user-pending.out"; then
|
if ! HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate" --pending >"$test_tmp/pending.out"; then
|
||||||
fail "user migration runner reports pending migrations before state exists"
|
fail "migration runner reports pending migrations before state exists"
|
||||||
fi
|
fi
|
||||||
grep -q '^200-user\.sh$' "$test_tmp/user-pending.out" || fail "user migration runner lists pending migration filename"
|
grep -q '^100-first\.sh$' "$test_tmp/pending.out" || fail "migration runner lists first pending migration filename"
|
||||||
pass "user migration runner detects pending migrations"
|
grep -q '^200-second\.sh$' "$test_tmp/pending.out" || fail "migration runner lists second pending migration filename"
|
||||||
|
pass "migration runner detects pending migrations"
|
||||||
|
|
||||||
HOME="$test_home" \
|
HOME="$test_home" \
|
||||||
OMARCHY_PATH="$test_root" \
|
OMARCHY_PATH="$test_root" \
|
||||||
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
|
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
|
||||||
TEST_CALLS="$calls" \
|
TEST_CALLS="$calls" \
|
||||||
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-first.out"
|
"$ROOT/bin/omarchy-migrate" >"$test_tmp/first-run.out"
|
||||||
[[ $(grep -c '^user$' "$calls") -eq 1 ]] || fail "user migration runner runs user migrations"
|
[[ $(sed -n '1p' "$calls") == "first" ]] || fail "migration runner runs first migration"
|
||||||
! grep -q '^system$' "$calls" || fail "user migration runner does not run system migrations"
|
[[ $(sed -n '2p' "$calls") == "second" ]] || fail "migration runner runs second migration"
|
||||||
[[ -f $test_home/.local/state/omarchy/migrations/user/200-user.sh ]] || fail "user migration runner records user migration marker"
|
[[ -f $test_home/.local/state/omarchy/migrations/100-first.sh ]] || fail "migration runner records first migration marker"
|
||||||
pass "user migration runner only runs user migrations"
|
[[ -f $test_home/.local/state/omarchy/migrations/200-second.sh ]] || fail "migration runner records second migration marker"
|
||||||
|
pass "migration runner runs all migrations"
|
||||||
|
|
||||||
HOME="$test_home" \
|
HOME="$test_home" \
|
||||||
OMARCHY_PATH="$test_root" \
|
OMARCHY_PATH="$test_root" \
|
||||||
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
|
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
|
||||||
TEST_CALLS="$calls" \
|
TEST_CALLS="$calls" \
|
||||||
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-second.out"
|
"$ROOT/bin/omarchy-migrate" >"$test_tmp/second-run.out"
|
||||||
[[ $(grep -c '^user$' "$calls") -eq 1 ]] || fail "user migration runner skips completed migrations"
|
[[ $(wc -l <"$calls") -eq 2 ]] || fail "migration runner skips completed migrations"
|
||||||
pass "user migration runner skips completed migrations"
|
pass "migration runner skips completed migrations"
|
||||||
|
|
||||||
if HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate-user" --pending >"$test_tmp/user-not-pending.out"; then
|
if HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate" --pending >"$test_tmp/not-pending.out"; then
|
||||||
fail "user migration runner reports no pending migrations after state exists"
|
fail "migration runner reports no pending migrations after state exists"
|
||||||
fi
|
fi
|
||||||
pass "user migration runner detects no pending migrations"
|
pass "migration runner detects no pending migrations"
|
||||||
|
|
||||||
if ! OMARCHY_PATH="$test_root" OMARCHY_SYSTEM_MIGRATION_STATE="$system_state" "$ROOT/bin/omarchy-migrate-system" --pending >"$test_tmp/system-pending.out"; then
|
|
||||||
fail "system migration runner reports pending migrations before state exists"
|
|
||||||
fi
|
|
||||||
grep -q '^100-system\.sh$' "$test_tmp/system-pending.out" || fail "system migration runner lists pending migration filename"
|
|
||||||
|
|
||||||
OMARCHY_PATH="$test_root" \
|
|
||||||
OMARCHY_SYSTEM_MIGRATION_STATE="$system_state" \
|
|
||||||
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
|
|
||||||
TEST_CALLS="$calls" \
|
|
||||||
"$ROOT/bin/omarchy-migrate-system" >"$test_tmp/system-first.out"
|
|
||||||
[[ $(grep -c '^system$' "$calls") -eq 1 ]] || fail "system migration runner runs system migrations"
|
|
||||||
[[ -f $system_state/100-system.sh ]] || fail "system migration runner records system migration marker"
|
|
||||||
pass "system migration runner only runs system migrations"
|
|
||||||
|
|
||||||
if OMARCHY_PATH="$test_root" OMARCHY_SYSTEM_MIGRATION_STATE="$system_state" "$ROOT/bin/omarchy-migrate-system" --pending >"$test_tmp/system-not-pending.out"; then
|
|
||||||
fail "system migration runner reports no pending migrations after state exists"
|
|
||||||
fi
|
|
||||||
pass "system migration runner detects no pending migrations"
|
|
||||||
|
|
||||||
failure_root="$test_tmp/failure-omarchy"
|
failure_root="$test_tmp/failure-omarchy"
|
||||||
failure_home="$test_tmp/failure-home"
|
failure_home="$test_tmp/failure-home"
|
||||||
failure_system_state="$test_tmp/failure-system-state"
|
mkdir -p "$failure_root/migrations" "$failure_home"
|
||||||
mkdir -p "$failure_root/migrations/system" "$failure_root/migrations/user" "$failure_home" "$failure_system_state"
|
|
||||||
|
|
||||||
cat >"$failure_root/migrations/user/300-fail-user.sh" <<'SH'
|
cat >"$failure_root/migrations/500-fail.sh" <<'SH'
|
||||||
echo user-before-fail >>"$TEST_CALLS"
|
echo before-fail >>"$TEST_CALLS"
|
||||||
false
|
false
|
||||||
echo user-after-fail >>"$TEST_CALLS"
|
echo after-fail >>"$TEST_CALLS"
|
||||||
SH
|
SH
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
HOME="$failure_home" \
|
HOME="$failure_home" \
|
||||||
OMARCHY_PATH="$failure_root" \
|
OMARCHY_PATH="$failure_root" \
|
||||||
TEST_CALLS="$calls" \
|
TEST_CALLS="$calls" \
|
||||||
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-failure.out" 2>"$test_tmp/user-failure.err"
|
"$ROOT/bin/omarchy-migrate" >"$test_tmp/failure.out" 2>"$test_tmp/failure.err"
|
||||||
user_failure_status=$?
|
failure_status=$?
|
||||||
set -e
|
set -e
|
||||||
[[ $user_failure_status -ne 0 ]] || fail "user migration runner exits non-zero when a migration fails"
|
[[ $failure_status -ne 0 ]] || fail "migration runner exits non-zero when a migration fails"
|
||||||
[[ ! -f $failure_home/.local/state/omarchy/migrations/user/300-fail-user.sh ]] || fail "user migration runner does not mark failed migration complete"
|
[[ ! -f $failure_home/.local/state/omarchy/migrations/500-fail.sh ]] || fail "migration runner does not mark failed migration complete"
|
||||||
grep -q '^user-before-fail$' "$calls" || fail "user migration runner started failing migration"
|
grep -q '^before-fail$' "$calls" || fail "migration runner started failing migration"
|
||||||
! grep -q '^user-after-fail$' "$calls" || fail "user migration runner stops failing migration under strict mode"
|
! grep -q '^after-fail$' "$calls" || fail "migration runner stops failing migration under strict mode"
|
||||||
pass "user migration runner does not mark failed migrations complete"
|
pass "migration runner does not mark failed migrations complete"
|
||||||
|
|
||||||
cat >"$failure_root/migrations/system/400-fail-system.sh" <<'SH'
|
|
||||||
echo system-before-fail >>"$TEST_CALLS"
|
|
||||||
false
|
|
||||||
echo system-after-fail >>"$TEST_CALLS"
|
|
||||||
SH
|
|
||||||
|
|
||||||
set +e
|
|
||||||
OMARCHY_PATH="$failure_root" \
|
|
||||||
OMARCHY_SYSTEM_MIGRATION_STATE="$failure_system_state" \
|
|
||||||
TEST_CALLS="$calls" \
|
|
||||||
"$ROOT/bin/omarchy-migrate-system" >"$test_tmp/system-failure.out" 2>"$test_tmp/system-failure.err"
|
|
||||||
system_failure_status=$?
|
|
||||||
set -e
|
|
||||||
[[ $system_failure_status -ne 0 ]] || fail "system migration runner exits non-zero when a migration fails"
|
|
||||||
[[ ! -f $failure_system_state/400-fail-system.sh ]] || fail "system migration runner does not mark failed migration complete"
|
|
||||||
grep -q '^system-before-fail$' "$calls" || fail "system migration runner started failing migration"
|
|
||||||
! grep -q '^system-after-fail$' "$calls" || fail "system migration runner stops failing migration under strict mode"
|
|
||||||
pass "system migration runner does not mark failed migrations complete"
|
|
||||||
|
|||||||
@@ -7,57 +7,33 @@ source "$(dirname "$0")/base-test.sh"
|
|||||||
test_tmp=$(mktemp -d)
|
test_tmp=$(mktemp -d)
|
||||||
trap 'rm -rf "$test_tmp"' EXIT
|
trap 'rm -rf "$test_tmp"' EXIT
|
||||||
|
|
||||||
stub_bin="$test_tmp/bin"
|
test_root="$test_tmp/omarchy"
|
||||||
test_home="$test_tmp/home"
|
test_home="$test_tmp/home"
|
||||||
mkdir -p "$stub_bin" "$test_home"
|
mkdir -p "$test_root/migrations" "$test_home"
|
||||||
|
|
||||||
cat >"$stub_bin/omarchy-migrate-system" <<'SH'
|
cat >"$test_root/migrations/100-migration.sh" <<'SH'
|
||||||
#!/bin/bash
|
echo migration >>"$TEST_CALLS"
|
||||||
if [[ ${1:-} == "--pending" ]]; then
|
|
||||||
[[ ${OMARCHY_TEST_PENDING_SYSTEM:-1} == 1 ]] || exit 1
|
|
||||||
echo 100-system.sh
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo system >>"$TEST_CALLS"
|
|
||||||
SH
|
SH
|
||||||
chmod +x "$stub_bin/omarchy-migrate-system"
|
|
||||||
|
|
||||||
cat >"$stub_bin/omarchy-migrate-user" <<'SH'
|
|
||||||
#!/bin/bash
|
|
||||||
if [[ ${1:-} == "--pending" ]]; then
|
|
||||||
[[ ${OMARCHY_TEST_PENDING_USER:-1} == 1 ]] || exit 1
|
|
||||||
echo 200-user.sh
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo user >>"$TEST_CALLS"
|
|
||||||
SH
|
|
||||||
chmod +x "$stub_bin/omarchy-migrate-user"
|
|
||||||
|
|
||||||
run_migrate() {
|
run_migrate() {
|
||||||
HOME="$test_home" \
|
HOME="$test_home" \
|
||||||
PATH="$stub_bin:$PATH" \
|
OMARCHY_PATH="$test_root" \
|
||||||
TEST_CALLS="$test_tmp/calls" \
|
TEST_CALLS="$test_tmp/calls" \
|
||||||
"$ROOT/bin/omarchy-migrate" "$@"
|
"$ROOT/bin/omarchy-migrate" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
: >"$test_tmp/calls"
|
: >"$test_tmp/calls"
|
||||||
run_migrate >"$test_tmp/migrate.out"
|
run_migrate >"$test_tmp/migrate.out"
|
||||||
[[ $(sed -n '1p' "$test_tmp/calls") == "system" ]] || fail "omarchy-migrate runs system migrations first"
|
[[ $(sed -n '1p' "$test_tmp/calls") == "migration" ]] || fail "omarchy-migrate runs pending migrations"
|
||||||
[[ $(sed -n '2p' "$test_tmp/calls") == "user" ]] || fail "omarchy-migrate runs user migrations second"
|
pass "omarchy-migrate runs migrations without force"
|
||||||
[[ $(wc -l <"$test_tmp/calls") -eq 2 ]] || fail "omarchy-migrate only delegates to system and user migration runners"
|
|
||||||
pass "omarchy-migrate runs system and user migrations without force"
|
|
||||||
|
|
||||||
run_migrate --pending >"$test_tmp/pending-all.out"
|
rm -rf "$test_home/.local/state/omarchy/migrations"
|
||||||
grep -q '^system/100-system\.sh$' "$test_tmp/pending-all.out" || fail "omarchy-migrate --pending lists pending system migrations"
|
run_migrate --pending >"$test_tmp/pending.out"
|
||||||
grep -q '^user/200-user\.sh$' "$test_tmp/pending-all.out" || fail "omarchy-migrate --pending lists pending user migrations"
|
grep -q '^100-migration\.sh$' "$test_tmp/pending.out" || fail "omarchy-migrate --pending lists pending migrations"
|
||||||
pass "omarchy-migrate --pending lists all pending migrations"
|
pass "omarchy-migrate --pending lists pending migrations"
|
||||||
|
|
||||||
run_migrate --pending user >"$test_tmp/pending-user.out"
|
run_migrate >"$test_tmp/migrate-second.out"
|
||||||
grep -q '^user/200-user\.sh$' "$test_tmp/pending-user.out" || fail "omarchy-migrate --pending user lists user migrations"
|
if run_migrate --pending >"$test_tmp/not-pending.out"; then
|
||||||
! grep -q '^system/' "$test_tmp/pending-user.out" || fail "omarchy-migrate --pending user omits system migrations"
|
|
||||||
pass "omarchy-migrate --pending user scopes pending output"
|
|
||||||
|
|
||||||
if OMARCHY_TEST_PENDING_SYSTEM=0 OMARCHY_TEST_PENDING_USER=0 run_migrate --pending >"$test_tmp/not-pending.out"; then
|
|
||||||
fail "omarchy-migrate --pending exits non-zero without pending migrations"
|
fail "omarchy-migrate --pending exits non-zero without pending migrations"
|
||||||
fi
|
fi
|
||||||
[[ ! -s $test_tmp/not-pending.out ]] || fail "omarchy-migrate --pending stays quiet without pending migrations"
|
[[ ! -s $test_tmp/not-pending.out ]] || fail "omarchy-migrate --pending stays quiet without pending migrations"
|
||||||
|
|||||||
Reference in New Issue
Block a user