mirror of
https://github.com/NixOS/nix.git
synced 2025-11-20 01:09:37 +01:00
Allow overring module options from the command line
E.g. $ nix build github:tweag/nix-ux/configs?dir=configs#hello --argstr who Everybody $ ./result/bin/hello Hello Everybody This works by generating a new flake that imports the specified one and sets the specified module options.
This commit is contained in:
parent
b068f96b92
commit
dc4a280318
6 changed files with 80 additions and 10 deletions
|
|
@ -78,7 +78,7 @@ struct CmdBundle : InstallableCommand
|
|||
auto bundler = InstallableFlake(
|
||||
evalState, std::move(bundlerFlakeRef),
|
||||
Strings{bundlerName == "" ? "defaultBundler" : bundlerName},
|
||||
Strings({"bundlers."}), lockFlags);
|
||||
Strings({"bundlers."}), lockFlags, nullptr);
|
||||
|
||||
Value * arg = evalState->allocValue();
|
||||
evalState->mkAttrs(*arg, 2);
|
||||
|
|
|
|||
|
|
@ -395,7 +395,8 @@ struct CmdDevelop : Common, MixEnvironment
|
|||
installable->nixpkgsFlakeRef(),
|
||||
Strings{"bashInteractive"},
|
||||
Strings{"legacyPackages." + settings.thisSystem.get() + "."},
|
||||
lockFlags);
|
||||
lockFlags,
|
||||
nullptr);
|
||||
|
||||
shell = state->store->printStorePath(
|
||||
toStorePath(state->store, Realise::Outputs, OperateOn::Output, bashInstallable)) + "/bin/bash";
|
||||
|
|
|
|||
|
|
@ -563,7 +563,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
|
|||
auto installable = InstallableFlake(
|
||||
evalState, std::move(templateFlakeRef),
|
||||
Strings{templateName == "" ? "defaultTemplate" : templateName},
|
||||
Strings(attrsPathPrefixes), lockFlags);
|
||||
Strings(attrsPathPrefixes), lockFlags, nullptr);
|
||||
|
||||
auto [cursor, attrPath] = installable.getCursor(*evalState);
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
#include "url.hh"
|
||||
#include "registry.hh"
|
||||
|
||||
#include "../cpptoml/cpptoml.h"
|
||||
|
||||
#include <regex>
|
||||
#include <queue>
|
||||
|
||||
|
|
@ -549,8 +551,61 @@ InstallableFlake::getCursors(EvalState & state)
|
|||
|
||||
std::shared_ptr<flake::LockedFlake> InstallableFlake::getLockedFlake() const
|
||||
{
|
||||
if (!_lockedFlake)
|
||||
if (!_lockedFlake) {
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlags));
|
||||
|
||||
if (options && options->size()) {
|
||||
/* Get the modules defined by this flake. */
|
||||
auto cache = openEvalCache(*state, _lockedFlake);
|
||||
auto root = cache->getRoot();
|
||||
auto aModules = root->maybeGetAttr(state->symbols.create("modules"));
|
||||
if (!aModules)
|
||||
throw Error("flake '%s' has no modules, so --arg cannot override anything", flakeRef);
|
||||
|
||||
auto toml = cpptoml::make_table();
|
||||
|
||||
auto base = cpptoml::make_table();
|
||||
base->insert("type", "path");
|
||||
base->insert("path", _lockedFlake->flake.sourceInfo->actualPath);
|
||||
if (_lockedFlake->flake.lockedRef.subdir != "")
|
||||
base->insert("dir", _lockedFlake->flake.lockedRef.subdir);
|
||||
// FIXME: copy rev etc.
|
||||
auto inputs = cpptoml::make_table();
|
||||
inputs->insert("base", base);
|
||||
|
||||
toml->insert("inputs", inputs);
|
||||
|
||||
for (auto & moduleName : aModules->getAttrs()) {
|
||||
auto module = cpptoml::make_table();
|
||||
auto extends = cpptoml::make_array();
|
||||
extends->push_back("base#" + (std::string) moduleName);
|
||||
module->insert("extends", extends);
|
||||
for (auto & option : options->lexicographicOrder()) {
|
||||
state->forceValue(*option->value);
|
||||
if (option->value->type == tString)
|
||||
module->insert(option->name, state->forceString(*option->value));
|
||||
else if (option->value->type == tInt)
|
||||
module->insert(option->name, option->value->integer);
|
||||
else
|
||||
throw Error("option '%s' is %s which is not supported",
|
||||
option->name, showType(*option->value));
|
||||
}
|
||||
toml->insert(moduleName, module);
|
||||
}
|
||||
|
||||
auto tempDir = createTempDir();
|
||||
AutoDelete cleanup(tempDir);
|
||||
|
||||
std::ostringstream str;
|
||||
str << *toml;
|
||||
debug("writing temporary flake:\n%s", str.str());
|
||||
writeFile(tempDir + "/nix.toml", str.str());
|
||||
|
||||
_lockedFlake = std::make_shared<flake::LockedFlake>(lockFlake(*state,
|
||||
parseFlakeRef("path://" + tempDir), lockFlags));
|
||||
}
|
||||
}
|
||||
|
||||
return _lockedFlake;
|
||||
}
|
||||
|
||||
|
|
@ -600,10 +655,14 @@ std::vector<std::shared_ptr<Installable>> SourceExprCommand::parseInstallables(
|
|||
|
||||
try {
|
||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath("."));
|
||||
auto state = getEvalState();
|
||||
result.push_back(std::make_shared<InstallableFlake>(
|
||||
getEvalState(), std::move(flakeRef),
|
||||
state,
|
||||
std::move(flakeRef),
|
||||
fragment == "" ? getDefaultFlakeAttrPaths() : Strings{fragment},
|
||||
getDefaultFlakeAttrPathPrefixes(), lockFlags));
|
||||
getDefaultFlakeAttrPathPrefixes(),
|
||||
lockFlags,
|
||||
getAutoArgs(*state)));
|
||||
continue;
|
||||
} catch (...) {
|
||||
ex = std::current_exception();
|
||||
|
|
|
|||
|
|
@ -98,11 +98,17 @@ struct InstallableFlake : InstallableValue
|
|||
Strings prefixes;
|
||||
const flake::LockFlags & lockFlags;
|
||||
mutable std::shared_ptr<flake::LockedFlake> _lockedFlake;
|
||||
Bindings * options;
|
||||
|
||||
InstallableFlake(ref<EvalState> state, FlakeRef && flakeRef,
|
||||
Strings && attrPaths, Strings && prefixes, const flake::LockFlags & lockFlags)
|
||||
InstallableFlake(
|
||||
ref<EvalState> state,
|
||||
FlakeRef && flakeRef,
|
||||
Strings && attrPaths,
|
||||
Strings && prefixes, const
|
||||
flake::LockFlags & lockFlags,
|
||||
Bindings * options)
|
||||
: InstallableValue(state), flakeRef(flakeRef), attrPaths(attrPaths),
|
||||
prefixes(prefixes), lockFlags(lockFlags)
|
||||
prefixes(prefixes), lockFlags(lockFlags), options(options)
|
||||
{ }
|
||||
|
||||
std::string what() override { return flakeRef.to_string() + "#" + *attrPaths.begin(); }
|
||||
|
|
|
|||
|
|
@ -342,7 +342,11 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf
|
|||
Activity act(*logger, lvlChatty, actUnknown,
|
||||
fmt("checking '%s' for updates", element.source->attrPath));
|
||||
|
||||
InstallableFlake installable(getEvalState(), FlakeRef(element.source->originalRef), {element.source->attrPath}, {}, lockFlags);
|
||||
InstallableFlake installable(
|
||||
getEvalState(),
|
||||
FlakeRef(element.source->originalRef),
|
||||
{element.source->attrPath},
|
||||
{}, lockFlags, nullptr);
|
||||
|
||||
auto [attrPath, resolvedRef, drv] = installable.toDerivation();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue