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
This commit is contained in:
eldritch horrors 2024-11-17 14:43:57 +01:00
parent c4a077d0b8
commit 9cf91b7385
17 changed files with 42 additions and 76 deletions

View file

@ -55,7 +55,7 @@ static bool allSupportedLocally(Store & store, const std::set<std::string>& 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);

View file

@ -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<Strings>(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");

View file

@ -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<std::string> 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:

View file

@ -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<Path> dirsToClean = {

View file

@ -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");

View file

@ -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");

View file

@ -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;

View file

@ -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");

View file

@ -2,12 +2,13 @@
///@file
#include <functional>
#include <list>
#include <map>
#include <string>
namespace nix {
typedef std::function<void(int, char * *)> MainFunction;
typedef std::function<void(std::string, std::list<std::string>)> MainFunction;
struct LegacyCommands
{

View file

@ -267,20 +267,6 @@ bool LegacyArgs::processArgs(const Strings & args, bool finish)
}
void parseCmdLine(int argc, char * * argv,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg)
{
parseCmdLine(std::string(baseNameOf(argv[0])), argvToStrings(argc, argv), parseArg);
}
void parseCmdLine(const std::string & programName, const Strings & args,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg)
{
LegacyArgs(programName, parseArg).parseCmdline(args);
}
void printVersion(const std::string & programName)
{
std::cout << fmt("%1% (Lix, like Nix) %2%", programName, nixVersion) << std::endl;

View file

@ -21,12 +21,6 @@ int handleExceptions(const std::string & programName, std::function<void()> fun)
*/
void initNix();
void parseCmdLine(int argc, char * * argv,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);
void parseCmdLine(const std::string & programName, const Strings & args,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg);
void printVersion(const std::string & programName);
/**

View file

@ -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<ExperimentalFeature> Command::experimentalFeature ()
{
return { Xp::NixCommand };

View file

@ -364,8 +364,6 @@ public:
nlohmann::json toJSON() override;
};
Strings argvToStrings(int argc, char * * argv);
struct Completion {
std::string completion;
std::string description;

View file

@ -436,13 +436,13 @@ static void runDaemon(bool stdio, std::optional<TrustedFlag> 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<TrustedFlag> 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);

View file

@ -155,7 +155,7 @@ struct CmdHash : MultiCommand
static auto rCmdHash = registerCommand<CmdHash>("hash");
/* Legacy nix-hash command. */
static int compatNixHash(int argc, char * * argv)
static int compatNixHash(std::string programName, Strings argv)
{
std::optional<HashType> ht;
bool flat = false;
@ -164,7 +164,7 @@ static int compatNixHash(int argc, char * * argv)
enum { opHash, opTo } op = opHash;
std::vector<std::string> 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);

View file

@ -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;
}

View file

@ -131,7 +131,7 @@ std::tuple<StorePath, Hash> 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");