Make subcommand construction in MultiCommand lazy

(cherry picked from commit a0de58f471)
This commit is contained in:
Eelco Dolstra 2019-06-18 16:01:35 +02:00
parent f964f428fe
commit ac67685606
28 changed files with 61 additions and 201 deletions

View file

@ -215,17 +215,15 @@ void Command::printHelp(const string & programName, std::ostream & out)
} }
} }
MultiCommand::MultiCommand(const std::vector<ref<Command>> & _commands) MultiCommand::MultiCommand(const Commands & commands)
: commands(commands)
{ {
for (auto & command : _commands)
commands.emplace(command->name(), command);
expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) { expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) {
assert(!command); assert(!command);
auto i = commands.find(ss[0]); auto i = commands.find(ss[0]);
if (i == commands.end()) if (i == commands.end())
throw UsageError("'%s' is not a recognised command", ss[0]); throw UsageError("'%s' is not a recognised command", ss[0]);
command = i->second; command = i->second();
}}); }});
} }
@ -246,10 +244,11 @@ void MultiCommand::printHelp(const string & programName, std::ostream & out)
out << "Available commands:\n"; out << "Available commands:\n";
Table2 table; Table2 table;
for (auto & command : commands) { for (auto & i : commands) {
auto descr = command.second->description(); auto command = i.second();
auto descr = command->description();
if (!descr.empty()) if (!descr.empty())
table.push_back(std::make_pair(command.second->name(), descr)); table.push_back(std::make_pair(command->name(), descr));
} }
printTable(out, table); printTable(out, table);
} }

View file

@ -192,8 +192,15 @@ public:
run() method. */ run() method. */
struct Command : virtual Args struct Command : virtual Args
{ {
private:
std::string _name;
public:
virtual ~Command() { } virtual ~Command() { }
virtual std::string name() = 0;
std::string name() { return _name; }
virtual void prepare() { }; virtual void prepare() { };
virtual void run() = 0; virtual void run() = 0;
@ -210,7 +217,7 @@ struct Command : virtual Args
void printHelp(const string & programName, std::ostream & out) override; void printHelp(const string & programName, std::ostream & out) override;
}; };
typedef std::map<std::string, ref<Command>> Commands; typedef std::map<std::string, std::function<ref<Command>()>> Commands;
/* An argument parser that supports multiple subcommands, /* An argument parser that supports multiple subcommands,
i.e. <command> <subcommand>. */ i.e. <command> <subcommand>. */
@ -221,7 +228,7 @@ public:
std::shared_ptr<Command> command; std::shared_ptr<Command> command;
MultiCommand(const std::vector<ref<Command>> & commands); MultiCommand(const Commands & commands);
void printHelp(const string & programName, std::ostream & out) override; void printHelp(const string & programName, std::ostream & out) override;

View file

@ -22,11 +22,6 @@ struct CmdAddToStore : MixDryRun, StoreCommand
.dest(&namePart); .dest(&namePart);
} }
std::string name() override
{
return "add-to-store";
}
std::string description() override std::string description() override
{ {
return "add a path to the Nix store"; return "add a path to the Nix store";
@ -58,4 +53,4 @@ struct CmdAddToStore : MixDryRun, StoreCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdAddToStore>()); static auto r1 = registerCommand<CmdAddToStore>("add-to-store");

View file

@ -24,11 +24,6 @@ struct CmdBuild : MixDryRun, InstallablesCommand
.set(&outLink, Path("")); .set(&outLink, Path(""));
} }
std::string name() override
{
return "build";
}
std::string description() override std::string description() override
{ {
return "build a derivation or fetch a store path"; return "build a derivation or fetch a store path";
@ -69,4 +64,4 @@ struct CmdBuild : MixDryRun, InstallablesCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdBuild>()); static auto r1 = registerCommand<CmdBuild>("build");

View file

@ -28,11 +28,6 @@ struct CmdCatStore : StoreCommand, MixCat
expectArg("path", &path); expectArg("path", &path);
} }
std::string name() override
{
return "cat-store";
}
std::string description() override std::string description() override
{ {
return "print the contents of a store file on stdout"; return "print the contents of a store file on stdout";
@ -54,11 +49,6 @@ struct CmdCatNar : StoreCommand, MixCat
expectArg("path", &path); expectArg("path", &path);
} }
std::string name() override
{
return "cat-nar";
}
std::string description() override std::string description() override
{ {
return "print the contents of a file inside a NAR file"; return "print the contents of a file inside a NAR file";
@ -70,5 +60,5 @@ struct CmdCatNar : StoreCommand, MixCat
} }
}; };
static RegisterCommand r1(make_ref<CmdCatStore>()); static auto r1 = registerCommand<CmdCatStore>("cat-store");
static RegisterCommand r2(make_ref<CmdCatNar>()); static auto r2 = registerCommand<CmdCatNar>("cat-nar");

