libcmd: factor out modifyInstallable

This commit is contained in:
Max Headroom 2023-05-03 23:17:31 +02:00
parent 8eb40776e5
commit d78992dbff
3 changed files with 106 additions and 86 deletions

View file

@ -4,6 +4,7 @@
#include "installables.hh"
#include "args.hh"
#include "common-eval-args.hh"
#include "outputs-spec.hh"
#include "path.hh"
#include "flake/lockfile.hh"
@ -107,6 +108,12 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
ref<Store> store, std::vector<std::string> ss,
bool applyOverrides = true, bool nestedIsExprOk = true);
std::shared_ptr<Installable> modifyInstallable(
ref<Store> store, ref<EvalState> state,
std::shared_ptr<Installable> installable,
std::string_view installableName,
std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec);
Bindings * getOverrideArgs(EvalState & state, ref<Store> store);
std::shared_ptr<Installable> parseInstallable(

View file

@ -733,7 +733,7 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
{
std::vector<std::shared_ptr<Installable>> result;
auto modifyInstallable = applyOverrides && ( applyToInstallable
auto doModifyInstallable = applyOverrides && ( applyToInstallable
|| installableOverrideAttrs || installableWithPackages || overrideArgs.size() > 0 );
if (nestedIsExprOk && (file || expr)) {
@ -762,50 +762,15 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
auto installableAttr = std::make_shared<InstallableAttrPath>(InstallableAttrPath::parse(
state, *this, vFile, prefix, extendedOutputsSpec
));
if (modifyInstallable) {
auto [v, pos] = installableAttr->toValue(*state);
auto vApply = state->allocValue();
auto vRes = state->allocValue();
auto state = getEvalState();
auto overrideSet = getOverrideArgs(*state, store);
// FIXME merge this and the code for the flake version into a single function ("modifyInstallables()"?)
if (applyToInstallable) {
state->eval(state->parseExprFromString(*applyToInstallable, absPath(".")), *vApply);
state->callFunction(*vApply, *v, *vRes, noPos);
} else if (overrideSet->size() > 0) {
Value * overrideValues = state->allocValue();
overrideValues->mkAttrs(state->buildBindings(overrideSet->size()).finish());
for (auto& v : *overrideSet) {
overrideValues->attrs->push_back(v);
}
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("override"));
if (!vOverrideFunctorAttr) {
throw Error("%s is not overridable", s);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *overrideValues, *vRes, noPos);
} else if (installableOverrideAttrs) {
state->eval(state->parseExprFromString(fmt("old: with old; %s",*installableOverrideAttrs), absPath(".")), *vApply);
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("overrideAttrs"));
if (!vOverrideFunctorAttr) {
throw Error("%s is not overrideAttrs-capable", s);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *vApply, *vRes, noPos);
} else if (installableWithPackages) {
state->eval(state->parseExprFromString(fmt("ps: with ps; %s",*installableWithPackages), absPath(".")), *vApply);
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("withPackages"));
if (!vOverrideFunctorAttr) {
throw Error("%s cannot be extended with additional packages", s);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *vApply, *vRes, noPos);
}
if (doModifyInstallable) {
result.push_back(
std::make_shared<InstallableAttrPath>(InstallableAttrPath::parse(
state, *this, vRes, prefix, extendedOutputsSpec
)));
modifyInstallable(
store, state,
installableAttr,
s,
prefix, extendedOutputsSpec
)
);
} else {
result.push_back(installableAttr);
}
@ -852,48 +817,15 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
getDefaultFlakeAttrPaths(),
getDefaultFlakeAttrPathPrefixes(),
lockFlags);
if (modifyInstallable) {
auto [v, pos] = installableFlake->toValue(*state);
auto vApply = state->allocValue();
auto vRes = state->allocValue();
auto state = getEvalState();
auto overrideSet = getOverrideArgs(*state, store);
if (applyToInstallable) {
state->eval(state->parseExprFromString(*applyToInstallable, absPath(".")), *vApply);
state->callFunction(*vApply, *v, *vRes, noPos);
} else if (overrideSet->size() > 0) {
Value * overrideValues = state->allocValue();
overrideValues->mkAttrs(state->buildBindings(overrideSet->size()).finish());
for (auto& v : *overrideSet) {
overrideValues->attrs->push_back(v);
}
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("override"));
if (!vOverrideFunctorAttr) {
throw Error("%s is not overridable", s);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *overrideValues, *vRes, noPos);
} else if (installableOverrideAttrs) {
state->eval(state->parseExprFromString(fmt("old: with old; %s",*installableOverrideAttrs), absPath(".")), *vApply);
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("overrideAttrs"));
if (!vOverrideFunctorAttr) {
throw Error("%s is not overrideAttrs-capable", s);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *vApply, *vRes, noPos);
} else if (installableWithPackages) {
state->eval(state->parseExprFromString(fmt("ps: with ps; %s",*installableWithPackages), absPath(".")), *vApply);
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("withPackages"));
if (!vOverrideFunctorAttr) {
throw Error("%s cannot be extended with additional packages", s);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *vApply, *vRes, noPos);
}
result.push_back(std::make_shared<InstallableAttrPath>(InstallableAttrPath::parse(
state, *this, vRes, "", extendedOutputsSpec
)));
if (doModifyInstallable) {
result.push_back(
modifyInstallable(
store, state,
installableFlake,
s,
"", extendedOutputsSpec
)
);
} else {
result.push_back(installableFlake);
}

