Tear down the mise Hermes CLI on Remove Hermes
Remove Hermes dropped the desktop package and its ~/.hermes runtime but never touched the mise CLI, on the assumption the install-time handoff had already removed it. A CLI the app never superseded -- an interrupted install, or the terminal CLI from before the app existed -- was left stranded on PATH after uninstall. Add a --remove mode to omarchy-install-hermes-cli that performs the same teardown the desktop takeover already does (mise rm -g + mise uninstall, and the marked stub), and call it from omarchy-remove-ai-hermes. The tool spec and ownership marker stay defined in one place, so the takeover and teardown paths cannot drift. Scoped to what Omarchy owns: a Hermes the user installed themselves is left alone. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
4 files changed
+84
-2
No files matched your search
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# omarchy:summary=Install the Hermes CLI as a mise-backed wrapper in ~/.local/bin
|
||||
# omarchy:args=[--check|--now|--owns]
|
||||
# omarchy:args=[--check|--now|--owns|--remove]
|
||||
# omarchy:examples=omarchy install hermes cli | omarchy install hermes cli --now
|
||||
|
||||
# Hermes pins every one of its dependencies exactly and declares
|
||||
@@ -112,6 +112,25 @@ if [[ $mode == "--owns" ]]; then
|
||||
if ours; then exit 0; else exit 1; fi
|
||||
fi
|
||||
|
||||
# --remove tears down a Hermes CLI this installer put in place -- the mise tool
|
||||
# it installs and the stub it marks -- so Remove Hermes clears a CLI the app
|
||||
# never superseded (an interrupted install, or the terminal CLI from before the
|
||||
# app existed) rather than leaving it stranded on PATH. Scoped to what is ours:
|
||||
# the tool spec is this installer's, and the stub goes only when it carries the
|
||||
# marker, so a Hermes the user installed themselves is untouched. Idempotent --
|
||||
# nothing installed means nothing to do -- and it is the same teardown the
|
||||
# desktop takeover above performs, kept in one place so the two cannot drift.
|
||||
if [[ $mode == "--remove" ]]; then
|
||||
mise rm -g "$tool" >/dev/null 2>&1 || true
|
||||
mise uninstall --all "$tool" >/dev/null 2>&1 || true
|
||||
|
||||
if ours; then
|
||||
rm -f "$HOME/.local/bin/hermes"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --check lets callers tell a cold stub from a working one before they commit
|
||||
# to a path that assumes Hermes is ready.
|
||||
if [[ $mode == "--check" ]]; then
|
||||
|
||||
@@ -8,6 +8,13 @@ set -euo pipefail
|
||||
|
||||
omarchy-pkg-drop hermes-desktop
|
||||
|
||||
# The mise CLI is the app's predecessor, not the app itself: Hermes Desktop takes
|
||||
# it over on install and runs its own runtime instead, so a copy still here is one
|
||||
# the app never superseded -- an interrupted install, or the terminal CLI from
|
||||
# before the app existed. Remove Hermes clears that too, scoped by the installer
|
||||
# to what Omarchy owns so a hermes the user set up themselves is left alone.
|
||||
omarchy-install-hermes-cli --remove
|
||||
|
||||
# The app writes this when the runtime it provisions under ~/.hermes has landed,
|
||||
# and it is the only thing that tells that runtime apart from one the user
|
||||
# installed themselves -- the paths are the same either way. Without it the app
|
||||
|
||||
@@ -402,6 +402,45 @@ marker_copies=$(grep -rl "Written by omarchy-install-hermes-cli" \
|
||||
fail "only omarchy-install-hermes-cli spells out the ownership marker"
|
||||
pass "the ownership marker is written down once"
|
||||
|
||||
# --remove tears down a Hermes CLI this installer owns, so Remove Hermes can
|
||||
# clear one the desktop app never superseded. It turns on the same ownership as
|
||||
# the rest of the file, so its cases mirror that split.
|
||||
remove_home="$test_tmp/remove-home"
|
||||
mkdir -p "$remove_home/.local/bin"
|
||||
|
||||
run_remove() {
|
||||
OMARCHY_TEST_DESKTOP_INSTALLED=0 \
|
||||
OMARCHY_TEST_MISE_WHERE_OK="${OMARCHY_TEST_MISE_WHERE_OK:-0}" \
|
||||
OMARCHY_TEST_MISE_ROOT="$test_tmp/mise" \
|
||||
OMARCHY_TEST_MISE_LOG="$mise_log" \
|
||||
HOME="$remove_home" \
|
||||
PATH="$mock_bin:$PATH" \
|
||||
bash "$ROOT/bin/omarchy-install-hermes-cli" --remove
|
||||
}
|
||||
|
||||
rm -f "$remove_home/.local/bin/hermes"
|
||||
: >"$mise_log"
|
||||
run_remove || fail "--remove succeeds when there is nothing to remove"
|
||||
pass "--remove is idempotent when no Hermes CLI is present"
|
||||
|
||||
printf '%s\n' "#!/bin/bash" "$stub_marker" >"$remove_home/.local/bin/hermes"
|
||||
chmod +x "$remove_home/.local/bin/hermes"
|
||||
: >"$mise_log"
|
||||
OMARCHY_TEST_MISE_WHERE_OK=1 run_remove || fail "--remove succeeds tearing down an owned CLI"
|
||||
tr '\0' '\n' <"$mise_log" | grep -q '^rm$' || fail "--remove drops the mise tool from config"
|
||||
tr '\0' '\n' <"$mise_log" | grep -q '^uninstall$' || fail "--remove uninstalls the mise tool"
|
||||
[[ ! -e $remove_home/.local/bin/hermes ]] || fail "--remove takes the stub it owns"
|
||||
pass "--remove tears down the mise CLI and the stub this installer owns"
|
||||
|
||||
foreign_remove_body="#!/bin/bash
|
||||
exec /usr/local/bin/my-own-hermes \"\$@\""
|
||||
printf '%s\n' "$foreign_remove_body" >"$remove_home/.local/bin/hermes"
|
||||
chmod +x "$remove_home/.local/bin/hermes"
|
||||
run_remove || fail "--remove succeeds with a foreign hermes present"
|
||||
[[ -f $remove_home/.local/bin/hermes && $(cat "$remove_home/.local/bin/hermes") == "$foreign_remove_body" ]] ||
|
||||
fail "--remove leaves a hermes it does not own untouched"
|
||||
pass "--remove leaves a Hermes the user installed themselves"
|
||||
|
||||
# The app's marker says its install once landed, not that it is still there. A
|
||||
# wrapper whose runtime has since gone answers for nothing, so readiness runs
|
||||
# the command, exactly as it does for a hermes the user installed themselves.
|
||||
|
||||
@@ -15,6 +15,14 @@ cat >"$mock_bin/omarchy-pkg-drop" <<'SH'
|
||||
#!/bin/bash
|
||||
printf '%s\0' "$@" >>"$OMARCHY_TEST_DROP_LOG"
|
||||
SH
|
||||
|
||||
# The CLI teardown is the installer's own, exercised in hermes-cli-test.sh; here
|
||||
# it is mocked to a logger so this test stays about what Remove Hermes does with
|
||||
# ~/.hermes, and to keep real mise out of a run with HOME pointed at a fixture.
|
||||
cat >"$mock_bin/omarchy-install-hermes-cli" <<'SH'
|
||||
#!/bin/bash
|
||||
printf '%s\0' "$@" >>"$OMARCHY_TEST_INSTALLER_LOG"
|
||||
SH
|
||||
chmod +x "$mock_bin"/*
|
||||
|
||||
seed_install() {
|
||||
@@ -35,7 +43,10 @@ seed_install() {
|
||||
}
|
||||
|
||||
remove() {
|
||||
OMARCHY_TEST_DROP_LOG="$test_tmp/drop-log" HOME="$test_home" PATH="$mock_bin:$PATH" \
|
||||
: >"$test_tmp/installer-log"
|
||||
OMARCHY_TEST_DROP_LOG="$test_tmp/drop-log" \
|
||||
OMARCHY_TEST_INSTALLER_LOG="$test_tmp/installer-log" \
|
||||
HOME="$test_home" PATH="$mock_bin:$PATH" \
|
||||
bash "$ROOT/bin/omarchy-remove-ai-hermes" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
@@ -67,6 +78,12 @@ pass "removal keeps what belongs to the user"
|
||||
[[ ! -e $test_home/.local/bin/hermes ]] || fail "the app's own hermes command is removed"
|
||||
pass "removal takes the command the app installed"
|
||||
|
||||
# Removal also asks the installer to tear down a mise CLI the app superseded, so
|
||||
# a copy left from before the app took over does not linger once Hermes is gone.
|
||||
tr '\0' '\n' <"$test_tmp/installer-log" | grep -qx -- '--remove' ||
|
||||
fail "removal asks the installer to tear down its own CLI"
|
||||
pass "removal tears down the mise CLI through the installer"
|
||||
|
||||
# A hermes command the app did not write survives even when the app did install
|
||||
# a runtime of its own.
|
||||
seed_install
|
||||
|
||||
Reference in new issue
Block a user