why-depends: initialize internal graph data from std::map<StorePath, StorePathSet>
The Node struct should become an implementation detail when moving this into libstore. A map from a node to its direct references is more intuitive here. Change-Id: I9fddce6b398b8bb97834e5586bee72b244885fdd
This commit is contained in:
+61
-41
@@ -7,6 +7,7 @@
|
||||
#include "lix/libutil/result.hh"
|
||||
#include "why-depends.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
|
||||
namespace nix {
|
||||
@@ -229,6 +230,61 @@ try {
|
||||
co_return result::current_exception();
|
||||
}
|
||||
|
||||
static std::map<StorePath, Node> mkGraph(
|
||||
const StorePath & packagePath,
|
||||
const StorePath & dependencyPath,
|
||||
const std::map<StorePath, StorePathSet> & graph,
|
||||
Store & store,
|
||||
bool all,
|
||||
bool precise
|
||||
)
|
||||
{
|
||||
std::map<StorePath, Node> graph_data;
|
||||
for (auto & [path, dependencies] : graph) {
|
||||
graph_data.emplace(
|
||||
path,
|
||||
Node{
|
||||
.path = path,
|
||||
.dependencies = dependencies,
|
||||
.dist = path == dependencyPath ? std::optional(0) : std::nullopt,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
for (auto & node : graph_data) {
|
||||
for (auto & ref : node.second.dependencies) {
|
||||
graph_data.find(ref)->second.dependents.insert(node.first);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run Dijkstra's shortest path algorithm to get the distance
|
||||
of every path in the closure to 'dependency'. */
|
||||
std::priority_queue<Node *> queue;
|
||||
|
||||
queue.push(&graph_data.at(dependencyPath));
|
||||
auto const inf = std::numeric_limits<size_t>::max();
|
||||
|
||||
while (!queue.empty()) {
|
||||
auto & node = *queue.top();
|
||||
queue.pop();
|
||||
|
||||
for (auto & rref : node.dependents) {
|
||||
auto & node2 = graph_data.at(rref);
|
||||
auto dist = node.dist.transform([](auto n) { return n + 1; });
|
||||
if (dist.value_or(inf) < node2.dist.value_or(inf)) {
|
||||
node2.dist = dist;
|
||||
node2.prev = &node;
|
||||
if (!node2.queued) {
|
||||
node2.queued = true;
|
||||
queue.push(&node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph_data;
|
||||
}
|
||||
|
||||
struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||
{
|
||||
std::string _package, _dependency;
|
||||
@@ -316,49 +372,13 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||
|
||||
auto accessor = store->getFSAccessor();
|
||||
|
||||
std::map<StorePath, Node> graph;
|
||||
|
||||
for (auto & path : closure)
|
||||
graph.emplace(
|
||||
path,
|
||||
Node{
|
||||
.path = path,
|
||||
.dependencies = aio().blockOn(store->queryPathInfo(path))->references,
|
||||
.dist = path == dependencyPath ? std::optional(0) : std::nullopt
|
||||
}
|
||||
);
|
||||
|
||||
// Transpose the graph.
|
||||
for (auto & node : graph)
|
||||
for (auto & ref : node.second.dependencies) {
|
||||
graph.find(ref)->second.dependents.insert(node.first);
|
||||
}
|
||||
|
||||
/* Run Dijkstra's shortest path algorithm to get the distance
|
||||
of every path in the closure to 'dependency'. */
|
||||
std::priority_queue<Node *> queue;
|
||||
|
||||
queue.push(&graph.at(dependencyPath));
|
||||
auto const inf = std::numeric_limits<size_t>::max();
|
||||
|
||||
while (!queue.empty()) {
|
||||
auto & node = *queue.top();
|
||||
queue.pop();
|
||||
|
||||
for (auto & rref : node.dependents) {
|
||||
auto & node2 = graph.at(rref);
|
||||
auto dist = node.dist.transform([](auto n) { return n + 1; });
|
||||
if (dist.value_or(inf) < node2.dist.value_or(inf)) {
|
||||
node2.dist = dist;
|
||||
node2.prev = &node;
|
||||
if (!node2.queued) {
|
||||
node2.queued = true;
|
||||
queue.push(&node2);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::map<StorePath, StorePathSet> graphData;
|
||||
for (auto & path : closure) {
|
||||
graphData.emplace(path, aio().blockOn(store->queryPathInfo(path))->references);
|
||||
}
|
||||
|
||||
auto graph = mkGraph(packagePath, dependencyPath, graphData, *store, all, precise);
|
||||
|
||||
/* Print the subgraph of nodes that have 'dependency' in their
|
||||
closure (i.e., that have a non-infinite distance to
|
||||
'dependency'). Print every edge on a path between `package`
|
||||
|
||||
Reference in New Issue
Block a user