No description
Find a file
Pandi bc633d2ae0 feat(discover): find the repos instead of maintaining a list of them
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.
2026-11-01 09:17:44 +01:00
src feat(discover): find the repos instead of maintaining a list of them 2026-11-01 09:17:44 +01:00
tests Add bundle-backup: verified git bundles per repo, optional Nextcloud upload 2026-10-30 18:46:58 +01:00
.gitignore Add bundle-backup: verified git bundles per repo, optional Nextcloud upload 2026-10-30 18:46:58 +01:00
Cargo.lock Add bundle-backup: verified git bundles per repo, optional Nextcloud upload 2026-10-30 18:46:58 +01:00
Cargo.toml Add bundle-backup: verified git bundles per repo, optional Nextcloud upload 2026-10-30 18:46:58 +01:00
README.md feat(discover): find the repos instead of maintaining a list of them 2026-11-01 09:17:44 +01:00

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-datei hat 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.
  • --all bundelt alle Refs inkl. Tags und Remote-Refs, keine History-Kürzung.
  • Upload zählt als Teil des Repo-Ergebnisses: schlägt nc-put fehl, ist das Repo failed und der Exit-Code 1. Das lokale Bundle bleibt gültig.
  • NC_BASE_URL setzt 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-Datei
  • sizes_are_human_readable, remote_join_avoids_double_slash
  • discovers_both_levels_and_ignores_plain_dirs — a/.git und b/c/.git werden gefunden, ein Ordner ohne .git nicht
  • oversized_git_is_skipped_with_reason — .git mit 256 MiB+1 (sparse via set_len) landet in skipped, mit Grund
  • discovery_order_is_sorted_and_repeatable — zwei Läufe liefern dieselbe sortierte Reihenfolge
  • two_repos_become_two_verified_bundles — zwei Wegwerf-Repos in TMPDIR, zwei Bundles, git bundle verify bestätigt sie im Test, Exit 0
  • non_repo_is_skipped_and_exit_stays_zero — Nicht-Repo wird skip, Exit 0
  • missing_repo_dir_fails_with_exit_one — fehlender Ordner wird failed, Exit 1

Kein Test deckt den Upload-Pfad ab (braucht Netz und Credentials); der echte Lauf ist die Prüfung.