View file

@ -5,7 +5,7 @@
namespace nix { namespace nix {
std::vector<ref<Command>> * RegisterCommand::commands = 0; Commands * RegisterCommand::commands = nullptr;
StoreCommand::StoreCommand() StoreCommand::StoreCommand()
{ {

View file

@ -151,15 +151,22 @@ struct StorePathCommand : public InstallablesCommand
/* A helper class for registering commands globally. */ /* A helper class for registering commands globally. */
struct RegisterCommand struct RegisterCommand
{ {
static std::vector<ref<Command>> * commands; static Commands * commands;
RegisterCommand(ref<Command> command) RegisterCommand(const std::string & name,
std::function<ref<Command>()> command)
{ {
if (!commands) commands = new std::vector<ref<Command>>; if (!commands) commands = new Commands;
commands->push_back(command); commands->emplace(name, command);
} }
}; };
template<class T>
static RegisterCommand registerCommand(const std::string & name)
{
return RegisterCommand(name, [](){ return make_ref<T>(); });
}
std::shared_ptr<Installable> parseInstallable( std::shared_ptr<Installable> parseInstallable(
SourceExprCommand & cmd, ref<Store> store, const std::string & installable, SourceExprCommand & cmd, ref<Store> store, const std::string & installable,
bool useDefaultInstallables); bool useDefaultInstallables);

View file

@ -42,11 +42,6 @@ struct CmdCopy : StorePathsCommand
.set(&substitute, Substitute); .set(&substitute, Substitute);
} }
std::string name() override
{
return "copy";
}
std::string description() override std::string description() override
{ {
return "copy paths between Nix stores"; return "copy paths between Nix stores";
@ -97,4 +92,4 @@ struct CmdCopy : StorePathsCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdCopy>()); static auto r1 = registerCommand<CmdCopy>("copy");

View file

@ -38,11 +38,6 @@ struct CmdDoctor : StoreCommand
{ {
bool success = true; bool success = true;
std::string name() override
{
return "doctor";
}
std::string description() override std::string description() override
{ {
return "check your system for potential problems and print a PASS or FAIL for each check."; return "check your system for potential problems and print a PASS or FAIL for each check.";
@ -136,4 +131,4 @@ struct CmdDoctor : StoreCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdDoctor>()); static auto r1 = registerCommand<CmdDoctor>("doctore");

View file

@ -5,11 +5,6 @@ using namespace nix;
struct CmdDumpPath : StorePathCommand struct CmdDumpPath : StorePathCommand
{ {
std::string name() override
{
return "dump-path";
}
std::string description() override std::string description() override
{ {
return "dump a store path to stdout (in NAR format)"; return "dump a store path to stdout (in NAR format)";
@ -33,4 +28,4 @@ struct CmdDumpPath : StorePathCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdDumpPath>()); static auto r1 = registerCommand<CmdDumpPath>("dump-path");

View file

@ -10,11 +10,6 @@ using namespace nix;
struct CmdEdit : InstallableCommand struct CmdEdit : InstallableCommand
{ {
std::string name() override
{
return "edit";
}
std::string description() override std::string description() override
{ {
return "open the Nix expression of a Nix package in $EDITOR"; return "open the Nix expression of a Nix package in $EDITOR";
@ -50,4 +45,4 @@ struct CmdEdit : InstallableCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdEdit>()); static auto r1 = registerCommand<CmdEdit>("edit");

View file

@ -18,11 +18,6 @@ struct CmdEval : MixJSON, InstallableCommand
mkFlag(0, "raw", "print strings unquoted", &raw); mkFlag(0, "raw", "print strings unquoted", &raw);
} }
std::string name() override
{
return "eval";
}
std::string description() override std::string description() override
{ {
return "evaluate a Nix expression"; return "evaluate a Nix expression";
@ -74,4 +69,4 @@ struct CmdEval : MixJSON, InstallableCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdEval>()); static auto r1 = registerCommand<CmdEval>("eval");

View file

@ -36,11 +36,6 @@ struct CmdHash : Command
expectArgs("paths", &paths); expectArgs("paths", &paths);
} }
std::string name() override
{
return mode == mFile ? "hash-file" : "hash-path";
}
std::string description() override std::string description() override
{ {
return mode == mFile return mode == mFile
@ -71,8 +66,8 @@ struct CmdHash : Command
} }
}; };
static RegisterCommand r1(make_ref<CmdHash>(CmdHash::mFile)); static RegisterCommand r1("hash-file", [](){ return make_ref<CmdHash>(CmdHash::mFile); });
static RegisterCommand r2(make_ref<CmdHash>(CmdHash::mPath)); static RegisterCommand r2("hash-path", [](){ return make_ref<CmdHash>(CmdHash::mPath); });
struct CmdToBase : Command struct CmdToBase : Command
{ {
@ -88,15 +83,6 @@ struct CmdToBase : Command
expectArgs("strings", &args); expectArgs("strings", &args);
} }
std::string name() override
{
return
base == Base16 ? "to-base16" :
base == Base32 ? "to-base32" :
base == Base64 ? "to-base64" :
"to-sri";
}
std::string description() override std::string description() override
{ {
return fmt("convert a hash to %s representation", return fmt("convert a hash to %s representation",
@ -113,10 +99,10 @@ struct CmdToBase : Command
} }
}; };
static RegisterCommand r3(make_ref<CmdToBase>(Base16)); static RegisterCommand r3("to-base16", [](){ return make_ref<CmdToBase>(Base16); });
static RegisterCommand r4(make_ref<CmdToBase>(Base32)); static RegisterCommand r4("to-base32", [](){ return make_ref<CmdToBase>(Base32); });
static RegisterCommand r5(make_ref<CmdToBase>(Base64)); static RegisterCommand r5("to-base64", [](){ return make_ref<CmdToBase>(Base64); });
static RegisterCommand r6(make_ref<CmdToBase>(SRI)); static RegisterCommand r6("to-sri", [](){ return make_ref<CmdToBase>(SRI); });
/* Legacy nix-hash command. */ /* Legacy nix-hash command. */
static int compatNixHash(int argc, char * * argv) static int compatNixHash(int argc, char * * argv)

View file

@ -8,15 +8,6 @@ using namespace nix;
struct CmdLog : InstallableCommand struct CmdLog : InstallableCommand
{ {
CmdLog()
{
}
std::string name() override
{
return "log";
}
std::string description() override std::string description() override
{ {
return "show the build log of the specified packages or paths, if available"; return "show the build log of the specified packages or paths, if available";
@ -68,4 +59,4 @@ struct CmdLog : InstallableCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdLog>()); static auto r1 = registerCommand<CmdLog>("log");

View file

@ -100,11 +100,6 @@ struct CmdLsStore : StoreCommand, MixLs
}; };
} }
std::string name() override
{
return "ls-store";
}
std::string description() override std::string description() override
{ {
return "show information about a store path"; return "show information about a store path";
@ -136,11 +131,6 @@ struct CmdLsNar : Command, MixLs
}; };
} }
std::string name() override
{
return "ls-nar";
}
std::string description() override std::string description() override
{ {
return "show information about the contents of a NAR file"; return "show information about the contents of a NAR file";
@ -152,5 +142,5 @@ struct CmdLsNar : Command, MixLs
} }
}; };
static RegisterCommand r1(make_ref<CmdLsStore>()); static auto r1 = registerCommand<CmdLsStore>("ls-store");
static RegisterCommand r2(make_ref<CmdLsNar>()); static auto r2 = registerCommand<CmdLsNar>("ls-nar");

View file

@ -11,11 +11,6 @@ struct CmdMakeContentAddressable : StorePathsCommand
realiseMode = Build; realiseMode = Build;
} }
std::string name() override
{
return "make-content-addressable";
}
std::string description() override std::string description() override
{ {
return "rewrite a path or closure to content-addressable form"; return "rewrite a path or closure to content-addressable form";
@ -92,4 +87,4 @@ struct CmdMakeContentAddressable : StorePathsCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdMakeContentAddressable>()); static auto r1 = registerCommand<CmdMakeContentAddressable>("make-content-addressable");

View file

@ -8,15 +8,6 @@ using namespace nix;
struct CmdOptimiseStore : StoreCommand struct CmdOptimiseStore : StoreCommand
{ {
CmdOptimiseStore()
{
}
std::string name() override
{
return "optimise-store";
}
std::string description() override std::string description() override
{ {
return "replace identical files in the store by hard links"; return "replace identical files in the store by hard links";
@ -38,4 +29,4 @@ struct CmdOptimiseStore : StoreCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdOptimiseStore>()); static auto r1 = registerCommand<CmdOptimiseStore>("optimise-store");

View file

@ -24,11 +24,6 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
mkFlag(0, "sigs", "show signatures", &showSigs); mkFlag(0, "sigs", "show signatures", &showSigs);
} }
std::string name() override
{
return "path-info";
}
std::string description() override std::string description() override
{ {
return "query information about store paths"; return "query information about store paths";
@ -130,4 +125,4 @@ struct CmdPathInfo : StorePathsCommand, MixJSON
} }
}; };
static RegisterCommand r1(make_ref<CmdPathInfo>()); static auto r1 = registerCommand<CmdPathInfo>("path-info");

