2026-06-02 10:36:16 +00:00
|
|
|
|
#!/usr/bin/env sh
|
|
|
|
|
|
# copilot-update.sh
|
|
|
|
|
|
# Zieht die neueste Version des Copilot-Setup-Repos und aktualisiert:
|
2026-06-03 09:21:53 +00:00
|
|
|
|
# - Dieses Script selbst (~/.local/bin/copilot-update.sh)
|
2026-06-02 10:36:16 +00:00
|
|
|
|
# - Globale Git-Templates (~/.git-templates/)
|
|
|
|
|
|
# - VS Code Prompt-Dateien
|
2026-06-03 09:21:53 +00:00
|
|
|
|
# - Git-Hooks im aktuellen Repo (pre-commit)
|
|
|
|
|
|
# - .github/copilot-instructions.md (Framework-Sektion immer, Projekt-Teil bleibt)
|
2026-06-02 10:36:16 +00:00
|
|
|
|
#
|
|
|
|
|
|
# Usage:
|
|
|
|
|
|
# copilot-update.sh # aktuelles Verzeichnis (Git-Repo optional)
|
|
|
|
|
|
# git copilot-update # via Git-Alias
|
|
|
|
|
|
|
2026-06-10 09:54:07 +02:00
|
|
|
|
# ── Konfiguration laden: env > config-file > leer ─────────────────────────
|
|
|
|
|
|
# Env-Variablen (Vorrang):
|
|
|
|
|
|
# COPILOT_SETUP_REMOTE_SSH / _HTTP Remote-URLs des Setup-Repos
|
|
|
|
|
|
# COPILOT_SETUP_DIR lokaler Klon/Arbeitskopie (Offline)
|
|
|
|
|
|
# COPILOT_SETUP_CONFIG alternativer Pfad zur Config-Datei
|
|
|
|
|
|
# Config-Datei (sh-Syntax, gesourct): $XDG_CONFIG_HOME/copilot-setup/config
|
|
|
|
|
|
# Standalone-Skript -> keine gemeinsame Lib sourcebar; gleiche Aufloesung in
|
|
|
|
|
|
# deploy.sh. Bei Aenderungen beide Stellen pflegen.
|
|
|
|
|
|
_env_ssh="${COPILOT_SETUP_REMOTE_SSH:-}"
|
|
|
|
|
|
_env_http="${COPILOT_SETUP_REMOTE_HTTP:-}"
|
|
|
|
|
|
_env_dir="${COPILOT_SETUP_DIR:-}"
|
|
|
|
|
|
|
|
|
|
|
|
CONFIG_FILE="${COPILOT_SETUP_CONFIG:-${XDG_CONFIG_HOME:-$HOME/.config}/copilot-setup/config}"
|
|
|
|
|
|
if [ -f "$CONFIG_FILE" ]; then
|
|
|
|
|
|
. "$CONFIG_FILE"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
# Env ueberschreibt Werte aus der Config-Datei
|
|
|
|
|
|
[ -n "$_env_ssh" ] && COPILOT_SETUP_REMOTE_SSH="$_env_ssh"
|
|
|
|
|
|
[ -n "$_env_http" ] && COPILOT_SETUP_REMOTE_HTTP="$_env_http"
|
|
|
|
|
|
[ -n "$_env_dir" ] && COPILOT_SETUP_DIR="$_env_dir"
|
|
|
|
|
|
|
|
|
|
|
|
SETUP_REPO_SSH="${COPILOT_SETUP_REMOTE_SSH:-}"
|
|
|
|
|
|
SETUP_REPO_HTTP="${COPILOT_SETUP_REMOTE_HTTP:-}"
|
2026-06-02 10:36:16 +00:00
|
|
|
|
CACHE_DIR="${COPILOT_SETUP_DIR:-$HOME/.copilot-setup}"
|
|
|
|
|
|
|
2026-06-10 09:54:07 +02:00
|
|
|
|
have_remote() { [ -n "$SETUP_REPO_SSH" ] || [ -n "$SETUP_REPO_HTTP" ]; }
|
|
|
|
|
|
|
|
|
|
|
|
clone_setup_repo() {
|
|
|
|
|
|
if [ -n "$SETUP_REPO_SSH" ]; then
|
|
|
|
|
|
echo " → Klone Setup-Repo (SSH)..."
|
|
|
|
|
|
if git clone --quiet "$SETUP_REPO_SSH" "$CACHE_DIR" 2>/dev/null; then
|
|
|
|
|
|
echo " ✓ Geklont via SSH"; return 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
echo " ✗ SSH fehlgeschlagen"
|
|
|
|
|
|
fi
|
|
|
|
|
|
if [ -n "$SETUP_REPO_HTTP" ]; then
|
|
|
|
|
|
echo " → Klone Setup-Repo (HTTP)..."
|
|
|
|
|
|
if git clone --quiet "$SETUP_REPO_HTTP" "$CACHE_DIR" 2>/dev/null; then
|
|
|
|
|
|
echo " ✓ Geklont via HTTP"; return 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
echo " ✗ HTTP fehlgeschlagen"
|
|
|
|
|
|
fi
|
|
|
|
|
|
return 1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# VS Code User-Verzeichnis portabel ueber Editionen/OS ermitteln.
|
|
|
|
|
|
# Identischer Block in deploy.sh (Standalone -> keine Lib sourcebar).
|
|
|
|
|
|
detect_vscode_user_dir() {
|
|
|
|
|
|
for d in \
|
|
|
|
|
|
"$HOME/.vscode-server/data/User" \
|
|
|
|
|
|
"$HOME/.vscode-server-insiders/data/User" \
|
|
|
|
|
|
"$HOME/Library/Application Support/Code/User" \
|
|
|
|
|
|
"$HOME/Library/Application Support/Code - Insiders/User" \
|
|
|
|
|
|
"$HOME/Library/Application Support/VSCodium/User" \
|
|
|
|
|
|
"$HOME/Library/Application Support/Cursor/User" \
|
|
|
|
|
|
"$HOME/.config/Code/User" \
|
|
|
|
|
|
"$HOME/.config/Code - Insiders/User" \
|
|
|
|
|
|
"$HOME/.config/VSCodium/User" \
|
|
|
|
|
|
"$HOME/.config/Cursor/User" \
|
|
|
|
|
|
"$HOME/.var/app/com.visualstudio.code/config/Code/User" \
|
|
|
|
|
|
"/mnt/c/Users/$USER/AppData/Roaming/Code/User" \
|
|
|
|
|
|
"/mnt/c/Users/$USER/AppData/Roaming/Code - Insiders/User"
|
|
|
|
|
|
do
|
|
|
|
|
|
if [ -d "$d" ]; then
|
|
|
|
|
|
printf '%s\n' "$d"
|
|
|
|
|
|
return 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
done
|
|
|
|
|
|
case "$(uname -s)" in
|
|
|
|
|
|
Darwin) printf '%s\n' "$HOME/Library/Application Support/Code/User" ;;
|
|
|
|
|
|
*) printf '%s\n' "$HOME/.config/Code/User" ;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-02 10:36:16 +00:00
|
|
|
|
echo "=== Copilot Update ==="
|
|
|
|
|
|
|
|
|
|
|
|
# ── 1. Setup-Repo Cache aktuell halten ───────────────────────────────────────
|
|
|
|
|
|
if [ -d "$CACHE_DIR/.git" ]; then
|
2026-06-10 09:54:07 +02:00
|
|
|
|
if have_remote; then
|
|
|
|
|
|
echo " → Pulling latest from setup repo..."
|
|
|
|
|
|
if git -C "$CACHE_DIR" pull --ff-only --quiet 2>/dev/null; then
|
|
|
|
|
|
echo " ✓ Cache aktualisiert: $CACHE_DIR"
|
|
|
|
|
|
else
|
|
|
|
|
|
echo " ⚠ git pull fehlgeschlagen – nutze vorhandenen Cache (offline)"
|
|
|
|
|
|
fi
|
2026-06-02 10:36:16 +00:00
|
|
|
|
else
|
2026-06-10 09:54:07 +02:00
|
|
|
|
echo " ─ Kein Remote konfiguriert – nutze lokalen Klon: $CACHE_DIR"
|
2026-06-02 10:36:16 +00:00
|
|
|
|
fi
|
2026-06-10 09:54:07 +02:00
|
|
|
|
elif [ -d "$CACHE_DIR/git-templates" ]; then
|
|
|
|
|
|
echo " ─ Lokale Setup-Quelle ohne .git (Offline-Betrieb): $CACHE_DIR"
|
|
|
|
|
|
else
|
|
|
|
|
|
if have_remote && clone_setup_repo; then
|
|
|
|
|
|
:
|
2026-06-02 10:36:16 +00:00
|
|
|
|
else
|
2026-06-10 09:54:07 +02:00
|
|
|
|
echo ""
|
|
|
|
|
|
echo " ⚠ Keine Setup-Quelle verfuegbar – Update uebersprungen."
|
|
|
|
|
|
if have_remote; then
|
|
|
|
|
|
echo " Remote nicht erreichbar:"
|
|
|
|
|
|
[ -n "$SETUP_REPO_SSH" ] && echo " SSH: $SETUP_REPO_SSH"
|
|
|
|
|
|
[ -n "$SETUP_REPO_HTTP" ] && echo " HTTP: $SETUP_REPO_HTTP"
|
2026-06-02 10:36:16 +00:00
|
|
|
|
else
|
2026-06-10 09:54:07 +02:00
|
|
|
|
echo " Kein Remote konfiguriert. Setze COPILOT_SETUP_REMOTE_SSH/_HTTP,"
|
|
|
|
|
|
echo " COPILOT_SETUP_DIR (lokaler Klon) oder lege $CONFIG_FILE an."
|
2026-06-02 10:36:16 +00:00
|
|
|
|
fi
|
2026-06-10 09:54:07 +02:00
|
|
|
|
echo " (Kein Fehler – ohne Quelle gibt es nichts zu aktualisieren.)"
|
|
|
|
|
|
exit 0
|
2026-06-02 10:36:16 +00:00
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
SOURCE="$CACHE_DIR"
|
|
|
|
|
|
|
2026-06-03 09:21:53 +00:00
|
|
|
|
# ── 1b. Self-update: dieses Script selbst aktualisieren ─────────────────────
|
|
|
|
|
|
SELF="$HOME/.local/bin/copilot-update.sh"
|
|
|
|
|
|
if [ -f "$SOURCE/scripts/copilot-update.sh" ]; then
|
|
|
|
|
|
if ! cmp -s "$SOURCE/scripts/copilot-update.sh" "$SELF" 2>/dev/null; then
|
|
|
|
|
|
cp "$SOURCE/scripts/copilot-update.sh" "$SELF"
|
|
|
|
|
|
chmod +x "$SELF"
|
|
|
|
|
|
echo " ✓ copilot-update.sh selbst aktualisiert – starte neue Version..."
|
|
|
|
|
|
exec "$SELF" "$@"
|
|
|
|
|
|
fi
|
2026-06-03 09:59:18 +00:00
|
|
|
|
fi
|
|
|
|
|
|
|
2026-06-02 10:36:16 +00:00
|
|
|
|
GIT_TEMPLATE_DIR="$HOME/.git-templates"
|
2026-06-03 09:59:18 +00:00
|
|
|
|
|
|
|
|
|
|
# ── 2. ~/.git-templates/ aktualisieren ──────────────────────────────────────
|
2026-06-02 10:36:16 +00:00
|
|
|
|
mkdir -p "$GIT_TEMPLATE_DIR/.github" "$GIT_TEMPLATE_DIR/.vscode" \
|
|
|
|
|
|
"$GIT_TEMPLATE_DIR/hooks" "$GIT_TEMPLATE_DIR/docs" \
|
|
|
|
|
|
"$GIT_TEMPLATE_DIR/history/summary"
|
|
|
|
|
|
|
|
|
|
|
|
cp "$SOURCE/git-templates/.github/copilot-instructions.md" "$GIT_TEMPLATE_DIR/.github/"
|
|
|
|
|
|
cp "$SOURCE/git-templates/.vscode/settings.json" "$GIT_TEMPLATE_DIR/.vscode/"
|
|
|
|
|
|
cp "$SOURCE/git-templates/.vscode/extensions.json" "$GIT_TEMPLATE_DIR/.vscode/"
|
|
|
|
|
|
cp "$SOURCE/git-templates/hooks/pre-commit" "$GIT_TEMPLATE_DIR/hooks/"
|
2026-06-03 09:21:53 +00:00
|
|
|
|
chmod +x "$GIT_TEMPLATE_DIR/hooks/pre-commit"
|
2026-06-02 10:36:16 +00:00
|
|
|
|
if [ -f "$SOURCE/git-templates/hooks/post-merge" ]; then
|
|
|
|
|
|
cp "$SOURCE/git-templates/hooks/post-merge" "$GIT_TEMPLATE_DIR/hooks/"
|
|
|
|
|
|
chmod +x "$GIT_TEMPLATE_DIR/hooks/post-merge"
|
|
|
|
|
|
fi
|
|
|
|
|
|
cp "$SOURCE/git-templates/docs/USER.md" "$GIT_TEMPLATE_DIR/docs/"
|
|
|
|
|
|
cp "$SOURCE/git-templates/docs/ADMIN.md" "$GIT_TEMPLATE_DIR/docs/"
|
|
|
|
|
|
cp "$SOURCE/git-templates/docs/MAINTAINER.md" "$GIT_TEMPLATE_DIR/docs/"
|
|
|
|
|
|
cp "$SOURCE/git-templates/history/summary/PROJECT_CONTEXT.md" "$GIT_TEMPLATE_DIR/history/summary/"
|
|
|
|
|
|
|
|
|
|
|
|
echo " ✓ ~/.git-templates/ aktualisiert"
|
|
|
|
|
|
|
|
|
|
|
|
# ── 3. VS Code Prompt-Dateien aktualisieren ───────────────────────────────────
|
2026-06-10 09:54:07 +02:00
|
|
|
|
VSCODE_USER="$(detect_vscode_user_dir)"
|
2026-06-02 10:36:16 +00:00
|
|
|
|
|
|
|
|
|
|
if [ -d "$VSCODE_USER" ]; then
|
|
|
|
|
|
mkdir -p "$VSCODE_USER/prompts"
|
|
|
|
|
|
PROMPTS_UPDATED=0
|
|
|
|
|
|
for f in "$SOURCE/prompts/"*.prompt.md; do
|
|
|
|
|
|
fname="$(basename "$f")"
|
|
|
|
|
|
cp "$f" "$VSCODE_USER/prompts/$fname"
|
|
|
|
|
|
PROMPTS_UPDATED=$((PROMPTS_UPDATED + 1))
|
|
|
|
|
|
done
|
|
|
|
|
|
echo " ✓ $PROMPTS_UPDATED Prompt-Dateien aktualisiert → $VSCODE_USER/prompts/"
|
|
|
|
|
|
else
|
|
|
|
|
|
echo " ─ VS Code User-Verzeichnis nicht gefunden, Prompts übersprungen"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
# ── 4. Repo-lokale Updates (nur wenn in einem Git-Repo) ──────────────────────
|
|
|
|
|
|
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
|
|
|
|
|
|
|
|
|
|
if [ -z "$REPO_ROOT" ]; then
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
echo " ─ Kein Git-Repo erkannt – repo-lokale Updates übersprungen"
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
echo "=== Done ==="
|
|
|
|
|
|
exit 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
echo " Git-Repo erkannt: $REPO_ROOT"
|
|
|
|
|
|
|
|
|
|
|
|
# ── 4a. Git-Hooks aktualisieren ───────────────────────────────────────────────
|
|
|
|
|
|
HOOKS_DIR="$REPO_ROOT/.git/hooks"
|
|
|
|
|
|
mkdir -p "$HOOKS_DIR"
|
|
|
|
|
|
HOOKS_UPDATED=0
|
|
|
|
|
|
|
2026-06-03 09:21:53 +00:00
|
|
|
|
for hook in pre-commit; do
|
2026-06-02 10:36:16 +00:00
|
|
|
|
if [ -f "$SOURCE/git-templates/hooks/$hook" ]; then
|
|
|
|
|
|
cp "$SOURCE/git-templates/hooks/$hook" "$HOOKS_DIR/$hook"
|
|
|
|
|
|
chmod +x "$HOOKS_DIR/$hook"
|
|
|
|
|
|
HOOKS_UPDATED=$((HOOKS_UPDATED + 1))
|
|
|
|
|
|
echo " ✓ .git/hooks/$hook aktualisiert"
|
|
|
|
|
|
fi
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
if [ "$HOOKS_UPDATED" -eq 0 ]; then
|
|
|
|
|
|
echo " ─ Keine Hook-Templates gefunden"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2026-06-03 09:21:53 +00:00
|
|
|
|
# ── 4b. copilot-instructions.md: Framework-Sektion immer aktualisieren ─────────
|
|
|
|
|
|
# Die Datei besteht aus zwei Teilen:
|
|
|
|
|
|
# 1) Framework-Sektion (bis zum ersten ---): Session-Protokoll, Verbotene Aktionen
|
|
|
|
|
|
# 2) Projekt-Sektion (ab ---): Stack, Architecture, Conventions (repo-spezifisch)
|
|
|
|
|
|
# Der Framework-Teil wird immer aus dem Template aktualisiert.
|
|
|
|
|
|
# Der Projekt-Teil bleibt unverändert.
|
2026-06-02 10:36:16 +00:00
|
|
|
|
COPILOT_INSTRUCTIONS="$REPO_ROOT/.github/copilot-instructions.md"
|
2026-06-03 09:21:53 +00:00
|
|
|
|
TEMPLATE_INSTRUCTIONS="$SOURCE/git-templates/.github/copilot-instructions.md"
|
|
|
|
|
|
|
|
|
|
|
|
if [ -f "$COPILOT_INSTRUCTIONS" ] && [ -f "$TEMPLATE_INSTRUCTIONS" ]; then
|
|
|
|
|
|
# Framework-Sektion aus Template (alles vor erstem ---)
|
|
|
|
|
|
framework=$(awk '/^---$/{exit} {print}' "$TEMPLATE_INSTRUCTIONS")
|
|
|
|
|
|
# Projekt-Sektion aus Ziel-Datei (ab erstem --- inkl.)
|
|
|
|
|
|
project=$(awk '/^---$/{found=1} found{print}' "$COPILOT_INSTRUCTIONS")
|
|
|
|
|
|
if [ -n "$project" ]; then
|
2026-06-04 09:20:05 +00:00
|
|
|
|
printf '%s\n\n%s\n' "$framework" "$project" > "$COPILOT_INSTRUCTIONS"
|
2026-06-03 09:21:53 +00:00
|
|
|
|
echo " ✓ .github/copilot-instructions.md Framework-Sektion aktualisiert"
|
2026-06-02 10:36:16 +00:00
|
|
|
|
else
|
2026-06-03 09:21:53 +00:00
|
|
|
|
# Keine Projekt-Sektion vorhanden (noch nicht angepasst) – komplett ersetzen
|
|
|
|
|
|
cp "$TEMPLATE_INSTRUCTIONS" "$COPILOT_INSTRUCTIONS"
|
|
|
|
|
|
echo " ✓ .github/copilot-instructions.md aktualisiert (noch nicht angepasst)"
|
2026-06-02 10:36:16 +00:00
|
|
|
|
fi
|
|
|
|
|
|
else
|
|
|
|
|
|
echo " ─ .github/copilot-instructions.md nicht vorhanden, übersprungen"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2026-06-03 10:42:05 +00:00
|
|
|
|
# ── 4c. Fehlende 3-Zielgruppen-Docs anlegen (nur wenn noch nicht vorhanden) ──
|
|
|
|
|
|
# Überschreibt nie vorhandene Dateien – nur initial anlegen
|
|
|
|
|
|
if [ -d "$REPO_ROOT/docs" ]; then
|
|
|
|
|
|
DOCS_CREATED=0
|
|
|
|
|
|
for doc in USER.md ADMIN.md MAINTAINER.md; do
|
|
|
|
|
|
if [ ! -f "$REPO_ROOT/docs/$doc" ] && [ -f "$GIT_TEMPLATE_DIR/docs/$doc" ]; then
|
|
|
|
|
|
cp "$GIT_TEMPLATE_DIR/docs/$doc" "$REPO_ROOT/docs/$doc"
|
|
|
|
|
|
echo " ✓ docs/$doc angelegt (Template)"
|
|
|
|
|
|
DOCS_CREATED=$((DOCS_CREATED + 1))
|
|
|
|
|
|
fi
|
|
|
|
|
|
done
|
|
|
|
|
|
if [ "$DOCS_CREATED" -eq 0 ]; then
|
|
|
|
|
|
echo " ─ docs/ 3-Zielgruppen-Docs bereits vorhanden"
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2026-06-02 10:36:16 +00:00
|
|
|
|
echo ""
|
|
|
|
|
|
echo "=== Done ==="
|
|
|
|
|
|
echo "Tipp: 'git copilot-update' jederzeit ausführen um Templates aktuell zu halten."
|