dotfiles-rene/bin/git-sync-all.sh

190 lines
5 KiB
Bash
Executable file

#!/usr/bin/env bash
set -uo pipefail
BASE_DIR="${BASE_DIR:-$HOME/git-projekte}"
GITEA_BASE="https://git.motocamp.de/rene"
# Alle Repos auf dem Gitea-Server.
# Bei neuen Repos hier einen Eintrag ergaenzen.
REPO_NAMES=(
balkonsteuerung
berechnungstabellen
claude-skills
comfy
dotfiles-rene
esp32
ki-agenten
macbook-setup
Pi_pico_2w
portainer
skripte
test
web
zellenhalter-generator
)
# --- Farben ----------------------------------------------------------------
if [ -t 1 ]; then
C_RED=$'\033[31m'
C_GREEN=$'\033[32m'
C_YELLOW=$'\033[33m'
C_CYAN=$'\033[36m'
C_BOLD=$'\033[1m'
C_RESET=$'\033[0m'
else
C_RED=""; C_GREEN=""; C_YELLOW=""; C_CYAN=""; C_BOLD=""; C_RESET=""
fi
# --- Argumente -------------------------------------------------------------
DRY_RUN=false
while [[ $# -gt 0 ]]; do
case "$1" in
-p|--path) BASE_DIR="$2"; shift 2 ;;
-n|--dry-run) DRY_RUN=true; shift ;;
-h|--help)
cat <<EOF
Usage: ${0##*/} [OPTIONEN]
Synchronisiert alle Git-Repositories mit dem Gitea-Server:
- Fehlende Repos werden geklont
- Repos mit Remote-Aenderungen werden gepullt
- Repos mit lokalen Commits werden gepusht
- Repos mit uncommitteten Aenderungen werden markiert
Optionen:
-p, --path DIR anderes Basisverzeichnis statt ~/git-projekte
-n, --dry-run nur anzeigen, nichts aendern
-h, --help diese Hilfe anzeigen
EOF
exit 0
;;
*) echo "Unbekannte Option: $1" >&2; exit 2 ;;
esac
done
mkdir -p "$BASE_DIR"
echo "${C_BOLD}Git-Sync: $BASE_DIR${C_RESET}"
echo
# --- Zaehler ---------------------------------------------------------------
total=0
cloned=0
pulled=0
pushed=0
dirty=0
uptodate=0
failed=0
# --- Repos durchgehen ------------------------------------------------------
for NAME in "${REPO_NAMES[@]}"; do
URL="${GITEA_BASE}/${NAME}.git"
TARGET="$BASE_DIR/$NAME"
((total++))
# 1) Repo fehlt -> klonen
if [ ! -d "$TARGET/.git" ]; then
if [ -d "$TARGET" ]; then
printf "${C_YELLOW}SKIP${C_RESET} %-25s Verzeichnis existiert, kein Git-Repo\n" "$NAME"
((failed++))
continue
fi
if $DRY_RUN; then
printf "${C_CYAN}CLONE${C_RESET} %-25s (dry-run)\n" "$NAME"
else
if git clone --quiet "$URL" "$TARGET" 2>/dev/null; then
printf "${C_CYAN}CLONE${C_RESET} %-25s geklont\n" "$NAME"
((cloned++))
else
printf "${C_RED}FAIL${C_RESET} %-25s Klonen fehlgeschlagen\n" "$NAME"
((failed++))
fi
fi
continue
fi
# Ab hier: Repo existiert
cd "$TARGET" || continue
# Remote fetch
git fetch --quiet 2>/dev/null || true
# 2) Uncommittete Aenderungen?
has_changes=false
if [[ -n "$(git status --porcelain 2>/dev/null)" ]]; then
has_changes=true
fi
# 3) Ahead/Behind
ahead=0
behind=0
upstream_info="$(git rev-list --left-right --count "@{u}...HEAD" 2>/dev/null || true)"
if [[ -n "$upstream_info" ]]; then
read -r behind ahead <<<"$upstream_info"
fi
# 4) Aktionen
did_something=false
# Pull wenn behind
if ((behind > 0)); then
if $has_changes; then
printf "${C_YELLOW}DIRTY${C_RESET} %-25s %d neue Remote-Commits + lokale Aenderungen\n" "$NAME" "$behind"
((dirty++))
if ((ahead > 0)); then
printf " %-25s + %d lokale Commits nicht gepusht\n" "" "$ahead"
fi
continue
fi
if $DRY_RUN; then
printf "${C_GREEN}PULL${C_RESET} %-25s %d Commits (dry-run)\n" "$NAME" "$behind"
else
if git pull --ff-only --quiet 2>/dev/null; then
printf "${C_GREEN}PULL${C_RESET} %-25s %d Commits geholt\n" "$NAME" "$behind"
((pulled++))
else
printf "${C_RED}FAIL${C_RESET} %-25s Pull fehlgeschlagen (evtl. diverged)\n" "$NAME"
((failed++))
continue
fi
fi
did_something=true
fi
# Push wenn ahead
if ((ahead > 0)); then
if $DRY_RUN; then
printf "${C_GREEN}PUSH${C_RESET} %-25s %d Commits (dry-run)\n" "$NAME" "$ahead"
else
if git push --quiet 2>/dev/null; then
printf "${C_GREEN}PUSH${C_RESET} %-25s %d Commits gepusht\n" "$NAME" "$ahead"
((pushed++))
else
printf "${C_RED}FAIL${C_RESET} %-25s Push fehlgeschlagen\n" "$NAME"
((failed++))
fi
fi
did_something=true
fi
if ! $did_something; then
if $has_changes; then
printf "${C_YELLOW}DIRTY${C_RESET} %-25s uncommittete Aenderungen\n" "$NAME"
((dirty++))
else
printf "${C_GREEN}OK${C_RESET} %-25s aktuell\n" "$NAME"
((uptodate++))
fi
fi
done
# --- Zusammenfassung -------------------------------------------------------
echo
echo "${C_BOLD}Gesamt:${C_RESET} $total Repositories"
((cloned > 0)) && echo "${C_CYAN}Geklont:${C_RESET} $cloned"
((pulled > 0)) && echo "${C_GREEN}Gepullt:${C_RESET} $pulled"
((pushed > 0)) && echo "${C_GREEN}Gepusht:${C_RESET} $pushed"
((dirty > 0)) && echo "${C_YELLOW}Dirty:${C_RESET} $dirty"
((failed > 0)) && echo "${C_RED}Fehlgeschlagen:${C_RESET} $failed"
((uptodate > 0)) && echo "${C_GREEN}Aktuell:${C_RESET} $uptodate"
echo