View file

@ -0,0 +1,81 @@
#include "globals.hh"
#include "installables.hh"
#include "installable-derived-path.hh"
#include "installable-attr-path.hh"
#include "installable-flake.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>
#include <string_view>
namespace nix {
std::shared_ptr<Installable> SourceExprCommand::modifyInstallable (
ref<Store> store, ref<EvalState> state,
std::shared_ptr<Installable> installable,
std::string_view installableName,
std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec
)
{
auto [v, pos] = installable->toValue(*state);
auto vApply = state->allocValue();
auto vRes = state->allocValue();
auto overrideSet = getOverrideArgs(*state, store);
if (applyToInstallable) {
state->eval(state->parseExprFromString(*applyToInstallable, absPath(".")), *vApply);
state->callFunction(*vApply, *v, *vRes, noPos);
} else if (overrideSet->size() > 0) {
Value * overrideValues = state->allocValue();
overrideValues->mkAttrs(state->buildBindings(overrideSet->size()).finish());
for (auto& v : *overrideSet) {
overrideValues->attrs->push_back(v);
}
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("override"));
if (!vOverrideFunctorAttr) {
throw Error("%s is not overridable", installableName);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *overrideValues, *vRes, noPos);
} else if (installableOverrideAttrs) {
state->eval(state->parseExprFromString(fmt("old: with old; %s",*installableOverrideAttrs), absPath(".")), *vApply);
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("overrideAttrs"));
if (!vOverrideFunctorAttr) {
throw Error("%s is not overrideAttrs-capable", installableName);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *vApply, *vRes, noPos);
} else if (installableWithPackages) {
state->eval(state->parseExprFromString(fmt("ps: with ps; %s",*installableWithPackages), absPath(".")), *vApply);
auto vOverrideFunctorAttr = v->attrs->get(state->symbols.create("withPackages"));
if (!vOverrideFunctorAttr) {
throw Error("%s cannot be extended with additional packages", installableName);
}
auto vOverrideFunctor = vOverrideFunctorAttr->value;
state->callFunction(*vOverrideFunctor, *vApply, *vRes, noPos);
}
return
std::make_shared<InstallableAttrPath>(InstallableAttrPath::parse(
state, *this, vRes, prefix, extendedOutputsSpec
));
}
}