mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-13 09:46:16 +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>
121 lines
3.3 KiB
C++
121 lines
3.3 KiB
C++
#include "globals.hh"
|
|
#include "installable-attr-path.hh"
|
|
#include "outputs-spec.hh"
|
|
#include "util.hh"
|
|
#include "command.hh"
|
|
#include "attr-path.hh"
|
|
#include "common-eval-args.hh"
|
|
#include "derivations.hh"
|
|
#include "eval-inline.hh"
|
|
#include "eval.hh"
|
|
#include "get-drvs.hh"
|
|
#include "store-api.hh"
|
|
#include "shared.hh"
|
|
#include "flake/flake.hh"
|
|
#include "eval-cache.hh"
|
|
#include "url.hh"
|
|
#include "registry.hh"
|
|
#include "build-result.hh"
|
|
|
|
#include <regex>
|
|
#include <queue>
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
namespace nix {
|
|
|
|
InstallableAttrPath::InstallableAttrPath(
|
|
ref<EvalState> state,
|
|
SourceExprCommand & cmd,
|
|
Value * v,
|
|
const std::string & attrPath,
|
|
ExtendedOutputsSpec extendedOutputsSpec)
|
|
: InstallableValue(state)
|
|
, cmd(cmd)
|
|
, v(allocRootValue(v))
|
|
, attrPath(attrPath)
|
|
, extendedOutputsSpec(std::move(extendedOutputsSpec))
|
|
{ }
|
|
|
|
std::pair<Value *, PosIdx> InstallableAttrPath::toValue(EvalState & state)
|
|
{
|
|
auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(state), **v);
|
|
state.forceValue(*vRes, pos);
|
|
return {vRes, pos};
|
|
}
|
|
|
|
DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths()
|
|
{
|
|
auto [v, pos] = toValue(*state);
|
|
|
|
if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths(
|
|
*v,
|
|
pos,
|
|
fmt("while evaluating the attribute '%s'", attrPath)))
|
|
{
|
|
return { *derivedPathWithInfo };
|
|
}
|
|
|
|
Bindings & autoArgs = *cmd.getAutoArgs(*state);
|
|
|
|
DrvInfos drvInfos;
|
|
getDerivations(*state, *v, "", autoArgs, drvInfos, false);
|
|
|
|
// Backward compatibility hack: group results by drvPath. This
|
|
// helps keep .all output together.
|
|
std::map<StorePath, OutputsSpec> byDrvPath;
|
|
|
|
for (auto & drvInfo : drvInfos) {
|
|
auto drvPath = drvInfo.queryDrvPath();
|
|
if (!drvPath)
|
|
throw Error("'%s' is not a derivation", what());
|
|
|
|
auto newOutputs = std::visit(overloaded {
|
|
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
|
|
std::set<std::string> outputsToInstall;
|
|
for (auto & output : drvInfo.queryOutputs(false, true))
|
|
outputsToInstall.insert(output.first);
|
|
return OutputsSpec::Names { std::move(outputsToInstall) };
|
|
},
|
|
[&](const ExtendedOutputsSpec::Explicit & e) -> OutputsSpec {
|
|
return e;
|
|
},
|
|
}, extendedOutputsSpec.raw());
|
|
|
|
auto [iter, didInsert] = byDrvPath.emplace(*drvPath, newOutputs);
|
|
|
|
if (!didInsert)
|
|
iter->second = iter->second.union_(newOutputs);
|
|
}
|
|
|
|
DerivedPathsWithInfo res;
|
|
for (auto & [drvPath, outputs] : byDrvPath)
|
|
res.push_back({
|
|
.path = DerivedPath::Built {
|
|
.drvPath = makeConstantStorePathRef(drvPath),
|
|
.outputs = outputs,
|
|
},
|
|
.info = make_ref<ExtraPathInfoValue>(ExtraPathInfoValue::Value {
|
|
/* FIXME: reconsider backwards compatibility above
|
|
so we can fill in this info. */
|
|
}),
|
|
});
|
|
|
|
return res;
|
|
}
|
|
|
|
InstallableAttrPath InstallableAttrPath::parse(
|
|
ref<EvalState> state,
|
|
SourceExprCommand & cmd,
|
|
Value * v,
|
|
std::string_view prefix,
|
|
ExtendedOutputsSpec extendedOutputsSpec)
|
|
{
|
|
return {
|
|
state, cmd, v,
|
|
prefix == "." ? "" : std::string { prefix },
|
|
extendedOutputsSpec
|
|
};
|
|
}
|
|
|
|
}
|