mirror of
https://github.com/arthur-pbty/arthur-os.git
synced 2026-08-01 20:28:16 +02:00
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.
|
||||
|
||||
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.
|
||||
- `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.
|
||||
To create a new migration, run `omarchy-dev-add-migration --no-edit`.
|
||||
|
||||
New migration format:
|
||||
- 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
|
||||
|
||||
# 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
|
||||
|
||||
scope="${1:-}"
|
||||
case "$scope" in
|
||||
system|user)
|
||||
shift
|
||||
;;
|
||||
-h|--help|"")
|
||||
echo "Usage: omarchy-dev-add-migration <system|user> [--no-edit]"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown migration scope: $scope" >&2
|
||||
echo "Usage: omarchy-dev-add-migration <system|user> [--no-edit]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
no_edit=0
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--no-edit)
|
||||
no_edit=1
|
||||
shift
|
||||
;;
|
||||
system|user)
|
||||
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
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
echo "Usage: omarchy-dev-add-migration [--no-edit]" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
cd "${OMARCHY_PATH:-$(pwd)}"
|
||||
mkdir -p "migrations/$scope"
|
||||
migration_file="migrations/$scope/$(git log -1 --format=%cd --date=unix).sh"
|
||||
mkdir -p migrations
|
||||
migration_file="migrations/$(git log -1 --format=%cd --date=unix).sh"
|
||||
touch "$migration_file"
|
||||
|
||||
if [[ ${1:-} != "--no-edit" ]]; then
|
||||
if (( ! no_edit )); then
|
||||
nvim "$migration_file"
|
||||
fi
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ For shipped configs see /etc/skel (new users) and omarchy-reinstall-configs
|
||||
(existing users explicitly resyncing).
|
||||
|
||||
--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
|
||||
USAGE
|
||||
@@ -123,9 +123,9 @@ xdg-settings set default-web-browser chromium.desktop
|
||||
xdg-mime default HEY.desktop x-scheme-handler/mailto
|
||||
|
||||
if (( first_install )); then
|
||||
mkdir -p "$state_dir/migrations/user"
|
||||
for migration in "$OMARCHY_PATH"/migrations/user/*.sh; do
|
||||
[[ -f $migration ]] && touch "$state_dir/migrations/user/$(basename "$migration")"
|
||||
mkdir -p "$state_dir/migrations"
|
||||
for migration in "$OMARCHY_PATH"/migrations/*.sh; do
|
||||
[[ -f $migration ]] && touch "$state_dir/migrations/$(basename "$migration")"
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ if [[ ! -f $MIGRATION_NOTIFY_WATCH_MARKER || $force -eq 1 ]]; then
|
||||
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"
|
||||
if [[ ! -f $USER_MARKER || $force -eq 1 ]]; then
|
||||
|
||||
+41
-41
@@ -1,15 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Run pending Omarchy system and user migrations.
|
||||
# omarchy:args=[--pending [all|system|user]]
|
||||
# omarchy:summary=Run pending Omarchy migrations.
|
||||
# omarchy:args=[--pending]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
mode="run"
|
||||
pending_scope="all"
|
||||
|
||||
usage() {
|
||||
echo "Usage: omarchy-migrate [--pending [all|system|user]]"
|
||||
echo "Usage: omarchy-migrate [--pending]"
|
||||
}
|
||||
|
||||
while (($#)); do
|
||||
@@ -17,15 +16,6 @@ while (($#)); do
|
||||
--pending|--check)
|
||||
mode="pending"
|
||||
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)
|
||||
usage
|
||||
@@ -38,38 +28,37 @@ while (($#)); do
|
||||
esac
|
||||
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() {
|
||||
local scope="$1"
|
||||
local command="$2"
|
||||
local output=""
|
||||
local migration=""
|
||||
migration_entries() {
|
||||
[[ -d $MIGRATIONS_DIR ]] || return 0
|
||||
|
||||
if output=$("$command" --pending 2>/dev/null); then
|
||||
while IFS= read -r migration; do
|
||||
[[ -n $migration ]] || continue
|
||||
pending_output+="$scope/$migration"$'\n'
|
||||
done <<<"$output"
|
||||
fi
|
||||
local file filename
|
||||
|
||||
for file in "$MIGRATIONS_DIR"/*.sh; do
|
||||
[[ -f $file ]] || continue
|
||||
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
|
||||
done < <(migration_entries)
|
||||
}
|
||||
|
||||
if [[ $mode == "pending" ]]; then
|
||||
case "$pending_scope" in
|
||||
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
|
||||
|
||||
pending_output=$(pending_migrations)
|
||||
if [[ -n $pending_output ]]; then
|
||||
printf '%s' "$pending_output"
|
||||
printf '%s\n' "$pending_output"
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
@@ -93,5 +82,16 @@ wait_for_pacman_transaction() {
|
||||
|
||||
wait_for_pacman_transaction
|
||||
|
||||
omarchy-migrate-system
|
||||
omarchy-migrate-user
|
||||
mkdir -p "$STATE_DIR"
|
||||
[[ -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
|
||||
|
||||
# omarchy:summary=Notify the user when Omarchy has pending user migrations
|
||||
# omarchy:summary=Notify the user when Omarchy has pending migrations
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
[[ -n $migration ]] || continue
|
||||
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]
|
||||
Description=Watch for Omarchy user migrations
|
||||
Description=Watch for Omarchy migrations
|
||||
|
||||
[Path]
|
||||
PathExistsGlob=/usr/share/omarchy/migrations/user/*.sh
|
||||
PathModified=/usr/share/omarchy/migrations/user
|
||||
PathExistsGlob=/usr/share/omarchy/migrations/*.sh
|
||||
PathModified=/usr/share/omarchy/migrations
|
||||
Unit=omarchy-update-user-notify.service
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Notify about pending Omarchy user migrations
|
||||
ConditionPathExistsGlob=/usr/share/omarchy/migrations/user/*.sh
|
||||
Description=Notify about pending Omarchy migrations
|
||||
ConditionPathIsDirectory=/usr/share/omarchy/migrations
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
|
||||
+18
-31
@@ -63,12 +63,11 @@ default/libalpm/hooks/*.hook
|
||||
──► omarchy /usr/share/libalpm/hooks/*.hook
|
||||
|
||||
install/** ──► omarchy /usr/share/omarchy/install/
|
||||
migrations/system/** ──► omarchy /usr/share/omarchy/migrations/system/
|
||||
migrations/user/** ──► omarchy /usr/share/omarchy/migrations/user/
|
||||
migrations/** ──► omarchy /usr/share/omarchy/migrations/
|
||||
themes/** ──► omarchy /usr/share/omarchy/themes/
|
||||
shell/** ──► omarchy /usr/share/omarchy/shell/
|
||||
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)
|
||||
/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
|
||||
guidelines, and troubleshooting notes.
|
||||
|
||||
Omarchy migrations are split by scope:
|
||||
|
||||
- `migrations/system/*.sh` — root, noninteractive, safe to run from pacman.
|
||||
The `omarchy` package `post_upgrade()` runs `omarchy-migrate-system` after an
|
||||
`omarchy` package upgrade, so even explicit direct-pacman bypasses still get
|
||||
system migrations applied. Completion state lives in
|
||||
`/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.
|
||||
Omarchy migrations live in `migrations/*.sh` and run per-user through
|
||||
`omarchy-migrate`. Completion state lives in
|
||||
`~/.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. Migrations must be idempotent;
|
||||
machine-wide repairs should no-op when another user already applied them.
|
||||
|
||||
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
|
||||
`omarchy-migrate-notify` as that user. The notifier checks
|
||||
`omarchy-migrate --pending user`. If this user has missing migration state, it
|
||||
shows a notification that opens a terminal for `omarchy-migrate`. The notifier
|
||||
never runs user migrations in the background.
|
||||
`omarchy-migrate --pending`. If this user has missing migration state, it shows a
|
||||
notification that opens a terminal for `omarchy-migrate`. The notifier never runs
|
||||
migrations in the background.
|
||||
|
||||
`omarchy-migrate` waits for any active pacman transaction to finish, runs
|
||||
pending system migrations, then runs pending user migrations. It does not need
|
||||
`--force`; migrations happen when state files are missing. For watchers and
|
||||
diagnostics, `omarchy-migrate --pending [all|system|user]` prints
|
||||
scope-prefixed pending migration filenames and exits `0` when any are pending.
|
||||
`omarchy update` runs `omarchy-migrate` after the package transaction in the
|
||||
already-visible update terminal, then runs `omarchy-hook post-update`.
|
||||
`omarchy-migrate` waits for any active pacman transaction to finish, then runs
|
||||
pending migrations. It does not need `--force`; migrations happen when state
|
||||
files are missing. `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`)
|
||||
|
||||
@@ -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 |
|
||||
| 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` |
|
||||
| Noninteractive root fix for existing installs | `migrations/system/<unix-timestamp>.sh` |
|
||||
| User/session fix for existing installs | `migrations/user/<unix-timestamp>.sh` |
|
||||
| One-time fix for existing installs | `migrations/<unix-timestamp>.sh` |
|
||||
| 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) |
|
||||
| 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
|
||||
itself.
|
||||
|
||||
## The two migration scopes
|
||||
## Migration model
|
||||
|
||||
Omarchy migrations are split by execution context:
|
||||
Migrations live in:
|
||||
|
||||
```text
|
||||
migrations/system/*.sh
|
||||
migrations/user/*.sh
|
||||
migrations/*.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.
|
||||
|
||||
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:
|
||||
Completion state is per-user:
|
||||
|
||||
```text
|
||||
/var/lib/omarchy/migrations/system/<migration filename>
|
||||
~/.local/state/omarchy/migrations/<migration filename>
|
||||
```
|
||||
|
||||
### User migrations
|
||||
|
||||
User migrations run as the current graphical/login user and may be interactive.
|
||||
|
||||
Use user migrations for per-user or session-aware state, for example:
|
||||
|
||||
- `~/.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.
|
||||
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
|
||||
prompt themselves. Migrations must be idempotent: if one user already applied a
|
||||
machine-wide repair, the same migration running for another user should detect
|
||||
that and no-op.
|
||||
|
||||
## When migrations run
|
||||
|
||||
@@ -69,15 +40,8 @@ omarchy-migrate
|
||||
omarchy-hook post-update
|
||||
```
|
||||
|
||||
`omarchy-migrate`:
|
||||
|
||||
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.
|
||||
`omarchy-migrate` waits for any active pacman transaction to finish, then runs
|
||||
all pending migrations for the current user in the visible update terminal.
|
||||
|
||||
### During direct pacman updates
|
||||
|
||||
@@ -87,28 +51,21 @@ Raw `sudo pacman -Syu` is guarded. Users should normally run:
|
||||
omarchy update
|
||||
```
|
||||
|
||||
If a user explicitly bypasses the guard, the `omarchy` package still runs system
|
||||
migrations from `post_upgrade()`:
|
||||
If a user explicitly bypasses the guard, user sessions watch the packaged
|
||||
migration directory and run a notifier. The notifier checks:
|
||||
|
||||
```bash
|
||||
omarchy-migrate-system
|
||||
omarchy-migrate --pending
|
||||
```
|
||||
|
||||
User migrations are never run by pacman. Instead, the user session watches the
|
||||
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
|
||||
If that user has pending migrations, it shows a notification that opens a
|
||||
terminal for:
|
||||
|
||||
```bash
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
The notifier never runs user migrations silently in the background.
|
||||
The notifier never runs migrations silently in the background.
|
||||
|
||||
### Manually
|
||||
|
||||
@@ -126,179 +83,72 @@ Use:
|
||||
|
||||
```bash
|
||||
omarchy-migrate --pending
|
||||
omarchy-migrate --pending system
|
||||
omarchy-migrate --pending user
|
||||
```
|
||||
|
||||
Exit behavior:
|
||||
|
||||
- `0` — one or more matching migrations are pending
|
||||
- non-zero — no matching migrations are pending
|
||||
- `0` — one or more migrations are pending
|
||||
- non-zero — no migrations are pending
|
||||
|
||||
Output is scope-prefixed:
|
||||
Output is one pending migration per line:
|
||||
|
||||
```text
|
||||
system/100-system.sh
|
||||
user/200-user.sh
|
||||
1781158082.sh
|
||||
```
|
||||
|
||||
The lower-level runners also support `--pending` and print filenames without the
|
||||
scope prefix:
|
||||
## Creating a migration
|
||||
|
||||
Use the helper:
|
||||
|
||||
```bash
|
||||
omarchy-migrate-system --pending
|
||||
omarchy-migrate-user --pending
|
||||
omarchy-dev-add-migration --no-edit
|
||||
```
|
||||
|
||||
Prefer `omarchy-migrate --pending ...` in user-facing tools and watchers.
|
||||
This creates:
|
||||
|
||||
## Writing migrations
|
||||
|
||||
Create a migration with:
|
||||
|
||||
```bash
|
||||
omarchy-dev-add-migration system --no-edit
|
||||
omarchy-dev-add-migration user --no-edit
|
||||
```text
|
||||
migrations/<unix timestamp>.sh
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
- 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:
|
||||
Example:
|
||||
|
||||
```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
|
||||
echo "Refresh user app launchers"
|
||||
|
||||
omarchy-refresh-applications
|
||||
HOME=$(mktemp -d) bash -euo pipefail migrations/<timestamp>.sh
|
||||
```
|
||||
|
||||
### Execution model
|
||||
|
||||
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:
|
||||
To rerun a migration locally, remove its marker and run the migrator:
|
||||
|
||||
```bash
|
||||
rm ~/.local/state/omarchy/migrations/<migration>.sh
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
A failed migration is not marked complete, so it will retry.
|
||||
|
||||
### Re-run a completed migration manually
|
||||
|
||||
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.
|
||||
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
|
||||
layouts; put pre-4 package-layout transition work in the upgrade command instead.
|
||||
|
||||
+40
-104
@@ -10,13 +10,12 @@ bypass it:
|
||||
|
||||
The design goal is:
|
||||
|
||||
- System/root migrations should run automatically from package transactions when
|
||||
safe.
|
||||
- User/session migrations should never run invisibly from pacman because they may
|
||||
need `$HOME`, DBus/session state, a graphical session, or user interaction.
|
||||
- Users who bypass `omarchy update` should still get system migrations from
|
||||
pacman and should be notified only when their own user migration state is
|
||||
missing a shipped user migration.
|
||||
- `omarchy update` owns the visible update pipeline: package transaction,
|
||||
migrations, post-update hooks, update-state refresh, and restart checks.
|
||||
- Migrations run per-user after pacman finishes, because they may need `$HOME`,
|
||||
DBus/session state, a graphical session, sudo, or user interaction.
|
||||
- Users who bypass `omarchy update` are nudged back by the pacman guard; if they
|
||||
explicitly bypass it, their session is notified when migrations are pending.
|
||||
|
||||
## 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`. |
|
||||
| `~/.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. |
|
||||
| `/var/lib/omarchy/migrations/system/` | root | System migration markers. |
|
||||
| `~/.local/state/omarchy/migrations/user/` | user | User migration markers. |
|
||||
| `~/.local/state/omarchy/migrations/` | user | Per-user migration markers. |
|
||||
| `~/.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`. |
|
||||
|
||||
@@ -36,83 +34,32 @@ The design goal is:
|
||||
See [`migrations.md`](migrations.md) for the full migration model, authoring
|
||||
guidelines, and troubleshooting notes.
|
||||
|
||||
Migrations are scoped by directory:
|
||||
Migrations live in:
|
||||
|
||||
```text
|
||||
migrations/system/*.sh
|
||||
migrations/user/*.sh
|
||||
migrations/*.sh
|
||||
```
|
||||
|
||||
### System migrations
|
||||
|
||||
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:
|
||||
They run as the current user through:
|
||||
|
||||
```bash
|
||||
omarchy-migrate
|
||||
```
|
||||
|
||||
Completion state:
|
||||
Completion state is per-user:
|
||||
|
||||
```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
|
||||
that user's matching state file is missing. There is no global root-owned queue
|
||||
for user migrations.
|
||||
Every user gets a chance to run every migration. Migrations run as the user;
|
||||
privileged work should invoke the appropriate helper or privilege prompt.
|
||||
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
|
||||
transaction to finish, runs pending system migrations, then runs pending user
|
||||
migrations. It does not need `--force`; migrations should happen when they are
|
||||
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.
|
||||
For watchers and diagnostics, `omarchy-migrate --pending` prints pending
|
||||
migration names and exits `0` when any are pending. When no migrations are
|
||||
pending, it prints nothing and exits non-zero.
|
||||
|
||||
## Raw pacman guard
|
||||
|
||||
@@ -187,10 +134,8 @@ omarchy-update
|
||||
|
||||
Important behavior:
|
||||
|
||||
- `omarchy update` checks/runs system and user migrations in the same visible
|
||||
terminal via `omarchy-migrate`.
|
||||
- `omarchy update` still benefits from pacman-triggered system migrations
|
||||
because the system migration hook runs as part of the pacman transaction.
|
||||
- `omarchy update` checks/runs migrations in the same visible terminal via
|
||||
`omarchy-migrate` after pacman finishes.
|
||||
- A failure should leave enough output in `/tmp/omarchy-update.log` and the
|
||||
terminal transcript to debug.
|
||||
|
||||
@@ -202,10 +147,9 @@ High-level flow:
|
||||
sudo pacman -Syu
|
||||
├─ pre-transaction guard aborts and tells the user to run omarchy update
|
||||
└─ if explicitly bypassed, upgrades omarchy and related packages
|
||||
├─ omarchy post_upgrade runs omarchy-migrate-system as root
|
||||
└─ user session notices migration directory changes
|
||||
├─ 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
|
||||
└─ click opens terminal: omarchy-migrate
|
||||
```
|
||||
@@ -215,12 +159,11 @@ Fallbacks:
|
||||
- `omarchy-first-run` enables the user notification path unit.
|
||||
- `omarchy-first-run` also invokes `omarchy-migrate-notify` on graphical
|
||||
startup, so users who updated before the path unit existed still get prompted
|
||||
if they have missing user migration state.
|
||||
- The notifier is only a prompt. It does not run user migrations in the
|
||||
background.
|
||||
if they have missing migration state.
|
||||
- The notifier is only a prompt. It does not run migrations in the background.
|
||||
- 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
|
||||
pending state we can derive is missing user migration markers.
|
||||
explicitly runs that hook; without a package-update marker, the only pending
|
||||
state we can derive is missing per-user migration markers.
|
||||
|
||||
## 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-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-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-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-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-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-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. |
|
||||
@@ -282,36 +223,31 @@ scripts.
|
||||
|
||||
## Closed decisions
|
||||
|
||||
1. **System migrations run from the `omarchy` package**
|
||||
- `omarchy.install post_upgrade()` calls `omarchy-migrate-system`.
|
||||
- We do not need a separate system-migration ALPM hook from
|
||||
`omarchy-settings`.
|
||||
1. **Migrations run per-user from the update pipeline**
|
||||
- `omarchy update` runs `omarchy-migrate` after pacman finishes.
|
||||
- Package-time migration runners do not apply migrations inside pacman.
|
||||
- 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**
|
||||
- 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**
|
||||
2. **Migration notification naming**
|
||||
- The real helper is `omarchy-migrate-notify`.
|
||||
- `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-perform` is only a hidden compatibility wrapper for
|
||||
`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`.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
- User notifications are shown only when `omarchy-migrate --pending user`
|
||||
finds missing per-user migration state.
|
||||
- User notifications are shown only when `omarchy-migrate --pending` finds
|
||||
missing per-user migration state.
|
||||
|
||||
## Remaining concerns
|
||||
|
||||
|
||||
@@ -393,7 +393,7 @@ package.path = os.getenv("HOME")
|
||||
.. package.path
|
||||
LUA
|
||||
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"
|
||||
[[ ! -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"
|
||||
@@ -415,7 +415,7 @@ for nvim_legacy_target in \
|
||||
"../../../omarchy/current/theme/neovim.lua" \
|
||||
"$NVIM_MIGRATION_TMPDIR/.config/omarchy/current/theme/neovim.lua"; do
|
||||
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_resolved_target=$(readlink -f "$nvim_theme_link")
|
||||
[[ $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
|
||||
pass "shell config removes widgets with remove alias"
|
||||
|
||||
mapfile -t migrations < <(find "$ROOT/migrations" -maxdepth 1 -type f -name '*.sh' -printf '%f\n' | sort)
|
||||
[[ ${#migrations[@]} -eq 0 ]] || fail "4.0 upgrade is not modeled as a migration"
|
||||
if grep -RIl 'upgrade-to-4\|Omarchy 4\.0 is upgraded' "$ROOT/migrations" >/dev/null; then
|
||||
fail "4.0 upgrade is not modeled as a migration"
|
||||
fi
|
||||
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"
|
||||
|
||||
cat >"$TMPDIR/home/.config/omarchy/shell.json" <<'JSON'
|
||||
|
||||
@@ -11,16 +11,16 @@ stub_bin="$test_tmp/bin"
|
||||
test_home="$test_tmp/home"
|
||||
mkdir -p "$stub_bin" "$test_home"
|
||||
|
||||
cat >"$stub_bin/omarchy-migrate-user" <<'SH'
|
||||
cat >"$stub_bin/omarchy-migrate" <<'SH'
|
||||
#!/bin/bash
|
||||
if [[ ${1:-} == "--pending" && ${OMARCHY_TEST_PENDING_MIGRATIONS:-0} == 1 ]]; then
|
||||
echo 200-user.sh
|
||||
echo 200-migration.sh
|
||||
exit 0
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
SH
|
||||
chmod +x "$stub_bin/omarchy-migrate-user"
|
||||
chmod +x "$stub_bin/omarchy-migrate"
|
||||
|
||||
cat >"$stub_bin/systemd-run" <<'SH'
|
||||
#!/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"
|
||||
|
||||
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 'user/200-user.sh' "$test_tmp/pending.err" || fail "migration notifier lists pending migration names"
|
||||
pass "migration notifier reports pending user migrations"
|
||||
grep -q 'Omarchy has pending migrations' "$test_tmp/pending.err" || fail "migration notifier explains pending migrations without notification system"
|
||||
grep -q '200-migration.sh' "$test_tmp/pending.err" || fail "migration notifier lists pending migration names"
|
||||
pass "migration notifier reports pending migrations"
|
||||
|
||||
@@ -9,107 +9,69 @@ trap 'rm -rf "$test_tmp"' EXIT
|
||||
|
||||
test_root="$test_tmp/omarchy"
|
||||
test_home="$test_tmp/home"
|
||||
system_state="$test_tmp/system-state"
|
||||
mkdir -p "$test_root/migrations/system" "$test_root/migrations/user" "$test_home" "$system_state"
|
||||
mkdir -p "$test_root/migrations" "$test_home"
|
||||
|
||||
cat >"$test_root/migrations/system/100-system.sh" <<'SH'
|
||||
cat >"$test_root/migrations/100-first.sh" <<'SH'
|
||||
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
|
||||
echo system >>"$TEST_CALLS"
|
||||
echo first >>"$TEST_CALLS"
|
||||
SH
|
||||
cat >"$test_root/migrations/user/200-user.sh" <<'SH'
|
||||
cat >"$test_root/migrations/200-second.sh" <<'SH'
|
||||
[[ $OMARCHY_PATH == "$TEST_EXPECTED_OMARCHY_PATH" ]]
|
||||
echo user >>"$TEST_CALLS"
|
||||
echo second >>"$TEST_CALLS"
|
||||
SH
|
||||
|
||||
calls="$test_tmp/calls"
|
||||
|
||||
if ! HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate-user" --pending >"$test_tmp/user-pending.out"; then
|
||||
fail "user migration runner reports pending migrations before state exists"
|
||||
if ! HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate" --pending >"$test_tmp/pending.out"; then
|
||||
fail "migration runner reports pending migrations before state exists"
|
||||
fi
|
||||
grep -q '^200-user\.sh$' "$test_tmp/user-pending.out" || fail "user migration runner lists pending migration filename"
|
||||
pass "user migration runner detects pending migrations"
|
||||
grep -q '^100-first\.sh$' "$test_tmp/pending.out" || fail "migration runner lists first pending migration filename"
|
||||
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" \
|
||||
OMARCHY_PATH="$test_root" \
|
||||
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
|
||||
TEST_CALLS="$calls" \
|
||||
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-first.out"
|
||||
[[ $(grep -c '^user$' "$calls") -eq 1 ]] || fail "user migration runner runs user migrations"
|
||||
! grep -q '^system$' "$calls" || fail "user migration runner does not run system migrations"
|
||||
[[ -f $test_home/.local/state/omarchy/migrations/user/200-user.sh ]] || fail "user migration runner records user migration marker"
|
||||
pass "user migration runner only runs user migrations"
|
||||
"$ROOT/bin/omarchy-migrate" >"$test_tmp/first-run.out"
|
||||
[[ $(sed -n '1p' "$calls") == "first" ]] || fail "migration runner runs first migration"
|
||||
[[ $(sed -n '2p' "$calls") == "second" ]] || fail "migration runner runs second migration"
|
||||
[[ -f $test_home/.local/state/omarchy/migrations/100-first.sh ]] || fail "migration runner records first migration marker"
|
||||
[[ -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" \
|
||||
OMARCHY_PATH="$test_root" \
|
||||
TEST_EXPECTED_OMARCHY_PATH="$test_root" \
|
||||
TEST_CALLS="$calls" \
|
||||
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-second.out"
|
||||
[[ $(grep -c '^user$' "$calls") -eq 1 ]] || fail "user migration runner skips completed migrations"
|
||||
pass "user migration runner skips completed migrations"
|
||||
"$ROOT/bin/omarchy-migrate" >"$test_tmp/second-run.out"
|
||||
[[ $(wc -l <"$calls") -eq 2 ]] || fail "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
|
||||
fail "user migration runner reports no pending migrations after state exists"
|
||||
if HOME="$test_home" OMARCHY_PATH="$test_root" "$ROOT/bin/omarchy-migrate" --pending >"$test_tmp/not-pending.out"; then
|
||||
fail "migration runner reports no pending migrations after state exists"
|
||||
fi
|
||||
pass "user 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"
|
||||
pass "migration runner detects no pending migrations"
|
||||
|
||||
failure_root="$test_tmp/failure-omarchy"
|
||||
failure_home="$test_tmp/failure-home"
|
||||
failure_system_state="$test_tmp/failure-system-state"
|
||||
mkdir -p "$failure_root/migrations/system" "$failure_root/migrations/user" "$failure_home" "$failure_system_state"
|
||||
mkdir -p "$failure_root/migrations" "$failure_home"
|
||||
|
||||
cat >"$failure_root/migrations/user/300-fail-user.sh" <<'SH'
|
||||
echo user-before-fail >>"$TEST_CALLS"
|
||||
cat >"$failure_root/migrations/500-fail.sh" <<'SH'
|
||||
echo before-fail >>"$TEST_CALLS"
|
||||
false
|
||||
echo user-after-fail >>"$TEST_CALLS"
|
||||
echo after-fail >>"$TEST_CALLS"
|
||||
SH
|
||||
|
||||
set +e
|
||||
HOME="$failure_home" \
|
||||
OMARCHY_PATH="$failure_root" \
|
||||
TEST_CALLS="$calls" \
|
||||
"$ROOT/bin/omarchy-migrate-user" >"$test_tmp/user-failure.out" 2>"$test_tmp/user-failure.err"
|
||||
user_failure_status=$?
|
||||
"$ROOT/bin/omarchy-migrate" >"$test_tmp/failure.out" 2>"$test_tmp/failure.err"
|
||||
failure_status=$?
|
||||
set -e
|
||||
[[ $user_failure_status -ne 0 ]] || fail "user 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"
|
||||
grep -q '^user-before-fail$' "$calls" || fail "user migration runner started failing migration"
|
||||
! grep -q '^user-after-fail$' "$calls" || fail "user migration runner stops failing migration under strict mode"
|
||||
pass "user 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"
|
||||
[[ $failure_status -ne 0 ]] || fail "migration runner exits non-zero when a migration fails"
|
||||
[[ ! -f $failure_home/.local/state/omarchy/migrations/500-fail.sh ]] || fail "migration runner does not mark failed migration complete"
|
||||
grep -q '^before-fail$' "$calls" || fail "migration runner started failing migration"
|
||||
! grep -q '^after-fail$' "$calls" || fail "migration runner stops failing migration under strict mode"
|
||||
pass "migration runner does not mark failed migrations complete"
|
||||
|
||||
@@ -7,57 +7,33 @@ source "$(dirname "$0")/base-test.sh"
|
||||
test_tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$test_tmp"' EXIT
|
||||
|
||||
stub_bin="$test_tmp/bin"
|
||||
test_root="$test_tmp/omarchy"
|
||||
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'
|
||||
#!/bin/bash
|
||||
if [[ ${1:-} == "--pending" ]]; then
|
||||
[[ ${OMARCHY_TEST_PENDING_SYSTEM:-1} == 1 ]] || exit 1
|
||||
echo 100-system.sh
|
||||
exit 0
|
||||
fi
|
||||
echo system >>"$TEST_CALLS"
|
||||
cat >"$test_root/migrations/100-migration.sh" <<'SH'
|
||||
echo migration >>"$TEST_CALLS"
|
||||
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() {
|
||||
HOME="$test_home" \
|
||||
PATH="$stub_bin:$PATH" \
|
||||
OMARCHY_PATH="$test_root" \
|
||||
TEST_CALLS="$test_tmp/calls" \
|
||||
"$ROOT/bin/omarchy-migrate" "$@"
|
||||
}
|
||||
|
||||
: >"$test_tmp/calls"
|
||||
run_migrate >"$test_tmp/migrate.out"
|
||||
[[ $(sed -n '1p' "$test_tmp/calls") == "system" ]] || fail "omarchy-migrate runs system migrations first"
|
||||
[[ $(sed -n '2p' "$test_tmp/calls") == "user" ]] || fail "omarchy-migrate runs user migrations second"
|
||||
[[ $(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"
|
||||
[[ $(sed -n '1p' "$test_tmp/calls") == "migration" ]] || fail "omarchy-migrate runs pending migrations"
|
||||
pass "omarchy-migrate runs migrations without force"
|
||||
|
||||
run_migrate --pending >"$test_tmp/pending-all.out"
|
||||
grep -q '^system/100-system\.sh$' "$test_tmp/pending-all.out" || fail "omarchy-migrate --pending lists pending system migrations"
|
||||
grep -q '^user/200-user\.sh$' "$test_tmp/pending-all.out" || fail "omarchy-migrate --pending lists pending user migrations"
|
||||
pass "omarchy-migrate --pending lists all pending migrations"
|
||||
rm -rf "$test_home/.local/state/omarchy/migrations"
|
||||
run_migrate --pending >"$test_tmp/pending.out"
|
||||
grep -q '^100-migration\.sh$' "$test_tmp/pending.out" || fail "omarchy-migrate --pending lists pending migrations"
|
||||
pass "omarchy-migrate --pending lists pending migrations"
|
||||
|
||||
run_migrate --pending user >"$test_tmp/pending-user.out"
|
||||
grep -q '^user/200-user\.sh$' "$test_tmp/pending-user.out" || fail "omarchy-migrate --pending user lists user migrations"
|
||||
! 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
|
||||
run_migrate >"$test_tmp/migrate-second.out"
|
||||
if run_migrate --pending >"$test_tmp/not-pending.out"; then
|
||||
fail "omarchy-migrate --pending exits non-zero without pending migrations"
|
||||
fi
|
||||
[[ ! -s $test_tmp/not-pending.out ]] || fail "omarchy-migrate --pending stays quiet without pending migrations"
|
||||
|
||||
Reference in New Issue
Block a user