patch: cli: apply-to-installable, nix-dram edition

This commit is contained in:
Max Headroom 2022-02-21 23:11:52 +01:00
parent a72dd4916f
commit 78384699de
2 changed files with 34 additions and 3 deletions

View file

@ -94,6 +94,7 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
{ {
std::optional<Path> file; std::optional<Path> file;
std::optional<std::string> expr; std::optional<std::string> expr;
std::optional<std::string> applyToInstallable;
// FIXME: move this; not all commands (e.g. 'nix run') use it. // FIXME: move this; not all commands (e.g. 'nix run') use it.
OperateOn operateOn = OperateOn::Output; OperateOn operateOn = OperateOn::Output;

View file

@ -158,6 +158,14 @@ SourceExprCommand::SourceExprCommand()
.category = installablesCategory, .category = installablesCategory,
.handler = {&operateOn, OperateOn::Derivation}, .handler = {&operateOn, OperateOn::Derivation},
}); });
addFlag({
.longName = "apply-to-installable",
.description = "Apply the function *expr* to each installable.",
.category = installablesCategory,
.labels = {"expr"},
.handler = {&applyToInstallable},
});
} }
Strings SourceExprCommand::getDefaultFlakeAttrPaths() Strings SourceExprCommand::getDefaultFlakeAttrPaths()
@ -745,6 +753,14 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
state->eval(e, *vFile); state->eval(e, *vFile);
} }
if (applyToInstallable) {
auto vApply = state->allocValue();
state->eval(state->parseExprFromString(*applyToInstallable, absPath(".")), *vApply);
auto vRes = state->allocValue();
state->callFunction(*vApply, *vFile, *vRes, noPos);
vFile = vRes;
}
for (auto & s : ss) for (auto & s : ss)
result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vFile, s == "." ? "" : s)); result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vFile, s == "." ? "" : s));
@ -754,6 +770,9 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
std::exception_ptr ex; std::exception_ptr ex;
if (s.find('/') != std::string::npos) { if (s.find('/') != std::string::npos) {
if (applyToInstallable) {
throw Error("cannot apply function: installable cannot be evaluated");
}
try { try {
result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s))); result.push_back(std::make_shared<InstallableStorePath>(store, store->followLinksToStorePath(s)));
continue; continue;
@ -772,14 +791,25 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
? std::make_pair(parseFlakeRef("flake:default", absPath(".")), s) ? std::make_pair(parseFlakeRef("flake:default", absPath(".")), s)
: parseFlakeRefWithFragment(s, absPath(".")); : parseFlakeRefWithFragment(s, absPath("."));
result.push_back(std::make_shared<InstallableFlake>( auto state = getEvalState();
auto installableFlake = std::make_shared<InstallableFlake>(
this, this,
getEvalState(), state,
std::move(flakeRef), std::move(flakeRef),
fragment, fragment,
getDefaultFlakeAttrPaths(), getDefaultFlakeAttrPaths(),
getDefaultFlakeAttrPathPrefixes(), getDefaultFlakeAttrPathPrefixes(),
lockFlags)); lockFlags);
if (applyToInstallable) {
auto [v, pos] = installableFlake->toValue(*state);
auto vApply = state->allocValue();
state->eval(state->parseExprFromString(*applyToInstallable, absPath(".")), *vApply);
auto vRes = state->allocValue();
state->callFunction(*vApply, *v, *vRes, noPos);
result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vRes, ""));
} else {
result.push_back(installableFlake);
}
continue; continue;
} catch (...) { } catch (...) {
ex = std::current_exception(); ex = std::current_exception();