aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/primops
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-01-03 11:44:59 -0500
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-01-10 13:10:49 -0500
commit5576d5e987e907bf13ae6c7fe79ececce4e86e2d (patch)
tree058d40aea1fc3775061a99baa838a20e09963ba6 /src/libexpr/primops
parentda64f026dd7b12d72ffbc15752e8b95707fa1f9f (diff)
Parse string context elements properly
Prior to this change, we had a bunch of ad-hoc string manipulation code scattered around. This made it hard to figure out what data model for string contexts is. Now, we still store string contexts most of the time as encoded strings --- I was wary of the performance implications of changing that --- but whenever we parse them we do so only through the `NixStringContextElem::parse` method, which handles all cases. This creates a data type that is very similar to `DerivedPath` but: - Represents the funky `=<drvpath>` case as properly distinct from the others. - Only encodes a single output, no wildcards and no set, for the "built" case. (I would like to deprecate `=<path>`, after which we are in spitting distance of `DerivedPath` and could maybe get away with fewer types, but that is another topic for another day.)
Diffstat (limited to 'src/libexpr/primops')
-rw-r--r--src/libexpr/primops/context.cc51
1 files changed, 23 insertions, 28 deletions
diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc
index 9fae0b14d..0c65a6b98 100644
--- a/src/libexpr/primops/context.cc
+++ b/src/libexpr/primops/context.cc
@@ -37,8 +37,15 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const PosIdx p
auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardOutputDependency");
PathSet context2;
- for (auto & p : context)
- context2.insert(p.at(0) == '=' ? std::string(p, 1) : p);
+ for (auto && p : context) {
+ auto c = NixStringContextElem::parse(*state.store, p);
+ if (auto * ptr = std::get_if<NixStringContextElem::DrvDeep>(&c)) {
+ context2.emplace(state.store->printStorePath(ptr->drvPath));
+ } else {
+ /* Can reuse original item */
+ context2.emplace(std::move(p));
+ }
+ }
v.mkString(*s, context2);
}
@@ -74,34 +81,22 @@ static void prim_getContext(EvalState & state, const PosIdx pos, Value * * args,
};
PathSet context;
state.forceString(*args[0], context, pos, "while evaluating the argument passed to builtins.getContext");
- auto contextInfos = std::map<Path, ContextInfo>();
+ auto contextInfos = std::map<StorePath, ContextInfo>();
for (const auto & p : context) {
Path drv;
std::string output;
- const Path * path = &p;
- if (p.at(0) == '=') {
- drv = std::string(p, 1);
- path = &drv;
- } else if (p.at(0) == '!') {
- NixStringContextElem ctx = decodeContext(*state.store, p);
- drv = state.store->printStorePath(ctx.first);
- output = ctx.second;
- path = &drv;
- }
- auto isPath = drv.empty();
- auto isAllOutputs = (!drv.empty()) && output.empty();
-
- auto iter = contextInfos.find(*path);
- if (iter == contextInfos.end()) {
- contextInfos.emplace(*path, ContextInfo{isPath, isAllOutputs, output.empty() ? Strings{} : Strings{std::move(output)}});
- } else {
- if (isPath)
- iter->second.path = true;
- else if (isAllOutputs)
- iter->second.allOutputs = true;
- else
- iter->second.outputs.emplace_back(std::move(output));
- }
+ NixStringContextElem ctx = NixStringContextElem::parse(*state.store, p);
+ std::visit(overloaded {
+ [&](NixStringContextElem::DrvDeep & d) {
+ contextInfos[d.drvPath].allOutputs = true;
+ },
+ [&](NixStringContextElem::Built & b) {
+ contextInfos[b.drvPath].outputs.emplace_back(std::move(output));
+ },
+ [&](NixStringContextElem::Opaque & o) {
+ contextInfos[o.path].path = true;
+ },
+ }, ctx.raw());
}
auto attrs = state.buildBindings(contextInfos.size());
@@ -120,7 +115,7 @@ static void prim_getContext(EvalState & state, const PosIdx pos, Value * * args,
for (const auto & [i, output] : enumerate(info.second.outputs))
(outputsVal.listElems()[i] = state.allocValue())->mkString(output);
}
- attrs.alloc(info.first).mkAttrs(infoAttrs);
+ attrs.alloc(state.store->printStorePath(info.first)).mkAttrs(infoAttrs);
}
v.mkAttrs(attrs);