Install Elsewhen, the world clock plugin, by default
Elsewhen (omacom.elsewhen) arrives as the elsewhen package under /usr/share/omarchy/plugins, the packaged root the shell scans between its bundled plugins and the user's. It opens the right section of the default bar, just before the tray, and a migration installs the package, writes the widget into a customized shell.json in the same spot, and retires a pristine pre-package clone of the upstream repo that the package now shadows.
This commit is contained in:
10 files changed
+417
-3
No files matched your search
@@ -0,0 +1,285 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
require_command jq
|
||||
require_command git
|
||||
|
||||
migration="$ROOT/migrations/1789581661.sh"
|
||||
test_dir=$(mktemp -d)
|
||||
trap 'rm -rf "$test_dir"' EXIT
|
||||
|
||||
mkdir -p "$test_dir/bin"
|
||||
export INSTALLED_PACKAGES="$test_dir/installed" CALL_LOG="$test_dir/calls" SHELL_CALLS="$test_dir/shell-calls"
|
||||
# The checkout cases use the real git; keep the developer's config (signing,
|
||||
# hooks, safe.directory) out of what it sees.
|
||||
export GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_NOSYSTEM=1
|
||||
export GIT_AUTHOR_NAME=test GIT_AUTHOR_EMAIL=test@example.com
|
||||
export GIT_COMMITTER_NAME=test GIT_COMMITTER_EMAIL=test@example.com
|
||||
|
||||
# Keep the real package helpers, but contain every pacman transaction here.
|
||||
cat >"$test_dir/bin/pacman" <<'SH'
|
||||
#!/bin/bash
|
||||
case "$1" in
|
||||
-Q) grep -Fxq -- "$2" "$INSTALLED_PACKAGES" ;;
|
||||
-S)
|
||||
[[ ${FAIL_INSTALL:-0} == 0 ]] || exit 1
|
||||
shift 3 # -S --noconfirm --needed
|
||||
printf '%s\n' "$@" >>"$INSTALLED_PACKAGES"
|
||||
printf '%s\n' "$@" >>"$CALL_LOG"
|
||||
;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
SH
|
||||
cat >"$test_dir/bin/sudo" <<'SH'
|
||||
#!/bin/bash
|
||||
[[ $1 == "pacman" ]] || exit 1
|
||||
"$@"
|
||||
SH
|
||||
# The migration runs under a shell that predates the packaged root, or under
|
||||
# none at all, so it must only ever ask the shell for best-effort refreshes.
|
||||
cat >"$test_dir/bin/omarchy-shell" <<'SH'
|
||||
#!/bin/bash
|
||||
printf '%s\n' "$*" >>"$SHELL_CALLS"
|
||||
[[ $1 != "-q" ]] || exit 0
|
||||
exit "${SHELL_STATUS:-0}"
|
||||
SH
|
||||
chmod +x "$test_dir/bin/"*
|
||||
|
||||
home="$test_dir/home"
|
||||
config="$home/.config/omarchy/shell.json"
|
||||
checkout="$home/.config/omarchy/plugins/omacom.elsewhen"
|
||||
output="$test_dir/output"
|
||||
mkdir -p "$home/.config/omarchy"
|
||||
|
||||
run_migration() {
|
||||
: >"$CALL_LOG"
|
||||
: >"$SHELL_CALLS"
|
||||
HOME="$home" OMARCHY_PATH="$ROOT" PATH="$test_dir/bin:$ROOT/bin:$PATH" \
|
||||
bash -euo pipefail "$migration" >"$output"
|
||||
}
|
||||
|
||||
ids() {
|
||||
jq -c ".bar.layout.$1 | map(if type == \"object\" then .id else . end)" "$config"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------ package install
|
||||
: >"$INSTALLED_PACKAGES"
|
||||
cat >"$config" <<'JSON'
|
||||
{
|
||||
"version": 1,
|
||||
"bar": {
|
||||
"layout": {
|
||||
"left": [{ "id": "omarchy.menu" }],
|
||||
"center": [{ "id": "omarchy.clock", "format": "HH:mm" }],
|
||||
"right": [
|
||||
{ "id": "omarchy.tray" },
|
||||
{ "id": "omarchy.agents", "syncMode": "On" },
|
||||
{ "id": "omarchy.power" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"plugins": []
|
||||
}
|
||||
JSON
|
||||
|
||||
run_migration
|
||||
grep -Fxq elsewhen "$CALL_LOG" || fail "migration installs the elsewhen package" "$(cat "$CALL_LOG")"
|
||||
pass "migration installs the elsewhen package"
|
||||
|
||||
[[ $(ids right) == '["omacom.elsewhen","omarchy.tray","omarchy.agents","omarchy.power"]' ]] ||
|
||||
fail "migration puts the widget just before the tray" "$(cat "$config")"
|
||||
pass "migration puts the widget just before the tray"
|
||||
|
||||
[[ $(jq -c '.bar.layout.right[2]' "$config") == '{"id":"omarchy.agents","syncMode":"On"}' ]] ||
|
||||
fail "migration keeps the settings of its neighbours" "$(cat "$config")"
|
||||
[[ $(jq -c '.bar.layout.center[0]' "$config") == '{"format":"HH:mm","id":"omarchy.clock"}' ]] ||
|
||||
fail "migration leaves other sections alone" "$(cat "$config")"
|
||||
pass "migration leaves the rest of the layout alone"
|
||||
|
||||
grep -q 'shell rescanPlugins' "$SHELL_CALLS" && grep -q 'shell reloadConfig' "$SHELL_CALLS" ||
|
||||
fail "migration asks the running shell to rescan and reload" "$(cat "$SHELL_CALLS")"
|
||||
pass "migration asks the running shell to rescan and reload"
|
||||
|
||||
before=$(sha256sum "$config")
|
||||
run_migration
|
||||
[[ $before == $(sha256sum "$config") ]] || fail "migration is idempotent" "$(cat "$config")"
|
||||
[[ ! -s $CALL_LOG ]] || fail "migration does not reinstall a present package" "$(cat "$CALL_LOG")"
|
||||
pass "migration is idempotent"
|
||||
|
||||
# ------------------------------------------------------------- placements
|
||||
cat >"$config" <<'JSON'
|
||||
{
|
||||
"version": 1,
|
||||
"bar": { "layout": { "left": [], "center": ["omarchy.clock", "omarchy.tray"], "right": ["omarchy.power"] } }
|
||||
}
|
||||
JSON
|
||||
run_migration
|
||||
[[ $(ids center) == '["omarchy.clock","omacom.elsewhen","omarchy.tray"]' && $(ids right) == '["omarchy.power"]' ]] ||
|
||||
fail "migration follows the tray into another section and reads string entries" "$(cat "$config")"
|
||||
pass "migration follows the tray into another section and reads string entries"
|
||||
|
||||
cat >"$config" <<'JSON'
|
||||
{ "version": 1, "bar": { "layout": { "right": [{ "id": "omarchy.agents" }, { "id": "omarchy.power" }] } } }
|
||||
JSON
|
||||
run_migration
|
||||
[[ $(ids right) == '["omacom.elsewhen","omarchy.agents","omarchy.power"]' ]] ||
|
||||
fail "migration prepends to the right section when the tray is off the bar" "$(cat "$config")"
|
||||
pass "migration prepends to the right section when the tray is off the bar"
|
||||
|
||||
cat >"$config" <<'JSON'
|
||||
{
|
||||
"version": 1,
|
||||
"bar": { "layout": { "left": [{ "id": "omacom.elsewhen" }], "center": [], "right": [{ "id": "omarchy.tray" }, { "id": "omarchy.agents" }] } }
|
||||
}
|
||||
JSON
|
||||
before=$(sha256sum "$config")
|
||||
run_migration
|
||||
[[ $before == $(sha256sum "$config") ]] ||
|
||||
fail "migration leaves a widget the user already placed where it is" "$(cat "$config")"
|
||||
pass "migration leaves a widget the user already placed where it is"
|
||||
|
||||
# ------------------------------------------------------------- edge cases
|
||||
rm -f "$config"
|
||||
run_migration
|
||||
[[ ! -e $config ]] || fail "migration writes no shell.json where the defaults apply" "$(cat "$config")"
|
||||
pass "migration writes no shell.json where the defaults apply"
|
||||
|
||||
printf '{ not json' >"$config"
|
||||
run_migration
|
||||
[[ $(cat "$config") == '{ not json' ]] || fail "migration leaves an unparsable config untouched" "$(cat "$config")"
|
||||
pass "migration leaves an unparsable config untouched"
|
||||
|
||||
cat >"$config" <<'JSON'
|
||||
{ "version": 1, "bar": { "layout": { "right": [{ "id": "omarchy.tray" }, { "id": "omarchy.agents" }] } } }
|
||||
JSON
|
||||
SHELL_STATUS=1 run_migration
|
||||
[[ $(ids right) == '["omacom.elsewhen","omarchy.tray","omarchy.agents"]' ]] ||
|
||||
fail "migration places the widget with no shell running" "$(cat "$config")"
|
||||
pass "migration places the widget with no shell running"
|
||||
|
||||
# A package the mirror does not carry yet leaves the migration pending rather
|
||||
# than half-done: the layout must not name a widget nothing can install.
|
||||
: >"$INSTALLED_PACKAGES"
|
||||
cat >"$config" <<'JSON'
|
||||
{ "version": 1, "bar": { "layout": { "right": [{ "id": "omarchy.tray" }, { "id": "omarchy.agents" }] } } }
|
||||
JSON
|
||||
before=$(sha256sum "$config")
|
||||
if FAIL_INSTALL=1 run_migration 2>/dev/null; then
|
||||
fail "a failed package installation must leave the migration pending"
|
||||
fi
|
||||
[[ $before == $(sha256sum "$config") ]] ||
|
||||
fail "a failed package installation leaves the layout untouched" "$(cat "$config")"
|
||||
pass "a failed package installation is propagated and changes nothing"
|
||||
|
||||
# ------------------------------------------------- pre-package checkouts
|
||||
# Users who followed the README before the package existed hold a git clone
|
||||
# under ~/.config/omarchy/plugins, which the packaged copy now shadows. Only a
|
||||
# clone of the upstream repo with nothing local in it is retired; everything
|
||||
# else is the user's and stays, and shell.json gets the widget either way.
|
||||
|
||||
# A clone made by `omarchy plugin add`: one commit, the given origin, nothing
|
||||
# local. Built with init rather than clone so the origin can be any URL form.
|
||||
make_checkout() {
|
||||
local origin="$1"
|
||||
rm -rf "$checkout"
|
||||
mkdir -p "$checkout"
|
||||
git -C "$checkout" init -q
|
||||
git -C "$checkout" remote add origin "$origin"
|
||||
printf '{ "id": "omacom.elsewhen" }\n' >"$checkout/manifest.json"
|
||||
printf 'import QtQuick\nItem {}\n' >"$checkout/Panel.qml"
|
||||
git -C "$checkout" add -A
|
||||
git -C "$checkout" commit -q -m "Elsewhen"
|
||||
}
|
||||
|
||||
reset_layout() {
|
||||
cat >"$config" <<'JSON'
|
||||
{ "version": 1, "bar": { "layout": { "right": [{ "id": "omarchy.tray" }, { "id": "omarchy.power" }] } } }
|
||||
JSON
|
||||
}
|
||||
|
||||
assert_widget_placed() {
|
||||
[[ $(ids right) == '["omacom.elsewhen","omarchy.tray","omarchy.power"]' ]] ||
|
||||
fail "$1 still gets the widget" "$(cat "$config")"
|
||||
}
|
||||
|
||||
assert_retired() {
|
||||
local description="$1"
|
||||
[[ ! -e $checkout && ! -L $checkout ]] || fail "$description is retired" "$(ls -la "$checkout")"
|
||||
grep -q 'Retired the omacom.elsewhen checkout' "$output" || fail "$description is reported as retired" "$(cat "$output")"
|
||||
assert_widget_placed "$description"
|
||||
pass "$description is retired"
|
||||
}
|
||||
|
||||
assert_kept() {
|
||||
local description="$1"
|
||||
[[ -e $checkout || -L $checkout ]] || fail "$description is kept"
|
||||
grep -q 'takes precedence over' "$output" || fail "$description is reported as shadowed" "$(cat "$output")"
|
||||
assert_widget_placed "$description"
|
||||
pass "$description is kept"
|
||||
}
|
||||
|
||||
for origin in \
|
||||
https://github.com/omacom/elsewhen.git \
|
||||
https://github.com/omacom/elsewhen \
|
||||
git@github.com:omacom/elsewhen.git \
|
||||
ssh://git@github.com/omacom/elsewhen.git \
|
||||
https://GitHub.com/Omacom/Elsewhen/; do
|
||||
make_checkout "$origin"
|
||||
reset_layout
|
||||
run_migration
|
||||
assert_retired "a pristine clone with origin $origin"
|
||||
done
|
||||
|
||||
make_checkout https://github.com/omacom/elsewhen.git
|
||||
printf 'import QtQuick\nItem { id: mine }\n' >"$checkout/Panel.qml"
|
||||
reset_layout
|
||||
run_migration
|
||||
assert_kept "a clone with a modified tracked file"
|
||||
[[ $(cat "$checkout/Panel.qml") == $'import QtQuick\nItem { id: mine }' ]] ||
|
||||
fail "a kept clone keeps its local change" "$(cat "$checkout/Panel.qml")"
|
||||
pass "a kept clone keeps its local change"
|
||||
|
||||
make_checkout https://github.com/omacom/elsewhen.git
|
||||
printf 'notes\n' >"$checkout/NOTES.md"
|
||||
reset_layout
|
||||
run_migration
|
||||
assert_kept "a clone with an untracked file"
|
||||
|
||||
make_checkout https://github.com/someone/elsewhen-fork.git
|
||||
reset_layout
|
||||
run_migration
|
||||
assert_kept "a clone of another repository"
|
||||
|
||||
make_checkout https://github.com/omacom/elsewhen.git
|
||||
git -C "$checkout" remote remove origin
|
||||
reset_layout
|
||||
run_migration
|
||||
assert_kept "a clone without an origin remote"
|
||||
|
||||
rm -rf "$checkout"
|
||||
mkdir -p "$checkout"
|
||||
printf '{ "id": "omacom.elsewhen" }\n' >"$checkout/manifest.json"
|
||||
reset_layout
|
||||
run_migration
|
||||
assert_kept "a plain directory without .git"
|
||||
|
||||
rm -rf "$checkout"
|
||||
make_checkout https://github.com/omacom/elsewhen.git
|
||||
mv "$checkout" "$test_dir/elsewhen-src"
|
||||
ln -s "$test_dir/elsewhen-src" "$checkout"
|
||||
reset_layout
|
||||
run_migration
|
||||
assert_kept "a symlinked checkout"
|
||||
[[ -L $checkout && -f $test_dir/elsewhen-src/manifest.json ]] ||
|
||||
fail "a symlinked checkout stays a symlink with its target intact" "$(ls -la "$checkout" "$test_dir/elsewhen-src")"
|
||||
pass "a symlinked checkout stays a symlink with its target intact"
|
||||
|
||||
rm -f "$checkout"
|
||||
reset_layout
|
||||
run_migration
|
||||
grep -q 'omacom.elsewhen checkout\|takes precedence' "$output" && fail "no checkout means no checkout report" "$(cat "$output")"
|
||||
assert_widget_placed "a machine without a checkout"
|
||||
pass "a machine without a checkout is left alone"
|
||||
Reference in new issue
Block a user