mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-13 17:56:15 +02:00
60b7121d2c
We want to be able to write down `foo.drv^bar.drv^baz`: `foo.drv^bar.drv` is the dynamic derivation (since it is itself a derivation output, `bar.drv` from `foo.drv`). To that end, we create `Single{Derivation,BuiltPath}` types, that are very similar except instead of having multiple outputs (in a set or map), they have a single one. This is for everything to the left of the rightmost `^`. `NixStringContextElem` has an analogous change, and now can reuse `SingleDerivedPath` at the top level. In fact, if we ever get rid of `DrvDeep`, `NixStringContextElem` could be replaced with `SingleDerivedPath` entirely! Important note: some JSON formats have changed. We already can *produce* dynamic derivations, but we can't refer to them directly. Today, we can merely express building or example at the top imperatively over time by building `foo.drv^bar.drv`, and then with a second nix invocation doing `<result-from-first>^baz`, but this is not declarative. The ethos of Nix of being able to write down the full plan everything you want to do, and then execute than plan with a single command, and for that we need the new inductive form of these types. Co-authored-by: Robert Hensing <roberth@users.noreply.github.com> Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io>
107 lines
3 KiB
C++
107 lines
3 KiB
C++
#include "value/context.hh"
|
|
|
|
#include <optional>
|
|
|
|
namespace nix {
|
|
|
|
NixStringContextElem NixStringContextElem::parse(
|
|
std::string_view s0,
|
|
const ExperimentalFeatureSettings & xpSettings)
|
|
{
|
|
std::string_view s = s0;
|
|
|
|
std::function<SingleDerivedPath()> parseRest;
|
|
parseRest = [&]() -> SingleDerivedPath {
|
|
// Case on whether there is a '!'
|
|
size_t index = s.find("!");
|
|
if (index == std::string_view::npos) {
|
|
return SingleDerivedPath::Opaque {
|
|
.path = StorePath { s },
|
|
};
|
|
} else {
|
|
std::string output { s.substr(0, index) };
|
|
// Advance string to parse after the '!'
|
|
s = s.substr(index + 1);
|
|
auto drv = make_ref<SingleDerivedPath>(parseRest());
|
|
drvRequireExperiment(*drv, xpSettings);
|
|
return SingleDerivedPath::Built {
|
|
.drvPath = std::move(drv),
|
|
.output = std::move(output),
|
|
};
|
|
}
|
|
};
|
|
|
|
if (s.size() == 0) {
|
|
throw BadNixStringContextElem(s0,
|
|
"String context element should never be an empty string");
|
|
}
|
|
|
|
switch (s.at(0)) {
|
|
case '!': {
|
|
// Advance string to parse after the '!'
|
|
s = s.substr(1);
|
|
|
|
// Find *second* '!'
|
|
if (s.find("!") == std::string_view::npos) {
|
|
throw BadNixStringContextElem(s0,
|
|
"String content element beginning with '!' should have a second '!'");
|
|
}
|
|
|
|
return std::visit(
|
|
[&](auto x) -> NixStringContextElem { return std::move(x); },
|
|
parseRest());
|
|
}
|
|
case '=': {
|
|
return NixStringContextElem::DrvDeep {
|
|
.drvPath = StorePath { s.substr(1) },
|
|
};
|
|
}
|
|
default: {
|
|
// Ensure no '!'
|
|
if (s.find("!") != std::string_view::npos) {
|
|
throw BadNixStringContextElem(s0,
|
|
"String content element not beginning with '!' should not have a second '!'");
|
|
}
|
|
return std::visit(
|
|
[&](auto x) -> NixStringContextElem { return std::move(x); },
|
|
parseRest());
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string NixStringContextElem::to_string() const
|
|
{
|
|
std::string res;
|
|
|
|
std::function<void(const SingleDerivedPath &)> toStringRest;
|
|
toStringRest = [&](auto & p) {
|
|
std::visit(overloaded {
|
|
[&](const SingleDerivedPath::Opaque & o) {
|
|
res += o.path.to_string();
|
|
},
|
|
[&](const SingleDerivedPath::Built & o) {
|
|
res += o.output;
|
|
res += '!';
|
|
toStringRest(*o.drvPath);
|
|
},
|
|
}, p.raw());
|
|
};
|
|
|
|
std::visit(overloaded {
|
|
[&](const NixStringContextElem::Built & b) {
|
|
res += '!';
|
|
toStringRest(b);
|
|
},
|
|
[&](const NixStringContextElem::Opaque & o) {
|
|
toStringRest(o);
|
|
},
|
|
[&](const NixStringContextElem::DrvDeep & d) {
|
|
res += '=';
|
|
res += d.drvPath.to_string();
|
|
},
|
|
}, raw());
|
|
|
|
return res;
|
|
}
|
|
|
|
}
|