1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 20:16:03 +01:00

refactor(libstore/find-cycles): use SourceAccessor for filesystem access

Replace direct `std::filesystem` operations with `SourceAccessor`..
This commit is contained in:
Bernardo Meurer Costa 2025-10-12 00:40:13 +00:00
parent 7a7b9fdf1c
commit a9aaf0ed1d
No known key found for this signature in database
2 changed files with 41 additions and 50 deletions

View file

@ -1,10 +1,7 @@
#include "nix/store/build/find-cycles.hh" #include "nix/store/build/find-cycles.hh"
#include "nix/store/store-api.hh" #include "nix/store/store-api.hh"
#include "nix/util/file-system.hh" #include "nix/util/source-accessor.hh"
#ifdef __APPLE__
# include "nix/util/archive.hh" // For caseHackSuffix
#endif
#include <algorithm> #include <algorithm>
#include <filesystem> #include <filesystem>
@ -72,8 +69,9 @@ void scanForCycleEdges(const Path & path, const StorePathSet & refs, StoreCycleE
// Create sink that reuses RefScanSink's hash-finding logic // Create sink that reuses RefScanSink's hash-finding logic
CycleEdgeScanSink sink(std::move(hashes), storePrefix); CycleEdgeScanSink sink(std::move(hashes), storePrefix);
// Walk the filesystem and scan files using the sink // Get filesystem accessor and walk the tree
walkAndScanPath(std::filesystem::path(path), sink); auto accessor = getFSSourceAccessor();
walkAndScanPath(*accessor, CanonPath(path), path, sink);
// Extract the found edges // Extract the found edges
edges = sink.getEdges(); edges = sink.getEdges();
@ -83,61 +81,51 @@ void scanForCycleEdges(const Path & path, const StorePathSet & refs, StoreCycleE
* Recursively walk filesystem and stream files into the sink. * Recursively walk filesystem and stream files into the sink.
* This reuses RefScanSink's hash-finding logic instead of reimplementing it. * This reuses RefScanSink's hash-finding logic instead of reimplementing it.
*/ */
void walkAndScanPath(const std::filesystem::path & path, CycleEdgeScanSink & sink) void walkAndScanPath(
SourceAccessor & accessor, const CanonPath & path, const std::string & displayPath, CycleEdgeScanSink & sink)
{ {
auto status = std::filesystem::symlink_status(path); auto stat = accessor.lstat(path);
debug("walkAndScanPath: scanning path = %s", path.string()); debug("walkAndScanPath: scanning path = %s", displayPath);
if (std::filesystem::is_regular_file(status)) { switch (stat.type) {
case SourceAccessor::tRegular: {
// Handle regular files - stream contents into sink // Handle regular files - stream contents into sink
// The sink (RefScanSink) handles all hash detection and buffer management sink.setCurrentPath(displayPath);
sink.setCurrentPath(path.string()); accessor.readFile(path, sink);
break;
}
// Use Nix's portable readFile that streams into a sink case SourceAccessor::tDirectory: {
// This handles all file I/O portably across platforms
readFile(path.string(), sink);
} else if (std::filesystem::is_directory(status)) {
// Handle directories - recursively scan contents // Handle directories - recursively scan contents
std::map<std::string, std::string> unhacked; auto entries = accessor.readDirectory(path);
for (const auto & [name, entryType] : entries) {
for (DirectoryIterator i(path); i != DirectoryIterator(); ++i) { auto childPath = path / name;
std::string entryName = i->path().filename().string(); auto childDisplayPath = displayPath + "/" + name;
debug("walkAndScanPath: recursing into %s", childDisplayPath);
#ifdef __APPLE__ walkAndScanPath(accessor, childPath, childDisplayPath, sink);
// Handle case-insensitive filesystems on macOS
std::string name(entryName);
size_t pos = entryName.find(caseHackSuffix);
if (pos != std::string::npos) {
debug("removing case hack suffix from '%s'", (path / entryName).string());
name.erase(pos);
} }
if (unhacked.find(name) != unhacked.end()) { break;
throw Error(
"file name collision between '%1%' and '%2%'",
(path / unhacked[name]).string(),
(path / entryName).string());
}
unhacked[name] = entryName;
#else
unhacked[entryName] = entryName;
#endif
} }
for (auto & [name, actualName] : unhacked) { case SourceAccessor::tSymlink: {
debug("walkAndScanPath: recursing into %s/%s", path.string(), actualName);
walkAndScanPath(path / actualName, sink);
}
} else if (std::filesystem::is_symlink(status)) {
// Handle symlinks - stream link target into sink // Handle symlinks - stream link target into sink
auto linkTarget = std::filesystem::read_symlink(path).string(); auto linkTarget = accessor.readLink(path);
debug("walkAndScanPath: scanning symlink %s -> %s", path.string(), linkTarget); debug("walkAndScanPath: scanning symlink %s -> %s", displayPath, linkTarget);
sink.setCurrentPath(path.string()); sink.setCurrentPath(displayPath);
sink(std::string_view(linkTarget)); sink(std::string_view(linkTarget));
} else { break;
throw Error("file '%1%' has an unsupported type", path); }
case SourceAccessor::tChar:
case SourceAccessor::tBlock:
case SourceAccessor::tSocket:
case SourceAccessor::tFifo:
case SourceAccessor::tUnknown:
default:
throw Error("file '%1%' has an unsupported type", displayPath);
} }
} }

View file

@ -83,10 +83,13 @@ void scanForCycleEdges(const Path & path, const StorePathSet & refs, StoreCycleE
* the provided sink which performs the actual hash detection. This reuses * the provided sink which performs the actual hash detection. This reuses
* the existing RefScanSink infrastructure for robustness. * the existing RefScanSink infrastructure for robustness.
* *
* @param accessor Source accessor for reading files
* @param path Current path being scanned * @param path Current path being scanned
* @param displayPath Physical path for error messages
* @param sink The CycleEdgeScanSink that will detect and record hash references * @param sink The CycleEdgeScanSink that will detect and record hash references
*/ */
void walkAndScanPath(const std::filesystem::path & path, CycleEdgeScanSink & sink); void walkAndScanPath(
SourceAccessor & accessor, const CanonPath & path, const std::string & displayPath, CycleEdgeScanSink & sink);
/** /**
* Transform individual edges into connected multi-edges (paths). * Transform individual edges into connected multi-edges (paths).