mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
refactor(libstore/find-cycles): use SourceAccessor for filesystem access
Replace direct `std::filesystem` operations with `SourceAccessor`..
This commit is contained in:
parent
7a7b9fdf1c
commit
a9aaf0ed1d
2 changed files with 41 additions and 50 deletions
|
|
@ -1,10 +1,7 @@
|
|||
#include "nix/store/build/find-cycles.hh"
|
||||
|
||||
#include "nix/store/store-api.hh"
|
||||
#include "nix/util/file-system.hh"
|
||||
#ifdef __APPLE__
|
||||
# include "nix/util/archive.hh" // For caseHackSuffix
|
||||
#endif
|
||||
#include "nix/util/source-accessor.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
|
|
@ -72,8 +69,9 @@ void scanForCycleEdges(const Path & path, const StorePathSet & refs, StoreCycleE
|
|||
// Create sink that reuses RefScanSink's hash-finding logic
|
||||
CycleEdgeScanSink sink(std::move(hashes), storePrefix);
|
||||
|
||||
// Walk the filesystem and scan files using the sink
|
||||
walkAndScanPath(std::filesystem::path(path), sink);
|
||||
// Get filesystem accessor and walk the tree
|
||||
auto accessor = getFSSourceAccessor();
|
||||
walkAndScanPath(*accessor, CanonPath(path), path, sink);
|
||||
|
||||
// Extract the found edges
|
||||
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.
|
||||
* 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
|
||||
// The sink (RefScanSink) handles all hash detection and buffer management
|
||||
sink.setCurrentPath(path.string());
|
||||
sink.setCurrentPath(displayPath);
|
||||
accessor.readFile(path, sink);
|
||||
break;
|
||||
}
|
||||
|
||||
// Use Nix's portable readFile that streams into a sink
|
||||
// This handles all file I/O portably across platforms
|
||||
readFile(path.string(), sink);
|
||||
} else if (std::filesystem::is_directory(status)) {
|
||||
case SourceAccessor::tDirectory: {
|
||||
// Handle directories - recursively scan contents
|
||||
std::map<std::string, std::string> unhacked;
|
||||
|
||||
for (DirectoryIterator i(path); i != DirectoryIterator(); ++i) {
|
||||
std::string entryName = i->path().filename().string();
|
||||
|
||||
#ifdef __APPLE__
|
||||
// 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()) {
|
||||
throw Error(
|
||||
"file name collision between '%1%' and '%2%'",
|
||||
(path / unhacked[name]).string(),
|
||||
(path / entryName).string());
|
||||
}
|
||||
unhacked[name] = entryName;
|
||||
#else
|
||||
unhacked[entryName] = entryName;
|
||||
#endif
|
||||
auto entries = accessor.readDirectory(path);
|
||||
for (const auto & [name, entryType] : entries) {
|
||||
auto childPath = path / name;
|
||||
auto childDisplayPath = displayPath + "/" + name;
|
||||
debug("walkAndScanPath: recursing into %s", childDisplayPath);
|
||||
walkAndScanPath(accessor, childPath, childDisplayPath, sink);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto & [name, actualName] : unhacked) {
|
||||
debug("walkAndScanPath: recursing into %s/%s", path.string(), actualName);
|
||||
walkAndScanPath(path / actualName, sink);
|
||||
}
|
||||
} else if (std::filesystem::is_symlink(status)) {
|
||||
case SourceAccessor::tSymlink: {
|
||||
// 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));
|
||||
} else {
|
||||
throw Error("file '%1%' has an unsupported type", path);
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 existing RefScanSink infrastructure for robustness.
|
||||
*
|
||||
* @param accessor Source accessor for reading files
|
||||
* @param path Current path being scanned
|
||||
* @param displayPath Physical path for error messages
|
||||
* @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).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue