mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-11 00:36:20 +02:00
patch: cli overrides beta, nix-dram edition
This commit is contained in:
parent
78384699de
commit
9e592b8085
2 changed files with 171 additions and 21 deletions
|
@ -95,6 +95,10 @@ 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;
|
std::optional<std::string> applyToInstallable;
|
||||||
|
std::optional<std::string> installableOverrideAttrs;
|
||||||
|
std::optional<std::string> installableWithPackages;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> overrideArgs;
|
||||||
|
|
||||||
// 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;
|
||||||
|
@ -102,10 +106,14 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions
|
||||||
SourceExprCommand();
|
SourceExprCommand();
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Installable>> parseInstallables(
|
std::vector<std::shared_ptr<Installable>> parseInstallables(
|
||||||
ref<Store> store, std::vector<std::string> ss);
|
ref<Store> store, std::vector<std::string> ss,
|
||||||
|
bool applyOverrides = true, bool nestedIsExprOk = true);
|
||||||
|
|
||||||
|
Bindings * getOverrideArgs(EvalState & state, ref<Store> store);
|
||||||
|
|
||||||
std::shared_ptr<Installable> parseInstallable(
|
std::shared_ptr<Installable> parseInstallable(
|
||||||
ref<Store> store, const std::string & installable);
|
ref<Store> store, const std::string & installable,
|
||||||
|
bool applyOverrides = true, bool nestedIsExprOk = true);
|
||||||
|
|
||||||
virtual Strings getDefaultFlakeAttrPaths();
|
virtual Strings getDefaultFlakeAttrPaths();
|
||||||
|
|
||||||
|
|
|
@ -166,6 +166,46 @@ SourceExprCommand::SourceExprCommand()
|
||||||
.labels = {"expr"},
|
.labels = {"expr"},
|
||||||
.handler = {&applyToInstallable},
|
.handler = {&applyToInstallable},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addFlag({
|
||||||
|
.longName = "override",
|
||||||
|
.description = "Override derivation arguments: --override *name* *expr*",
|
||||||
|
.category = installablesCategory,
|
||||||
|
.labels = {"name", "expr"},
|
||||||
|
.handler = {[&](std::string name, std::string expr) { overrideArgs[name] = 'E' + expr; }}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFlag({
|
||||||
|
.longName = "override-pkg",
|
||||||
|
.description = "Override dependency *name* of the given derivations with other packages, using *flakeref*.",
|
||||||
|
.category = installablesCategory,
|
||||||
|
.labels = {"name", "flakeref"},
|
||||||
|
.handler = {[&](std::string name, std::string expr) { overrideArgs[name] = 'F' + expr; }}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFlag({
|
||||||
|
.longName = "override-from",
|
||||||
|
.description = "Override dependency *name* of the given derivations with other packages, using *attrpath*. (Only applicable when using --file)",
|
||||||
|
.category = installablesCategory,
|
||||||
|
.labels = {"name", "attrpath"},
|
||||||
|
.handler = {[&](std::string name, std::string expr) { overrideArgs[name] = 'X' + expr; }}
|
||||||
|
});
|
||||||
|
|
||||||
|
addFlag({
|
||||||
|
.longName = "override-attrs",
|
||||||
|
.description = "Override the given derivations' attributes using *expr*.",
|
||||||
|
.category = installablesCategory,
|
||||||
|
.labels = {"expr"},
|
||||||
|
.handler = {&installableOverrideAttrs},
|
||||||
|
});
|
||||||
|
|
||||||
|
addFlag({
|
||||||
|
.longName = "with",
|
||||||
|
.description = "Enhance the given derivations using an environment specified in *expr*.",
|
||||||
|
.category = installablesCategory,
|
||||||
|
.labels = {"expr"},
|
||||||
|
.handler = {&installableWithPackages},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Strings SourceExprCommand::getDefaultFlakeAttrPaths()
|
Strings SourceExprCommand::getDefaultFlakeAttrPaths()
|
||||||
|
@ -731,12 +771,44 @@ FlakeRef InstallableFlake::nixpkgsFlakeRef() const
|
||||||
return Installable::nixpkgsFlakeRef();
|
return Installable::nixpkgsFlakeRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bindings * SourceExprCommand::getOverrideArgs(EvalState & state, ref<Store> store)
|
||||||
|
{
|
||||||
|
Bindings * res = state.allocBindings(overrideArgs.size());
|
||||||
|
for (auto & i : overrideArgs) {
|
||||||
|
Value * v = state.allocValue();
|
||||||
|
if (i.second[0] == 'E') {
|
||||||
|
// is a raw expression, parse
|
||||||
|
state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
|
||||||
|
} else if (i.second[0] == 'F') {
|
||||||
|
// is a flakeref
|
||||||
|
auto [vNew, pos] = parseInstallable(store, string(i.second, 1), false, false)->toValue(state);
|
||||||
|
v = vNew;
|
||||||
|
} else if (i.second[0] == 'X') {
|
||||||
|
// is not a flakeref, use attrPath from file
|
||||||
|
// error because --override covers expressions already
|
||||||
|
if (!file)
|
||||||
|
throw Error("no file to reference override from");
|
||||||
|
auto [vNew, pos] = parseInstallable(store, string(i.second, 1), false, true)->toValue(state);
|
||||||
|
v = vNew;
|
||||||
|
} else {
|
||||||
|
throw Error("[BUG] unknown argtype %s",i.second[0]);
|
||||||
|
}
|
||||||
|
res->push_back(Attr(state.symbols.create(i.first), v));
|
||||||
|
}
|
||||||
|
res->sort();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||||
ref<Store> store, std::vector<std::string> ss)
|
ref<Store> store, std::vector<std::string> ss,
|
||||||
|
bool applyOverrides, bool nestedIsExprOk)
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<Installable>> result;
|
std::vector<std::shared_ptr<Installable>> result;
|
||||||
|
|
||||||
if (file || expr) {
|
auto modifyInstallable = applyOverrides && ( applyToInstallable
|
||||||
|
|| installableOverrideAttrs || installableWithPackages || overrideArgs.size() > 0 );
|
||||||
|
|
||||||
|
if (nestedIsExprOk && (file || expr)) {
|
||||||
if (file && expr)
|
if (file && expr)
|
||||||
throw UsageError("'--file' and '--expr' are exclusive");
|
throw UsageError("'--file' and '--expr' are exclusive");
|
||||||
|
|
||||||
|
@ -753,26 +825,62 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||||
state->eval(e, *vFile);
|
state->eval(e, *vFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (applyToInstallable) {
|
for (auto & s : ss) {
|
||||||
auto vApply = state->allocValue();
|
auto installableAttr = std::make_shared<InstallableAttrPath>(state, *this, vFile, s == "." ? "" : s);
|
||||||
state->eval(state->parseExprFromString(*applyToInstallable, absPath(".")), *vApply);
|
if (modifyInstallable) {
|
||||||
auto vRes = state->allocValue();
|
auto [v, pos] = installableAttr->toValue(*state);
|
||||||
state->callFunction(*vApply, *vFile, *vRes, noPos);
|
auto vApply = state->allocValue();
|
||||||
vFile = vRes;
|
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);
|
||||||
|
}
|
||||||
|
result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vRes, ""));
|
||||||
|
} else {
|
||||||
|
result.push_back(installableAttr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & s : ss)
|
|
||||||
result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vFile, s == "." ? "" : s));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
for (auto & s : ss) {
|
for (auto & s : ss) {
|
||||||
std::exception_ptr ex;
|
std::exception_ptr ex;
|
||||||
|
|
||||||
if (s.find('/') != std::string::npos) {
|
if (s.find('/') != std::string::npos) {
|
||||||
if (applyToInstallable) {
|
/*if (modifyInstallable) {
|
||||||
throw Error("cannot apply function: installable cannot be evaluated");
|
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;
|
||||||
|
@ -800,12 +908,45 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||||
getDefaultFlakeAttrPaths(),
|
getDefaultFlakeAttrPaths(),
|
||||||
getDefaultFlakeAttrPathPrefixes(),
|
getDefaultFlakeAttrPathPrefixes(),
|
||||||
lockFlags);
|
lockFlags);
|
||||||
if (applyToInstallable) {
|
if (modifyInstallable) {
|
||||||
auto [v, pos] = installableFlake->toValue(*state);
|
auto [v, pos] = installableFlake->toValue(*state);
|
||||||
auto vApply = state->allocValue();
|
auto vApply = state->allocValue();
|
||||||
state->eval(state->parseExprFromString(*applyToInstallable, absPath(".")), *vApply);
|
|
||||||
auto vRes = state->allocValue();
|
auto vRes = state->allocValue();
|
||||||
state->callFunction(*vApply, *v, *vRes, noPos);
|
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>(state, *this, vRes, ""));
|
result.push_back(std::make_shared<InstallableAttrPath>(state, *this, vRes, ""));
|
||||||
} else {
|
} else {
|
||||||
result.push_back(installableFlake);
|
result.push_back(installableFlake);
|
||||||
|
@ -823,9 +964,10 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
|
std::shared_ptr<Installable> SourceExprCommand::parseInstallable(
|
||||||
ref<Store> store, const std::string & installable)
|
ref<Store> store, const std::string & installable,
|
||||||
|
bool applyOverrides, bool nestedIsExprOk)
|
||||||
{
|
{
|
||||||
auto installables = parseInstallables(store, {installable});
|
auto installables = parseInstallables(store, {installable}, applyOverrides, nestedIsExprOk);
|
||||||
assert(installables.size() == 1);
|
assert(installables.size() == 1);
|
||||||
return installables.front();
|
return installables.front();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue