fix: use NAS directory filenames for already-safe matching when manifest is sparse

When Kisani's manifest has 0–1 entries but the NAS directory contains thousands of
files uploaded by other tools, reconcile previously showed Already Safe = 1 because
countSafe only matched against the tiny manifest.

The validity check in buildManifestIndex now:
- Stores the filtered NAS filenames in NASManifestCache (directoryFilenames field)
- Returns a ManifestIndex(nasListing:) for filename-based matching against all NAS files

The fast-path reconcile now:
- Detects a sparse manifest (entries ≤ 1, dirCount > 1)
- Rebuilds ManifestIndex(nasFilenames:) from the cached filenames for O(1) filename matching
- Falls back to full NAS reconcile if cached filenames aren't available yet

Adds ManifestIndex.init(nasFilenames:) for fast-path reconstruction from cached strings.

Co-Authored-By: Kutesir <kutesir@provoc.ug>
Co-Authored-By: Sentry <sentry@provoc.ug>
This commit is contained in:
Robin Kutesa
2026-05-18 21:07:00 +03:00
parent 809929e0ed
commit 2384a74517
4 changed files with 68 additions and 15 deletions

View File

@@ -75,6 +75,16 @@ struct ManifestIndex: Sendable {
self.totalCount = overrideTotalCount
}
// Rebuild from cached NAS filenames (fast-path for sparse-manifest reconcile).
// Filenames are expected to already be filtered (no dirs, no hidden, no manifest file).
init(nasFilenames filenames: [String]) {
let names = Set(filenames.map { $0.lowercased() })
self.localIdentifiers = []
self.lowercasedFilenames = names
self.unclaimedFilenames = names
self.totalCount = names.count
}
// Build from NAS directory listing (bootstrap no localIdentifiers known)
init(nasListing items: [NASItem]) {
var names = Set<String>()