v0.12.8: complete cross-drive backup + per-tier UI

- Cross-drive now copies DB dumps (_db/) and config (_config/) alongside user data
- restic cross-drive includes config dir + full DB dump dir
- UI: per-tier rows (1. mentés / 2. mentés) instead of per-layer (DB/Konfig/Data)
- UI: BackupContents label shows what each tier protects (DB + Konfig + Adatok)
- UI: rsync backups show browsable indicator (📁)
- Cleanup: removed unused filterSnapshotsByPaths + pathCovers from router.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-18 11:37:48 +01:00
parent b65ab612f0
commit 4a9aea647b
7 changed files with 274 additions and 173 deletions
-27
View File
@@ -469,33 +469,6 @@ func (r *Router) backupSnapshots(w http.ResponseWriter, req *http.Request) {
writeJSON(w, http.StatusOK, apiResponse{OK: true, Data: snapshots})
}
// filterSnapshotsByPaths returns only snapshots whose Paths overlap with requiredPaths.
// A snapshot matches if any of its paths is a prefix of (or prefixed by) any required path.
// M10: Uses separator-aware prefix check to prevent /mnt/hdd_1 matching /mnt/hdd_10/data.
func filterSnapshotsByPaths(snapshots []backup.SnapshotInfo, requiredPaths []string) []backup.SnapshotInfo {
var filtered []backup.SnapshotInfo
outer:
for _, snap := range snapshots {
for _, required := range requiredPaths {
for _, sp := range snap.Paths {
if pathCovers(required, sp) || pathCovers(sp, required) {
filtered = append(filtered, snap)
continue outer
}
}
}
}
return filtered
}
// pathCovers returns true if base is equal to or a directory-prefix of target.
func pathCovers(base, target string) bool {
if base == target {
return true
}
return strings.HasPrefix(target, strings.TrimRight(base, "/")+"/")
}
// --- Metrics handlers ---
func (r *Router) metricsSystem(w http.ResponseWriter, req *http.Request) {