aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/flake
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2020-01-29 14:57:57 +0100
committerEelco Dolstra <edolstra@gmail.com>2020-01-29 18:41:25 +0100
commitf68bed7f67d9acc13ebe38e6f5aa8a641f6e557d (patch)
tree1370862f1228da0d524c64eca129956691232762 /src/libexpr/flake
parente53c89a64388ba2dc39f956c8f63620d28cc32af (diff)
Add flag --override-input to override specific lock file entries
E.g. $ nix flake update ~/Misc/eelco-configurations/hagbard \ --override-input 'dwarffs/nixpkgs' ../my-nixpkgs overrides the 'nixpkgs' input of the 'dwarffs' input of the top-level flake. Fixes #2837.
Diffstat (limited to 'src/libexpr/flake')
-rw-r--r--src/libexpr/flake/flake.cc32
-rw-r--r--src/libexpr/flake/flake.hh11
-rw-r--r--src/libexpr/flake/lockfile.cc17
-rw-r--r--src/libexpr/flake/lockfile.hh2
4 files changed, 41 insertions, 21 deletions
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 15b852c7c..2982f7718 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -4,7 +4,6 @@
#include "eval-inline.hh"
#include "store-api.hh"
#include "fetchers/fetchers.hh"
-#include "fetchers/regex.hh"
#include <iostream>
#include <ctime>
@@ -62,22 +61,6 @@ static void expectType(EvalState & state, ValueType type,
showType(type), showType(value.type), pos);
}
-static InputPath parseInputPath(std::string_view s, const Pos & pos)
-{
- InputPath path;
-
- for (auto & elem : tokenizeString<std::vector<std::string>>(s, "/")) {
- if (!std::regex_match(elem, fetchers::flakeIdRegex))
- throw Error("invalid flake input path element '%s' at %s", elem, pos);
- path.push_back(elem);
- }
-
- if (path.empty())
- throw Error("flake input path is empty at %s", pos);
-
- return path;
-}
-
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
EvalState & state, Value * value, const Pos & pos);
@@ -107,7 +90,11 @@ static FlakeInput parseFlakeInput(EvalState & state,
input.overrides = parseFlakeInputs(state, attr.value, *attr.pos);
} else if (attr.name == sFollows) {
expectType(state, tString, *attr.value, *attr.pos);
- input.follows = parseInputPath(attr.value->string.s, *attr.pos);
+ try {
+ input.follows = parseInputPath(attr.value->string.s);
+ } catch (Error & e) {
+ e.addPrefix("in flake attribute at '%s':\n");
+ }
} else
throw Error("flake input '%s' has an unsupported attribute '%s', at %s",
inputName, attr.name, *attr.pos);
@@ -324,7 +311,8 @@ static std::string diffLockFiles(const LockedInputs & oldLocks, const LockedInpu
LockedFlake lockFlake(
EvalState & state,
const FlakeRef & topRef,
- LockFileMode lockFileMode)
+ LockFileMode lockFileMode,
+ const LockFlags & lockFlags)
{
settings.requireExperimentalFeature("flakes");
@@ -350,6 +338,9 @@ LockedFlake lockFlake(
// FIXME: check whether all overrides are used.
std::map<InputPath, FlakeInput> overrides;
+ for (auto & i : lockFlags.inputOverrides)
+ overrides.insert_or_assign(i.first, FlakeInput { .ref = i.second });
+
/* Compute the new lock file. This is dones as a fixpoint
iteration: we repeat until the new lock file no longer changes
and there are no unresolved "follows" inputs. */
@@ -664,8 +655,9 @@ void callFlake(EvalState & state,
// This function is exposed to be used in nix files.
static void prim_getFlake(EvalState & state, const Pos & pos, Value * * args, Value & v)
{
+ LockFlags lockFlags;
callFlake(state, lockFlake(state, parseFlakeRef(state.forceStringNoCtx(*args[0], pos)),
- evalSettings.pureEval ? AllPure : UseUpdatedLockFile), v);
+ evalSettings.pureEval ? AllPure : UseUpdatedLockFile, lockFlags), v);
}
static RegisterPrimOp r2("getFlake", 1, prim_getFlake);
diff --git a/src/libexpr/flake/flake.hh b/src/libexpr/flake/flake.hh
index 83dae1d90..eb013c4ba 100644
--- a/src/libexpr/flake/flake.hh
+++ b/src/libexpr/flake/flake.hh
@@ -59,7 +59,16 @@ struct LockedFlake
Fingerprint getFingerprint() const;
};
-LockedFlake lockFlake(EvalState &, const FlakeRef &, LockFileMode);
+struct LockFlags
+{
+ std::map<InputPath, FlakeRef> inputOverrides;
+};
+
+LockedFlake lockFlake(
+ EvalState &,
+ const FlakeRef &,
+ LockFileMode,
+ const LockFlags &);
void callFlake(EvalState & state,
const Flake & flake,
diff --git a/src/libexpr/flake/lockfile.cc b/src/libexpr/flake/lockfile.cc
index a7291db5b..b92ffb70e 100644
--- a/src/libexpr/flake/lockfile.cc
+++ b/src/libexpr/flake/lockfile.cc
@@ -1,5 +1,6 @@
#include "lockfile.hh"
#include "store-api.hh"
+#include "fetchers/regex.hh"
#include <nlohmann/json.hpp>
@@ -104,4 +105,20 @@ void LockFile::write(const Path & path) const
writeFile(path, fmt("%s\n", *this));
}
+InputPath parseInputPath(std::string_view s)
+{
+ InputPath path;
+
+ for (auto & elem : tokenizeString<std::vector<std::string>>(s, "/")) {
+ if (!std::regex_match(elem, fetchers::flakeIdRegex))
+ throw Error("invalid flake input path element '%s'", elem);
+ path.push_back(elem);
+ }
+
+ if (path.empty())
+ throw Error("flake input path is empty");
+
+ return path;
+}
+
}
diff --git a/src/libexpr/flake/lockfile.hh b/src/libexpr/flake/lockfile.hh
index 9210a59e2..626c7d9e0 100644
--- a/src/libexpr/flake/lockfile.hh
+++ b/src/libexpr/flake/lockfile.hh
@@ -81,5 +81,7 @@ struct LockFile : LockedInputs
std::ostream & operator <<(std::ostream & stream, const LockFile & lockFile);
+InputPath parseInputPath(std::string_view s);
+
}