diff --git a/src/libstore/include/nix/store/path-references.hh b/src/libstore/include/nix/store/path-references.hh index 6aa506da4..cfaa76f3b 100644 --- a/src/libstore/include/nix/store/path-references.hh +++ b/src/libstore/include/nix/store/path-references.hh @@ -3,10 +3,12 @@ #include "nix/store/references.hh" #include "nix/store/path.hh" +#include "nix/store/dependency-graph.hh" #include "nix/util/source-accessor.hh" #include #include +#include namespace nix { @@ -59,7 +61,7 @@ void scanForReferencesDeep( SourceAccessor & accessor, const CanonPath & rootPath, const StorePathSet & refs, - std::function callback); + std::function callback); /** * Scan a store path tree and return which references appear in which files. @@ -78,4 +80,25 @@ void scanForReferencesDeep( std::map scanForReferencesDeep(SourceAccessor & accessor, const CanonPath & rootPath, const StorePathSet & refs); +/** + * Build a StorePath-level dependency graph from file scanning. + * + * This scans the given path for references and builds a graph where: + * - Nodes are StorePaths + * - Edges represent dependencies between StorePaths + * - Edge properties store the files that created each dependency + * + * This unified approach allows both cycle detection and why-depends to share + * the same graph-building logic while maintaining file-level information for + * detailed error messages embedded directly in the graph. + * + * @param accessor Source accessor to read the tree + * @param rootPath Root path to scan + * @param rootStorePath The StorePath that rootPath belongs to + * @param refs Set of store paths to search for + * @return StorePathGraphWithFiles where edge properties contain file lists + */ +DependencyGraph buildStorePathGraphFromScan( + SourceAccessor & accessor, const CanonPath & rootPath, const StorePath & rootStorePath, const StorePathSet & refs); + } // namespace nix diff --git a/src/libstore/path-references.cc b/src/libstore/path-references.cc index 3d783bbe4..60cdcfb80 100644 --- a/src/libstore/path-references.cc +++ b/src/libstore/path-references.cc @@ -1,4 +1,5 @@ #include "nix/store/path-references.hh" +#include "nix/store/dependency-graph.hh" #include "nix/util/hash.hh" #include "nix/util/archive.hh" #include "nix/util/source-accessor.hh" @@ -62,7 +63,7 @@ void scanForReferencesDeep( SourceAccessor & accessor, const CanonPath & rootPath, const StorePathSet & refs, - std::function callback) + std::function callback) { // Recursive tree walker auto walk = [&](this auto & self, const CanonPath & path) -> void { @@ -137,11 +138,35 @@ scanForReferencesDeep(SourceAccessor & accessor, const CanonPath & rootPath, con { std::map results; - scanForReferencesDeep(accessor, rootPath, refs, [&](FileRefScanResult result) { - results[std::move(result.filePath)] = std::move(result.foundRefs); + scanForReferencesDeep(accessor, rootPath, refs, [&](const FileRefScanResult & result) { + results[result.filePath] = result.foundRefs; }); return results; } +DependencyGraph buildStorePathGraphFromScan( + SourceAccessor & accessor, const CanonPath & rootPath, const StorePath & rootStorePath, const StorePathSet & refs) +{ + DependencyGraph graph; + + scanForReferencesDeep(accessor, rootPath, refs, [&](const FileRefScanResult & result) { + // All files in this scan belong to rootStorePath + for (const auto & foundRef : result.foundRefs) { + // Add StorePath -> StorePath edge with file metadata + FileListEdgeProperty edgeProp; + edgeProp.files.push_back(result.filePath); + graph.addEdge(rootStorePath, foundRef, std::move(edgeProp)); + + debug( + "buildStorePathGraphFromScan: %s (in %s) → %s", + rootStorePath.to_string(), + result.filePath.abs(), + foundRef.to_string()); + } + }); + + return graph; +} + } // namespace nix