diff --git a/src/persist.cpp b/src/persist.cpp index 5f7055e..0d24c2c 100644 --- a/src/persist.cpp +++ b/src/persist.cpp @@ -281,18 +281,23 @@ PruneReport ReaSamplerSession::pruneDryRun() const { // and the manifest. Non-recursive: the bank folder is flat (capture writes files // directly here); skip any subdirectory. Size is stat'd here and cached by relative // path so the report's byte tally reuses the same on-disk read. + // Manual iterator form (it.increment(ec)) keeps the loop non-throwing: a mid-iteration + // failure (file removed, permission flip) breaks out with a best-effort partial list + // rather than propagating std::filesystem_error across REAPER's C ABI. std::vector present; std::unordered_map sizeByRel; - for (const auto& entry : fs::directory_iterator(bankDir, ec)) { - if (ec) break; - std::error_code fec; - if (!entry.is_regular_file(fec)) continue; // skip subdirs / specials + fs::directory_iterator it(bankDir, ec); + for (; !ec && it != fs::directory_iterator{}; it.increment(ec)) { + const auto& entry = *it; + std::error_code reg_ec; + if (!entry.is_regular_file(reg_ec)) continue; // skip subdirs / specials const std::string name = entry.path().filename().string(); const std::string rel = bankRelativeForName(name); if (rel.empty()) continue; present.push_back(rel); - const std::uintmax_t sz = entry.file_size(fec); - sizeByRel[rel] = fec ? 0 : static_cast(sz); + std::error_code sz_ec; + const std::uintmax_t sz = entry.file_size(sz_ec); + sizeByRel[rel] = sz_ec ? 0 : static_cast(sz); } // The decision lives in the pure core — read-only inputs from the session's book and