View file

@ -6,11 +6,6 @@ using namespace nix;
struct CmdPingStore : StoreCommand struct CmdPingStore : StoreCommand
{ {
std::string name() override
{
return "ping-store";
}
std::string description() override std::string description() override
{ {
return "test whether a store can be opened"; return "test whether a store can be opened";
@ -32,4 +27,4 @@ struct CmdPingStore : StoreCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdPingStore>()); static auto r1 = registerCommand<CmdPingStore>("ping-store");

View file

@ -801,8 +801,6 @@ struct CmdRepl : StoreCommand, MixEvalArgs
expectArgs("files", &files); expectArgs("files", &files);
} }
std::string name() override { return "repl"; }
std::string description() override std::string description() override
{ {
return "start an interactive environment for evaluating Nix expressions"; return "start an interactive environment for evaluating Nix expressions";
@ -816,6 +814,6 @@ struct CmdRepl : StoreCommand, MixEvalArgs
} }
}; };
static RegisterCommand r1(make_ref<CmdRepl>()); static auto r1 = registerCommand<CmdRepl>("repl");
} }

View file

@ -61,11 +61,6 @@ struct CmdRun : InstallablesCommand
.handler([&](std::vector<std::string> ss) { unset.insert(ss.front()); }); .handler([&](std::vector<std::string> ss) { unset.insert(ss.front()); });
} }
std::string name() override
{
return "run";
}
std::string description() override std::string description() override
{ {
return "run a shell in which the specified packages are available"; return "run a shell in which the specified packages are available";
@ -182,7 +177,7 @@ struct CmdRun : InstallablesCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdRun>()); static auto r1 = registerCommand<CmdRun>("run");
void chrootHelper(int argc, char * * argv) void chrootHelper(int argc, char * * argv)
{ {

View file

@ -52,11 +52,6 @@ struct CmdSearch : SourceExprCommand, MixJSON
.handler([&]() { writeCache = false; useCache = false; }); .handler([&]() { writeCache = false; useCache = false; });
} }
std::string name() override
{
return "search";
}
std::string description() override std::string description() override
{ {
return "query available packages"; return "query available packages";
@ -277,4 +272,4 @@ struct CmdSearch : SourceExprCommand, MixJSON
} }
}; };
static RegisterCommand r1(make_ref<CmdSearch>()); static auto r1 = registerCommand<CmdSearch>("search");

