diff --git a/scripts/install.sh b/scripts/install.sh index 179d41aa..8fde392a 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1390,6 +1390,9 @@ install_hermes() { local src="$INTEGRATIONS/hermes/agency-agents-router" local hermes_home; hermes_home="$(hermes_home_dir)" local dest; dest="$(resolve_dest hermes "${hermes_home}/plugins/agency-agents-router")" + # Strip trailing slashes first: basename ignores them, but `rm -rf link/` + # follows a symlink and empties its target instead of removing the link. + while [[ "$dest" == */ && "$dest" != "/" ]]; do dest="${dest%/}"; done # HERMES_PLUGIN_DIR is ambiguous: its name invites setting it to the plugins # parent (~/.hermes/plugins) rather than the full plugin path. Always target # the agency-agents-router subdir so we never rm -rf a shared plugins dir that @@ -1417,7 +1420,12 @@ install_hermes() { return 1 fi fi - rm -rf "$dest" + # A symlink (e.g. from an earlier --link install) is replaced, never followed. + if [[ -L "$dest" ]]; then + rm -f -- "$dest" + else + rm -rf -- "$dest" + fi if $USE_LINK; then ln -s "$src" "$dest" else diff --git a/scripts/test-install-hermes-destination.sh b/scripts/test-install-hermes-destination.sh index 28bba326..6c0b02a3 100644 --- a/scripts/test-install-hermes-destination.sh +++ b/scripts/test-install-hermes-destination.sh @@ -57,3 +57,30 @@ HOME="$fresh_home" bash "$repo/scripts/install.sh" --no-interactive --tool herme exit 1 } echo 'PASS: fresh Hermes installation works normally' + +# A trailing slash must not turn "replace the plugin" into "empty whatever a +# symlink points at": `rm -rf link/` follows the link and deletes the target's +# contents. Seen on real installs via HERMES_PLUGIN_DIR=".../agency-agents-router/". +link_home="$tmp/link-home" +link_plugin="$link_home/.hermes/plugins/agency-agents-router" +personal="$tmp/personal" +mkdir -p "$personal" "$(dirname "$link_plugin")" +printf 'name: agency-agents-router\n' > "$personal/plugin.yaml" +printf 'personal content\n' > "$personal/personal.txt" +ln -s "$personal" "$link_plugin" +HOME="$link_home" HERMES_PLUGIN_DIR="$link_plugin/" bash "$repo/scripts/install.sh" --no-interactive --tool hermes --no-convert > "$tmp/slash-output" 2>&1 || true +[[ -f "$personal/personal.txt" ]] || { + echo 'FAIL: a trailing slash deleted the contents of a symlinked directory' >&2 + exit 1 +} +echo 'PASS: a trailing slash on a symlinked destination leaves its target intact' + +relink_home="$tmp/relink-home" +HOME="$relink_home" bash "$repo/scripts/install.sh" --no-interactive --tool hermes --no-convert --link > "$tmp/link-output" 2>&1 +HOME="$relink_home" HERMES_PLUGIN_DIR="$relink_home/.hermes/plugins/agency-agents-router/" \ + bash "$repo/scripts/install.sh" --no-interactive --tool hermes --no-convert > "$tmp/relink-output" 2>&1 +[[ -f "$repo/integrations/hermes/agency-agents-router/plugin.yaml" ]] || { + echo 'FAIL: re-installing over a --link install deleted the plugin source in the clone' >&2 + exit 1 +} +echo 'PASS: re-installing over a --link install keeps the clone intact'