aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake/flake.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/flake/flake.cc')
-rw-r--r--src/libexpr/flake/flake.cc129
1 files changed, 44 insertions, 85 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 249ceba6c..c58b0eea9 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -293,52 +293,6 @@ Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup
return getFlake(state, originalRef, {}, allowLookup, flakeCache);
}
-static void flattenLockFile(
- const LockedInputs & inputs,
- const InputPath & prefix,
- std::map<InputPath, const LockedInput *> & res)
-{
- for (auto &[id, input] : inputs.inputs) {
- auto inputPath(prefix);
- inputPath.push_back(id);
- res.emplace(inputPath, &input);
- flattenLockFile(input, inputPath, res);
- }
-}
-
-static std::string diffLockFiles(const LockedInputs & oldLocks, const LockedInputs & newLocks)
-{
- std::map<InputPath, const LockedInput *> oldFlat, newFlat;
- flattenLockFile(oldLocks, {}, oldFlat);
- flattenLockFile(newLocks, {}, newFlat);
-
- auto i = oldFlat.begin();
- auto j = newFlat.begin();
- std::string res;
-
- while (i != oldFlat.end() || j != newFlat.end()) {
- if (j != newFlat.end() && (i == oldFlat.end() || i->first > j->first)) {
- res += fmt("* Added '%s': '%s'\n", concatStringsSep("/", j->first), j->second->lockedRef);
- ++j;
- } else if (i != oldFlat.end() && (j == newFlat.end() || i->first < j->first)) {
- res += fmt("* Removed '%s'\n", concatStringsSep("/", i->first));
- ++i;
- } else {
- if (!(i->second->lockedRef == j->second->lockedRef)) {
- assert(i->second->lockedRef.to_string() != j->second->lockedRef.to_string());
- res += fmt("* Updated '%s': '%s' -> '%s'\n",
- concatStringsSep("/", i->first),
- i->second->lockedRef,
- j->second->lockedRef);
- }
- ++i;
- ++j;
- }
- }
-
- return res;
-}
-
/* Compute an in-memory lock file for the specified top-level flake,
and optionally write it to file, it the flake is writable. */
LockedFlake lockFlake(
@@ -380,8 +334,8 @@ LockedFlake lockFlake(
/* Recurse into the flake inputs. */
std::function<void(
const FlakeInputs & flakeInputs,
- const LockedInputs & oldLocks,
- LockedInputs & newLocks,
+ std::shared_ptr<const Node> oldLocks,
+ std::shared_ptr<Node> newLocks,
const InputPath & inputPathPrefix)>
updateLocks;
@@ -389,8 +343,8 @@ LockedFlake lockFlake(
updateLocks = [&](
const FlakeInputs & flakeInputs,
- const LockedInputs & oldLocks,
- LockedInputs & newLocks,
+ std::shared_ptr<const Node> oldLocks,
+ std::shared_ptr<Node> newLocks,
const InputPath & inputPathPrefix)
{
/* Get the overrides (i.e. attributes of the form
@@ -428,14 +382,16 @@ LockedFlake lockFlake(
input of the dwarffs input of the root flake),
but if it's from an override, it's relative to
the *root* of the lock file. */
- auto follows = (hasOverride ? newLockFile : newLocks).findInput(*input.follows);
+ auto follows = (hasOverride ? newLockFile.root : newLocks)->findInput(*input.follows);
if (follows)
- newLocks.inputs.insert_or_assign(id, **follows);
+ newLocks->inputs.insert_or_assign(id, follows);
else
/* We haven't processed the source of the
"follows" yet (e.g. "dwarffs/nixpkgs"). So
we'll need another round of the fixpoint
iteration. */
+ // FIXME: now that LockFile is a graph, we
+ // could pre-create the missing node.
unresolved.push_back(inputPath);
continue;
}
@@ -443,16 +399,25 @@ LockedFlake lockFlake(
/* Do we have an entry in the existing lock file? And
we don't have a --update-input flag for this
input? */
- auto oldLock =
+ auto oldLockIt =
lockFlags.inputUpdates.count(inputPath)
- ? oldLocks.inputs.end()
- : oldLocks.inputs.find(id);
+ ? oldLocks->inputs.end()
+ : oldLocks->inputs.find(id);
+
+ std::shared_ptr<const LockedNode> oldLock;
+ if (oldLockIt != oldLocks->inputs.end()) {
+ oldLock = std::dynamic_pointer_cast<const LockedNode>(oldLockIt->second);
+ assert(oldLock);
+ }
- if (oldLock != oldLocks.inputs.end() && oldLock->second.originalRef == input.ref && !hasOverride) {
+ if (oldLock
+ && oldLock->originalRef == input.ref
+ && !hasOverride)
+ {
/* Copy the input from the old lock file if its
flakeref didn't change and there is no override
from a higher level flake. */
- newLocks.inputs.insert_or_assign(id, oldLock->second);
+ newLocks->inputs.insert_or_assign(id, std::make_shared<LockedNode>(*oldLock));
/* If we have an --update-input flag for an input
of this input, then we must fetch the flake to
@@ -466,11 +431,11 @@ LockedFlake lockFlake(
if (hasChildUpdate) {
auto inputFlake = getFlake(
- state, oldLock->second.lockedRef, oldLock->second.info, false, flakeCache);
+ state, oldLock->lockedRef, oldLock->info, false, flakeCache);
updateLocks(inputFlake.inputs,
- (const LockedInputs &) oldLock->second,
- newLocks.inputs.find(id)->second,
+ oldLock,
+ newLocks->inputs.find(id)->second,
inputPath);
} else {
@@ -480,12 +445,14 @@ LockedFlake lockFlake(
check those. */
FlakeInputs fakeInputs;
- for (auto & i : oldLock->second.inputs)
- fakeInputs.emplace(i.first, FlakeInput { .ref = i.second.originalRef });
+ for (auto & i : oldLock->inputs)
+ fakeInputs.emplace(i.first, FlakeInput {
+ .ref = std::dynamic_pointer_cast<LockedNode>(i.second)->originalRef
+ });
updateLocks(fakeInputs,
- oldLock->second,
- newLocks.inputs.find(id)->second,
+ oldLock,
+ newLocks->inputs.find(id)->second,
inputPath);
}
@@ -499,8 +466,8 @@ LockedFlake lockFlake(
if (input.isFlake) {
auto inputFlake = getFlake(state, input.ref, {}, lockFlags.useRegistries, flakeCache);
- newLocks.inputs.insert_or_assign(id,
- LockedInput(inputFlake.lockedRef, inputFlake.originalRef, inputFlake.sourceInfo->info));
+ newLocks->inputs.insert_or_assign(id,
+ std::make_shared<LockedNode>(inputFlake.lockedRef, inputFlake.originalRef, inputFlake.sourceInfo->info));
/* Recursively process the inputs of this
flake. Also, unless we already have this
@@ -515,25 +482,25 @@ LockedFlake lockFlake(
Finally cleanup([&]() { parents.pop_back(); });
updateLocks(inputFlake.inputs,
- oldLock != oldLocks.inputs.end()
- ? (const LockedInputs &) oldLock->second
+ oldLock
+ ? std::dynamic_pointer_cast<const Node>(oldLock)
: LockFile::read(
- inputFlake.sourceInfo->actualPath + "/" + inputFlake.lockedRef.subdir + "/flake.lock"),
- newLocks.inputs.find(id)->second,
+ inputFlake.sourceInfo->actualPath + "/" + inputFlake.lockedRef.subdir + "/flake.lock").root,
+ newLocks->inputs.find(id)->second,
inputPath);
}
else {
auto [sourceInfo, lockedRef] = fetchOrSubstituteTree(
state, input.ref, {}, lockFlags.useRegistries, flakeCache);
- newLocks.inputs.insert_or_assign(id,
- LockedInput(lockedRef, input.ref, sourceInfo.info, false));
+ newLocks->inputs.insert_or_assign(id,
+ std::make_shared<LockedNode>(lockedRef, input.ref, sourceInfo.info, false));
}
}
}
};
- updateLocks(flake.inputs, oldLockFile, newLockFile, {});
+ updateLocks(flake.inputs, oldLockFile.root, newLockFile.root, {});
/* Check if there is a cycle in the "follows" inputs. */
if (!unresolved.empty() && unresolved == prevUnresolved) {
@@ -619,8 +586,7 @@ LockedFlake lockFlake(
}
void callFlake(EvalState & state,
- const Flake & flake,
- const LockedInputs & lockedInputs,
+ const LockedFlake & lockedFlake,
Value & vRes)
{
auto vLocks = state.allocValue();
@@ -629,11 +595,11 @@ void callFlake(EvalState & state,
auto vTmp1 = state.allocValue();
auto vTmp2 = state.allocValue();
- mkString(*vLocks, lockedInputs.to_string());
+ mkString(*vLocks, lockedFlake.lockFile.to_string());
- emitTreeAttrs(state, *flake.sourceInfo, flake.lockedRef.input, *vRootSrc);
+ emitTreeAttrs(state, *lockedFlake.flake.sourceInfo, lockedFlake.flake.lockedRef.input, *vRootSrc);
- mkString(*vRootSubdir, flake.lockedRef.subdir);
+ mkString(*vRootSubdir, lockedFlake.flake.lockedRef.subdir);
static Value * vCallFlake = nullptr;
@@ -649,13 +615,6 @@ void callFlake(EvalState & state,
state.callFunction(*vTmp2, *vRootSubdir, vRes, noPos);
}
-void callFlake(EvalState & state,
- const LockedFlake & lockedFlake,
- Value & v)
-{
- callFlake(state, lockedFlake.flake, lockedFlake.lockFile, v);
-}
-
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
callFlake(state,