aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/eval.cc8
-rw-r--r--src/libstore/misc.cc51
-rw-r--r--src/libutil/topo-sort.hh40
3 files changed, 60 insertions, 39 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 7a2f55504..ecac5d522 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -1256,10 +1256,10 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
try {
lambda.body->eval(*this, env2, v);
} catch (Error & e) {
- addErrorTrace(e, lambda.pos, "while evaluating %s",
- (lambda.name.set()
- ? "'" + (string) lambda.name + "'"
- : "anonymous lambdaction"));
+ addErrorTrace(e, lambda.pos, "while evaluating %s",
+ (lambda.name.set()
+ ? "'" + (string) lambda.name + "'"
+ : "anonymous lambda"));
addErrorTrace(e, pos, "from call site%s", "");
throw;
}
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 7f1b62f26..ddba5d052 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -4,6 +4,7 @@
#include "local-store.hh"
#include "store-api.hh"
#include "thread-pool.hh"
+#include "topo-sort.hh"
namespace nix {
@@ -256,41 +257,21 @@ void Store::queryMissing(const std::vector<StorePathWithOutputs> & targets,
StorePaths Store::topoSortPaths(const StorePathSet & paths)
{
- StorePaths sorted;
- StorePathSet visited, parents;
-
- std::function<void(const StorePath & path, const StorePath * parent)> dfsVisit;
-
- dfsVisit = [&](const StorePath & path, const StorePath * parent) {
- if (parents.count(path))
- throw BuildError("cycle detected in the references of '%s' from '%s'",
- printStorePath(path), printStorePath(*parent));
-
- if (!visited.insert(path).second) return;
- parents.insert(path);
-
- StorePathSet references;
- try {
- references = queryPathInfo(path)->references;
- } catch (InvalidPath &) {
- }
-
- for (auto & i : references)
- /* Don't traverse into paths that don't exist. That can
- happen due to substitutes for non-existent paths. */
- if (i != path && paths.count(i))
- dfsVisit(i, &path);
-
- sorted.push_back(path);
- parents.erase(path);
- };
-
- for (auto & i : paths)
- dfsVisit(i, nullptr);
-
- std::reverse(sorted.begin(), sorted.end());
-
- return sorted;
+ return topoSort(paths,
+ {[&](const StorePath & path) {
+ StorePathSet references;
+ try {
+ references = queryPathInfo(path)->references;
+ } catch (InvalidPath &) {
+ }
+ return references;
+ }},
+ {[&](const StorePath & path, const StorePath & parent) {
+ return BuildError(
+ "cycle detected in the references of '%s' from '%s'",
+ printStorePath(path),
+ printStorePath(parent));
+ }});
}
diff --git a/src/libutil/topo-sort.hh b/src/libutil/topo-sort.hh
new file mode 100644
index 000000000..7a68ff169
--- /dev/null
+++ b/src/libutil/topo-sort.hh
@@ -0,0 +1,40 @@
+#include "error.hh"
+
+namespace nix {
+
+template<typename T>
+std::vector<T> topoSort(std::set<T> items,
+ std::function<std::set<T>(const T &)> getChildren,
+ std::function<Error(const T &, const T &)> makeCycleError)
+{
+ std::vector<T> sorted;
+ std::set<T> visited, parents;
+
+ std::function<void(const T & path, const T * parent)> dfsVisit;
+
+ dfsVisit = [&](const T & path, const T * parent) {
+ if (parents.count(path)) throw makeCycleError(path, *parent);
+
+ if (!visited.insert(path).second) return;
+ parents.insert(path);
+
+ std::set<T> references = getChildren(path);
+
+ for (auto & i : references)
+ /* Don't traverse into items that don't exist in our starting set. */
+ if (i != path && items.count(i))
+ dfsVisit(i, &path);
+
+ sorted.push_back(path);
+ parents.erase(path);
+ };
+
+ for (auto & i : items)
+ dfsVisit(i, nullptr);
+
+ std::reverse(sorted.begin(), sorted.end());
+
+ return sorted;
+}
+
+}