diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 1b8dcfbd0..aa047ac21 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -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, std::vector ss, bool applyOverrides = true, bool nestedIsExprOk = true); + std::shared_ptr modifyInstallable( + ref store, ref state, + std::shared_ptr installable, + std::string_view installableName, + std::string_view prefix, ExtendedOutputsSpec extendedOutputsSpec); + Bindings * getOverrideArgs(EvalState & state, ref store); std::shared_ptr parseInstallable( diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 93456655e..0ab958a05 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -733,7 +733,7 @@ std::vector> SourceExprCommand::parseInstallables( { std::vector> result; - auto modifyInstallable = applyOverrides && ( applyToInstallable + auto doModifyInstallable = applyOverrides && ( applyToInstallable || installableOverrideAttrs || installableWithPackages || overrideArgs.size() > 0 ); if (nestedIsExprOk && (file || expr)) { @@ -762,50 +762,15 @@ std::vector> SourceExprCommand::parseInstallables( auto installableAttr = std::make_shared(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::parse( - state, *this, vRes, prefix, extendedOutputsSpec - ))); + modifyInstallable( + store, state, + installableAttr, + s, + prefix, extendedOutputsSpec + ) + ); } else { result.push_back(installableAttr); } @@ -852,48 +817,15 @@ std::vector> 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::parse( - state, *this, vRes, "", extendedOutputsSpec - ))); + if (doModifyInstallable) { + result.push_back( + modifyInstallable( + store, state, + installableFlake, + s, + "", extendedOutputsSpec + ) + ); } else { result.push_back(installableFlake); } diff --git a/src/libcmd/modify-installables.cc b/src/libcmd/modify-installables.cc new file mode 100644 index 000000000..187460ee8 --- /dev/null +++ b/src/libcmd/modify-installables.cc @@ -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 +#include + +#include +#include + +namespace nix { + +std::shared_ptr SourceExprCommand::modifyInstallable ( + ref store, ref state, + std::shared_ptr 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::parse( + state, *this, vRes, prefix, extendedOutputsSpec + )); +} + +}