mirror of
https://github.com/NixOS/nix.git
synced 2025-11-10 20:46:01 +01:00
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>
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 = 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
|
|
};
|
|
}
|
|
|
|
}
|