aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-02-02 13:14:34 +0100
committerEelco Dolstra <edolstra@gmail.com>2020-02-02 13:14:34 +0100
commitaf35b318f3312ba8147fe2d44eef71ad7924939e (patch)
tree9d5510a1e0f4d301d0c710f1d821d550ce4920fa /src
parenta9ebc3ea5db2fb0cbf7ab8ea35c9d9d5073abfc8 (diff)
Detect circular flake imports
Fixes #2997.
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/flake/flake.cc11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 8b92da2c3..e3fb02591 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -4,6 +4,7 @@
#include "eval-inline.hh"
#include "store-api.hh"
#include "fetchers/fetchers.hh"
+#include "finally.hh"
#include <iostream>
#include <ctime>
@@ -387,6 +388,8 @@ LockedFlake lockFlake(
const InputPath & inputPathPrefix)>
updateLocks;
+ std::vector<FlakeRef> parents;
+
updateLocks = [&](
const FlakeInputs & flakeInputs,
const LockedInputs & oldLocks,
@@ -506,6 +509,14 @@ LockedFlake lockFlake(
flake. Also, unless we already have this
flake in the top-level lock file, use this
flake's own lock file. */
+
+ /* Guard against circular flake imports. */
+ for (auto & parent : parents)
+ if (parent == input.ref)
+ throw Error("found circular import of flake '%s'", parent);
+ parents.push_back(input.ref);
+ Finally cleanup([&]() { parents.pop_back(); });
+
updateLocks(inputFlake.inputs,
oldLock != oldLocks.inputs.end()
? (const LockedInputs &) oldLock->second