aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc6
-rw-r--r--src/libexpr/flake/lockfile.hh2
-rw-r--r--src/libexpr/get-drvs.cc14
-rw-r--r--src/libexpr/get-drvs.hh2
-rw-r--r--src/libexpr/primops.cc86
5 files changed, 78 insertions, 32 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index d678231c6..139067f20 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -370,7 +370,11 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
for (auto & i : _searchPath) addToSearchPath(i);
for (auto & i : evalSettings.nixPath.get()) addToSearchPath(i);
}
- addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs", true));
+
+ try {
+ addToSearchPath("nix=" + canonPath(settings.nixDataDir + "/nix/corepkgs", true));
+ } catch (Error &) {
+ }
if (evalSettings.restrictEval || evalSettings.pureEval) {
allowedPaths = PathSet();
diff --git a/src/libexpr/flake/lockfile.hh b/src/libexpr/flake/lockfile.hh
index 5e7cfda3e..9ec8b39c3 100644
--- a/src/libexpr/flake/lockfile.hh
+++ b/src/libexpr/flake/lockfile.hh
@@ -6,7 +6,7 @@
namespace nix {
class Store;
-struct StorePath;
+class StorePath;
}
namespace nix::flake {
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 5d6e39aa0..91916e8bf 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -38,8 +38,11 @@ DrvInfo::DrvInfo(EvalState & state, ref<Store> store, const std::string & drvPat
auto i = drv.outputs.find(outputName);
if (i == drv.outputs.end())
throw Error("derivation '%s' does not have output '%s'", store->printStorePath(drvPath), outputName);
+ auto & [outputName, output] = *i;
- outPath = store->printStorePath(i->second.path(*store, drv.name));
+ auto optStorePath = output.path(*store, drv.name, outputName);
+ if (optStorePath)
+ outPath = store->printStorePath(*optStorePath);
}
@@ -77,12 +80,15 @@ string DrvInfo::queryDrvPath() const
string DrvInfo::queryOutPath() const
{
- if (outPath == "" && attrs) {
+ if (!outPath && attrs) {
Bindings::iterator i = attrs->find(state->sOutPath);
PathSet context;
- outPath = i != attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "";
+ if (i != attrs->end())
+ outPath = state->coerceToPath(*i->pos, *i->value, context);
}
- return outPath;
+ if (!outPath)
+ throw UnimplementedError("CA derivations are not yet supported");
+ return *outPath;
}
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index d7860fc6a..29bb6a660 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -20,7 +20,7 @@ private:
mutable string name;
mutable string system;
mutable string drvPath;
- mutable string outPath;
+ mutable std::optional<string> outPath;
mutable string outputName;
Outputs outputs;
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 3350d05d4..d0b0c57b2 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -44,16 +44,6 @@ void EvalState::realiseContext(const PathSet & context)
throw InvalidPathError(store->printStorePath(ctx));
if (!outputName.empty() && ctx.isDerivation()) {
drvs.push_back(StorePathWithOutputs{ctx, {outputName}});
-
- /* Add the output of this derivation to the allowed
- paths. */
- if (allowedPaths) {
- auto drv = store->derivationFromPath(ctx);
- DerivationOutputs::iterator i = drv.outputs.find(outputName);
- if (i == drv.outputs.end())
- throw Error("derivation '%s' does not have an output named '%s'", ctxS, outputName);
- allowedPaths->insert(store->printStorePath(i->second.path(*store, drv.name)));
- }
}
}
@@ -69,8 +59,50 @@ void EvalState::realiseContext(const PathSet & context)
store->queryMissing(drvs, willBuild, willSubstitute, unknown, downloadSize, narSize);
store->buildPaths(drvs);
+
+ /* Add the output of this derivations to the allowed
+ paths. */
+ if (allowedPaths) {
+ for (auto & [drvPath, outputs] : drvs) {
+ auto outputPaths = store->queryDerivationOutputMap(drvPath);
+ for (auto & outputName : outputs) {
+ if (outputPaths.count(outputName) == 0)
+ throw Error("derivation '%s' does not have an output named '%s'",
+ store->printStorePath(drvPath), outputName);
+ allowedPaths->insert(store->printStorePath(outputPaths.at(outputName)));
+ }
+ }
+ }
}
+/* Add and attribute to the given attribute map from the output name to
+ the output path, or a placeholder.
+
+ Where possible the path is used, but for floating CA derivations we
+ may not know it. For sake of determinism we always assume we don't
+ and instead put in a place holder. In either case, however, the
+ string context will contain the drv path and output name, so
+ downstream derivations will have the proper dependency, and in
+ addition, before building, the placeholder will be rewritten to be
+ the actual path.
+
+ The 'drv' and 'drvPath' outputs must correspond. */
+static void mkOutputString(EvalState & state, Value & v,
+ const StorePath & drvPath, const BasicDerivation & drv,
+ std::pair<string, DerivationOutput> o)
+{
+ auto optOutputPath = o.second.path(*state.store, drv.name, o.first);
+ mkString(
+ *state.allocAttr(v, state.symbols.create(o.first)),
+ optOutputPath
+ ? state.store->printStorePath(*optOutputPath)
+ /* Downstream we would substitute this for an actual path once
+ we build the floating CA derivation */
+ /* FIXME: we need to depend on the basic derivation, not
+ derivation */
+ : downstreamPlaceholder(*state.store, drvPath, o.first),
+ {"!" + o.first + "!" + state.store->printStorePath(drvPath)});
+}
/* Load and evaluate an expression from path specified by the
argument. */
@@ -114,9 +146,8 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
state.mkList(*outputsVal, drv.outputs.size());
unsigned int outputs_index = 0;
- for (const auto & o : drv.outputsAndPaths(*state.store)) {
- v2 = state.allocAttr(w, state.symbols.create(o.first));
- mkString(*v2, state.store->printStorePath(o.second.second), {"!" + o.first + "!" + path});
+ for (const auto & o : drv.outputs) {
+ mkOutputString(state, w, storePath, drv, o);
outputsVal->listElems()[outputs_index] = state.allocValue();
mkString(*(outputsVal->listElems()[outputs_index++]), o.first);
}
@@ -1080,16 +1111,18 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
/* Optimisation, but required in read-only mode! because in that
case we don't actually write store derivations, so we can't
- read them later. */
- drvHashes.insert_or_assign(drvPath,
- hashDerivationModulo(*state.store, Derivation(drv), false));
+ read them later.
+
+ However, we don't bother doing this for floating CA derivations because
+ their "hash modulo" is indeterminate until built. */
+ if (drv.type() != DerivationType::CAFloating)
+ drvHashes.insert_or_assign(drvPath,
+ hashDerivationModulo(*state.store, Derivation(drv), false));
state.mkAttrs(v, 1 + drv.outputs.size());
mkString(*state.allocAttr(v, state.sDrvPath), drvPathS, {"=" + drvPathS});
- for (auto & i : drv.outputsAndPaths(*state.store)) {
- mkString(*state.allocAttr(v, state.symbols.create(i.first)),
- state.store->printStorePath(i.second.second), {"!" + i.first + "!" + drvPathS});
- }
+ for (auto & i : drv.outputs)
+ mkOutputString(state, v, drvPath, drv, i);
v.attrs->sort();
}
@@ -1671,7 +1704,7 @@ static RegisterPrimOp primop_toFile({
...
cp ${configFile} $out/etc/foo.conf
";
- ```
+ ```
Note that `${configFile}` is an
[antiquotation](language-values.md), so the result of the
@@ -3532,10 +3565,13 @@ void EvalState::createBaseEnv()
/* Add a wrapper around the derivation primop that computes the
`drvPath' and `outPath' attributes lazily. */
- string path = canonPath(settings.nixDataDir + "/nix/corepkgs/derivation.nix", true);
- sDerivationNix = symbols.create(path);
- evalFile(path, v);
- addConstant("derivation", v);
+ try {
+ string path = canonPath(settings.nixDataDir + "/nix/corepkgs/derivation.nix", true);
+ sDerivationNix = symbols.create(path);
+ evalFile(path, v);
+ addConstant("derivation", v);
+ } catch (SysError &) {
+ }
/* Now that we've added all primops, sort the `builtins' set,
because attribute lookups expect it to be sorted. */