aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake/lockfile.cc
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-06-11 23:34:02 +0200
committerEelco Dolstra <edolstra@gmail.com>2020-06-12 00:52:56 +0200
commit7db879e65e83b1c65206b490d36a69e97c5a877a (patch)
treefecb0d376bbaf8b784b12c1fba3c5a402e1b04e1 /src/libexpr/flake/lockfile.cc
parentd15c20efd5fa1744a4d6835365a0b4d3ceb3432c (diff)
Check 'follows' inputs
Diffstat (limited to 'src/libexpr/flake/lockfile.cc')
-rw-r--r--src/libexpr/flake/lockfile.cc61
1 files changed, 41 insertions, 20 deletions
diff --git a/src/libexpr/flake/lockfile.cc b/src/libexpr/flake/lockfile.cc
index fd5a68825..a74846944 100644
--- a/src/libexpr/flake/lockfile.cc
+++ b/src/libexpr/flake/lockfile.cc
@@ -238,21 +238,29 @@ InputPath parseInputPath(std::string_view s)
return path;
}
-static void flattenLockFile(
- std::shared_ptr<const Node> node,
- const InputPath & prefix,
- std::unordered_set<std::shared_ptr<const Node>> & done,
- std::map<InputPath, Node::Edge> & res)
+std::map<InputPath, Node::Edge> LockFile::getAllInputs() const
{
- if (!done.insert(node).second) return;
-
- for (auto &[id, input] : node->inputs) {
- auto inputPath(prefix);
- inputPath.push_back(id);
- res.emplace(inputPath, input);
- if (auto child = std::get_if<0>(&input))
- flattenLockFile(*child, inputPath, done, res);
- }
+ std::unordered_set<std::shared_ptr<Node>> done;
+ std::map<InputPath, Node::Edge> res;
+
+ std::function<void(const InputPath & prefix, std::shared_ptr<Node> node)> recurse;
+
+ recurse = [&](const InputPath & prefix, std::shared_ptr<Node> node)
+ {
+ if (!done.insert(node).second) return;
+
+ for (auto &[id, input] : node->inputs) {
+ auto inputPath(prefix);
+ inputPath.push_back(id);
+ res.emplace(inputPath, input);
+ if (auto child = std::get_if<0>(&input))
+ recurse(inputPath, *child);
+ }
+ };
+
+ recurse({}, root);
+
+ return res;
}
std::ostream & operator <<(std::ostream & stream, const Node::Edge & edge)
@@ -275,13 +283,10 @@ static bool equals(const Node::Edge & e1, const Node::Edge & e2)
return false;
}
-std::string diffLockFiles(const LockFile & oldLocks, const LockFile & newLocks)
+std::string LockFile::diff(const LockFile & oldLocks, const LockFile & newLocks)
{
- std::unordered_set<std::shared_ptr<const Node>> done;
- std::map<InputPath, Node::Edge> oldFlat, newFlat;
- flattenLockFile(oldLocks.root, {}, done, oldFlat);
- done.clear();
- flattenLockFile(newLocks.root, {}, done, newFlat);
+ auto oldFlat = oldLocks.getAllInputs();
+ auto newFlat = newLocks.getAllInputs();
auto i = oldFlat.begin();
auto j = newFlat.begin();
@@ -309,6 +314,22 @@ std::string diffLockFiles(const LockFile & oldLocks, const LockFile & newLocks)
return res;
}
+void LockFile::check()
+{
+ auto inputs = getAllInputs();
+
+ for (auto & [inputPath, input] : inputs) {
+ if (auto follows = std::get_if<1>(&input)) {
+ if (!follows->empty() && !get(inputs, *follows))
+ throw Error("input '%s' follows a non-existent input '%s'",
+ printInputPath(inputPath),
+ printInputPath(*follows));
+ }
+ }
+}
+
+void check();
+
std::string printInputPath(const InputPath & path)
{
return concatStringsSep("/", path);