View file

@ -8,15 +8,6 @@ using namespace nix;
struct CmdShowConfig : Command, MixJSON struct CmdShowConfig : Command, MixJSON
{ {
CmdShowConfig()
{
}
std::string name() override
{
return "show-config";
}
std::string description() override std::string description() override
{ {
return "show the Nix configuration"; return "show the Nix configuration";
@ -37,4 +28,4 @@ struct CmdShowConfig : Command, MixJSON
} }
}; };
static RegisterCommand r1(make_ref<CmdShowConfig>()); static auto r1 = registerCommand<CmdShowConfig>("show-config");

View file

@ -22,11 +22,6 @@ struct CmdShowDerivation : InstallablesCommand
.set(&recursive, true); .set(&recursive, true);
} }
std::string name() override
{
return "show-derivation";
}
std::string description() override std::string description() override
{ {
return "show the contents of a store derivation"; return "show the contents of a store derivation";
@ -116,4 +111,4 @@ struct CmdShowDerivation : InstallablesCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdShowDerivation>()); static auto r1 = registerCommand<CmdShowDerivation>("show-derivation");

View file

@ -22,11 +22,6 @@ struct CmdCopySigs : StorePathsCommand
.handler([&](std::vector<std::string> ss) { substituterUris.push_back(ss[0]); }); .handler([&](std::vector<std::string> ss) { substituterUris.push_back(ss[0]); });
} }
std::string name() override
{
return "copy-sigs";
}
std::string description() override std::string description() override
{ {
return "copy path signatures from substituters (like binary caches)"; return "copy path signatures from substituters (like binary caches)";
@ -93,7 +88,7 @@ struct CmdCopySigs : StorePathsCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdCopySigs>()); static auto r1 = registerCommand<CmdCopySigs>("copy-sigs");
struct CmdSignPaths : StorePathsCommand struct CmdSignPaths : StorePathsCommand
{ {
@ -109,11 +104,6 @@ struct CmdSignPaths : StorePathsCommand
.dest(&secretKeyFile); .dest(&secretKeyFile);
} }
std::string name() override
{
return "sign-paths";
}
std::string description() override std::string description() override
{ {
return "sign the specified paths"; return "sign the specified paths";
@ -146,4 +136,4 @@ struct CmdSignPaths : StorePathsCommand
} }
}; };
static RegisterCommand r3(make_ref<CmdSignPaths>()); static auto r2 = registerCommand<CmdSignPaths>("sign-paths");

