install.sh: add --only and --skip flags for subset installs

This commit is contained in:
Joakim Persson
2026-05-05 22:50:27 +02:00
parent 6307072b21
commit dee755e291
2 changed files with 69 additions and 15 deletions
+10
View File
@@ -19,6 +19,16 @@ chmod +x install.sh
Each `.ts` file in `extensions/` is symlinked into `~/.pi/agent/extensions/`. Existing real files are backed up with a timestamp. Re-runs are idempotent.
**Install a subset:**
```bash
./install.sh --only ssh-controlmaster # just this one
./install.sh --only "ssh-controlmaster,other" # explicit list
./install.sh --skip "git-checkpoint" # all except these
```
`--only` and `--skip` accept comma-separated names without the `.ts` suffix. `--only` takes precedence if both are given.
### Alternative: pi install (local path)
Because `package.json` declares a `pi` manifest, you can also register this repo as a pi package:
+56 -12
View File
@@ -5,9 +5,12 @@
# loads them automatically on every session. Idempotent and non-destructive.
#
# Usage:
# ./install.sh # install (interactive confirm)
# ./install.sh --yes # install without prompt
# ./install.sh --uninstall # remove symlinks that point into this repo
# ./install.sh install all extensions
# ./install.sh --only ssh-controlmaster install one extension
# ./install.sh --only "ext1,ext2" install a subset
# ./install.sh --skip "ext1,ext2" install all except these
# ./install.sh --yes skip confirmation prompt
# ./install.sh --uninstall remove symlinks that point into this repo
set -euo pipefail
@@ -49,22 +52,34 @@ require_pi_installed() {
# ── args ─────────────────────────────────────────────
ACTION="install"
ASSUME_YES="no"
ONLY="" # comma-separated names to include (empty = all)
SKIP="" # comma-separated names to exclude (empty = none)
while [[ $# -gt 0 ]]; do
case "$1" in
--uninstall) ACTION="uninstall"; shift ;;
-y|--yes) ASSUME_YES="yes"; shift ;;
--only) ONLY="$2"; shift 2 ;;
--only=*) ONLY="${1#--only=}"; shift ;;
--skip) SKIP="$2"; shift 2 ;;
--skip=*) SKIP="${1#--skip=}"; shift ;;
-h|--help)
cat <<EOF
install.sh — install pi-extensions
Usage:
./install.sh install (interactive confirm)
./install.sh --yes install without prompt
./install.sh install all extensions
./install.sh --only ssh-controlmaster install one extension
./install.sh --only "ext1,ext2" install a subset
./install.sh --skip "ext1,ext2" install all except these
./install.sh --yes skip confirmation prompt
./install.sh --uninstall remove symlinks that point into this repo
--only and --skip accept comma-separated extension names (without .ts suffix).
--only takes precedence over --skip if both are given.
Each .ts file in extensions/ is symlinked into ~/.pi/agent/extensions/.
Existing files that are already symlinked into this repo are left alone.
Existing files already symlinked into this repo are left alone.
Existing real files or foreign symlinks are backed up with a timestamp.
EOF
exit 0 ;;
@@ -72,6 +87,31 @@ EOF
esac
done
# ── build install set ─────────────────────────────────
# Populates INSTALL_SET associative array: keys are bare names (no .ts suffix).
declare -A INSTALL_SET
build_install_set() {
if [[ -n "$ONLY" ]]; then
# Explicit allowlist — only install what's named
IFS=',' read -ra names <<< "$ONLY"
for n in "${names[@]}"; do
INSTALL_SET["${n%.ts}"]=1
done
else
# Start with everything present on disk, then remove --skip entries
for f in "${EXTENSIONS_SRC}"/*.ts; do
[[ -e "$f" ]] && INSTALL_SET["$(basename "$f" .ts)"]=1
done
if [[ -n "$SKIP" ]]; then
IFS=',' read -ra names <<< "$SKIP"
for n in "${names[@]}"; do
unset "INSTALL_SET[${n%.ts}]" 2>/dev/null || true
done
fi
fi
}
# ── install ──────────────────────────────────────────
do_install() {
echo
@@ -80,24 +120,28 @@ do_install() {
echo
require_pi_installed
build_install_set
local extensions=("${EXTENSIONS_SRC}"/*.ts)
if [[ ! -e "${extensions[0]}" ]]; then
warn "No .ts files found in ${EXTENSIONS_SRC}/ — nothing to install."
if [[ ${#INSTALL_SET[@]} -eq 0 ]]; then
warn "No extensions selected — nothing to install."
exit 0
fi
echo "==> Extensions to symlink into ${EXTENSIONS_DEST}/:"
for src in "${extensions[@]}"; do
printf ' %s\n' "$(basename "$src")"
for n in "${!INSTALL_SET[@]}"; do
printf ' %s.ts\n' "$n"
done
echo
confirm || { echo "Aborted."; exit 0; }
echo
for src in "${extensions[@]}"; do
for src in "${EXTENSIONS_SRC}"/*.ts; do
[[ -e "$src" ]] || continue
local name
name="$(basename "$src")"
local bare="${name%.ts}"
[[ -n "${INSTALL_SET[$bare]:-}" ]] || continue
local dest="${EXTENSIONS_DEST}/${name}"
note "Linking ${name}"