fix: harden installer symlink logic and interactive sourcing #1

Merged
dschlueter merged 1 commit from fix/installer-strict-mode into main 2026-06-28 03:49:13 +02:00
Owner

Härtet zwei Stellen, die beim Wechsel auf einen env-basierten OpenRouter-Key aufgefallen sind.

Die bisherige Prüfung [[ ! -e "$TARGET_REPO" ]] folgt dem Link und kann einen kaputten Symlink nicht von einem freien Pfad unterscheiden. Das führt zu drei Problemszenarien:

Szenario Vorher Nachher
Kaputter Symlink (dangling) ln -s scheitert („File exists") → set -e bricht die Installation ab ln -sfn hängt auf das neue Ziel um
Echtes Verzeichnis an der Stelle wird stillschweigend ignoriert → Aliase laufen ins alte Repo Warning auf stderr, Installation läuft weiter
Pfad frei Link anlegen Link anlegen (unverändert)

Neue Logik mit Fallunterscheidung -L (Symlink, ohne Verfolgung) / -e (existiert) / else (frei).

lib/profiles.sh – strikter Modus nur nicht-interaktiv (E8)

set -euo pipefail war am Dateianfang global aktiv. Wer die Datei zum Debuggen in einer interaktiven Shell sourcet, bekommt errexit/pipefail in seine Session gezwängt. Jetzt: [[ $- == *i* ]] || set -euo pipefail – streng bleibt streng beim Aufruf über bin/claude-profile, interaktiv wird die Session nicht angefasst.

Tests

  • Profile-Logik (pro/glm/free, fehlender Key, unbekanntes Profil) per Stub-claude verifiziert.
  • Installer-Symlink-Szenarien S1–S3 isoliert mit temporärem HOME durchgespielt, alle verhalten sich wie in der Tabelle.
Härtet zwei Stellen, die beim Wechsel auf einen env-basierten OpenRouter-Key aufgefallen sind. ## `bin/install-claude-profiles` – Symlink-Logik (D7) Die bisherige Prüfung `[[ ! -e "$TARGET_REPO" ]]` folgt dem Link und kann einen *kaputten* Symlink nicht von einem *freien* Pfad unterscheiden. Das führt zu drei Problemszenarien: | Szenario | Vorher | Nachher | |---|---|---| | Kaputter Symlink (dangling) | `ln -s` scheitert („File exists") → `set -e` bricht die Installation ab | `ln -sfn` hängt auf das neue Ziel um | | Echtes Verzeichnis an der Stelle | wird stillschweigend ignoriert → Aliase laufen ins alte Repo | Warning auf stderr, Installation läuft weiter | | Pfad frei | Link anlegen | Link anlegen (unverändert) | Neue Logik mit Fallunterscheidung `-L` (Symlink, ohne Verfolgung) / `-e` (existiert) / `else` (frei). ## `lib/profiles.sh` – strikter Modus nur nicht-interaktiv (E8) `set -euo pipefail` war am Dateianfang global aktiv. Wer die Datei zum Debuggen in einer interaktiven Shell `source`t, bekommt `errexit`/`pipefail` in seine Session gezwängt. Jetzt: `[[ $- == *i* ]] || set -euo pipefail` – streng bleibt streng beim Aufruf über `bin/claude-profile`, interaktiv wird die Session nicht angefasst. ## Tests - Profile-Logik (pro/glm/free, fehlender Key, unbekanntes Profil) per Stub-`claude` verifiziert. - Installer-Symlink-Szenarien S1–S3 isoliert mit temporärem `HOME` durchgespielt, alle verhalten sich wie in der Tabelle.
- install-claude-profiles: distinguish broken symlink vs real dir vs free
  path via -L/-e, repoint existing links with ln -sfn, warn instead of
  silently skipping when target is a non-symlink dir.
- profiles.sh: only set -euo pipefail when sourced non-interactively so
  sourcing in an interactive shell doesn't clobber session settings.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dschlueter/claude-launcher-profiles!1
No description provided.