- Rust 100%
The hardcoded DEFAULT_REPOS covered 17 repos while 23 live on disk: voice-stack, this crate, stundenplan-widget, ableitungen-quiz and gnome-sudoku-web were never backed up, and every new project would have repeated that. Repos are now discovered under /home/pandi/coding (two levels, .git must be a directory, symlinked project folders followed — five of them point at $HOME). A repo whose .git exceeds 256 MiB is skipped with a visible reason: sml's 1.1 GiB would fail the Nextcloud limit and turn the whole run red. Real run: 22 repos bundled, verified and uploaded, 69.1 MiB; sml skipped. |
||
|---|---|---|
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
bundle-backup
Ein git bundle --all pro lokalem Repo, per git bundle verify geprüft,
optional per nc-put nach Nextcloud geladen. Für Hosts ohne Push-Remote ist
das die einzige Kopie der lokalen Commits.
Bauen
cargo build --release
install -m 755 target/release/bundle-backup /home/pandi/bin/bundle-backup
Keine Dependencies. git, nc-put und date müssen im PATH liegen.
Benutzen
export NC_BASE_URL=https://<host>/remote.php/dav/files/<user>/
bundle-backup # Discovery unter /home/pandi/coding, mit Upload
bundle-backup --no-upload # nur lokal nach /home/pandi/backups/git
bundle-backup --dry-run # nur zeigen, was passieren würde
bundle-backup --repos-datei meine-repos.txt --remote-dir hermes-backups/git/2026-10-30
Ohne --repos-datei wird /home/pandi/coding zwei Ebenen tief durchsucht
(coding/*/.git und coding/*/*/.git, Symlinks auf Projektordner werden
verfolgt). Repos, deren .git größer als 256 MiB ist, werden übersprungen —
ein Bundle davon scheitert am Nextcloud-Limit und macht den Lauf rot.
Optionen: --repos-datei PFAD, --out-dir DIR, --remote-dir PFAD,
--no-upload, --dry-run.
Eine Zeile pro Repo:
ok DarkOaktyl 33.0 MiB 2.1s hochgeladen
skip irgendwas kein Git-Repo
skip sml (zu groß: 1.1 GiB)
failed weg Pfad existiert nicht: /tmp/weg
Am Ende: 22 Repos gefunden, 1 übersprungen.
Exit 0 = alles ok, 1 = mindestens ein Repo fehlgeschlagen, 2 = Aufruffehler.
Repos-Datei: eine Zeile pro Pfad, Leerzeilen und #-Kommentare erlaubt,
führendes ~/ wird gegen $HOME expandiert.
Abweichungen / Entscheidungen
- Kein Prune. Alte Bundles bleiben liegen; Aufräumen ist Handarbeit.
- Repo-Liste per Discovery, nicht gepflegt: alles unter
/home/pandi/coding, zwei Ebenen tief, mit.git-Verzeichnis. Neue Projekte werden ohne Codeänderung gesichert.--repos-dateihat Vorrang. - Größenwächter
MAX_REPO_BYTES= 256 MiB.git: darüber wird übersprungen und mit Grund gemeldet (sml, 1,2 GB). Ceiling: ein einzelnes Repo über dem Nextcloud-Limit könnte nur per Shallow-Bundle oder Git-LFS gesichert werden. - Sequenziell. 22 Repos, davon eines mit ~27 MB
.git— Parallelität wäre mehr Code für ein paar Sekunden. Nachrüsten, wenn der Lauf zu lang wird. --allbundelt alle Refs inkl. Tags und Remote-Refs, keine History-Kürzung.- Upload zählt als Teil des Repo-Ergebnisses: schlägt
nc-putfehl, ist das Repofailedund der Exit-Code 1. Das lokale Bundle bleibt gültig. NC_BASE_URLsetzt der Aufrufer; das Tool kennt weder Host noch Zugangsdaten.- Kein Git-Protokoll selbst implementiert, kein Netz im Tool ausser via
nc-put.
Tests
cargo test
parses_comments_blanks_and_tilde,empty_file_yields_nothing— Parser der Repos-Dateisizes_are_human_readable,remote_join_avoids_double_slashdiscovers_both_levels_and_ignores_plain_dirs—a/.gitundb/c/.gitwerden gefunden, ein Ordner ohne.gitnichtoversized_git_is_skipped_with_reason—.gitmit 256 MiB+1 (sparse viaset_len) landet inskipped, mit Grunddiscovery_order_is_sorted_and_repeatable— zwei Läufe liefern dieselbe sortierte Reihenfolgetwo_repos_become_two_verified_bundles— zwei Wegwerf-Repos inTMPDIR, zwei Bundles,git bundle verifybestätigt sie im Test, Exit 0non_repo_is_skipped_and_exit_stays_zero— Nicht-Repo wirdskip, Exit 0missing_repo_dir_fails_with_exit_one— fehlender Ordner wirdfailed, Exit 1
Kein Test deckt den Upload-Pfad ab (braucht Netz und Credentials); der echte Lauf ist die Prüfung.