Start of new Nix command-line interface
This commit is contained in:
		
							parent
							
								
									0db9e6cd1a
								
							
						
					
					
						commit
						cd2196b089
					
				
					 14 changed files with 362 additions and 74 deletions
				
			
		
							
								
								
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -73,9 +73,6 @@ Makefile.config | ||||||
| # /src/nix-env/ | # /src/nix-env/ | ||||||
| /src/nix-env/nix-env | /src/nix-env/nix-env | ||||||
| 
 | 
 | ||||||
| # /src/nix-hash/ |  | ||||||
| /src/nix-hash/nix-hash |  | ||||||
| 
 |  | ||||||
| # /src/nix-instantiate/ | # /src/nix-instantiate/ | ||||||
| /src/nix-instantiate/nix-instantiate | /src/nix-instantiate/nix-instantiate | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -5,7 +5,7 @@ makefiles = \ | ||||||
|   src/libstore/local.mk \
 |   src/libstore/local.mk \
 | ||||||
|   src/libmain/local.mk \
 |   src/libmain/local.mk \
 | ||||||
|   src/libexpr/local.mk \
 |   src/libexpr/local.mk \
 | ||||||
|   src/nix-hash/local.mk \
 |   src/nix/local.mk \
 | ||||||
|   src/nix-store/local.mk \
 |   src/nix-store/local.mk \
 | ||||||
|   src/nix-instantiate/local.mk \
 |   src/nix-instantiate/local.mk \
 | ||||||
|   src/nix-env/local.mk \
 |   src/nix-env/local.mk \
 | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
