#!/usr/bin/env bash # # Werkbaum — mirror-docs: mehrere Server-Dokumente in ein git-Worktree # spiegeln. Liest eine Liste, ruft je Zeile `pull-doc --git-commit` und pusht # auf Wunsch einmal am Ende. Gedacht für einen Timer auf dem Backend-Host # (D88-Nachtrag 3): Der geteilte Plan bekommt so ohne Zutun eine Git-Historie. # # Verwendung: # mirror-docs [--push] [--api ] # # --push Nach dem Durchlauf `git push`, wenn etwas committet wurde. # Der Branch braucht dafür einen Upstream. # --api Basis-Adresse des Backends (…/api/v1) für Zeilen, die nur # eine UUID nennen; sonst aus WERKBAUM_API. # Wurzel des git-Worktrees, in das gespiegelt wird. # Textdatei, je Zeile ` `; der Pfad ist # relativ zum Worktree. Leerzeilen und `#`-Zeilen sind # Kommentar. Ein neues Dokument ist eine Zeile mehr. # # Jede Zeile läuft für sich: Ein gescheiterter Abruf bricht die übrigen nicht # ab, steht aber auf stderr, und der Lauf endet dann mit 1 — ein Timer sieht # so im Journal, was fehlt, statt still zu bleiben. Unverändertes committet # nichts (das regelt pull-doc); ohne neuen Commit wird nicht gepusht. # # Siehe docs/DECISIONS.md D88. set -euo pipefail usage(){ sed -n '2,25p' "$0" | sed 's/^# \{0,1\}//'; } do_push=0; api="${WERKBAUM_API:-}" while [ $# -gt 0 ]; do case "$1" in -h|--help) usage; exit 0;; --push) do_push=1; shift;; --api) [ $# -ge 2 ] || { echo "Fehler: --api braucht eine Adresse." >&2; exit 2; }; api="$2"; shift 2;; --*) echo "Fehler: unbekannter Schalter $1" >&2; echo >&2; usage >&2; exit 2;; *) break;; esac done [ $# -eq 2 ] || { echo "Fehler: erwartet [--push] [--api ] Worktree und Liste." >&2; echo >&2; usage >&2; exit 2; } tree="$1"; list="$2" pulldoc="$(dirname -- "$0")/pull-doc" [ -x "$pulldoc" ] || { echo "Fehler: $pulldoc fehlt oder ist nicht ausführbar." >&2; exit 2; } [ -f "$list" ] || { echo "Fehler: Liste $list gibt es nicht." >&2; exit 2; } [ "$(git -C "$tree" rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ] \ || { echo "Fehler: $tree ist kein git-Worktree." >&2; exit 2; } before="$(git -C "$tree" rev-parse HEAD)" fail=0; n=0 while read -r src path _; do case "$src" in ''|'#'*) continue;; esac n=$((n+1)) [ -n "$path" ] || { echo "Fehler: Zeile ohne Pfad: $src" >&2; fail=1; continue; } case "$src" in http://*|https://*) url="$src";; *) [ -n "$api" ] || { echo "Fehler: $src ist keine URL, und --api/WERKBAUM_API fehlt." >&2; fail=1; continue; } url="${api%/}/documents/$src";; esac case "$path" in /*|*..*) echo "Fehler: Pfad muss relativ und ohne .. sein: $path" >&2; fail=1; continue;; esac mkdir -p -- "$tree/$(dirname -- "$path")" "$pulldoc" --git-commit "$url" "$tree/$path" || { echo "Fehler bei $path (siehe oben)." >&2; fail=1; } done < "$list" [ "$n" -gt 0 ] || echo "Hinweis: Liste $list nennt kein Dokument." >&2 after="$(git -C "$tree" rev-parse HEAD)" if [ "$do_push" = 1 ] && [ "$before" != "$after" ]; then git -C "$tree" push -q || { echo "Fehler: push gescheitert — Commits liegen lokal in $tree." >&2; fail=1; } [ "$fail" = 0 ] && echo "Gepusht: $(git -C "$tree" rev-parse --short HEAD)" fi exit "$fail"