From e8a8236a22e9d05f4fccded51639d522a88903ca Mon Sep 17 00:00:00 2001 From: Spencer Bull Date: Thu, 17 Sep 2026 22:07:54 -0500 Subject: [PATCH] Preserve local Elsewhen work and fallback bar layouts Retire only checkouts whose refs and reflogs are reachable from recorded origin history, and preserve ignored files. Leave configs without an explicit supported bar layout untouched so migration does not replace the shell fallback with an almost empty bar. Co-Authored-By: Codex XHigh --- migrations/1789581661.sh | 13 ++-- .../elsewhen-default-migration-test.sh | 69 +++++++++++++++++++ 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/migrations/1789581661.sh b/migrations/1789581661.sh index 163deb9c..f581d4d0 100644 --- a/migrations/1789581661.sh +++ b/migrations/1789581661.sh @@ -29,15 +29,18 @@ omarchy-shell -q shell rescanPlugins || true # one that finds the package. A one-time gap of a few minutes, during the # update itself. upstream_checkout() { - local dir="$1" origin status + local dir="$1" origin status unpublished [[ -d $dir && ! -L $dir && -d $dir/.git ]] || return 1 origin=$(git -C "$dir" remote get-url origin 2>/dev/null) || return 1 origin=${origin,,} origin=${origin%/} origin=${origin%.git} [[ $origin =~ ^([a-z+]+://)?([^/@]+@)?github\.com[/:]omacom/elsewhen$ ]] || return 1 - status=$(git -C "$dir" status --porcelain 2>/dev/null) || return 1 - [[ -z $status ]] + status=$(git -C "$dir" status --porcelain --untracked-files=all --ignored 2>/dev/null) || return 1 + [[ -z $status ]] || return 1 + # Local branches, stashes, and reflogs may hold work absent from a clean tree. + unpublished=$(git -C "$dir" rev-list HEAD --all --reflog --not --remotes=origin 2>/dev/null) || return 1 + [[ -z $unpublished ]] } checkout="$HOME/.config/omarchy/plugins/omacom.elsewhen" @@ -60,8 +63,8 @@ fi source omarchy-shell-config [[ -s $CONFIG_FILE ]] || exit 0 -# A file the shell cannot read is left for its owner to repair. -jq empty "$CONFIG_FILE" 2>/dev/null || exit 0 +# Preserve configs whose bar comes from the shell fallback instead of an explicit layout. +jq -e 'type == "object" and .version == 1 and (.bar | type == "object") and (.bar.layout | type == "object")' "$CONFIG_FILE" >/dev/null 2>&1 || exit 0 entry_id='def entry_id: if type == "object" then (.id // "" | tostring) else tostring end;' diff --git a/test/shell.d/elsewhen-default-migration-test.sh b/test/shell.d/elsewhen-default-migration-test.sh index 89585f22..525094e5 100644 --- a/test/shell.d/elsewhen-default-migration-test.sh +++ b/test/shell.d/elsewhen-default-migration-test.sh @@ -156,6 +156,18 @@ 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" +for partial in \ + '{"version":1,"idle":{"lock":600}}' \ + '{"version":1,"bar":null,"idle":{"lock":600}}' \ + '{"version":1,"bar":{"position":"bottom"}}' \ + '{"bar":{"layout":{"center":["omarchy.clock"]}}}'; do + printf '%s\n' "$partial" >"$config" + before=$(sha256sum "$config") + run_migration + [[ $before == $(sha256sum "$config") ]] || fail "migration preserves fallback configuration" "$(cat "$config")" + pass "migration preserves fallback configuration: $partial" +done + printf '{ not json' >"$config" run_migration [[ $(cat "$config") == '{ not json' ]] || fail "migration leaves an unparsable config untouched" "$(cat "$config")" @@ -201,6 +213,7 @@ make_checkout() { printf 'import QtQuick\nItem {}\n' >"$checkout/Panel.qml" git -C "$checkout" add -A git -C "$checkout" commit -q -m "Elsewhen" + git -C "$checkout" update-ref refs/remotes/origin/main HEAD } reset_layout() { @@ -257,6 +270,62 @@ reset_layout run_migration assert_kept "a clone with an untracked file" +make_checkout https://github.com/omacom/elsewhen.git +printf 'import QtQuick\nItem { id: mine }\n' >"$checkout/Panel.qml" +git -C "$checkout" add Panel.qml +git -C "$checkout" commit -q -m "Local customization" +local_commit=$(git -C "$checkout" rev-parse HEAD) +reset_layout +run_migration +assert_kept "a clean clone with an unpublished commit" +[[ $(git -C "$checkout" rev-parse HEAD) == "$local_commit" ]] || fail "local commit survives" + +make_checkout https://github.com/omacom/elsewhen.git +git -C "$checkout" checkout -qb local-work +printf 'local branch\n' >"$checkout/Panel.qml" +git -C "$checkout" commit -qam "Unpublished branch" +git -C "$checkout" checkout -q --detach refs/remotes/origin/main +reset_layout +run_migration +assert_kept "an unpublished commit on another branch" + +make_checkout https://github.com/omacom/elsewhen.git +printf 'stashed work\n' >"$checkout/Panel.qml" +git -C "$checkout" stash push -q +reset_layout +run_migration +assert_kept "a clean clone with stashed work" + +make_checkout https://github.com/omacom/elsewhen.git +git -C "$checkout" config status.showUntrackedFiles no +printf 'private-notes\n' >"$checkout/.git/info/exclude" +printf 'ignored work\n' >"$checkout/private-notes" +reset_layout +run_migration +assert_kept "a clone with an ignored file" +[[ $(cat "$checkout/private-notes") == "ignored work" ]] || fail "ignored file survives" + +make_checkout https://github.com/omacom/elsewhen.git +printf 'recoverable work\n' >"$checkout/Panel.qml" +git -C "$checkout" commit -qam "Recoverable local commit" +git -C "$checkout" reset -q --hard refs/remotes/origin/main +reset_layout +run_migration +assert_kept "a local commit retained only by the reflog" + +make_checkout https://github.com/omacom/elsewhen.git +git -C "$checkout" update-ref -d refs/remotes/origin/main +reset_layout +run_migration +assert_kept "a clone without recorded upstream history" + +make_checkout https://github.com/omacom/elsewhen.git +git -C "$checkout" config status.showUntrackedFiles no +printf 'untracked work\n' >"$checkout/NOTES.md" +reset_layout +run_migration +assert_kept "untracked files hidden by the user Git configuration" + make_checkout https://github.com/someone/elsewhen-fork.git reset_layout run_migration