From 47e185847e729d49e6aa376e8299fd66ef834a0a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 13 Aug 2014 03:50:44 +0200 Subject: [PATCH] Refactor option handling --- src/download-via-ssh/download-via-ssh.cc | 76 +++--- src/libexpr/common-opts.cc | 47 ++-- src/libexpr/common-opts.hh | 9 +- src/libmain/shared.cc | 82 +++---- src/libmain/shared.hh | 39 +-- src/nix-daemon/nix-daemon.cc | 33 ++- src/nix-env/nix-env.cc | 292 +++++++++++------------ src/nix-hash/nix-hash.cc | 83 ++++--- src/nix-instantiate/nix-instantiate.cc | 194 +++++++-------- src/nix-store/nix-store.cc | 179 +++++++------- 10 files changed, 503 insertions(+), 531 deletions(-) diff --git a/src/download-via-ssh/download-via-ssh.cc b/src/download-via-ssh/download-via-ssh.cc index 688fb523a..ac0f5826d 100644 --- a/src/download-via-ssh/download-via-ssh.cc +++ b/src/download-via-ssh/download-via-ssh.cc @@ -91,55 +91,49 @@ static void query(std::pair & pipes) } -void run(Strings args) +int main(int argc, char * * argv) { - if (args.empty()) - throw UsageError("download-via-ssh requires an argument"); + return handleExceptions(argv[0], [&]() { + initNix(); - if (settings.sshSubstituterHosts.empty()) - return; + if (argc < 2) + throw UsageError("download-via-ssh requires an argument"); - std::cout << std::endl; + if (settings.sshSubstituterHosts.empty()) + return; - /* Pass on the location of the daemon client's SSH authentication - socket. */ - string sshAuthSock = settings.get("ssh-auth-sock", ""); - if (sshAuthSock != "") setenv("SSH_AUTH_SOCK", sshAuthSock.c_str(), 1); + std::cout << std::endl; - string host = settings.sshSubstituterHosts.front(); - std::pair pipes = connect(host); + /* Pass on the location of the daemon client's SSH + authentication socket. */ + string sshAuthSock = settings.get("ssh-auth-sock", ""); + if (sshAuthSock != "") setenv("SSH_AUTH_SOCK", sshAuthSock.c_str(), 1); - /* Exchange the greeting */ - writeInt(SERVE_MAGIC_1, pipes.first); - pipes.first.flush(); - unsigned int magic = readInt(pipes.second); - if (magic != SERVE_MAGIC_2) - throw Error("protocol mismatch"); - readInt(pipes.second); // Server version, unused for now - writeInt(SERVE_PROTOCOL_VERSION, pipes.first); - pipes.first.flush(); + string host = settings.sshSubstituterHosts.front(); + std::pair pipes = connect(host); - Strings::iterator i = args.begin(); - if (*i == "--query") - query(pipes); - else if (*i == "--substitute") - if (args.size() != 3) - throw UsageError("download-via-ssh: --substitute takes exactly two arguments"); - else { - Path storePath = *++i; - Path destPath = *++i; + /* Exchange the greeting */ + writeInt(SERVE_MAGIC_1, pipes.first); + pipes.first.flush(); + unsigned int magic = readInt(pipes.second); + if (magic != SERVE_MAGIC_2) + throw Error("protocol mismatch"); + readInt(pipes.second); // Server version, unused for now + writeInt(SERVE_PROTOCOL_VERSION, pipes.first); + pipes.first.flush(); + + string arg = argv[1]; + if (arg == "--query") + query(pipes); + else if (arg == "--substitute") { + if (argc != 4) + throw UsageError("download-via-ssh: --substitute takes exactly two arguments"); + Path storePath = argv[2]; + Path destPath = argv[3]; printMsg(lvlError, format("downloading `%1%' via SSH from `%2%'...") % storePath % host); substitute(pipes, storePath, destPath); } - else - throw UsageError(format("download-via-ssh: unknown command `%1%'") % *i); + else + throw UsageError(format("download-via-ssh: unknown command `%1%'") % arg); + }); } - - -void printHelp() -{ - std::cerr << "Usage: download-via-ssh --query|--substitute store-path dest-path" << std::endl; -} - - -string programId = "download-via-ssh"; diff --git a/src/libexpr/common-opts.cc b/src/libexpr/common-opts.cc index a3ea202e8..2e8bb29c7 100644 --- a/src/libexpr/common-opts.cc +++ b/src/libexpr/common-opts.cc @@ -6,40 +6,45 @@ namespace nix { -bool parseOptionArg(const string & arg, Strings::iterator & i, - const Strings::iterator & argsEnd, EvalState & state, - Bindings & autoArgs) +bool parseAutoArgs(Strings::iterator & i, + const Strings::iterator & argsEnd, std::map & res) { + string arg = *i; if (arg != "--arg" && arg != "--argstr") return false; UsageError error(format("`%1%' requires two arguments") % arg); - if (i == argsEnd) throw error; - string name = *i++; - if (i == argsEnd) throw error; - string value = *i++; + if (++i == argsEnd) throw error; + string name = *i; + if (++i == argsEnd) throw error; + string value = *i; - /* !!! check for duplicates! */ - Value * v = state.allocValue(); - autoArgs.push_back(Attr(state.symbols.create(name), v)); - - if (arg == "--arg") - state.mkThunk_(*v, state.parseExprFromString(value, absPath("."))); - else - mkString(*v, value); - - autoArgs.sort(); // !!! inefficient + res[name] = (arg == "--arg" ? 'E' : 'S') + value; return true; } -bool parseSearchPathArg(const string & arg, Strings::iterator & i, +void evalAutoArgs(EvalState & state, std::map & in, Bindings & out) +{ + for (auto & i: in) { + Value * v = state.allocValue(); + if (i.second[0] == 'E') + state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath("."))); + else + mkString(*v, string(i.second, 1)); + out.push_back(Attr(state.symbols.create(i.first), v)); + } + out.sort(); +} + + +bool parseSearchPathArg(Strings::iterator & i, const Strings::iterator & argsEnd, Strings & searchPath) { - if (arg != "-I") return false; - if (i == argsEnd) throw UsageError(format("`%1%' requires an argument") % arg);; - searchPath.push_back(*i++); + if (*i != "-I") return false; + if (++i == argsEnd) throw UsageError("`-I' requires an argument"); + searchPath.push_back(*i); return true; } diff --git a/src/libexpr/common-opts.hh b/src/libexpr/common-opts.hh index 759358950..bb6d399a8 100644 --- a/src/libexpr/common-opts.hh +++ b/src/libexpr/common-opts.hh @@ -5,11 +5,12 @@ namespace nix { /* Some common option parsing between nix-env and nix-instantiate. */ -bool parseOptionArg(const string & arg, Strings::iterator & i, - const Strings::iterator & argsEnd, EvalState & state, - Bindings & autoArgs); +bool parseAutoArgs(Strings::iterator & i, + const Strings::iterator & argsEnd, std::map & res); -bool parseSearchPathArg(const string & arg, Strings::iterator & i, +void evalAutoArgs(EvalState & state, std::map & in, Bindings & out); + +bool parseSearchPathArg(Strings::iterator & i, const Strings::iterator & argsEnd, Strings & searchPath); Path lookupFileArg(EvalState & state, string s); diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 467a15e76..ec05db0a6 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -100,10 +100,16 @@ string getArg(const string & opt, void detectStackOverflow(); -/* Initialize and reorder arguments, then call the actual argument - processor. */ -static void initAndRun(int argc, char * * argv) +void initNix() { + /* Turn on buffering for cerr. */ +#if HAVE_PUBSETBUF + static char buf[1024]; + std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf)); +#endif + + std::ios::sync_with_stdio(false); + settings.processEnvironment(); settings.loadConfFile(); @@ -144,6 +150,14 @@ static void initAndRun(int argc, char * * argv) gettimeofday(&tv, 0); srandom(tv.tv_usec); + if (char *pack = getenv("_NIX_OPTIONS")) + settings.unpack(pack); +} + + +void parseCmdLine(int argc, char * * argv, + std::function parseArg) +{ /* Put the arguments in a vector. */ Strings args, remaining; while (argc--) args.push_back(*argv++); @@ -164,7 +178,6 @@ static void initAndRun(int argc, char * * argv) } else remaining.push_back(arg); } args = remaining; - remaining.clear(); /* Process default options. */ for (Strings::iterator i = args.begin(); i != args.end(); ++i) { @@ -179,14 +192,6 @@ static void initAndRun(int argc, char * * argv) settings.buildVerbosity = lvlVomit; else if (arg == "--print-build-trace") settings.printBuildTrace = true; - else if (arg == "--help") { - printHelp(); - return; - } - else if (arg == "--version") { - std::cout << format("%1% (Nix) %2%") % programId % nixVersion << std::endl; - return; - } else if (arg == "--keep-failed" || arg == "-K") settings.keepFailed = true; else if (arg == "--keep-going" || arg == "-k") @@ -216,25 +221,20 @@ static void initAndRun(int argc, char * * argv) string value = *i; settings.set(name, value); } - else if (arg == "--arg" || arg == "--argstr") { - remaining.push_back(arg); - ++i; if (i == args.end()) throw UsageError(format("`%1%' requires two arguments") % arg); - remaining.push_back(*i); - ++i; if (i == args.end()) throw UsageError(format("`%1%' requires two arguments") % arg); - remaining.push_back(*i); + else { + if (!parseArg(i, args.end())) + throw UsageError(format("unrecognised option `%1%'") % *i); } - else remaining.push_back(arg); } - if (char *pack = getenv("_NIX_OPTIONS")) - settings.unpack(pack); - settings.update(); +} - run(remaining); - /* Close the Nix database. */ - store.reset((StoreAPI *) 0); +void printVersion(const string & programName) +{ + std::cout << format("%1% (Nix) %2%") % programName % nixVersion << std::endl; + throw Exit(); } @@ -246,30 +246,11 @@ void showManPage(const string & name) } -int exitCode = 0; -char * * argvSaved = 0; - -} - - -static char buf[1024]; - -int main(int argc, char * * argv) +int handleExceptions(const string & programName, std::function fun) { - using namespace nix; - - argvSaved = argv; - - /* Turn on buffering for cerr. */ -#if HAVE_PUBSETBUF - std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf)); -#endif - - std::ios::sync_with_stdio(false); - try { try { - initAndRun(argc, argv); + fun(); } catch (...) { /* Subtle: we have to make sure that any `interrupted' condition is discharged before we reach printMsg() @@ -279,12 +260,14 @@ int main(int argc, char * * argv) _isInterrupted = 0; throw; } + } catch (Exit & e) { + return e.status; } catch (UsageError & e) { printMsg(lvlError, format( "error: %1%\n" "Try `%2% --help' for more information.") - % e.what() % programId); + % e.what() % programName); return 1; } catch (BaseError & e) { printMsg(lvlError, format("error: %1%%2%") % (settings.showTrace ? e.prefix() : "") % e.msg()); @@ -299,5 +282,8 @@ int main(int argc, char * * argv) return 1; } - return exitCode; + return 0; +} + + } diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh index b29b08bb5..c74e7cbc1 100644 --- a/src/libmain/shared.hh +++ b/src/libmain/shared.hh @@ -7,26 +7,29 @@ #include -/* These are not implemented here, but must be implemented by a - program linking against libmain. */ - -/* Main program. Called by main() after the ATerm library has been - initialised and some default arguments have been processed (and - removed from `args'). main() will catch all exceptions. */ -void run(nix::Strings args); - -/* Should print a help message to stdout and return. */ -void printHelp(); - -extern std::string programId; - - namespace nix { MakeError(UsageError, nix::Error); +class Exit : public std::exception +{ +public: + int status; + Exit() : status(0) { } + Exit(int status) : status(status) { } +}; + class StoreAPI; +int handleExceptions(const string & programName, std::function fun); + +void initNix(); + +void parseCmdLine(int argc, char * * argv, + std::function parseArg); + +void printVersion(const string & programName); + /* Ugh. No better place to put this. */ void printGCWarning(); @@ -36,6 +39,9 @@ void printMissing(const PathSet & willBuild, const PathSet & willSubstitute, const PathSet & unknown, unsigned long long downloadSize, unsigned long long narSize); +string getArg(const string & opt, + Strings::iterator & i, const Strings::iterator & end); + template N getIntArg(const string & opt, Strings::iterator & i, const Strings::iterator & end, bool allowUnit) { @@ -65,9 +71,4 @@ void showManPage(const string & name); extern volatile ::sig_atomic_t blockInt; -/* Exit code of the program. */ -extern int exitCode; - -extern char * * argvSaved; - } diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index 69d5fd84e..3e6d6b2b1 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -645,8 +645,10 @@ bool matchUser(const string & user, const string & group, const Strings & users) #define SD_LISTEN_FDS_START 3 -static void daemonLoop() +static void daemonLoop(char * * argv) { + chdir("/"); + /* Get rid of children automatically; don't let them become zombies. */ setSigChldAction(true); @@ -766,9 +768,9 @@ static void daemonLoop() setSigChldAction(false); /* For debugging, stuff the pid into argv[1]. */ - if (clientPid != -1 && argvSaved[1]) { + if (clientPid != -1 && argv[1]) { string processName = int2String(clientPid); - strncpy(argvSaved[1], processName.c_str(), strlen(argvSaved[1])); + strncpy(argv[1], processName.c_str(), strlen(argv[1])); } /* Handle the connection. */ @@ -792,18 +794,27 @@ void run(Strings args) { for (Strings::iterator i = args.begin(); i != args.end(); ) { string arg = *i++; - if (arg == "--daemon") /* ignored for backwards compatibility */; } - chdir("/"); - daemonLoop(); } -void printHelp() +int main(int argc, char * * argv) { - showManPage("nix-daemon"); + return handleExceptions(argv[0], [&]() { + initNix(); + + parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + if (*arg == "--daemon") + ; /* ignored for backwards compatibility */ + else if (*arg == "--help") + showManPage("nix-daemon"); + else if (*arg == "--version") + printVersion("nix-daemon"); + else return false; + return true; + }); + + daemonLoop(argv); + }); } - - -string programId = "nix-daemon"; diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 062118d8a..e65dc4e51 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -52,24 +52,17 @@ struct Globals { InstallSourceInfo instSource; Path profile; - EvalState state; + std::shared_ptr state; bool dryRun; bool preserveInstalled; bool removeAll; string forceName; bool prebuiltOnly; - Globals(const Strings & searchPath) : state(searchPath) { } }; typedef void (* Operation) (Globals & globals, - Strings args, Strings opFlags, Strings opArgs); - - -void printHelp() -{ - showManPage("nix-env"); -} + Strings opFlags, Strings opArgs); static string needArg(Strings::iterator & i, @@ -467,11 +460,11 @@ static void installDerivations(Globals & globals, /* Get the set of user environment elements to be installed. */ DrvInfos newElems, newElemsTmp; - queryInstSources(globals.state, globals.instSource, args, newElemsTmp, true); + queryInstSources(*globals.state, globals.instSource, args, newElemsTmp, true); /* If --prebuilt-only is given, filter out source-only packages. */ foreach (DrvInfos::iterator, i, newElemsTmp) - if (!globals.prebuiltOnly || isPrebuilt(globals.state, *i)) + if (!globals.prebuiltOnly || isPrebuilt(*globals.state, *i)) newElems.push_back(*i); StringSet newNames; @@ -494,7 +487,7 @@ static void installDerivations(Globals & globals, /* Add in the already installed derivations, unless they have the same name as a to-be-installed element. */ if (!globals.removeAll) { - DrvInfos installedElems = queryInstalled(globals.state, profile); + DrvInfos installedElems = queryInstalled(*globals.state, profile); foreach (DrvInfos::iterator, i, installedElems) { DrvName drvName(i->name); @@ -510,18 +503,17 @@ static void installDerivations(Globals & globals, printMsg(lvlInfo, format("installing `%1%'") % i->name); } - printMissing(globals.state, newElems); + printMissing(*globals.state, newElems); if (globals.dryRun) return; - if (createUserEnv(globals.state, allElems, + if (createUserEnv(*globals.state, allElems, profile, settings.envKeepDerivations, lockToken)) break; } } -static void opInstall(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opInstall(Globals & globals, Strings opFlags, Strings opArgs) { for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { string arg = *i++; @@ -553,11 +545,11 @@ static void upgradeDerivations(Globals & globals, while (true) { string lockToken = optimisticLockProfile(globals.profile); - DrvInfos installedElems = queryInstalled(globals.state, globals.profile); + DrvInfos installedElems = queryInstalled(*globals.state, globals.profile); /* Fetch all derivations from the input file. */ DrvInfos availElems; - queryInstSources(globals.state, globals.instSource, args, availElems, false); + queryInstSources(*globals.state, globals.instSource, args, availElems, false); /* Go through all installed derivations. */ DrvInfos newElems; @@ -582,7 +574,7 @@ static void upgradeDerivations(Globals & globals, foreach (DrvInfos::iterator, j, availElems) { DrvName newName(j->name); if (newName.name == drvName.name) { - int d = comparePriorities(globals.state, *i, *j); + int d = comparePriorities(*globals.state, *i, *j); if (d == 0) d = compareVersions(drvName.version, newName.version); if ((upgradeType == utLt && d < 0) || (upgradeType == utLeq && d <= 0) || @@ -591,10 +583,10 @@ static void upgradeDerivations(Globals & globals, { int d2 = -1; if (bestElem != availElems.end()) { - d2 = comparePriorities(globals.state, *bestElem, *j); + d2 = comparePriorities(*globals.state, *bestElem, *j); if (d2 == 0) d2 = compareVersions(bestName.version, newName.version); } - if (d2 < 0 && (!globals.prebuiltOnly || isPrebuilt(globals.state, *j))) { + if (d2 < 0 && (!globals.prebuiltOnly || isPrebuilt(*globals.state, *j))) { bestElem = j; bestName = newName; } @@ -618,18 +610,17 @@ static void upgradeDerivations(Globals & globals, } } - printMissing(globals.state, newElems); + printMissing(*globals.state, newElems); if (globals.dryRun) return; - if (createUserEnv(globals.state, newElems, + if (createUserEnv(*globals.state, newElems, globals.profile, settings.envKeepDerivations, lockToken)) break; } } -static void opUpgrade(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs) { UpgradeType upgradeType = utLt; for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { @@ -655,8 +646,7 @@ static void setMetaFlag(EvalState & state, DrvInfo & drv, } -static void opSetFlag(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); @@ -671,7 +661,7 @@ static void opSetFlag(Globals & globals, while (true) { string lockToken = optimisticLockProfile(globals.profile); - DrvInfos installedElems = queryInstalled(globals.state, globals.profile); + DrvInfos installedElems = queryInstalled(*globals.state, globals.profile); /* Update all matching derivations. */ foreach (DrvInfos::iterator, i, installedElems) { @@ -680,7 +670,7 @@ static void opSetFlag(Globals & globals, if (j->matches(drvName)) { printMsg(lvlInfo, format("setting flag on `%1%'") % i->name); j->hits++; - setMetaFlag(globals.state, *i, flagName, flagValue); + setMetaFlag(*globals.state, *i, flagName, flagValue); break; } } @@ -688,14 +678,13 @@ static void opSetFlag(Globals & globals, checkSelectorUse(selectors); /* Write the new user environment. */ - if (createUserEnv(globals.state, installedElems, + if (createUserEnv(*globals.state, installedElems, globals.profile, settings.envKeepDerivations, lockToken)) break; } } -static void opSet(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opSet(Globals & globals, Strings opFlags, Strings opArgs) { for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { string arg = *i++; @@ -704,7 +693,7 @@ static void opSet(Globals & globals, } DrvInfos elems; - queryInstSources(globals.state, globals.instSource, opArgs, elems, true); + queryInstSources(*globals.state, globals.instSource, opArgs, elems, true); if (elems.size() != 1) throw Error("--set requires exactly one derivation"); @@ -715,7 +704,7 @@ static void opSet(Globals & globals, PathSet paths = singleton(drv.queryDrvPath()); printMissing(*store, paths); if (globals.dryRun) return; - store->buildPaths(paths, globals.state.repair ? bmRepair : bmNormal); + store->buildPaths(paths, globals.state->repair ? bmRepair : bmNormal); } else { printMissing(*store, singleton(drv.queryOutPath())); @@ -735,7 +724,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors, while (true) { string lockToken = optimisticLockProfile(profile); - DrvInfos installedElems = queryInstalled(globals.state, profile); + DrvInfos installedElems = queryInstalled(*globals.state, profile); DrvInfos newElems; foreach (DrvInfos::iterator, i, installedElems) { @@ -756,14 +745,13 @@ static void uninstallDerivations(Globals & globals, Strings & selectors, if (globals.dryRun) return; - if (createUserEnv(globals.state, newElems, + if (createUserEnv(*globals.state, newElems, profile, settings.envKeepDerivations, lockToken)) break; } } -static void opUninstall(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opUninstall(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); @@ -887,15 +875,14 @@ static void queryJSON(Globals & globals, vector & elems) cout << "null"; } else { PathSet context; - printValueAsJSON(globals.state, true, *v, cout, context); + printValueAsJSON(*globals.state, true, *v, cout, context); } } } } -static void opQuery(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) { Strings remaining; string attrPath; @@ -916,7 +903,7 @@ static void opQuery(Globals & globals, settings.readOnlyMode = true; /* makes evaluation a bit faster */ - for (Strings::iterator i = args.begin(); i != args.end(); ) { + for (Strings::iterator i = opFlags.begin(); i != opFlags.end(); ) { string arg = *i++; if (arg == "--status" || arg == "-s") printStatus = true; else if (arg == "--no-name") printName = false; @@ -932,10 +919,9 @@ static void opQuery(Globals & globals, else if (arg == "--json") jsonOutput = true; else if (arg == "--attr-path" || arg == "-P") printAttrPath = true; else if (arg == "--attr" || arg == "-A") - attrPath = needArg(i, args, arg); - else if (arg[0] == '-') + attrPath = needArg(i, opFlags, arg); + else throw UsageError(format("unknown flag `%1%'") % arg); - else remaining.push_back(arg); } @@ -943,16 +929,16 @@ static void opQuery(Globals & globals, DrvInfos availElems, installedElems; if (source == sInstalled || compareVersions || printStatus) - installedElems = queryInstalled(globals.state, globals.profile); + installedElems = queryInstalled(*globals.state, globals.profile); if (source == sAvailable || compareVersions) - loadDerivations(globals.state, globals.instSource.nixExprPath, + loadDerivations(*globals.state, globals.instSource.nixExprPath, globals.instSource.systemFilter, globals.instSource.autoArgs, attrPath, availElems); - DrvInfos elems_ = filterBySelector(globals.state, + DrvInfos elems_ = filterBySelector(*globals.state, source == sInstalled ? installedElems : availElems, - remaining, false); + opArgs, false); DrvInfos & otherElems(source == sInstalled ? availElems : installedElems); @@ -1173,8 +1159,7 @@ static void opQuery(Globals & globals, } -static void opSwitchProfile(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opSwitchProfile(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); @@ -1222,8 +1207,7 @@ static void switchGeneration(Globals & globals, int dstGen) } -static void opSwitchGeneration(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opSwitchGeneration(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); @@ -1238,8 +1222,7 @@ static void opSwitchGeneration(Globals & globals, } -static void opRollback(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opRollback(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); @@ -1250,8 +1233,7 @@ static void opRollback(Globals & globals, } -static void opListGenerations(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opListGenerations(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); @@ -1288,8 +1270,7 @@ static void deleteGeneration2(Globals & globals, unsigned int gen) } -static void opDeleteGenerations(Globals & globals, - Strings args, Strings opFlags, Strings opArgs) +static void opDeleteGenerations(Globals & globals, Strings opFlags, Strings opArgs) { if (opFlags.size() > 0) throw UsageError(format("unknown flag `%1%'") % opFlags.front()); @@ -1348,110 +1329,115 @@ static void opDeleteGenerations(Globals & globals, } -void run(Strings args) +int main(int argc, char * * argv) { - Strings opFlags, opArgs, remaining; - Operation op = 0; + return handleExceptions(argv[0], [&]() { + initNix(); - /* FIXME: hack. */ - Strings searchPath; - Strings args2; - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; - if (!parseSearchPathArg(arg, i, args.end(), searchPath)) - args2.push_back(arg); - } - args = args2; + Strings opFlags, opArgs, searchPath; + std::map autoArgs_; + Operation op = 0; + bool repair = false; + string file; - Globals globals(searchPath); + Globals globals; - globals.instSource.type = srcUnknown; - globals.instSource.nixExprPath = getDefNixExprPath(); - globals.instSource.systemFilter = "*"; + globals.instSource.type = srcUnknown; + globals.instSource.nixExprPath = getDefNixExprPath(); + globals.instSource.systemFilter = "*"; - globals.dryRun = false; - globals.preserveInstalled = false; - globals.removeAll = false; - globals.prebuiltOnly = false; + globals.dryRun = false; + globals.preserveInstalled = false; + globals.removeAll = false; + globals.prebuiltOnly = false; - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; + parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + Operation oldOp = op; - Operation oldOp = op; + if (*arg == "--help") + showManPage("nix-env"); + else if (*arg == "--version") + printVersion("nix-env"); + else if (*arg == "--install" || *arg == "-i") + op = opInstall; + else if (parseAutoArgs(arg, end, autoArgs_)) + ; + else if (parseSearchPathArg(arg, end, searchPath)) + ; + else if (*arg == "--force-name") // undocumented flag for nix-install-package + globals.forceName = getArg(*arg, arg, end); + else if (*arg == "--uninstall" || *arg == "-e") + op = opUninstall; + else if (*arg == "--upgrade" || *arg == "-u") + op = opUpgrade; + else if (*arg == "--set-flag") + op = opSetFlag; + else if (*arg == "--set") + op = opSet; + else if (*arg == "--query" || *arg == "-q") + op = opQuery; + else if (*arg == "--profile" || *arg == "-p") + globals.profile = absPath(getArg(*arg, arg, end)); + else if (*arg == "--file" || *arg == "-f") + file = getArg(*arg, arg, end); + else if (*arg == "--switch-profile" || *arg == "-S") + op = opSwitchProfile; + else if (*arg == "--switch-generation" || *arg == "-G") + op = opSwitchGeneration; + else if (*arg == "--rollback") + op = opRollback; + else if (*arg == "--list-generations") + op = opListGenerations; + else if (*arg == "--delete-generations") + op = opDeleteGenerations; + else if (*arg == "--dry-run") { + printMsg(lvlInfo, "(dry run; not doing anything)"); + globals.dryRun = true; + } + else if (*arg == "--system-filter") + globals.instSource.systemFilter = getArg(*arg, arg, end); + else if (*arg == "--prebuilt-only" || *arg == "-b") + globals.prebuiltOnly = true; + else if (*arg == "--repair") + repair = true; + else if (*arg != "" && arg->at(0) == '-') { + opFlags.push_back(*arg); + if (*arg == "--from-profile" || *arg == "--atr" || *arg == "-A") /* !!! hack */ + opFlags.push_back(getArg(*arg, arg, end)); + } + else + opArgs.push_back(*arg); - if (arg == "--install" || arg == "-i") - op = opInstall; - else if (parseOptionArg(arg, i, args.end(), - globals.state, globals.instSource.autoArgs)) - ; - else if (arg == "--force-name") // undocumented flag for nix-install-package - globals.forceName = needArg(i, args, arg); - else if (arg == "--uninstall" || arg == "-e") - op = opUninstall; - else if (arg == "--upgrade" || arg == "-u") - op = opUpgrade; - else if (arg == "--set-flag") - op = opSetFlag; - else if (arg == "--set") - op = opSet; - else if (arg == "--query" || arg == "-q") - op = opQuery; - else if (arg == "--profile" || arg == "-p") - globals.profile = absPath(needArg(i, args, arg)); - else if (arg == "--file" || arg == "-f") - globals.instSource.nixExprPath = lookupFileArg(globals.state, needArg(i, args, arg)); - else if (arg == "--switch-profile" || arg == "-S") - op = opSwitchProfile; - else if (arg == "--switch-generation" || arg == "-G") - op = opSwitchGeneration; - else if (arg == "--rollback") - op = opRollback; - else if (arg == "--list-generations") - op = opListGenerations; - else if (arg == "--delete-generations") - op = opDeleteGenerations; - else if (arg == "--dry-run") { - printMsg(lvlInfo, "(dry run; not doing anything)"); - globals.dryRun = true; - } - else if (arg == "--system-filter") - globals.instSource.systemFilter = needArg(i, args, arg); - else if (arg == "--prebuilt-only" || arg == "-b") - globals.prebuiltOnly = true; - else if (arg == "--repair") - globals.state.repair = true; - else { - remaining.push_back(arg); - if (arg[0] == '-') { - opFlags.push_back(arg); - if (arg == "--from-profile") { /* !!! hack */ - if (i != args.end()) opFlags.push_back(*i++); - } - } else opArgs.push_back(arg); + if (oldOp && oldOp != op) + throw UsageError("only one operation may be specified"); + + return true; + }); + + if (!op) throw UsageError("no operation specified"); + + globals.state = std::shared_ptr(new EvalState(searchPath)); + globals.state->repair = repair; + + if (file != "") + globals.instSource.nixExprPath = lookupFileArg(*globals.state, file); + + evalAutoArgs(*globals.state, autoArgs_, globals.instSource.autoArgs); + + if (globals.profile == "") + globals.profile = getEnv("NIX_PROFILE", ""); + + if (globals.profile == "") { + Path profileLink = getHomeDir() + "/.nix-profile"; + globals.profile = pathExists(profileLink) + ? absPath(readLink(profileLink), dirOf(profileLink)) + : canonPath(settings.nixStateDir + "/profiles/default"); } - if (oldOp && oldOp != op) - throw UsageError("only one operation may be specified"); - } + store = openStore(); - if (!op) throw UsageError("no operation specified"); + op(globals, opFlags, opArgs); - if (globals.profile == "") - globals.profile = getEnv("NIX_PROFILE", ""); - - if (globals.profile == "") { - Path profileLink = getHomeDir() + "/.nix-profile"; - globals.profile = pathExists(profileLink) - ? absPath(readLink(profileLink), dirOf(profileLink)) - : canonPath(settings.nixStateDir + "/profiles/default"); - } - - store = openStore(); - - op(globals, remaining, opFlags, opArgs); - - globals.state.printStats(); + globals.state->printStats(); + }); } - - -string programId = "nix-env"; diff --git a/src/nix-hash/nix-hash.cc b/src/nix-hash/nix-hash.cc index af3dda4ad..b08f0b0b1 100644 --- a/src/nix-hash/nix-hash.cc +++ b/src/nix-hash/nix-hash.cc @@ -3,17 +3,10 @@ #include - using namespace nix; -void printHelp() -{ - showManPage("nix-hash"); -} - - -void run(Strings args) +int main(int argc, char * * argv) { HashType ht = htMD5; bool flat = false; @@ -23,42 +16,48 @@ void run(Strings args) Strings ss; - for (Strings::iterator i = args.begin(); - i != args.end(); i++) - { - if (*i == "--flat") flat = true; - else if (*i == "--base32") base32 = true; - else if (*i == "--truncate") truncate = true; - else if (*i == "--type") { - ++i; - if (i == args.end()) throw UsageError("`--type' requires an argument"); - ht = parseHashType(*i); - if (ht == htUnknown) - throw UsageError(format("unknown hash type `%1%'") % *i); - } - else if (*i == "--to-base16") op = opTo16; - else if (*i == "--to-base32") op = opTo32; - else ss.push_back(*i); - } + return handleExceptions(argv[0], [&]() { + initNix(); - if (op == opHash) { - foreach (Strings::iterator, i, ss) { - Hash h = flat ? hashFile(ht, *i) : hashPath(ht, *i).first; - if (truncate && h.hashSize > 20) h = compressHash(h, 20); - std::cout << format("%1%\n") % - (base32 ? printHash32(h) : printHash(h)); - } - } + parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + if (*arg == "--help") + showManPage("nix-hash"); + else if (*arg == "--version") + printVersion("nix-hash"); + else if (*arg == "--flat") flat = true; + else if (*arg == "--base32") base32 = true; + else if (*arg == "--truncate") truncate = true; + else if (*arg == "--type") { + string s = getArg(*arg, arg, end); + ht = parseHashType(s); + if (ht == htUnknown) + throw UsageError(format("unknown hash type `%1%'") % s); + } + else if (*arg == "--to-base16") op = opTo16; + else if (*arg == "--to-base32") op = opTo32; + else if (*arg != "" && arg->at(0) == '-') + return false; + else + ss.push_back(*arg); + return true; + }); - else { - foreach (Strings::iterator, i, ss) { - Hash h = parseHash16or32(ht, *i); - std::cout << format("%1%\n") % - (op == opTo16 ? printHash(h) : printHash32(h)); + if (op == opHash) { + for (auto & i : ss) { + Hash h = flat ? hashFile(ht, i) : hashPath(ht, i).first; + if (truncate && h.hashSize > 20) h = compressHash(h, 20); + std::cout << format("%1%\n") % + (base32 ? printHash32(h) : printHash(h)); + } } - } + + else { + for (auto & i : ss) { + Hash h = parseHash16or32(ht, i); + std::cout << format("%1%\n") % + (op == opTo16 ? printHash(h) : printHash32(h)); + } + } + }); } - -string programId = "nix-hash"; - diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index a188b28fe..e9f942769 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -18,12 +18,6 @@ using namespace nix; -void printHelp() -{ - showManPage("nix-instantiate"); -} - - static Expr * parseStdin(EvalState & state) { startNest(nest, lvlTalkative, format("parsing standard input")); @@ -95,112 +89,108 @@ void processExpr(EvalState & state, const Strings & attrPaths, } -void run(Strings args) +int main(int argc, char * * argv) { - /* FIXME: hack. */ - Strings searchPath; - Strings args2; - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; - if (!parseSearchPathArg(arg, i, args.end(), searchPath)) - args2.push_back(arg); - } - args = args2; + return handleExceptions(argv[0], [&]() { + initNix(); - EvalState state(searchPath); - Strings files; - bool readStdin = false; - bool fromArgs = false; - bool findFile = false; - bool evalOnly = false; - bool parseOnly = false; - OutputKind outputKind = okPlain; - bool xmlOutputSourceLocation = true; - bool strict = false; - Strings attrPaths; - Bindings autoArgs; - bool wantsReadWrite = false; + Strings files, searchPath; + bool readStdin = false; + bool fromArgs = false; + bool findFile = false; + bool evalOnly = false; + bool parseOnly = false; + OutputKind outputKind = okPlain; + bool xmlOutputSourceLocation = true; + bool strict = false; + Strings attrPaths; + bool wantsReadWrite = false; + std::map autoArgs_; + bool repair = false; - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; + parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + if (*arg == "--help") + showManPage("nix-instantiate"); + else if (*arg == "--version") + printVersion("nix-instantiate"); + else if (*arg == "-") + readStdin = true; + else if (*arg == "--expr" || *arg == "-E") + fromArgs = true; + else if (*arg == "--eval" || *arg == "--eval-only") + evalOnly = true; + else if (*arg == "--read-write-mode") + wantsReadWrite = true; + else if (*arg == "--parse" || *arg == "--parse-only") + parseOnly = evalOnly = true; + else if (*arg == "--find-file") + findFile = true; + else if (*arg == "--attr" || *arg == "-A") + attrPaths.push_back(getArg(*arg, arg, end)); + else if (parseAutoArgs(arg, end, autoArgs_)) + ; + else if (parseSearchPathArg(arg, end, searchPath)) + ; + else if (*arg == "--add-root") + gcRoot = getArg(*arg, arg, end); + else if (*arg == "--indirect") + indirectRoot = true; + else if (*arg == "--xml") + outputKind = okXML; + else if (*arg == "--json") + outputKind = okJSON; + else if (*arg == "--no-location") + xmlOutputSourceLocation = false; + else if (*arg == "--strict") + strict = true; + else if (*arg == "--repair") + repair = true; + else if (*arg == "--dry-run") + settings.readOnlyMode = true; + else if (*arg != "" && arg->at(0) == '-') + return false; + else + files.push_back(*arg); + return true; + }); - if (arg == "-") - readStdin = true; - else if (arg == "--expr" || arg == "-E") - fromArgs = true; - else if (arg == "--eval" || arg == "--eval-only") - evalOnly = true; - else if (arg == "--read-write-mode") - wantsReadWrite = true; - else if (arg == "--parse" || arg == "--parse-only") - parseOnly = evalOnly = true; - else if (arg == "--find-file") - findFile = true; - else if (arg == "--attr" || arg == "-A") { - if (i == args.end()) - throw UsageError("`--attr' requires an argument"); - attrPaths.push_back(*i++); - } - else if (parseOptionArg(arg, i, args.end(), state, autoArgs)) - ; - else if (arg == "--add-root") { - if (i == args.end()) - throw UsageError("`--add-root' requires an argument"); - gcRoot = absPath(*i++); - } - else if (arg == "--indirect") - indirectRoot = true; - else if (arg == "--xml") - outputKind = okXML; - else if (arg == "--json") - outputKind = okJSON; - else if (arg == "--no-location") - xmlOutputSourceLocation = false; - else if (arg == "--strict") - strict = true; - else if (arg == "--repair") - state.repair = true; - else if (arg == "--dry-run") + EvalState state(searchPath); + state.repair = repair; + + Bindings autoArgs; + evalAutoArgs(state, autoArgs_, autoArgs); + + if (evalOnly && !wantsReadWrite) settings.readOnlyMode = true; - else if (arg[0] == '-') - throw UsageError(format("unknown flag `%1%'") % arg); - else - files.push_back(arg); - } - if (evalOnly && !wantsReadWrite) - settings.readOnlyMode = true; + if (attrPaths.empty()) attrPaths.push_back(""); - if (attrPaths.empty()) attrPaths.push_back(""); - - if (findFile) { - foreach (Strings::iterator, i, files) { - Path p = state.findFile(*i); - if (p == "") throw Error(format("unable to find `%1%'") % *i); - std::cout << p << std::endl; + if (findFile) { + foreach (Strings::iterator, i, files) { + Path p = state.findFile(*i); + if (p == "") throw Error(format("unable to find `%1%'") % *i); + std::cout << p << std::endl; + } + return; } - return; - } - store = openStore(); + store = openStore(); - if (readStdin) { - Expr * e = parseStdin(state); - processExpr(state, attrPaths, parseOnly, strict, autoArgs, - evalOnly, outputKind, xmlOutputSourceLocation, e); - } else if (files.empty() && !fromArgs) - files.push_back("./default.nix"); + if (readStdin) { + Expr * e = parseStdin(state); + processExpr(state, attrPaths, parseOnly, strict, autoArgs, + evalOnly, outputKind, xmlOutputSourceLocation, e); + } else if (files.empty() && !fromArgs) + files.push_back("./default.nix"); - foreach (Strings::iterator, i, files) { - Expr * e = fromArgs - ? state.parseExprFromString(*i, absPath(".")) - : state.parseExprFromFile(resolveExprPath(lookupFileArg(state, *i))); - processExpr(state, attrPaths, parseOnly, strict, autoArgs, - evalOnly, outputKind, xmlOutputSourceLocation, e); - } + foreach (Strings::iterator, i, files) { + Expr * e = fromArgs + ? state.parseExprFromString(*i, absPath(".")) + : state.parseExprFromFile(resolveExprPath(lookupFileArg(state, *i))); + processExpr(state, attrPaths, parseOnly, strict, autoArgs, + evalOnly, outputKind, xmlOutputSourceLocation, e); + } - state.printStats(); + state.printStats(); + }); } - - -string programId = "nix-instantiate"; diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 932789f2c..6a297b429 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -29,12 +29,6 @@ using std::cout; typedef void (* Operation) (Strings opFlags, Strings opArgs); -void printHelp() -{ - showManPage("nix-store"); -} - - static Path gcRoot; static int rootNr = 0; static bool indirectRoot = false; @@ -782,7 +776,7 @@ static void opVerify(Strings opFlags, Strings opArgs) if (ensureLocalStore().verifyStore(checkContents, repair)) { printMsg(lvlError, "warning: not all errors were fixed"); - exitCode = 1; + throw Exit(1); } } @@ -793,6 +787,8 @@ static void opVerifyPath(Strings opFlags, Strings opArgs) if (!opFlags.empty()) throw UsageError("no flags expected"); + int status = 0; + foreach (Strings::iterator, i, opArgs) { Path path = followLinksToStorePath(*i); printMsg(lvlTalkative, format("checking path `%1%'...") % path); @@ -802,9 +798,11 @@ static void opVerifyPath(Strings opFlags, Strings opArgs) printMsg(lvlError, format("path `%1%' was modified! expected hash `%2%', got `%3%'") % path % printHash(info.hash) % printHash(current.first)); - exitCode = 1; + status = 1; } } + + throw Exit(status); } @@ -1017,95 +1015,96 @@ static void opServe(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. */ -void run(Strings args) +int main(int argc, char * * argv) { - Strings opFlags, opArgs; - Operation op = 0; + return handleExceptions(argv[0], [&]() { + initNix(); - for (Strings::iterator i = args.begin(); i != args.end(); ) { - string arg = *i++; + Strings opFlags, opArgs; + Operation op = 0; - Operation oldOp = op; + parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { + Operation oldOp = op; - if (arg == "--realise" || arg == "--realize" || arg == "-r") - op = opRealise; - else if (arg == "--add" || arg == "-A") - op = opAdd; - else if (arg == "--add-fixed") - op = opAddFixed; - else if (arg == "--print-fixed-path") - op = opPrintFixedPath; - else if (arg == "--delete") - op = opDelete; - else if (arg == "--query" || arg == "-q") - op = opQuery; - else if (arg == "--print-env") - op = opPrintEnv; - else if (arg == "--read-log" || arg == "-l") - op = opReadLog; - else if (arg == "--dump-db") - op = opDumpDB; - else if (arg == "--load-db") - op = opLoadDB; - else if (arg == "--register-validity") - op = opRegisterValidity; - else if (arg == "--check-validity") - op = opCheckValidity; - else if (arg == "--gc") - op = opGC; - else if (arg == "--dump") - op = opDump; - else if (arg == "--restore") - op = opRestore; - else if (arg == "--export") - op = opExport; - else if (arg == "--import") - op = opImport; - else if (arg == "--init") - op = opInit; - else if (arg == "--verify") - op = opVerify; - else if (arg == "--verify-path") - op = opVerifyPath; - else if (arg == "--repair-path") - op = opRepairPath; - else if (arg == "--optimise" || arg == "--optimize") - op = opOptimise; - else if (arg == "--query-failed-paths") - op = opQueryFailedPaths; - else if (arg == "--clear-failed-paths") - op = opClearFailedPaths; - else if (arg == "--add-root") { - if (i == args.end()) - throw UsageError("`--add-root requires an argument"); - gcRoot = absPath(*i++); - } - else if (arg == "--indirect") - indirectRoot = true; - else if (arg == "--no-output") - noOutput = true; - else if (arg == "--serve") - op = opServe; - else if (arg[0] == '-') { - opFlags.push_back(arg); - if (arg == "--max-freed" || arg == "--max-links" || arg == "--max-atime") { /* !!! hack */ - if (i != args.end()) opFlags.push_back(*i++); + if (*arg == "--help") + showManPage("nix-store"); + else if (*arg == "--version") + printVersion("nix-store"); + else if (*arg == "--realise" || *arg == "--realize" || *arg == "-r") + op = opRealise; + else if (*arg == "--add" || *arg == "-A") + op = opAdd; + else if (*arg == "--add-fixed") + op = opAddFixed; + else if (*arg == "--print-fixed-path") + op = opPrintFixedPath; + else if (*arg == "--delete") + op = opDelete; + else if (*arg == "--query" || *arg == "-q") + op = opQuery; + else if (*arg == "--print-env") + op = opPrintEnv; + else if (*arg == "--read-log" || *arg == "-l") + op = opReadLog; + else if (*arg == "--dump-db") + op = opDumpDB; + else if (*arg == "--load-db") + op = opLoadDB; + else if (*arg == "--register-validity") + op = opRegisterValidity; + else if (*arg == "--check-validity") + op = opCheckValidity; + else if (*arg == "--gc") + op = opGC; + else if (*arg == "--dump") + op = opDump; + else if (*arg == "--restore") + op = opRestore; + else if (*arg == "--export") + op = opExport; + else if (*arg == "--import") + op = opImport; + else if (*arg == "--init") + op = opInit; + else if (*arg == "--verify") + op = opVerify; + else if (*arg == "--verify-path") + op = opVerifyPath; + else if (*arg == "--repair-path") + op = opRepairPath; + else if (*arg == "--optimise" || *arg == "--optimize") + op = opOptimise; + else if (*arg == "--query-failed-paths") + op = opQueryFailedPaths; + else if (*arg == "--clear-failed-paths") + op = opClearFailedPaths; + else if (*arg == "--add-root") + gcRoot = absPath(getArg(*arg, arg, end)); + else if (*arg == "--indirect") + indirectRoot = true; + else if (*arg == "--no-output") + noOutput = true; + else if (*arg == "--serve") + op = opServe; + else if (*arg != "" && arg->at(0) == '-') { + opFlags.push_back(*arg); + if (*arg == "--max-freed" || *arg == "--max-links" || *arg == "--max-atime") /* !!! hack */ + opFlags.push_back(getArg(*arg, arg, end)); } - } - else - opArgs.push_back(arg); + else + opArgs.push_back(*arg); - if (oldOp && oldOp != op) - throw UsageError("only one operation may be specified"); - } + if (oldOp && oldOp != op) + throw UsageError("only one operation may be specified"); - if (!op) throw UsageError("no operation specified"); + return true; + }); - if (op != opDump && op != opRestore) /* !!! hack */ - store = openStore(op != opGC); + if (!op) throw UsageError("no operation specified"); - op(opFlags, opArgs); + if (op != opDump && op != opRestore) /* !!! hack */ + store = openStore(op != opGC); + + op(opFlags, opArgs); + }); } - - -string programId = "nix-store";