aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/flake')
-rw-r--r--src/libexpr/flake/call-flake.nix2
-rw-r--r--src/libexpr/flake/flake.cc52
-rw-r--r--src/libexpr/flake/flake.hh2
-rw-r--r--src/libexpr/flake/flakeref.cc22
-rw-r--r--src/libexpr/flake/flakeref.hh10
-rw-r--r--src/libexpr/flake/lockfile.cc40
-rw-r--r--src/libexpr/flake/lockfile.hh4
7 files changed, 64 insertions, 68 deletions
diff --git a/src/libexpr/flake/call-flake.nix b/src/libexpr/flake/call-flake.nix
index 8ee17b8f4..2084e3fb3 100644
--- a/src/libexpr/flake/call-flake.nix
+++ b/src/libexpr/flake/call-flake.nix
@@ -11,7 +11,7 @@ let
sourceInfo =
if key == lockFile.root
then rootSrc
- else fetchTree ({ inherit (node.info) narHash; } // removeAttrs node.locked ["dir"]);
+ else fetchTree (node.info or {} // removeAttrs node.locked ["dir"]);
subdir = if key == lockFile.root then rootSubdir else node.locked.dir or "";
flake = import (sourceInfo + (if subdir != "" then "/" else "") + subdir + "/flake.nix");
inputs = builtins.mapAttrs (inputName: key: allNodes.${key}) (node.inputs or {});
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 78b58cdfa..9741d98c5 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -19,7 +19,7 @@ static FlakeRef maybeLookupFlake(
const FlakeRef & flakeRef,
bool allowLookup)
{
- if (!flakeRef.input->isDirect()) {
+ if (!flakeRef.input.isDirect()) {
if (allowLookup)
return flakeRef.resolve(store);
else
@@ -49,16 +49,15 @@ static FlakeRef lookupInFlakeCache(
static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
EvalState & state,
const FlakeRef & originalRef,
- std::optional<TreeInfo> treeInfo,
bool allowLookup,
FlakeCache & flakeCache)
{
/* The tree may already be in the Nix store, or it could be
substituted (which is often faster than fetching from the
original source). So check that. */
- if (treeInfo && originalRef.input->isDirect() && originalRef.input->isImmutable()) {
+ if (originalRef.input.isDirect() && originalRef.input.isImmutable() && originalRef.input.hasAllInfo()) {
try {
- auto storePath = treeInfo->computeStorePath(*state.store);
+ auto storePath = originalRef.input.computeStorePath(*state.store);
state.store->ensurePath(storePath);
@@ -74,7 +73,6 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
Tree {
.actualPath = actualPath,
.storePath = std::move(storePath),
- .info = *treeInfo,
},
originalRef,
originalRef
@@ -99,8 +97,7 @@ static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> fetchOrSubstituteTree(
if (state.allowedPaths)
state.allowedPaths->insert(tree.actualPath);
- if (treeInfo)
- assert(tree.storePath == treeInfo->computeStorePath(*state.store));
+ assert(!originalRef.input.getNarHash() || tree.storePath == originalRef.input.computeStorePath(*state.store));
return {std::move(tree), resolvedRef, lockedRef};
}
@@ -202,12 +199,11 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
static Flake getFlake(
EvalState & state,
const FlakeRef & originalRef,
- std::optional<TreeInfo> treeInfo,
bool allowLookup,
FlakeCache & flakeCache)
{
auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree(
- state, originalRef, treeInfo, allowLookup, flakeCache);
+ state, originalRef, allowLookup, flakeCache);
// Guard against symlink attacks.
auto flakeFile = canonPath(sourceInfo.actualPath + "/" + lockedRef.subdir + "/flake.nix");
@@ -278,7 +274,7 @@ static Flake getFlake(
Flake getFlake(EvalState & state, const FlakeRef & originalRef, bool allowLookup)
{
FlakeCache flakeCache;
- return getFlake(state, originalRef, {}, allowLookup, flakeCache);
+ return getFlake(state, originalRef, allowLookup, flakeCache);
}
/* Compute an in-memory lock file for the specified top-level flake,
@@ -292,7 +288,7 @@ LockedFlake lockFlake(
FlakeCache flakeCache;
- auto flake = getFlake(state, topRef, {}, lockFlags.useRegistries, flakeCache);
+ auto flake = getFlake(state, topRef, lockFlags.useRegistries, flakeCache);
// FIXME: symlink attack
auto oldLockFile = LockFile::read(
@@ -393,7 +389,7 @@ LockedFlake lockFlake(
didn't change and there is no override from a
higher level flake. */
auto childNode = std::make_shared<LockedNode>(
- oldLock->lockedRef, oldLock->originalRef, oldLock->info, oldLock->isFlake);
+ oldLock->lockedRef, oldLock->originalRef, oldLock->isFlake);
node->inputs.insert_or_assign(id, childNode);
@@ -409,7 +405,7 @@ LockedFlake lockFlake(
if (hasChildUpdate) {
auto inputFlake = getFlake(
- state, oldLock->lockedRef, oldLock->info, false, flakeCache);
+ state, oldLock->lockedRef, false, flakeCache);
computeLocks(inputFlake.inputs, childNode, inputPath, oldLock);
} else {
/* No need to fetch this flake, we can be
@@ -440,11 +436,11 @@ LockedFlake lockFlake(
/* We need to create a new lock file entry. So fetch
this input. */
- if (!lockFlags.allowMutable && !input.ref.input->isImmutable())
+ if (!lockFlags.allowMutable && !input.ref.input.isImmutable())
throw Error("cannot update flake input '%s' in pure mode", inputPathS);
if (input.isFlake) {
- auto inputFlake = getFlake(state, input.ref, {}, lockFlags.useRegistries, flakeCache);
+ auto inputFlake = getFlake(state, input.ref, lockFlags.useRegistries, flakeCache);
/* Note: in case of an --override-input, we use
the *original* ref (input2.ref) for the
@@ -454,7 +450,7 @@ LockedFlake lockFlake(
file. That is, overrides are sticky unless you
use --no-write-lock-file. */
auto childNode = std::make_shared<LockedNode>(
- inputFlake.lockedRef, input2.ref, inputFlake.sourceInfo->info);
+ inputFlake.lockedRef, input2.ref);
node->inputs.insert_or_assign(id, childNode);
@@ -479,9 +475,9 @@ LockedFlake lockFlake(
else {
auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree(
- state, input.ref, {}, lockFlags.useRegistries, flakeCache);
+ state, input.ref, lockFlags.useRegistries, flakeCache);
node->inputs.insert_or_assign(id,
- std::make_shared<LockedNode>(lockedRef, input.ref, sourceInfo.info, false));
+ std::make_shared<LockedNode>(lockedRef, input.ref, false));
}
}
}
@@ -534,7 +530,7 @@ LockedFlake lockFlake(
printInfo("inputs of flake '%s' changed:\n%s", topRef, chomp(diff));
if (lockFlags.writeLockFile) {
- if (auto sourcePath = topRef.input->getSourcePath()) {
+ if (auto sourcePath = topRef.input.getSourcePath()) {
if (!newLockFile.isImmutable()) {
if (settings.warnDirty)
warn("will not write lock file of flake '%s' because it has a mutable input", topRef);
@@ -555,7 +551,7 @@ LockedFlake lockFlake(
newLockFile.write(path);
- topRef.input->markChangedFile(
+ topRef.input.markChangedFile(
(topRef.subdir == "" ? "" : topRef.subdir + "/") + "flake.lock",
lockFlags.commitLockFile
? std::optional<std::string>(fmt("%s: %s\n\nFlake input changes:\n\n%s",
@@ -567,19 +563,19 @@ LockedFlake lockFlake(
also just clear the 'rev' field... */
auto prevLockedRef = flake.lockedRef;
FlakeCache dummyCache;
- flake = getFlake(state, topRef, {}, lockFlags.useRegistries, dummyCache);
+ flake = getFlake(state, topRef, lockFlags.useRegistries, dummyCache);
if (lockFlags.commitLockFile &&
- flake.lockedRef.input->getRev() &&
- prevLockedRef.input->getRev() != flake.lockedRef.input->getRev())
- warn("committed new revision '%s'", flake.lockedRef.input->getRev()->gitRev());
+ flake.lockedRef.input.getRev() &&
+ prevLockedRef.input.getRev() != flake.lockedRef.input.getRev())
+ warn("committed new revision '%s'", flake.lockedRef.input.getRev()->gitRev());
/* Make sure that we picked up the change,
i.e. the tree should usually be dirty
now. Corner case: we could have reverted from a
dirty to a clean tree! */
if (flake.lockedRef.input == prevLockedRef.input
- && !flake.lockedRef.input->isImmutable())
+ && !flake.lockedRef.input.isImmutable())
throw Error("'%s' did not change after I updated its 'flake.lock' file; is 'flake.lock' under version control?", flake.originalRef);
}
} else
@@ -625,7 +621,7 @@ static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Va
{
auto flakeRefS = state.forceStringNoCtx(*args[0], pos);
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
- if (evalSettings.pureEval && !flakeRef.input->isImmutable())
+ if (evalSettings.pureEval && !flakeRef.input.isImmutable())
throw Error("cannot call 'getFlake' on mutable flake reference '%s', at %s (use --impure to override)", flakeRefS, pos);
callFlake(state,
@@ -650,8 +646,8 @@ Fingerprint LockedFlake::getFingerprint() const
return hashString(htSHA256,
fmt("%s;%d;%d;%s",
flake.sourceInfo->storePath.to_string(),
- flake.sourceInfo->info.revCount.value_or(0),
- flake.sourceInfo->info.lastModified.value_or(0),
+ flake.lockedRef.input.getRevCount().value_or(0),
+ flake.lockedRef.input.getLastModified().value_or(0),
lockFile));
}
diff --git a/src/libexpr/flake/flake.hh b/src/libexpr/flake/flake.hh
index 59a1adb3b..ebf81362c 100644
--- a/src/libexpr/flake/flake.hh
+++ b/src/libexpr/flake/flake.hh
@@ -104,7 +104,7 @@ void callFlake(
void emitTreeAttrs(
EvalState & state,
const fetchers::Tree & tree,
- std::shared_ptr<const fetchers::Input> input,
+ const fetchers::Input & input,
Value & v);
}
diff --git a/src/libexpr/flake/flakeref.cc b/src/libexpr/flake/flakeref.cc
index a70261a41..615269218 100644
--- a/src/libexpr/flake/flakeref.cc
+++ b/src/libexpr/flake/flakeref.cc
@@ -15,7 +15,7 @@ const static std::string subDirRegex = subDirElemRegex + "(?:/" + subDirElemRege
std::string FlakeRef::to_string() const
{
- auto url = input->toURL();
+ auto url = input.toURL();
if (subdir != "")
url.query.insert_or_assign("dir", subdir);
return url.to_string();
@@ -23,7 +23,7 @@ std::string FlakeRef::to_string() const
fetchers::Attrs FlakeRef::toAttrs() const
{
- auto attrs = input->toAttrs();
+ auto attrs = input.toAttrs();
if (subdir != "")
attrs.emplace("dir", subdir);
return attrs;
@@ -37,13 +37,13 @@ std::ostream & operator << (std::ostream & str, const FlakeRef & flakeRef)
bool FlakeRef::operator ==(const FlakeRef & other) const
{
- return *input == *other.input && subdir == other.subdir;
+ return input == other.input && subdir == other.subdir;
}
FlakeRef FlakeRef::resolve(ref<Store> store) const
{
auto [input2, extraAttrs] = lookupInRegistries(store, input);
- return FlakeRef(input2, fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir));
+ return FlakeRef(std::move(input2), fetchers::maybeGetStrAttr(extraAttrs, "dir").value_or(subdir));
}
FlakeRef parseFlakeRef(
@@ -98,7 +98,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
};
return std::make_pair(
- FlakeRef(inputFromURL(parsedURL), ""),
+ FlakeRef(Input::fromURL(parsedURL), ""),
percentDecode(std::string(match[6])));
}
@@ -143,7 +143,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
}
return std::make_pair(
- FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
+ FlakeRef(Input::fromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
fragment);
}
@@ -155,7 +155,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
attrs.insert_or_assign("type", "path");
attrs.insert_or_assign("path", path);
- return std::make_pair(FlakeRef(inputFromAttrs(attrs), ""), fragment);
+ return std::make_pair(FlakeRef(Input::fromAttrs(std::move(attrs)), ""), fragment);
}
else {
@@ -163,7 +163,7 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
std::string fragment;
std::swap(fragment, parsedURL.fragment);
return std::make_pair(
- FlakeRef(inputFromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
+ FlakeRef(Input::fromURL(parsedURL), get(parsedURL.query, "dir").value_or("")),
fragment);
}
}
@@ -183,14 +183,14 @@ FlakeRef FlakeRef::fromAttrs(const fetchers::Attrs & attrs)
auto attrs2(attrs);
attrs2.erase("dir");
return FlakeRef(
- fetchers::inputFromAttrs(attrs2),
+ fetchers::Input::fromAttrs(std::move(attrs2)),
fetchers::maybeGetStrAttr(attrs, "dir").value_or(""));
}
std::pair<fetchers::Tree, FlakeRef> FlakeRef::fetchTree(ref<Store> store) const
{
- auto [tree, lockedInput] = input->fetchTree(store);
- return {std::move(tree), FlakeRef(lockedInput, subdir)};
+ auto [tree, lockedInput] = input.fetch(store);
+ return {std::move(tree), FlakeRef(std::move(lockedInput), subdir)};
}
}
diff --git a/src/libexpr/flake/flakeref.hh b/src/libexpr/flake/flakeref.hh
index 72cbb2908..f4eb825a6 100644
--- a/src/libexpr/flake/flakeref.hh
+++ b/src/libexpr/flake/flakeref.hh
@@ -14,17 +14,15 @@ typedef std::string FlakeId;
struct FlakeRef
{
- std::shared_ptr<const fetchers::Input> input;
+ fetchers::Input input;
Path subdir;
bool operator==(const FlakeRef & other) const;
- FlakeRef(const std::shared_ptr<const fetchers::Input> & input, const Path & subdir)
- : input(input), subdir(subdir)
- {
- assert(input);
- }
+ FlakeRef(fetchers::Input && input, const Path & subdir)
+ : input(std::move(input)), subdir(subdir)
+ { }
// FIXME: change to operator <<.
std::string to_string() const;
diff --git a/src/libexpr/flake/lockfile.cc b/src/libexpr/flake/lockfile.cc
index 5c58d6080..68e587650 100644
--- a/src/libexpr/flake/lockfile.cc
+++ b/src/libexpr/flake/lockfile.cc
@@ -5,35 +5,40 @@
namespace nix::flake {
-FlakeRef flakeRefFromJson(const nlohmann::json & json)
-{
- return FlakeRef::fromAttrs(jsonToAttrs(json));
-}
-
FlakeRef getFlakeRef(
const nlohmann::json & json,
- const char * attr)
+ const char * attr,
+ const char * info)
{
auto i = json.find(attr);
- if (i != json.end())
- return flakeRefFromJson(*i);
+ if (i != json.end()) {
+ auto attrs = jsonToAttrs(*i);
+ // FIXME: remove when we drop support for version 5.
+ if (info) {
+ auto j = json.find(info);
+ if (j != json.end()) {
+ for (auto k : jsonToAttrs(*j))
+ attrs.insert_or_assign(k.first, k.second);
+ }
+ }
+ return FlakeRef::fromAttrs(attrs);
+ }
throw Error("attribute '%s' missing in lock file", attr);
}
LockedNode::LockedNode(const nlohmann::json & json)
- : lockedRef(getFlakeRef(json, "locked"))
- , originalRef(getFlakeRef(json, "original"))
- , info(TreeInfo::fromJson(json))
+ : lockedRef(getFlakeRef(json, "locked", "info"))
+ , originalRef(getFlakeRef(json, "original", nullptr))
, isFlake(json.find("flake") != json.end() ? (bool) json["flake"] : true)
{
- if (!lockedRef.input->isImmutable())
- throw Error("lockfile contains mutable flakeref '%s'", lockedRef);
+ if (!lockedRef.input.isImmutable())
+ throw Error("lockfile contains mutable lock '%s'", attrsToJson(lockedRef.input.toAttrs()));
}
StorePath LockedNode::computeStorePath(Store & store) const
{
- return info.computeStorePath(store);
+ return lockedRef.input.computeStorePath(store);
}
std::shared_ptr<Node> Node::findInput(const InputPath & path)
@@ -53,7 +58,7 @@ std::shared_ptr<Node> Node::findInput(const InputPath & path)
LockFile::LockFile(const nlohmann::json & json, const Path & path)
{
auto version = json.value("version", 0);
- if (version != 5)
+ if (version < 5 || version > 6)
throw Error("lock file '%s' has unsupported version %d", path, version);
std::unordered_map<std::string, std::shared_ptr<Node>> nodeMap;
@@ -119,7 +124,6 @@ nlohmann::json LockFile::toJson() const
if (auto lockedNode = std::dynamic_pointer_cast<const LockedNode>(node)) {
n["original"] = fetchers::attrsToJson(lockedNode->originalRef.toAttrs());
n["locked"] = fetchers::attrsToJson(lockedNode->lockedRef.toAttrs());
- n["info"] = lockedNode->info.toJson();
if (!lockedNode->isFlake) n["flake"] = false;
}
@@ -129,7 +133,7 @@ nlohmann::json LockFile::toJson() const
};
nlohmann::json json;
- json["version"] = 5;
+ json["version"] = 6;
json["root"] = dumpNode("root", root);
json["nodes"] = std::move(nodes);
@@ -176,7 +180,7 @@ bool LockFile::isImmutable() const
for (auto & i : nodes) {
if (i == root) continue;
auto lockedNode = std::dynamic_pointer_cast<const LockedNode>(i);
- if (lockedNode && !lockedNode->lockedRef.input->isImmutable()) return false;
+ if (lockedNode && !lockedNode->lockedRef.input.isImmutable()) return false;
}
return true;
diff --git a/src/libexpr/flake/lockfile.hh b/src/libexpr/flake/lockfile.hh
index c34939ebc..ba47f9b89 100644
--- a/src/libexpr/flake/lockfile.hh
+++ b/src/libexpr/flake/lockfile.hh
@@ -31,15 +31,13 @@ struct Node : std::enable_shared_from_this<Node>
struct LockedNode : Node
{
FlakeRef lockedRef, originalRef;
- TreeInfo info;
bool isFlake = true;
LockedNode(
const FlakeRef & lockedRef,
const FlakeRef & originalRef,
- const TreeInfo & info,
bool isFlake = true)
- : lockedRef(lockedRef), originalRef(originalRef), info(info), isFlake(isFlake)
+ : lockedRef(lockedRef), originalRef(originalRef), isFlake(isFlake)
{ }
LockedNode(const nlohmann::json & json);