| MixCommonArgs::MixCommonArgs(const string & programName) | MixCommonArgs::MixCommonArgs(const string & programName) | ||||||
|  |     : programName(programName) | ||||||
| { | { | ||||||
|     mkFlag('v', "verbose", "increase verbosity level", []() { |     mkFlag('v', "verbose", "increase verbosity level", []() { | ||||||
|         verbosity = (Verbosity) (verbosity + 1); |         verbosity = (Verbosity) (verbosity + 1); | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ namespace nix { | ||||||
| 
 | 
 | ||||||
| struct MixCommonArgs : virtual Args | struct MixCommonArgs : virtual Args | ||||||
| { | { | ||||||
|  |     string programName; | ||||||
|     MixCommonArgs(const string & programName); |     MixCommonArgs(const string & programName); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -145,6 +145,8 @@ public: | ||||||
|             *dest = ss; |             *dest = ss; | ||||||
|         }}); |         }}); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     friend class MultiCommand; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| Strings argvToStrings(int argc, char * * argv); | Strings argvToStrings(int argc, char * * argv); | ||||||
|  |  | ||||||
|  | @ -1,7 +0,0 @@ | ||||||
| programs += nix-hash |  | ||||||
| 
 |  | ||||||
| nix-hash_DIR := $(d) |  | ||||||
| 
 |  | ||||||
| nix-hash_SOURCES := $(d)/nix-hash.cc |  | ||||||
| 
 |  | ||||||
| nix-hash_LIBS = libmain libstore libutil libformat |  | ||||||
|  | @ -1,63 +0,0 @@ | ||||||
| #include "hash.hh" |  | ||||||
| #include "shared.hh" |  | ||||||
| 
 |  | ||||||
| #include <iostream> |  | ||||||
| 
 |  | ||||||
| using namespace nix; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| int main(int argc, char * * argv) |  | ||||||
| { |  | ||||||
|     HashType ht = htMD5; |  | ||||||
|     bool flat = false; |  | ||||||
|     bool base32 = false; |  | ||||||
|     bool truncate = false; |  | ||||||
|     enum { opHash, opTo32, opTo16 } op = opHash; |  | ||||||
| 
 |  | ||||||
|     Strings ss; |  | ||||||
| 
 |  | ||||||
|     return handleExceptions(argv[0], [&]() { |  | ||||||
|         initNix(); |  | ||||||
| 
 |  | ||||||
|         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; |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         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)); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
							
								
								
									
										65
									
								
								src/nix/command.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/nix/command.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | ||||||
|  | #include "command.hh" | ||||||
|  | #include "store-api.hh" | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | Commands * RegisterCommand::commands = 0; | ||||||
|  | 
 | ||||||
|  | MultiCommand::MultiCommand(const Commands & _commands) | ||||||
|  |     : commands(_commands) | ||||||
|  | { | ||||||
|  |     expectedArgs.push_back(ExpectedArg{"command", 1, [=](Strings ss) { | ||||||
|  |         assert(!command); | ||||||
|  |         auto i = commands.find(ss.front()); | ||||||
|  |         if (i == commands.end()) | ||||||
|  |             throw UsageError(format("‘%1%’ is not a recognised command") % ss.front()); | ||||||
|  |         command = i->second; | ||||||
|  |     }}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MultiCommand::printHelp(const string & programName, std::ostream & out) | ||||||
|  | { | ||||||
|  |     if (command) { | ||||||
|  |         command->printHelp(programName + " " + command->name(), out); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     out << "Usage: " << programName << " <COMMAND> <FLAGS>... <ARGS>...\n"; | ||||||
|  | 
 | ||||||
|  |     out << "\n"; | ||||||
|  |     out << "Common flags:\n"; | ||||||
|  |     printFlags(out); | ||||||
|  | 
 | ||||||
|  |     out << "\n"; | ||||||
|  |     out << "Available commands:\n"; | ||||||
|  | 
 | ||||||
|  |     Table2 table; | ||||||
|  |     for (auto & command : commands) | ||||||
|  |         table.push_back(std::make_pair(command.second->name(), command.second->description())); | ||||||
|  |     printTable(out, table); | ||||||
|  | 
 | ||||||
|  |     out << "\n"; | ||||||
|  |     out << "For full documentation, run ‘man " << programName << "’ or ‘man " << programName << "-<COMMAND>’.\n"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool MultiCommand::processFlag(Strings::iterator & pos, Strings::iterator end) | ||||||
|  | { | ||||||
|  |     if (Args::processFlag(pos, end)) return true; | ||||||
|  |     if (command && command->processFlag(pos, end)) return true; | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool MultiCommand::processArgs(const Strings & args, bool finish) | ||||||
|  | { | ||||||
|  |     if (command) | ||||||
|  |         return command->processArgs(args, finish); | ||||||
|  |     else | ||||||
|  |         return Args::processArgs(args, finish); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void StoreCommand::run() | ||||||
|  | { | ||||||
|  |     run(openStore(reserveSpace)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								src/nix/command.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/nix/command.hh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "args.hh" | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | /* A command is an argument parser that can be executed by calling its
 | ||||||
|  |    run() method. */ | ||||||
|  | struct Command : virtual Args | ||||||
|  | { | ||||||
|  |     virtual std::string name() = 0; | ||||||
|  |     virtual void prepare() { }; | ||||||
|  |     virtual void run() = 0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class Store; | ||||||
|  | 
 | ||||||
|  | /* A command that require a Nix store. */ | ||||||
|  | struct StoreCommand : virtual Command | ||||||
|  | { | ||||||
|  |     bool reserveSpace; | ||||||
|  |     StoreCommand(bool reserveSpace = true) | ||||||
|  |         : reserveSpace(reserveSpace) { }; | ||||||
|  |     void run() override; | ||||||
|  |     virtual void run(ref<Store>) = 0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | typedef std::map<std::string, ref<Command>> Commands; | ||||||
|  | 
 | ||||||
|  | /* An argument parser that supports multiple subcommands,
 | ||||||
|  |    i.e. ‘<command> <subcommand>’. */ | ||||||
|  | struct MultiCommand : virtual Args | ||||||
|  | { | ||||||
|  |     Commands commands; | ||||||
|  | 
 | ||||||
|  |     std::shared_ptr<Command> command; | ||||||
|  | 
 | ||||||
|  |     MultiCommand(const Commands & commands); | ||||||
|  | 
 | ||||||
|  |     void printHelp(const string & programName, std::ostream & out) override; | ||||||
|  | 
 | ||||||
|  |     bool processFlag(Strings::iterator & pos, Strings::iterator end) override; | ||||||
|  | 
 | ||||||
|  |     bool processArgs(const Strings & args, bool finish) override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* A helper class for registering commands globally. */ | ||||||
|  | struct RegisterCommand | ||||||
|  | { | ||||||
|  |     static Commands * commands; | ||||||
|  | 
 | ||||||
|  |     RegisterCommand(ref<Command> command) | ||||||
|  |     { | ||||||
|  |         if (!commands) commands = new Commands; | ||||||
|  |         commands->emplace(command->name(), command); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										140
									
								
								src/nix/hash.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/nix/hash.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,140 @@ | ||||||
|  | #include "command.hh" | ||||||
|  | #include "hash.hh" | ||||||
|  | #include "legacy.hh" | ||||||
|  | #include "shared.hh" | ||||||
|  | 
 | ||||||
|  | using namespace nix; | ||||||
|  | 
 | ||||||
|  | struct CmdHash : Command | ||||||
|  | { | ||||||
|  |     enum Mode { mFile, mPath }; | ||||||
|  |     Mode mode; | ||||||
|  |     bool base32 = false; | ||||||
|  |     bool truncate = false; | ||||||
|  |     HashType ht = htSHA512; | ||||||
|  |     Strings paths; | ||||||
|  | 
 | ||||||
|  |     CmdHash(Mode mode) : mode(mode) | ||||||
|  |     { | ||||||
|  |         mkFlag(0, "base32", "print hash in base-32", &base32); | ||||||
|  |         mkFlag(0, "base16", "print hash in base-16", &base32, false); | ||||||
|  |         mkHashTypeFlag("type", &ht); | ||||||
|  |         expectArgs("paths", &paths); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::string name() override | ||||||
|  |     { | ||||||
|  |         return mode == mFile ? "hash-file" : "hash-path"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::string description() override | ||||||
|  |     { | ||||||
|  |         return mode == mFile | ||||||
|  |             ? "print cryptographic hash of a regular file" | ||||||
|  |             : "print cryptographic hash of the NAR serialisation of a path"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void run() override | ||||||
|  |     { | ||||||
|  |         for (auto path : paths) { | ||||||
|  |             Hash h = mode == mFile ? hashFile(ht, path) : hashPath(ht, path).first; | ||||||
|  |             if (truncate && h.hashSize > 20) h = compressHash(h, 20); | ||||||
|  |             std::cout << format("%1%\n") % | ||||||
|  |                 (base32 ? printHash32(h) : printHash(h)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static RegisterCommand r1(make_ref<Command, CmdHash>(CmdHash::mFile)); | ||||||
|  | static RegisterCommand r2(make_ref<Command, CmdHash>(CmdHash::mPath)); | ||||||
|  | 
 | ||||||
|  | struct CmdToBase : Command | ||||||
|  | { | ||||||
|  |     bool toBase32; | ||||||
|  |     HashType ht = htSHA512; | ||||||
|  |     Strings args; | ||||||
|  | 
 | ||||||
|  |     CmdToBase(bool toBase32) : toBase32(toBase32) | ||||||
|  |     { | ||||||
|  |         mkHashTypeFlag("type", &ht); | ||||||
|  |         expectArgs("strings", &args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::string name() override | ||||||
|  |     { | ||||||
|  |         return toBase32 ? "to-base32" : "to-base16"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::string description() override | ||||||
|  |     { | ||||||
|  |         return toBase32 | ||||||
|  |             ? "convert a hash to base-32 representation" | ||||||
|  |             : "convert a hash to base-32 representation"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void run() override | ||||||
|  |     { | ||||||
|  |         for (auto s : args) { | ||||||
|  |             Hash h = parseHash16or32(ht, s); | ||||||
|  |             std::cout << format("%1%\n") % | ||||||
|  |                 (toBase32 ? printHash32(h) : printHash(h)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static RegisterCommand r3(make_ref<Command, CmdToBase>(false)); | ||||||
|  | static RegisterCommand r4(make_ref<Command, CmdToBase>(true)); | ||||||
|  | 
 | ||||||
|  | /* Legacy nix-hash command. */ | ||||||
|  | static int compatNixHash(int argc, char * * argv) | ||||||
|  | { | ||||||
|  |     HashType ht = htMD5; | ||||||
|  |     bool flat = false; | ||||||
|  |     bool base32 = false; | ||||||
|  |     bool truncate = false; | ||||||
|  |     enum { opHash, opTo32, opTo16 } op = opHash; | ||||||
|  |     Strings ss; | ||||||
|  | 
 | ||||||
|  |     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; | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     if (op == opHash) { | ||||||
|  |         CmdHash cmd(flat ? CmdHash::mFile : CmdHash::mPath); | ||||||
|  |         cmd.ht = ht; | ||||||
|  |         cmd.base32 = base32; | ||||||
|  |         cmd.truncate = truncate; | ||||||
|  |         cmd.paths = ss; | ||||||
|  |         cmd.run(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     else { | ||||||
|  |         CmdToBase cmd(op == opTo32); | ||||||
|  |         cmd.args = ss; | ||||||
|  |         cmd.ht = ht; | ||||||
|  |         cmd.run(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static RegisterLegacyCommand s1("nix-hash", compatNixHash); | ||||||
							
								
								
									
										7
									
								
								src/nix/legacy.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/nix/legacy.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | #include "legacy.hh" | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | RegisterLegacyCommand::Commands * RegisterLegacyCommand::commands = 0; | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								src/nix/legacy.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/nix/legacy.hh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <functional> | ||||||
|  | #include <map> | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | typedef std::function<void(int, char * *)> MainFunction; | ||||||
|  | 
 | ||||||
|  | struct RegisterLegacyCommand | ||||||
|  | { | ||||||
|  |     typedef std::map<std::string, MainFunction> Commands; | ||||||
|  |     static Commands * commands; | ||||||
|  | 
 | ||||||
|  |     RegisterLegacyCommand(const std::string & name, MainFunction fun) | ||||||
|  |     { | ||||||
|  |         if (!commands) commands = new Commands; | ||||||
|  |         (*commands)[name] = fun; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								src/nix/local.mk
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/nix/local.mk
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | programs += nix | ||||||
|  | 
 | ||||||
|  | nix_DIR := $(d) | ||||||
|  | 
 | ||||||
|  | nix_SOURCES := $(wildcard $(d)/*.cc) | ||||||
|  | 
 | ||||||
|  | nix_LIBS = libexpr libmain libstore libutil libformat | ||||||
|  | 
 | ||||||
|  | $(eval $(call install-symlink, nix, $(bindir)/nix-hash)) | ||||||
							
								
								
									
										55
									
								
								src/nix/main.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/nix/main.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | ||||||
|  | #include <algorithm> | ||||||
|  | 
 | ||||||
|  | #include "command.hh" | ||||||
|  | #include "common-args.hh" | ||||||
|  | #include "eval.hh" | ||||||
|  | #include "globals.hh" | ||||||
|  | #include "legacy.hh" | ||||||
|  | #include "shared.hh" | ||||||
|  | #include "store-api.hh" | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | struct NixArgs : virtual MultiCommand, virtual MixCommonArgs | ||||||
|  | { | ||||||
|  |     NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix") | ||||||
|  |     { | ||||||
|  |         mkFlag('h', "help", "show usage information", [=]() { | ||||||
|  |             printHelp(programName, std::cout); | ||||||
|  |             throw Exit(); | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         mkFlag(0, "version", "show version information", std::bind(printVersion, programName)); | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void mainWrapped(int argc, char * * argv) | ||||||
|  | { | ||||||
|  |     initNix(); | ||||||
|  |     initGC(); | ||||||
|  | 
 | ||||||
|  |     string programName = baseNameOf(argv[0]); | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         auto legacy = (*RegisterLegacyCommand::commands)[programName]; | ||||||
|  |         if (legacy) return legacy(argc, argv); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     NixArgs args; | ||||||
|  | 
 | ||||||
|  |     args.parseCmdline(argvToStrings(argc, argv)); | ||||||
|  | 
 | ||||||
|  |     assert(args.command); | ||||||
|  | 
 | ||||||
|  |     args.command->prepare(); | ||||||
|  |     args.command->run(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main(int argc, char * * argv) | ||||||
|  | { | ||||||
|  |     return nix::handleExceptions(argv[0], [&]() { | ||||||
|  |         nix::mainWrapped(argc, argv); | ||||||
|  |     }); | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue