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