#include "installable-attr-path.hh" #include "outputs-spec.hh" #include "command.hh" #include "attr-path.hh" #include "common-eval-args.hh" #include "eval.hh" #include "get-drvs.hh" #include "flake/flake.hh" #include namespace nix { InstallableAttrPath::InstallableAttrPath( ref 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 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 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 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::Value { .extendedOutputsSpec = outputs, /* FIXME: reconsider backwards compatibility above so we can fill in this info. */ }), }); return res; } InstallableAttrPath InstallableAttrPath::parse( ref state, SourceExprCommand & cmd, Value * v, std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec) { return { state, cmd, v, prefix == "." ? "" : std::string { prefix }, std::move(extendedOutputsSpec), }; } }