1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-11 04:56:01 +01:00

Refactor option handling

This commit is contained in:
Eelco Dolstra 2014-08-13 03:50:44 +02:00
parent 5bed74d1b0
commit 47e185847e
10 changed files with 503 additions and 531 deletions

View file

@ -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<bool(Strings::iterator & arg, const Strings::iterator & end)> 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<void()> 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;
}
}

View file

@ -7,26 +7,29 @@
#include <locale>
/* 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<void()> fun);
void initNix();
void parseCmdLine(int argc, char * * argv,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> 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<class N> 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;
}