#!/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 <&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