From 9cf91b7385e5b913126f0e2228d747b3d0953b1a Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sun, 17 Nov 2024 14:43:57 +0100 Subject: [PATCH] cli infra: modernize legacy command interface give legacy commands their program name and c++-converted argv directly instead of passing on the (argc, argv) pair untouched. all are required to process these things, and all of them do it in exactly the same way. we can also remove a few old helpers only used to make this less awful. Change-Id: I4ecd02343bca0cf85faf6fe043031d4f64c5f29c --- lix/legacy/build-remote.cc | 6 +++--- lix/legacy/nix-build.cc | 21 ++++++++------------- lix/legacy/nix-channel.cc | 6 +++--- lix/legacy/nix-collect-garbage.cc | 6 +++--- lix/legacy/nix-copy-closure.cc | 6 +++--- lix/legacy/nix-env.cc | 6 +++--- lix/legacy/nix-instantiate.cc | 6 +++--- lix/legacy/nix-store.cc | 6 +++--- lix/libcmd/legacy.hh | 3 ++- lix/libmain/shared.cc | 14 -------------- lix/libmain/shared.hh | 6 ------ lix/libutil/args.cc | 8 -------- lix/libutil/args.hh | 2 -- lix/nix/daemon.cc | 6 +++--- lix/nix/hash.cc | 6 +++--- lix/nix/main.cc | 4 ++-- lix/nix/prefetch.cc | 6 +++--- 17 files changed, 42 insertions(+), 76 deletions(-) diff --git a/lix/legacy/build-remote.cc b/lix/legacy/build-remote.cc index 7e659ebf8..e2d76d008 100644 --- a/lix/legacy/build-remote.cc +++ b/lix/legacy/build-remote.cc @@ -55,7 +55,7 @@ static bool allSupportedLocally(Store & store, const std::set& requ return true; } -static int main_build_remote(int argc, char * * argv) +static int main_build_remote(std::string programName, Strings argv) { { logger = makeJSONLogger(*logger); @@ -67,10 +67,10 @@ static int main_build_remote(int argc, char * * argv) /* If we ever use the common args framework, make sure to remove initPlugins below and initialize settings first. */ - if (argc != 2) + if (argv.size() != 1) throw UsageError("called without required arguments"); - verbosity = (Verbosity) std::stoll(argv[1]); + verbosity = (Verbosity) std::stoll(argv.front()); FdSource source(STDIN_FILENO); diff --git a/lix/legacy/nix-build.cc b/lix/legacy/nix-build.cc index 30b271bbd..7064e93df 100644 --- a/lix/legacy/nix-build.cc +++ b/lix/legacy/nix-build.cc @@ -33,10 +33,10 @@ namespace nix { using namespace std::string_literals; -static void main_nix_build(int argc, char * * argv) +static void main_nix_build(std::string programName, Strings argv) { auto dryRun = false; - auto runEnv = std::regex_search(argv[0], std::regex("nix-shell$")); + auto runEnv = std::regex_search(programName, std::regex("nix-shell$")); auto pure = false; auto fromArgs = false; auto packages = false; @@ -66,29 +66,24 @@ static void main_nix_build(int argc, char * * argv) "http_proxy", "https_proxy", "ftp_proxy", "all_proxy", "no_proxy" }; - Strings args; - for (int i = 1; i < argc; ++i) - args.push_back(argv[i]); - // Heuristic to see if we're invoked as a shebang script, namely, // if we have at least one argument, it's the name of an // executable file, and it starts with "#!". - if (runEnv && argc > 1) { - script = argv[1]; + if (runEnv && !argv.empty()) { + script = argv.front(); try { auto lines = tokenizeString(readFile(script), "\n"); if (std::regex_search(lines.front(), std::regex("^#!"))) { lines.pop_front(); inShebang = true; - for (int i = 2; i < argc; ++i) - savedArgs.push_back(argv[i]); - args.clear(); + savedArgs = {std::next(argv.begin()), argv.end()}; + argv.clear(); for (auto line : lines) { line = chomp(line); std::smatch match; if (std::regex_match(line, match, std::regex("^#!\\s*nix-shell\\s+(.*)$"))) for (const auto & word : shell_split(match[1].str())) - args.push_back(word); + argv.push_back(word); } } } catch (SysError &) { } @@ -191,7 +186,7 @@ static void main_nix_build(int argc, char * * argv) return true; }); - myArgs.parseCmdline(args); + myArgs.parseCmdline(argv); if (packages && fromArgs) throw UsageError("'-p' and '-E' are mutually exclusive"); diff --git a/lix/legacy/nix-channel.cc b/lix/legacy/nix-channel.cc index 042b96182..ac127f080 100644 --- a/lix/legacy/nix-channel.cc +++ b/lix/legacy/nix-channel.cc @@ -162,7 +162,7 @@ static void update(const StringSet & channelNames) replaceSymlink(profile, channelLink); } -static int main_nix_channel(int argc, char ** argv) +static int main_nix_channel(std::string programName, Strings argv) { { // Figure out the name of the `.nix-channels' file to use @@ -184,7 +184,7 @@ static int main_nix_channel(int argc, char ** argv) cRollback } cmd = cNone; std::vector args; - parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + LegacyArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") { showManPage("nix-channel"); } else if (*arg == "--version") { @@ -207,7 +207,7 @@ static int main_nix_channel(int argc, char ** argv) args.push_back(std::move(*arg)); } return true; - }); + }).parseCmdline(argv); switch (cmd) { case cNone: diff --git a/lix/legacy/nix-collect-garbage.cc b/lix/legacy/nix-collect-garbage.cc index 656ac0e51..b818611ab 100644 --- a/lix/legacy/nix-collect-garbage.cc +++ b/lix/legacy/nix-collect-garbage.cc @@ -56,14 +56,14 @@ void removeOldGenerations(std::string dir) } } -static int main_nix_collect_garbage(int argc, char * * argv) +static int main_nix_collect_garbage(std::string programName, Strings argv) { { bool removeOld = false; GCOptions options; - parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + LegacyArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") showManPage("nix-collect-garbage"); else if (*arg == "--version") @@ -79,7 +79,7 @@ static int main_nix_collect_garbage(int argc, char * * argv) else return false; return true; - }); + }).parseCmdline(argv); if (removeOld) { std::set dirsToClean = { diff --git a/lix/legacy/nix-copy-closure.cc b/lix/legacy/nix-copy-closure.cc index b56d4b833..ebed8a191 100644 --- a/lix/legacy/nix-copy-closure.cc +++ b/lix/legacy/nix-copy-closure.cc @@ -5,7 +5,7 @@ namespace nix { -static int main_nix_copy_closure(int argc, char ** argv) +static int main_nix_copy_closure(std::string programName, Strings argv) { { auto gzip = false; @@ -16,7 +16,7 @@ static int main_nix_copy_closure(int argc, char ** argv) std::string sshHost; PathSet storePaths; - parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + LegacyArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") showManPage("nix-copy-closure"); else if (*arg == "--version") @@ -42,7 +42,7 @@ static int main_nix_copy_closure(int argc, char ** argv) else storePaths.insert(*arg); return true; - }); + }).parseCmdline(argv); if (sshHost.empty()) throw UsageError("no host name specified"); diff --git a/lix/legacy/nix-env.cc b/lix/legacy/nix-env.cc index 5acea541d..f20673327 100644 --- a/lix/legacy/nix-env.cc +++ b/lix/legacy/nix-env.cc @@ -1395,7 +1395,7 @@ static void opVersion(Globals & globals, Strings opFlags, Strings opArgs) } -static int main_nix_env(int argc, char * * argv) +static int main_nix_env(std::string programName, Strings argv) { { Strings opFlags, opArgs; @@ -1434,7 +1434,7 @@ static int main_nix_env(int argc, char * * argv) using LegacyArgs::LegacyArgs; }; - MyArgs myArgs(std::string(baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) { + MyArgs myArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { Operation oldOp = op; if (*arg == "--help") @@ -1515,7 +1515,7 @@ static int main_nix_env(int argc, char * * argv) return true; }); - myArgs.parseCmdline(argvToStrings(argc, argv)); + myArgs.parseCmdline(argv); if (showHelp) showManPage("nix-env" + opName); if (!op) throw UsageError("no operation specified"); diff --git a/lix/legacy/nix-instantiate.cc b/lix/legacy/nix-instantiate.cc index bf39b0ef0..af6a67676 100644 --- a/lix/legacy/nix-instantiate.cc +++ b/lix/legacy/nix-instantiate.cc @@ -89,7 +89,7 @@ void processExpr(EvalState & state, const Strings & attrPaths, } -static int main_nix_instantiate(int argc, char * * argv) +static int main_nix_instantiate(std::string programName, Strings argv) { { Strings files; @@ -109,7 +109,7 @@ static int main_nix_instantiate(int argc, char * * argv) using LegacyArgs::LegacyArgs; }; - MyArgs myArgs(std::string(baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) { + MyArgs myArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") showManPage("nix-instantiate"); else if (*arg == "--version") @@ -149,7 +149,7 @@ static int main_nix_instantiate(int argc, char * * argv) return true; }); - myArgs.parseCmdline(argvToStrings(argc, argv)); + myArgs.parseCmdline(argv); if (evalOnly && !wantsReadWrite) settings.readOnlyMode = true; diff --git a/lix/legacy/nix-store.cc b/lix/legacy/nix-store.cc index 72600a141..d5c3d8fda 100644 --- a/lix/legacy/nix-store.cc +++ b/lix/legacy/nix-store.cc @@ -1031,7 +1031,7 @@ static void opVersion(Strings opFlags, Strings opArgs) /* Scan the arguments; find the operation, set global flags, put all other flags in a list, and put all other arguments in another list. */ -static int main_nix_store(int argc, char * * argv) +static int main_nix_store(std::string programName, Strings argv) { { Strings opFlags, opArgs; @@ -1040,7 +1040,7 @@ static int main_nix_store(int argc, char * * argv) std::string opName; bool showHelp = false; - parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + LegacyArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { Operation oldOp = op; if (*arg == "--help") @@ -1162,7 +1162,7 @@ static int main_nix_store(int argc, char * * argv) throw UsageError("only one operation may be specified"); return true; - }); + }).parseCmdline(argv); if (showHelp) showManPage("nix-store" + opName); if (!op) throw UsageError("no operation specified"); diff --git a/lix/libcmd/legacy.hh b/lix/libcmd/legacy.hh index 45a231983..9c80ae37d 100644 --- a/lix/libcmd/legacy.hh +++ b/lix/libcmd/legacy.hh @@ -2,12 +2,13 @@ ///@file #include +#include #include #include namespace nix { -typedef std::function MainFunction; +typedef std::function)> MainFunction; struct LegacyCommands { diff --git a/lix/libmain/shared.cc b/lix/libmain/shared.cc index 0aa9cca61..2d1728dce 100644 --- a/lix/libmain/shared.cc +++ b/lix/libmain/shared.cc @@ -267,20 +267,6 @@ bool LegacyArgs::processArgs(const Strings & args, bool finish) } -void parseCmdLine(int argc, char * * argv, - std::function parseArg) -{ - parseCmdLine(std::string(baseNameOf(argv[0])), argvToStrings(argc, argv), parseArg); -} - - -void parseCmdLine(const std::string & programName, const Strings & args, - std::function parseArg) -{ - LegacyArgs(programName, parseArg).parseCmdline(args); -} - - void printVersion(const std::string & programName) { std::cout << fmt("%1% (Lix, like Nix) %2%", programName, nixVersion) << std::endl; diff --git a/lix/libmain/shared.hh b/lix/libmain/shared.hh index df38c4c7f..20c6c4e60 100644 --- a/lix/libmain/shared.hh +++ b/lix/libmain/shared.hh @@ -21,12 +21,6 @@ int handleExceptions(const std::string & programName, std::function fun) */ void initNix(); -void parseCmdLine(int argc, char * * argv, - std::function parseArg); - -void parseCmdLine(const std::string & programName, const Strings & args, - std::function parseArg); - void printVersion(const std::string & programName); /** diff --git a/lix/libutil/args.cc b/lix/libutil/args.cc index ee9fa6b72..343101219 100644 --- a/lix/libutil/args.cc +++ b/lix/libutil/args.cc @@ -381,14 +381,6 @@ void Args::completeDir(AddCompletions & completions, size_t, std::string_view pr _completePath(completions, prefix, true); } -Strings argvToStrings(int argc, char * * argv) -{ - Strings args; - argc--; argv++; - while (argc--) args.push_back(*argv++); - return args; -} - std::optional Command::experimentalFeature () { return { Xp::NixCommand }; diff --git a/lix/libutil/args.hh b/lix/libutil/args.hh index 681d9c426..991695772 100644 --- a/lix/libutil/args.hh +++ b/lix/libutil/args.hh @@ -364,8 +364,6 @@ public: nlohmann::json toJSON() override; }; -Strings argvToStrings(int argc, char * * argv); - struct Completion { std::string completion; std::string description; diff --git a/lix/nix/daemon.cc b/lix/nix/daemon.cc index 0fe089e7f..e67197a0a 100644 --- a/lix/nix/daemon.cc +++ b/lix/nix/daemon.cc @@ -436,13 +436,13 @@ static void runDaemon(bool stdio, std::optional forceTrustClientOpt daemonLoop(forceTrustClientOpt); } -static int main_nix_daemon(int argc, char * * argv) +static int main_nix_daemon(std::string programName, Strings argv) { { auto stdio = false; std::optional isTrustedOpt = std::nullopt; - parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + LegacyArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--daemon") ; // ignored for backwards compatibility else if (*arg == "--help") @@ -462,7 +462,7 @@ static int main_nix_daemon(int argc, char * * argv) isTrustedOpt = std::nullopt; } else return false; return true; - }); + }).parseCmdline(argv); runDaemon(stdio, isTrustedOpt); diff --git a/lix/nix/hash.cc b/lix/nix/hash.cc index fbabe0345..0eb89b197 100644 --- a/lix/nix/hash.cc +++ b/lix/nix/hash.cc @@ -155,7 +155,7 @@ struct CmdHash : MultiCommand static auto rCmdHash = registerCommand("hash"); /* Legacy nix-hash command. */ -static int compatNixHash(int argc, char * * argv) +static int compatNixHash(std::string programName, Strings argv) { std::optional ht; bool flat = false; @@ -164,7 +164,7 @@ static int compatNixHash(int argc, char * * argv) enum { opHash, opTo } op = opHash; std::vector ss; - parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + LegacyArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") showManPage("nix-hash"); else if (*arg == "--version") @@ -200,7 +200,7 @@ static int compatNixHash(int argc, char * * argv) else ss.push_back(*arg); return true; - }); + }).parseCmdline(argv); if (op == opHash) { CmdHashBase cmd(flat ? FileIngestionMethod::Flat : FileIngestionMethod::Recursive); diff --git a/lix/nix/main.cc b/lix/nix/main.cc index 826b4f238..2de7c0105 100644 --- a/lix/nix/main.cc +++ b/lix/nix/main.cc @@ -391,7 +391,7 @@ void mainWrapped(int argc, char * * argv) { registerLegacyCommands(); auto legacy = (*LegacyCommands::commands)[programName]; - if (legacy) return legacy(argc, argv); + if (legacy) return legacy(std::string(baseNameOf(argv[0])), Strings(argv + 1, argv + argc)); } evalSettings.pureEval.setDefault(true); @@ -479,7 +479,7 @@ void mainWrapped(int argc, char * * argv) }); try { - args.parseCmdline(argvToStrings(argc, argv)); + args.parseCmdline({argv + 1, argv + argc}); } catch (UsageError &) { if (!args.helpRequested && !args.completions) throw; } diff --git a/lix/nix/prefetch.cc b/lix/nix/prefetch.cc index f3fd0d75e..3085d667f 100644 --- a/lix/nix/prefetch.cc +++ b/lix/nix/prefetch.cc @@ -131,7 +131,7 @@ std::tuple prefetchFile( return {storePath.value(), hash.value()}; } -static int main_nix_prefetch_url(int argc, char * * argv) +static int main_nix_prefetch_url(std::string programName, Strings argv) { { HashType ht = HashType::SHA256; @@ -148,7 +148,7 @@ static int main_nix_prefetch_url(int argc, char * * argv) using LegacyArgs::LegacyArgs; }; - MyArgs myArgs(std::string(baseNameOf(argv[0])), [&](Strings::iterator & arg, const Strings::iterator & end) { + MyArgs myArgs(programName, [&](Strings::iterator & arg, const Strings::iterator & end) { if (*arg == "--help") showManPage("nix-prefetch-url"); else if (*arg == "--version") @@ -176,7 +176,7 @@ static int main_nix_prefetch_url(int argc, char * * argv) return true; }); - myArgs.parseCmdline(argvToStrings(argc, argv)); + myArgs.parseCmdline(argv); if (args.size() > 2) throw UsageError("too many arguments");