View file

@ -30,11 +30,6 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
.dest(&storePathsUrl); .dest(&storePathsUrl);
} }
std::string name() override
{
return "upgrade-nix";
}
std::string description() override std::string description() override
{ {
return "upgrade Nix to the latest stable version"; return "upgrade Nix to the latest stable version";
@ -157,4 +152,4 @@ struct CmdUpgradeNix : MixDryRun, StoreCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdUpgradeNix>()); static auto r1 = registerCommand<CmdUpgradeNix>("upgrade-nix");

View file

@ -30,11 +30,6 @@ struct CmdVerify : StorePathsCommand
mkIntFlag('n', "sigs-needed", "require that each path has at least N valid signatures", &sigsNeeded); mkIntFlag('n', "sigs-needed", "require that each path has at least N valid signatures", &sigsNeeded);
} }
std::string name() override
{
return "verify";
}
std::string description() override std::string description() override
{ {
return "verify the integrity of store paths"; return "verify the integrity of store paths";
@ -180,4 +175,4 @@ struct CmdVerify : StorePathsCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdVerify>()); static auto r1 = registerCommand<CmdVerify>("verify");

View file

@ -44,11 +44,6 @@ struct CmdWhyDepends : SourceExprCommand
.set(&all, true); .set(&all, true);
} }
std::string name() override
{
return "why-depends";
}
std::string description() override std::string description() override
{ {
return "show why a package has another package in its closure"; return "show why a package has another package in its closure";
@ -264,4 +259,4 @@ struct CmdWhyDepends : SourceExprCommand
} }
}; };
static RegisterCommand r1(make_ref<CmdWhyDepends>()); static auto r1 = registerCommand<CmdWhyDepends>("why-depends");