2023-02-03 21:53:40 +02:00
|
|
|
#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()
|
|
|
|
{
|
Make more string values work as installables
As discussed in #7417, it would be good to make more string values work
as installables. That is to say, if an installable refers to a value,
and the value is a string, it used to not work at all, since #7484, it
works somewhat, and this PR make it work some more.
The new cases that are added for `BuiltPath` contexts:
- Fixed input- or content-addressed derivation:
```
nix-repl> hello.out.outPath
"/nix/store/jppfl2bp1zhx8sgs2mgifmsx6dv16mv2-hello-2.12"
nix-repl> :p builtins.getContext hello.out.outPath
{ "/nix/store/c7jrxqjhdda93lhbkanqfs07x2bzazbm-hello-2.12.drv" = { outputs = [ "out" ]; }; }
The string matches the specified single output of that derivation, so
it should also be valid.
- Floating content-addressed derivation:
```
nix-repl> (hello.overrideAttrs (_: { __contentAddressed = true; })).out.outPath
"/1a08j26xqc0zm8agps8anxpjji410yvsx4pcgyn4bfan1ddkx2g0"
nix-repl> :p builtins.getContext (hello.overrideAttrs (_: { __contentAddressed = true; })).out.outPath
{ "/nix/store/qc645pyf9wl37c6qvqzaqkwsm1gp48al-hello-2.12.drv" = { outputs = [ "out" ]; }; }
```
The string is not a path but a placeholder, however it also matches
the context, and because it is a CA derivation we have no better
option. This should also be valid.
We may also want to think about richer attrset based values (also
discussed in that issue and #6507), but this change "completes" our
string-based building blocks, from which the others can be desugared
into or at least described/document/taught in terms of.
Progress towards #7417
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
2023-01-11 00:18:59 +02:00
|
|
|
auto [v, pos] = toValue(*state);
|
|
|
|
|
|
|
|
if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths(
|
|
|
|
*v,
|
|
|
|
pos,
|
|
|
|
fmt("while evaluating the attribute '%s'", attrPath)))
|
|
|
|
{
|
|
|
|
return { *derivedPathWithInfo };
|
|
|
|
}
|
2023-02-03 21:53:40 +02:00
|
|
|
|
|
|
|
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 {
|
Make the Derived Path family of types inductive for dynamic derivations
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>
2023-01-16 00:39:04 +02:00
|
|
|
.drvPath = makeConstantStorePathRef(drvPath),
|
2023-02-03 21:53:40 +02:00
|
|
|
.outputs = outputs,
|
|
|
|
},
|
2023-02-06 06:28:18 +02:00
|
|
|
.info = make_ref<ExtraPathInfoValue>(ExtraPathInfoValue::Value {
|
|
|
|
/* FIXME: reconsider backwards compatibility above
|
|
|
|
so we can fill in this info. */
|
|
|
|
}),
|
2023-02-03 21:53:40 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
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
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|