nix: Respect -I, --arg, --argstr
Also, random cleanup to argument handling.
This commit is contained in:
		
							parent
							
								
									25f32625e2
								
							
						
					
					
						commit
						0d59f1ca49
					
				
					 26 changed files with 349 additions and 299 deletions
				
			
		
							
								
								
									
										57
									
								
								src/libexpr/common-eval-args.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/libexpr/common-eval-args.cc
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | ||||||
|  | #include "common-eval-args.hh" | ||||||
|  | #include "shared.hh" | ||||||
|  | #include "download.hh" | ||||||
|  | #include "util.hh" | ||||||
|  | #include "eval.hh" | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | MixEvalArgs::MixEvalArgs() | ||||||
|  | { | ||||||
|  |     mkFlag() | ||||||
|  |         .longName("arg") | ||||||
|  |         .description("argument to be passed to Nix functions") | ||||||
|  |         .labels({"name", "expr"}) | ||||||
|  |         .handler([&](std::vector<std::string> ss) { autoArgs[ss[0]] = 'E' + ss[1]; }); | ||||||
|  | 
 | ||||||
|  |     mkFlag() | ||||||
|  |         .longName("argstr") | ||||||
|  |         .description("string-valued argument to be passed to Nix functions") | ||||||
|  |         .labels({"name", "string"}) | ||||||
|  |         .handler([&](std::vector<std::string> ss) { autoArgs[ss[0]] = 'S' + ss[1]; }); | ||||||
|  | 
 | ||||||
|  |     mkFlag() | ||||||
|  |         .shortName('I') | ||||||
|  |         .longName("include") | ||||||
|  |         .description("add a path to the list of locations used to look up <...> file names") | ||||||
|  |         .label("path") | ||||||
|  |         .handler([&](std::string s) { searchPath.push_back(s); }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Bindings * MixEvalArgs::getAutoArgs(EvalState & state) | ||||||
|  | { | ||||||
|  |     Bindings * res = state.allocBindings(autoArgs.size()); | ||||||
|  |     for (auto & i : autoArgs) { | ||||||
|  |         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)); | ||||||
|  |         res->push_back(Attr(state.symbols.create(i.first), v)); | ||||||
|  |     } | ||||||
|  |     res->sort(); | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Path lookupFileArg(EvalState & state, string s) | ||||||
|  | { | ||||||
|  |     if (isUri(s)) | ||||||
|  |         return getDownloader()->downloadCached(state.store, s, true); | ||||||
|  |     else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { | ||||||
|  |         Path p = s.substr(1, s.size() - 2); | ||||||
|  |         return state.findFile(p); | ||||||
|  |     } else | ||||||
|  |         return absPath(s); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/libexpr/common-eval-args.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/libexpr/common-eval-args.hh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "args.hh" | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | class Store; | ||||||
|  | class EvalState; | ||||||
|  | struct Bindings; | ||||||
|  | 
 | ||||||
|  | struct MixEvalArgs : virtual Args | ||||||
|  | { | ||||||
|  |     MixEvalArgs(); | ||||||
|  | 
 | ||||||
|  |     Bindings * getAutoArgs(EvalState & state); | ||||||
|  | 
 | ||||||
|  |     Strings searchPath; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|  |     std::map<std::string, std::string> autoArgs; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | Path lookupFileArg(EvalState & state, string s); | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -1,67 +0,0 @@ | ||||||
| #include "common-opts.hh" |  | ||||||
| #include "shared.hh" |  | ||||||
| #include "download.hh" |  | ||||||
| #include "util.hh" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| namespace nix { |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| bool parseAutoArgs(Strings::iterator & i, |  | ||||||
|     const Strings::iterator & argsEnd, std::map<string, string> & 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; |  | ||||||
| 
 |  | ||||||
|     res[name] = (arg == "--arg" ? 'E' : 'S') + value; |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Bindings * evalAutoArgs(EvalState & state, std::map<string, string> & in) |  | ||||||
| { |  | ||||||
|     Bindings * res = state.allocBindings(in.size()); |  | ||||||
|     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)); |  | ||||||
|         res->push_back(Attr(state.symbols.create(i.first), v)); |  | ||||||
|     } |  | ||||||
|     res->sort(); |  | ||||||
|     return res; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| bool parseSearchPathArg(Strings::iterator & i, |  | ||||||
|     const Strings::iterator & argsEnd, Strings & searchPath) |  | ||||||
| { |  | ||||||
|     if (*i != "-I") return false; |  | ||||||
|     if (++i == argsEnd) throw UsageError("'-I' requires an argument"); |  | ||||||
|     searchPath.push_back(*i); |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| Path lookupFileArg(EvalState & state, string s) |  | ||||||
| { |  | ||||||
|     if (isUri(s)) |  | ||||||
|         return getDownloader()->downloadCached(state.store, s, true); |  | ||||||
|     else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { |  | ||||||
|         Path p = s.substr(1, s.size() - 2); |  | ||||||
|         return state.findFile(p); |  | ||||||
|     } else |  | ||||||
|         return absPath(s); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,20 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include "eval.hh" |  | ||||||
| 
 |  | ||||||
| namespace nix { |  | ||||||
| 
 |  | ||||||
| class Store; |  | ||||||
| 
 |  | ||||||
| /* Some common option parsing between nix-env and nix-instantiate. */ |  | ||||||
| bool parseAutoArgs(Strings::iterator & i, |  | ||||||
|     const Strings::iterator & argsEnd, std::map<string, string> & res); |  | ||||||
| 
 |  | ||||||
| Bindings * evalAutoArgs(EvalState & state, std::map<string, string> & in); |  | ||||||
| 
 |  | ||||||
| bool parseSearchPathArg(Strings::iterator & i, |  | ||||||
|     const Strings::iterator & argsEnd, Strings & searchPath); |  | ||||||
| 
 |  | ||||||
| Path lookupFileArg(EvalState & state, string s); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -6,28 +6,30 @@ namespace nix { | ||||||
| MixCommonArgs::MixCommonArgs(const string & programName) | MixCommonArgs::MixCommonArgs(const string & programName) | ||||||
|     : programName(programName) |     : programName(programName) | ||||||
| { | { | ||||||
|     mkFlag('v', "verbose", "increase verbosity level", []() { |     mkFlag() | ||||||
|         verbosity = (Verbosity) (verbosity + 1); |         .longName("verbose") | ||||||
|     }); |         .shortName('v') | ||||||
|  |         .description("increase verbosity level") | ||||||
|  |         .handler([]() { verbosity = (Verbosity) (verbosity + 1); }); | ||||||
| 
 | 
 | ||||||
|     mkFlag(0, "quiet", "decrease verbosity level", []() { |     mkFlag() | ||||||
|         verbosity = verbosity > lvlError ? (Verbosity) (verbosity - 1) : lvlError; |         .longName("quiet") | ||||||
|     }); |         .description("decrease verbosity level") | ||||||
|  |         .handler([]() { verbosity = verbosity > lvlError ? (Verbosity) (verbosity - 1) : lvlError; }); | ||||||
| 
 | 
 | ||||||
|     mkFlag(0, "debug", "enable debug output", []() { |     mkFlag() | ||||||
|         verbosity = lvlDebug; |         .longName("debug") | ||||||
|     }); |         .description("enable debug output") | ||||||
|  |         .handler([]() { verbosity = lvlDebug; }); | ||||||
| 
 | 
 | ||||||
|     mkFlag() |     mkFlag() | ||||||
|         .longName("option") |         .longName("option") | ||||||
|         .labels({"name", "value"}) |         .labels({"name", "value"}) | ||||||
|         .description("set a Nix configuration option (overriding nix.conf)") |         .description("set a Nix configuration option (overriding nix.conf)") | ||||||
|         .arity(2) |         .arity(2) | ||||||
|         .handler([](Strings ss) { |         .handler([](std::vector<std::string> ss) { | ||||||
|             auto name = ss.front(); ss.pop_front(); |  | ||||||
|             auto value = ss.front(); |  | ||||||
|             try { |             try { | ||||||
|                 settings.set(name, value); |                 settings.set(ss[0], ss[1]); | ||||||
|             } catch (UsageError & e) { |             } catch (UsageError & e) { | ||||||
|                 warn(e.what()); |                 warn(e.what()); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| #include "common-args.hh" |  | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
| #include "shared.hh" | #include "shared.hh" | ||||||
| #include "store-api.hh" | #include "store-api.hh" | ||||||
|  | @ -149,26 +148,32 @@ void initNix() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| struct LegacyArgs : public MixCommonArgs | LegacyArgs::LegacyArgs(const std::string & programName, | ||||||
| { |  | ||||||
|     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg; |  | ||||||
| 
 |  | ||||||
|     LegacyArgs(const std::string & programName, |  | ||||||
|     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg) |     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg) | ||||||
|     : MixCommonArgs(programName), parseArg(parseArg) |     : MixCommonArgs(programName), parseArg(parseArg) | ||||||
|     { | { | ||||||
|         mkFlag('Q', "no-build-output", "do not show build output", |     mkFlag() | ||||||
|             &settings.verboseBuild, false); |         .longName("no-build-output") | ||||||
|  |         .shortName('Q') | ||||||
|  |         .description("do not show build output") | ||||||
|  |         .set(&settings.verboseBuild, false); | ||||||
| 
 | 
 | ||||||
|         mkFlag('K', "keep-failed", "keep temporary directories of failed builds", |     mkFlag() | ||||||
|             &(bool&) settings.keepFailed); |         .longName("keep-failed") | ||||||
|  |         .shortName('K') | ||||||
|  |         .description("keep temporary directories of failed builds") | ||||||
|  |         .set(&(bool&) settings.keepFailed, true); | ||||||
| 
 | 
 | ||||||
|         mkFlag('k', "keep-going", "keep going after a build fails", |     mkFlag() | ||||||
|             &(bool&) settings.keepGoing); |         .longName("keep-going") | ||||||
|  |         .shortName('k') | ||||||
|  |         .description("keep going after a build fails") | ||||||
|  |         .set(&(bool&) settings.keepGoing, true); | ||||||
| 
 | 
 | ||||||
|         mkFlag(0, "fallback", "build from source if substitution fails", []() { |     mkFlag() | ||||||
|             settings.tryFallback = true; |         .longName("fallback") | ||||||
|         }); |         .description("build from source if substitution fails") | ||||||
|  |         .set(&(bool&) settings.tryFallback, true); | ||||||
| 
 | 
 | ||||||
|     mkFlag1('j', "max-jobs", "jobs", "maximum number of parallel builds", [=](std::string s) { |     mkFlag1('j', "max-jobs", "jobs", "maximum number of parallel builds", [=](std::string s) { | ||||||
|         settings.set("max-jobs", s); |         settings.set("max-jobs", s); | ||||||
|  | @ -193,18 +198,20 @@ struct LegacyArgs : public MixCommonArgs | ||||||
| 
 | 
 | ||||||
|     mkFlag(0, "no-gc-warning", "disable warning about not using '--add-root'", |     mkFlag(0, "no-gc-warning", "disable warning about not using '--add-root'", | ||||||
|         &gcWarning, false); |         &gcWarning, false); | ||||||
|     } | } | ||||||
| 
 | 
 | ||||||
|     bool processFlag(Strings::iterator & pos, Strings::iterator end) override | 
 | ||||||
|     { | bool LegacyArgs::processFlag(Strings::iterator & pos, Strings::iterator end) | ||||||
|  | { | ||||||
|     if (MixCommonArgs::processFlag(pos, end)) return true; |     if (MixCommonArgs::processFlag(pos, end)) return true; | ||||||
|     bool res = parseArg(pos, end); |     bool res = parseArg(pos, end); | ||||||
|     if (res) ++pos; |     if (res) ++pos; | ||||||
|     return res; |     return res; | ||||||
|     } | } | ||||||
| 
 | 
 | ||||||
|     bool processArgs(const Strings & args, bool finish) override | 
 | ||||||
|     { | bool LegacyArgs::processArgs(const Strings & args, bool finish) | ||||||
|  | { | ||||||
|     if (args.empty()) return true; |     if (args.empty()) return true; | ||||||
|     assert(args.size() == 1); |     assert(args.size() == 1); | ||||||
|     Strings ss(args); |     Strings ss(args); | ||||||
|  | @ -212,8 +219,7 @@ struct LegacyArgs : public MixCommonArgs | ||||||
|     if (!parseArg(pos, ss.end())) |     if (!parseArg(pos, ss.end())) | ||||||
|         throw UsageError(format("unexpected argument '%1%'") % args.front()); |         throw UsageError(format("unexpected argument '%1%'") % args.front()); | ||||||
|     return true; |     return true; | ||||||
|     } | } | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void parseCmdLine(int argc, char * * argv, | void parseCmdLine(int argc, char * * argv, | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
| #include "args.hh" | #include "args.hh" | ||||||
|  | #include "common-args.hh" | ||||||
| 
 | 
 | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
| 
 | 
 | ||||||
|  | @ -69,6 +70,19 @@ template<class N> N getIntArg(const string & opt, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | struct LegacyArgs : public MixCommonArgs | ||||||
|  | { | ||||||
|  |     std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg; | ||||||
|  | 
 | ||||||
|  |     LegacyArgs(const std::string & programName, | ||||||
|  |         std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg); | ||||||
|  | 
 | ||||||
|  |     bool processFlag(Strings::iterator & pos, Strings::iterator end) override; | ||||||
|  | 
 | ||||||
|  |     bool processArgs(const Strings & args, bool finish) override; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* Show the manual page for the specified program. */ | /* Show the manual page for the specified program. */ | ||||||
| void showManPage(const string & name); | void showManPage(const string & name); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -116,17 +116,17 @@ template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::s | ||||||
|     args.mkFlag() |     args.mkFlag() | ||||||
|         .longName(name) |         .longName(name) | ||||||
|         .description("Enable sandboxing.") |         .description("Enable sandboxing.") | ||||||
|         .handler([=](Strings ss) { value = smEnabled; }) |         .handler([=](std::vector<std::string> ss) { value = smEnabled; }) | ||||||
|         .category(category); |         .category(category); | ||||||
|     args.mkFlag() |     args.mkFlag() | ||||||
|         .longName("no-" + name) |         .longName("no-" + name) | ||||||
|         .description("Disable sandboxing.") |         .description("Disable sandboxing.") | ||||||
|         .handler([=](Strings ss) { value = smDisabled; }) |         .handler([=](std::vector<std::string> ss) { value = smDisabled; }) | ||||||
|         .category(category); |         .category(category); | ||||||
|     args.mkFlag() |     args.mkFlag() | ||||||
|         .longName("relaxed-" + name) |         .longName("relaxed-" + name) | ||||||
|         .description("Enable sandboxing, but allow builds to disable it.") |         .description("Enable sandboxing, but allow builds to disable it.") | ||||||
|         .handler([=](Strings ss) { value = smRelaxed; }) |         .handler([=](std::vector<std::string> ss) { value = smRelaxed; }) | ||||||
|         .category(category); |         .category(category); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -100,7 +100,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) | ||||||
| 
 | 
 | ||||||
|     auto process = [&](const std::string & name, const Flag & flag) -> bool { |     auto process = [&](const std::string & name, const Flag & flag) -> bool { | ||||||
|         ++pos; |         ++pos; | ||||||
|         Strings args; |         std::vector<std::string> args; | ||||||
|         for (size_t n = 0 ; n < flag.arity; ++n) { |         for (size_t n = 0 ; n < flag.arity; ++n) { | ||||||
|             if (pos == end) { |             if (pos == end) { | ||||||
|                 if (flag.arity == ArityAny) break; |                 if (flag.arity == ArityAny) break; | ||||||
|  | @ -109,7 +109,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) | ||||||
|             } |             } | ||||||
|             args.push_back(*pos++); |             args.push_back(*pos++); | ||||||
|         } |         } | ||||||
|         flag.handler(args); |         flag.handler(std::move(args)); | ||||||
|         return true; |         return true; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | @ -144,7 +144,9 @@ bool Args::processArgs(const Strings & args, bool finish) | ||||||
|     if ((exp.arity == 0 && finish) || |     if ((exp.arity == 0 && finish) || | ||||||
|         (exp.arity > 0 && args.size() == exp.arity)) |         (exp.arity > 0 && args.size() == exp.arity)) | ||||||
|     { |     { | ||||||
|         exp.handler(args); |         std::vector<std::string> ss; | ||||||
|  |         for (auto & s : args) ss.push_back(s); | ||||||
|  |         exp.handler(std::move(ss)); | ||||||
|         expectedArgs.pop_front(); |         expectedArgs.pop_front(); | ||||||
|         res = true; |         res = true; | ||||||
|     } |     } | ||||||
|  | @ -155,13 +157,17 @@ bool Args::processArgs(const Strings & args, bool finish) | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Args::mkHashTypeFlag(const std::string & name, HashType * ht) | Args::FlagMaker & Args::FlagMaker::mkHashTypeFlag(HashType * ht) | ||||||
| { | { | ||||||
|     mkFlag1(0, name, "TYPE", "hash algorithm ('md5', 'sha1', 'sha256', or 'sha512')", [=](std::string s) { |     arity(1); | ||||||
|  |     label("type"); | ||||||
|  |     description("hash algorithm ('md5', 'sha1', 'sha256', or 'sha512')"); | ||||||
|  |     handler([ht](std::string s) { | ||||||
|         *ht = parseHashType(s); |         *ht = parseHashType(s); | ||||||
|         if (*ht == htUnknown) |         if (*ht == htUnknown) | ||||||
|             throw UsageError(format("unknown hash type '%1%'") % s); |             throw UsageError("unknown hash type '%1%'", s); | ||||||
|     }); |     }); | ||||||
|  |     return *this; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Strings argvToStrings(int argc, char * * argv) | Strings argvToStrings(int argc, char * * argv) | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ protected: | ||||||
|         std::string description; |         std::string description; | ||||||
|         Strings labels; |         Strings labels; | ||||||
|         size_t arity = 0; |         size_t arity = 0; | ||||||
|         std::function<void(Strings)> handler; |         std::function<void(std::vector<std::string>)> handler; | ||||||
|         std::string category; |         std::string category; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  | @ -54,7 +54,7 @@ protected: | ||||||
|         std::string label; |         std::string label; | ||||||
|         size_t arity; // 0 = any
 |         size_t arity; // 0 = any
 | ||||||
|         bool optional; |         bool optional; | ||||||
|         std::function<void(Strings)> handler; |         std::function<void(std::vector<std::string>)> handler; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     std::list<ExpectedArg> expectedArgs; |     std::list<ExpectedArg> expectedArgs; | ||||||
|  | @ -76,24 +76,35 @@ public: | ||||||
|         FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; }; |         FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; }; | ||||||
|         FlagMaker & shortName(char s) { flag->shortName = s; return *this; }; |         FlagMaker & shortName(char s) { flag->shortName = s; return *this; }; | ||||||
|         FlagMaker & description(const std::string & s) { flag->description = s; return *this; }; |         FlagMaker & description(const std::string & s) { flag->description = s; return *this; }; | ||||||
|         FlagMaker & labels(const Strings & ls) { flag->labels = ls; return *this; }; |         FlagMaker & label(const std::string & l) { flag->arity = 1; flag->labels = {l}; return *this; }; | ||||||
|  |         FlagMaker & labels(const Strings & ls) { flag->arity = ls.size(); flag->labels = ls; return *this; }; | ||||||
|         FlagMaker & arity(size_t arity) { flag->arity = arity; return *this; }; |         FlagMaker & arity(size_t arity) { flag->arity = arity; return *this; }; | ||||||
|         FlagMaker & handler(std::function<void(Strings)> handler) { flag->handler = handler; return *this; }; |         FlagMaker & handler(std::function<void(std::vector<std::string>)> handler) { flag->handler = handler; return *this; }; | ||||||
|  |         FlagMaker & handler(std::function<void()> handler) { flag->handler = [handler](std::vector<std::string>) { handler(); }; return *this; }; | ||||||
|  |         FlagMaker & handler(std::function<void(std::string)> handler) { | ||||||
|  |             flag->arity = 1; | ||||||
|  |             flag->handler = [handler](std::vector<std::string> ss) { handler(std::move(ss[0])); }; | ||||||
|  |             return *this; | ||||||
|  |         }; | ||||||
|         FlagMaker & category(const std::string & s) { flag->category = s; return *this; }; |         FlagMaker & category(const std::string & s) { flag->category = s; return *this; }; | ||||||
| 
 | 
 | ||||||
|         template<class T> |         template<class T> | ||||||
|         FlagMaker & dest(T * dest) { |         FlagMaker & dest(T * dest) | ||||||
|  |         { | ||||||
|             flag->arity = 1; |             flag->arity = 1; | ||||||
|             flag->handler = [=](Strings ss) { *dest = ss.front(); }; |             flag->handler = [=](std::vector<std::string> ss) { *dest = ss[0]; }; | ||||||
|             return *this; |             return *this; | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         template<class T> |         template<class T> | ||||||
|         FlagMaker & set(T * dest, const T & val) { |         FlagMaker & set(T * dest, const T & val) | ||||||
|  |         { | ||||||
|             flag->arity = 0; |             flag->arity = 0; | ||||||
|             flag->handler = [=](Strings ss) { *dest = val; }; |             flag->handler = [=](std::vector<std::string> ss) { *dest = val; }; | ||||||
|             return *this; |             return *this; | ||||||
|         }; |         }; | ||||||
|  | 
 | ||||||
|  |         FlagMaker & mkHashTypeFlag(HashType * ht); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     FlagMaker mkFlag(); |     FlagMaker mkFlag(); | ||||||
|  | @ -101,16 +112,6 @@ public: | ||||||
|     /* Helper functions for constructing flags / positional
 |     /* Helper functions for constructing flags / positional
 | ||||||
|        arguments. */ |        arguments. */ | ||||||
| 
 | 
 | ||||||
|     void mkFlag(char shortName, const std::string & longName, |  | ||||||
|         const std::string & description, std::function<void()> fun) |  | ||||||
|     { |  | ||||||
|         mkFlag() |  | ||||||
|             .shortName(shortName) |  | ||||||
|             .longName(longName) |  | ||||||
|             .description(description) |  | ||||||
|             .handler(std::bind(fun)); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void mkFlag1(char shortName, const std::string & longName, |     void mkFlag1(char shortName, const std::string & longName, | ||||||
|         const std::string & label, const std::string & description, |         const std::string & label, const std::string & description, | ||||||
|         std::function<void(std::string)> fun) |         std::function<void(std::string)> fun) | ||||||
|  | @ -121,7 +122,7 @@ public: | ||||||
|             .labels({label}) |             .labels({label}) | ||||||
|             .description(description) |             .description(description) | ||||||
|             .arity(1) |             .arity(1) | ||||||
|             .handler([=](Strings ss) { fun(ss.front()); }); |             .handler([=](std::vector<std::string> ss) { fun(ss[0]); }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void mkFlag(char shortName, const std::string & name, |     void mkFlag(char shortName, const std::string & name, | ||||||
|  | @ -130,17 +131,6 @@ public: | ||||||
|         mkFlag(shortName, name, description, dest, true); |         mkFlag(shortName, name, description, dest, true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void mkFlag(char shortName, const std::string & longName, |  | ||||||
|         const std::string & label, const std::string & description, |  | ||||||
|         string * dest) |  | ||||||
|     { |  | ||||||
|         mkFlag1(shortName, longName, label, description, [=](std::string s) { |  | ||||||
|             *dest = s; |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void mkHashTypeFlag(const std::string & name, HashType * ht); |  | ||||||
| 
 |  | ||||||
|     template<class T> |     template<class T> | ||||||
|     void mkFlag(char shortName, const std::string & longName, const std::string & description, |     void mkFlag(char shortName, const std::string & longName, const std::string & description, | ||||||
|         T * dest, const T & value) |         T * dest, const T & value) | ||||||
|  | @ -149,7 +139,7 @@ public: | ||||||
|             .shortName(shortName) |             .shortName(shortName) | ||||||
|             .longName(longName) |             .longName(longName) | ||||||
|             .description(description) |             .description(description) | ||||||
|             .handler([=](Strings ss) { *dest = value; }); |             .handler([=](std::vector<std::string> ss) { *dest = value; }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     template<class I> |     template<class I> | ||||||
|  | @ -171,10 +161,10 @@ public: | ||||||
|             .labels({"N"}) |             .labels({"N"}) | ||||||
|             .description(description) |             .description(description) | ||||||
|             .arity(1) |             .arity(1) | ||||||
|             .handler([=](Strings ss) { |             .handler([=](std::vector<std::string> ss) { | ||||||
|                 I n; |                 I n; | ||||||
|                 if (!string2Int(ss.front(), n)) |                 if (!string2Int(ss[0], n)) | ||||||
|                     throw UsageError(format("flag '--%1%' requires a integer argument") % longName); |                     throw UsageError("flag '--%s' requires a integer argument", longName); | ||||||
|                 fun(n); |                 fun(n); | ||||||
|             }); |             }); | ||||||
|     } |     } | ||||||
|  | @ -182,16 +172,16 @@ public: | ||||||
|     /* Expect a string argument. */ |     /* Expect a string argument. */ | ||||||
|     void expectArg(const std::string & label, string * dest, bool optional = false) |     void expectArg(const std::string & label, string * dest, bool optional = false) | ||||||
|     { |     { | ||||||
|         expectedArgs.push_back(ExpectedArg{label, 1, optional, [=](Strings ss) { |         expectedArgs.push_back(ExpectedArg{label, 1, optional, [=](std::vector<std::string> ss) { | ||||||
|             *dest = ss.front(); |             *dest = ss[0]; | ||||||
|         }}); |         }}); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* Expect 0 or more arguments. */ |     /* Expect 0 or more arguments. */ | ||||||
|     void expectArgs(const std::string & label, Strings * dest) |     void expectArgs(const std::string & label, std::vector<std::string> * dest) | ||||||
|     { |     { | ||||||
|         expectedArgs.push_back(ExpectedArg{label, 0, false, [=](Strings ss) { |         expectedArgs.push_back(ExpectedArg{label, 0, false, [=](std::vector<std::string> ss) { | ||||||
|             *dest = ss; |             *dest = std::move(ss); | ||||||
|         }}); |         }}); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -152,7 +152,7 @@ void BaseSetting<T>::convertToArg(Args & args, const std::string & category) | ||||||
|         .longName(name) |         .longName(name) | ||||||
|         .description(description) |         .description(description) | ||||||
|         .arity(1) |         .arity(1) | ||||||
|         .handler([=](Strings ss) { set(*ss.begin()); }) |         .handler([=](std::vector<std::string> ss) { set(ss[0]); }) | ||||||
|         .category(category); |         .category(category); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -201,12 +201,12 @@ template<> void BaseSetting<bool>::convertToArg(Args & args, const std::string & | ||||||
|     args.mkFlag() |     args.mkFlag() | ||||||
|         .longName(name) |         .longName(name) | ||||||
|         .description(description) |         .description(description) | ||||||
|         .handler([=](Strings ss) { value = true; }) |         .handler([=](std::vector<std::string> ss) { value = true; }) | ||||||
|         .category(category); |         .category(category); | ||||||
|     args.mkFlag() |     args.mkFlag() | ||||||
|         .longName("no-" + name) |         .longName("no-" + name) | ||||||
|         .description(description) |         .description(description) | ||||||
|         .handler([=](Strings ss) { value = false; }) |         .handler([=](std::vector<std::string> ss) { value = false; }) | ||||||
|         .category(category); |         .category(category); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "eval-inline.hh" | #include "eval-inline.hh" | ||||||
| #include "get-drvs.hh" | #include "get-drvs.hh" | ||||||
| #include "common-opts.hh" | #include "common-eval-args.hh" | ||||||
| #include "attr-path.hh" | #include "attr-path.hh" | ||||||
| 
 | 
 | ||||||
| using namespace nix; | using namespace nix; | ||||||
|  | @ -80,8 +80,6 @@ void mainWrapped(int argc, char * * argv) | ||||||
|     auto interactive = isatty(STDIN_FILENO) && isatty(STDERR_FILENO); |     auto interactive = isatty(STDIN_FILENO) && isatty(STDERR_FILENO); | ||||||
|     Strings attrPaths; |     Strings attrPaths; | ||||||
|     Strings left; |     Strings left; | ||||||
|     Strings searchPath; |  | ||||||
|     std::map<string, string> autoArgs_; |  | ||||||
|     RepairFlag repair = NoRepair; |     RepairFlag repair = NoRepair; | ||||||
|     Path gcRoot; |     Path gcRoot; | ||||||
|     BuildMode buildMode = bmNormal; |     BuildMode buildMode = bmNormal; | ||||||
|  | @ -129,7 +127,12 @@ void mainWrapped(int argc, char * * argv) | ||||||
|         } catch (SysError &) { } |         } catch (SysError &) { } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     parseCmdLine(myName, args, [&](Strings::iterator & arg, const Strings::iterator & end) { |     struct MyArgs : LegacyArgs, MixEvalArgs | ||||||
|  |     { | ||||||
|  |         using LegacyArgs::LegacyArgs; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     MyArgs myArgs(myName, [&](Strings::iterator & arg, const Strings::iterator & end) { | ||||||
|         if (*arg == "--help") { |         if (*arg == "--help") { | ||||||
|             deletePath(tmpDir); |             deletePath(tmpDir); | ||||||
|             showManPage(myName); |             showManPage(myName); | ||||||
|  | @ -153,12 +156,6 @@ void mainWrapped(int argc, char * * argv) | ||||||
|         else if (*arg == "--out-link" || *arg == "-o") |         else if (*arg == "--out-link" || *arg == "-o") | ||||||
|             outLink = getArg(*arg, arg, end); |             outLink = getArg(*arg, arg, end); | ||||||
| 
 | 
 | ||||||
|         else if (parseAutoArgs(arg, end, autoArgs_)) |  | ||||||
|             ; |  | ||||||
| 
 |  | ||||||
|         else if (parseSearchPathArg(arg, end, searchPath)) |  | ||||||
|             ; |  | ||||||
| 
 |  | ||||||
|         else if (*arg == "--add-root") |         else if (*arg == "--add-root") | ||||||
|             gcRoot = getArg(*arg, arg, end); |             gcRoot = getArg(*arg, arg, end); | ||||||
| 
 | 
 | ||||||
|  | @ -237,15 +234,17 @@ void mainWrapped(int argc, char * * argv) | ||||||
|         return true; |         return true; | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     myArgs.parseCmdline(args); | ||||||
|  | 
 | ||||||
|     if (packages && fromArgs) |     if (packages && fromArgs) | ||||||
|         throw UsageError("'-p' and '-E' are mutually exclusive"); |         throw UsageError("'-p' and '-E' are mutually exclusive"); | ||||||
| 
 | 
 | ||||||
|     auto store = openStore(); |     auto store = openStore(); | ||||||
| 
 | 
 | ||||||
|     EvalState state(searchPath, store); |     EvalState state(myArgs.searchPath, store); | ||||||
|     state.repair = repair; |     state.repair = repair; | ||||||
| 
 | 
 | ||||||
|     Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); |     Bindings & autoArgs = *myArgs.getAutoArgs(state); | ||||||
| 
 | 
 | ||||||
|     if (packages) { |     if (packages) { | ||||||
|         std::ostringstream joined; |         std::ostringstream joined; | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| #include "attr-path.hh" | #include "attr-path.hh" | ||||||
| #include "common-opts.hh" | #include "common-eval-args.hh" | ||||||
| #include "derivations.hh" | #include "derivations.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "get-drvs.hh" | #include "get-drvs.hh" | ||||||
|  | @ -1309,8 +1309,7 @@ int main(int argc, char * * argv) | ||||||
|         initNix(); |         initNix(); | ||||||
|         initGC(); |         initGC(); | ||||||
| 
 | 
 | ||||||
|         Strings opFlags, opArgs, searchPath; |         Strings opFlags, opArgs; | ||||||
|         std::map<string, string> autoArgs_; |  | ||||||
|         Operation op = 0; |         Operation op = 0; | ||||||
|         RepairFlag repair = NoRepair; |         RepairFlag repair = NoRepair; | ||||||
|         string file; |         string file; | ||||||
|  | @ -1326,7 +1325,12 @@ int main(int argc, char * * argv) | ||||||
|         globals.removeAll = false; |         globals.removeAll = false; | ||||||
|         globals.prebuiltOnly = false; |         globals.prebuiltOnly = false; | ||||||
| 
 | 
 | ||||||
|         parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { |         struct MyArgs : LegacyArgs, MixEvalArgs | ||||||
|  |         { | ||||||
|  |             using LegacyArgs::LegacyArgs; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) { | ||||||
|             Operation oldOp = op; |             Operation oldOp = op; | ||||||
| 
 | 
 | ||||||
|             if (*arg == "--help") |             if (*arg == "--help") | ||||||
|  | @ -1335,10 +1339,6 @@ int main(int argc, char * * argv) | ||||||
|                 op = opVersion; |                 op = opVersion; | ||||||
|             else if (*arg == "--install" || *arg == "-i") |             else if (*arg == "--install" || *arg == "-i") | ||||||
|                 op = opInstall; |                 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
 |             else if (*arg == "--force-name") // undocumented flag for nix-install-package
 | ||||||
|                 globals.forceName = getArg(*arg, arg, end); |                 globals.forceName = getArg(*arg, arg, end); | ||||||
|             else if (*arg == "--uninstall" || *arg == "-e") |             else if (*arg == "--uninstall" || *arg == "-e") | ||||||
|  | @ -1391,17 +1391,19 @@ int main(int argc, char * * argv) | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |         myArgs.parseCmdline(argvToStrings(argc, argv)); | ||||||
|  | 
 | ||||||
|         if (!op) throw UsageError("no operation specified"); |         if (!op) throw UsageError("no operation specified"); | ||||||
| 
 | 
 | ||||||
|         auto store = openStore(); |         auto store = openStore(); | ||||||
| 
 | 
 | ||||||
|         globals.state = std::shared_ptr<EvalState>(new EvalState(searchPath, store)); |         globals.state = std::shared_ptr<EvalState>(new EvalState(myArgs.searchPath, store)); | ||||||
|         globals.state->repair = repair; |         globals.state->repair = repair; | ||||||
| 
 | 
 | ||||||
|         if (file != "") |         if (file != "") | ||||||
|             globals.instSource.nixExprPath = lookupFileArg(*globals.state, file); |             globals.instSource.nixExprPath = lookupFileArg(*globals.state, file); | ||||||
| 
 | 
 | ||||||
|         globals.instSource.autoArgs = evalAutoArgs(*globals.state, autoArgs_); |         globals.instSource.autoArgs = myArgs.getAutoArgs(*globals.state); | ||||||
| 
 | 
 | ||||||
|         if (globals.profile == "") |         if (globals.profile == "") | ||||||
|             globals.profile = getEnv("NIX_PROFILE", ""); |             globals.profile = getEnv("NIX_PROFILE", ""); | ||||||
|  |  | ||||||
|  | @ -8,7 +8,7 @@ | ||||||
| #include "value-to-json.hh" | #include "value-to-json.hh" | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
| #include "store-api.hh" | #include "store-api.hh" | ||||||
| #include "common-opts.hh" | #include "common-eval-args.hh" | ||||||
| 
 | 
 | ||||||
| #include <map> | #include <map> | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  | @ -89,7 +89,7 @@ int main(int argc, char * * argv) | ||||||
|         initNix(); |         initNix(); | ||||||
|         initGC(); |         initGC(); | ||||||
| 
 | 
 | ||||||
|         Strings files, searchPath; |         Strings files; | ||||||
|         bool readStdin = false; |         bool readStdin = false; | ||||||
|         bool fromArgs = false; |         bool fromArgs = false; | ||||||
|         bool findFile = false; |         bool findFile = false; | ||||||
|  | @ -100,10 +100,14 @@ int main(int argc, char * * argv) | ||||||
|         bool strict = false; |         bool strict = false; | ||||||
|         Strings attrPaths; |         Strings attrPaths; | ||||||
|         bool wantsReadWrite = false; |         bool wantsReadWrite = false; | ||||||
|         std::map<string, string> autoArgs_; |  | ||||||
|         RepairFlag repair = NoRepair; |         RepairFlag repair = NoRepair; | ||||||
| 
 | 
 | ||||||
|         parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { |         struct MyArgs : LegacyArgs, MixEvalArgs | ||||||
|  |         { | ||||||
|  |             using LegacyArgs::LegacyArgs; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) { | ||||||
|             if (*arg == "--help") |             if (*arg == "--help") | ||||||
|                 showManPage("nix-instantiate"); |                 showManPage("nix-instantiate"); | ||||||
|             else if (*arg == "--version") |             else if (*arg == "--version") | ||||||
|  | @ -122,10 +126,6 @@ int main(int argc, char * * argv) | ||||||
|                 findFile = true; |                 findFile = true; | ||||||
|             else if (*arg == "--attr" || *arg == "-A") |             else if (*arg == "--attr" || *arg == "-A") | ||||||
|                 attrPaths.push_back(getArg(*arg, arg, end)); |                 attrPaths.push_back(getArg(*arg, arg, end)); | ||||||
|             else if (parseAutoArgs(arg, end, autoArgs_)) |  | ||||||
|                 ; |  | ||||||
|             else if (parseSearchPathArg(arg, end, searchPath)) |  | ||||||
|                 ; |  | ||||||
|             else if (*arg == "--add-root") |             else if (*arg == "--add-root") | ||||||
|                 gcRoot = getArg(*arg, arg, end); |                 gcRoot = getArg(*arg, arg, end); | ||||||
|             else if (*arg == "--indirect") |             else if (*arg == "--indirect") | ||||||
|  | @ -149,15 +149,17 @@ int main(int argc, char * * argv) | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |         myArgs.parseCmdline(argvToStrings(argc, argv)); | ||||||
|  | 
 | ||||||
|         if (evalOnly && !wantsReadWrite) |         if (evalOnly && !wantsReadWrite) | ||||||
|             settings.readOnlyMode = true; |             settings.readOnlyMode = true; | ||||||
| 
 | 
 | ||||||
|         auto store = openStore(); |         auto store = openStore(); | ||||||
| 
 | 
 | ||||||
|         EvalState state(searchPath, store); |         EvalState state(myArgs.searchPath, store); | ||||||
|         state.repair = repair; |         state.repair = repair; | ||||||
| 
 | 
 | ||||||
|         Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); |         Bindings & autoArgs = *myArgs.getAutoArgs(state); | ||||||
| 
 | 
 | ||||||
|         if (attrPaths.empty()) attrPaths = {""}; |         if (attrPaths.empty()) attrPaths = {""}; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| #include "store-api.hh" | #include "store-api.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "eval-inline.hh" | #include "eval-inline.hh" | ||||||
| #include "common-opts.hh" | #include "common-eval-args.hh" | ||||||
| #include "attr-path.hh" | #include "attr-path.hh" | ||||||
| 
 | 
 | ||||||
| #include <iostream> | #include <iostream> | ||||||
|  | @ -48,15 +48,18 @@ int main(int argc, char * * argv) | ||||||
| 
 | 
 | ||||||
|         HashType ht = htSHA256; |         HashType ht = htSHA256; | ||||||
|         std::vector<string> args; |         std::vector<string> args; | ||||||
|         Strings searchPath; |  | ||||||
|         bool printPath = getEnv("PRINT_PATH") != ""; |         bool printPath = getEnv("PRINT_PATH") != ""; | ||||||
|         bool fromExpr = false; |         bool fromExpr = false; | ||||||
|         string attrPath; |         string attrPath; | ||||||
|         std::map<string, string> autoArgs_; |  | ||||||
|         bool unpack = false; |         bool unpack = false; | ||||||
|         string name; |         string name; | ||||||
| 
 | 
 | ||||||
|         parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { |         struct MyArgs : LegacyArgs, MixEvalArgs | ||||||
|  |         { | ||||||
|  |             using LegacyArgs::LegacyArgs; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         MyArgs myArgs(baseNameOf(argv[0]), [&](Strings::iterator & arg, const Strings::iterator & end) { | ||||||
|             if (*arg == "--help") |             if (*arg == "--help") | ||||||
|                 showManPage("nix-prefetch-url"); |                 showManPage("nix-prefetch-url"); | ||||||
|             else if (*arg == "--version") |             else if (*arg == "--version") | ||||||
|  | @ -77,10 +80,6 @@ int main(int argc, char * * argv) | ||||||
|                 unpack = true; |                 unpack = true; | ||||||
|             else if (*arg == "--name") |             else if (*arg == "--name") | ||||||
|                 name = getArg(*arg, arg, end); |                 name = getArg(*arg, arg, end); | ||||||
|             else if (parseAutoArgs(arg, end, autoArgs_)) |  | ||||||
|                 ; |  | ||||||
|             else if (parseSearchPathArg(arg, end, searchPath)) |  | ||||||
|                 ; |  | ||||||
|             else if (*arg != "" && arg->at(0) == '-') |             else if (*arg != "" && arg->at(0) == '-') | ||||||
|                 return false; |                 return false; | ||||||
|             else |             else | ||||||
|  | @ -88,13 +87,15 @@ int main(int argc, char * * argv) | ||||||
|             return true; |             return true; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |         myArgs.parseCmdline(argvToStrings(argc, argv)); | ||||||
|  | 
 | ||||||
|         if (args.size() > 2) |         if (args.size() > 2) | ||||||
|             throw UsageError("too many arguments"); |             throw UsageError("too many arguments"); | ||||||
| 
 | 
 | ||||||
|         auto store = openStore(); |         auto store = openStore(); | ||||||
|         EvalState state(searchPath, store); |         EvalState state(myArgs.searchPath, store); | ||||||
| 
 | 
 | ||||||
|         Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); |         Bindings & autoArgs = *myArgs.getAutoArgs(state); | ||||||
| 
 | 
 | ||||||
|         /* If -A is given, get the URI from the specified Nix
 |         /* If -A is given, get the URI from the specified Nix
 | ||||||
|            expression. */ |            expression. */ | ||||||
|  |  | ||||||
|  | @ -24,11 +24,11 @@ void Command::printHelp(const string & programName, std::ostream & out) | ||||||
| MultiCommand::MultiCommand(const Commands & _commands) | MultiCommand::MultiCommand(const Commands & _commands) | ||||||
|     : commands(_commands) |     : commands(_commands) | ||||||
| { | { | ||||||
|     expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](Strings ss) { |     expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) { | ||||||
|         assert(!command); |         assert(!command); | ||||||
|         auto i = commands.find(ss.front()); |         auto i = commands.find(ss[0]); | ||||||
|         if (i == commands.end()) |         if (i == commands.end()) | ||||||
|             throw UsageError(format("'%1%' is not a recognised command") % ss.front()); |             throw UsageError("'%s' is not a recognised command", ss[0]); | ||||||
|         command = i->second; |         command = i->second; | ||||||
|     }}); |     }}); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,10 +1,12 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "args.hh" | #include "args.hh" | ||||||
|  | #include "common-eval-args.hh" | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
| struct Value; | struct Value; | ||||||
|  | struct Bindings; | ||||||
| class EvalState; | class EvalState; | ||||||
| 
 | 
 | ||||||
| /* A command is an argument parser that can be executed by calling its
 | /* A command is an argument parser that can be executed by calling its
 | ||||||
|  | @ -68,14 +70,11 @@ struct Installable | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct SourceExprCommand : virtual Args, StoreCommand | struct SourceExprCommand : virtual Args, StoreCommand, MixEvalArgs | ||||||
| { | { | ||||||
|     Path file; |     Path file; | ||||||
| 
 | 
 | ||||||
|     SourceExprCommand() |     SourceExprCommand(); | ||||||
|     { |  | ||||||
|         mkFlag('f', "file", "file", "evaluate FILE rather than the default", &file); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /* Return a value representing the Nix expression from which we
 |     /* Return a value representing the Nix expression from which we
 | ||||||
|        are installing. This is either the file specified by ‘--file’, |        are installing. This is either the file specified by ‘--file’, | ||||||
|  | @ -111,7 +110,7 @@ struct InstallablesCommand : virtual Args, SourceExprCommand | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 
 | 
 | ||||||
|     Strings _installables; |     std::vector<std::string> _installables; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct InstallableCommand : virtual Args, SourceExprCommand | struct InstallableCommand : virtual Args, SourceExprCommand | ||||||
|  |  | ||||||
|  | @ -19,8 +19,16 @@ struct CmdCopy : StorePathsCommand | ||||||
|     CmdCopy() |     CmdCopy() | ||||||
|         : StorePathsCommand(true) |         : StorePathsCommand(true) | ||||||
|     { |     { | ||||||
|         mkFlag(0, "from", "store-uri", "URI of the source Nix store", &srcUri); |         mkFlag() | ||||||
|         mkFlag(0, "to", "store-uri", "URI of the destination Nix store", &dstUri); |             .longName("from") | ||||||
|  |             .labels({"store-uri"}) | ||||||
|  |             .description("URI of the source Nix store") | ||||||
|  |             .dest(&srcUri); | ||||||
|  |         mkFlag() | ||||||
|  |             .longName("to") | ||||||
|  |             .labels({"store-uri"}) | ||||||
|  |             .description("URI of the destination Nix store") | ||||||
|  |             .dest(&dstUri); | ||||||
| 
 | 
 | ||||||
|         mkFlag() |         mkFlag() | ||||||
|             .longName("no-check-sigs") |             .longName("no-check-sigs") | ||||||
|  |  | ||||||
|  | @ -12,14 +12,16 @@ struct CmdHash : Command | ||||||
|     Base base = Base16; |     Base base = Base16; | ||||||
|     bool truncate = false; |     bool truncate = false; | ||||||
|     HashType ht = htSHA512; |     HashType ht = htSHA512; | ||||||
|     Strings paths; |     std::vector<std::string> paths; | ||||||
| 
 | 
 | ||||||
|     CmdHash(Mode mode) : mode(mode) |     CmdHash(Mode mode) : mode(mode) | ||||||
|     { |     { | ||||||
|         mkFlag(0, "base64", "print hash in base-64", &base, Base64); |         mkFlag(0, "base64", "print hash in base-64", &base, Base64); | ||||||
|         mkFlag(0, "base32", "print hash in base-32 (Nix-specific)", &base, Base32); |         mkFlag(0, "base32", "print hash in base-32 (Nix-specific)", &base, Base32); | ||||||
|         mkFlag(0, "base16", "print hash in base-16", &base, Base16); |         mkFlag(0, "base16", "print hash in base-16", &base, Base16); | ||||||
|         mkHashTypeFlag("type", &ht); |         mkFlag() | ||||||
|  |             .longName("type") | ||||||
|  |             .mkHashTypeFlag(&ht); | ||||||
|         expectArgs("paths", &paths); |         expectArgs("paths", &paths); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -53,11 +55,13 @@ struct CmdToBase : Command | ||||||
| { | { | ||||||
|     Base base; |     Base base; | ||||||
|     HashType ht = htSHA512; |     HashType ht = htSHA512; | ||||||
|     Strings args; |     std::vector<std::string> args; | ||||||
| 
 | 
 | ||||||
|     CmdToBase(Base base) : base(base) |     CmdToBase(Base base) : base(base) | ||||||
|     { |     { | ||||||
|         mkHashTypeFlag("type", &ht); |         mkFlag() | ||||||
|  |             .longName("type") | ||||||
|  |             .mkHashTypeFlag(&ht); | ||||||
|         expectArgs("strings", &args); |         expectArgs("strings", &args); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -95,7 +99,7 @@ static int compatNixHash(int argc, char * * argv) | ||||||
|     bool base32 = false; |     bool base32 = false; | ||||||
|     bool truncate = false; |     bool truncate = false; | ||||||
|     enum { opHash, opTo32, opTo16 } op = opHash; |     enum { opHash, opTo32, opTo16 } op = opHash; | ||||||
|     Strings ss; |     std::vector<std::string> ss; | ||||||
| 
 | 
 | ||||||
|     parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { |     parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) { | ||||||
|         if (*arg == "--help") |         if (*arg == "--help") | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| #include "command.hh" | #include "command.hh" | ||||||
| #include "attr-path.hh" | #include "attr-path.hh" | ||||||
| #include "common-opts.hh" | #include "common-eval-args.hh" | ||||||
| #include "derivations.hh" | #include "derivations.hh" | ||||||
| #include "eval-inline.hh" | #include "eval-inline.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
|  | @ -12,6 +12,16 @@ | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
|  | SourceExprCommand::SourceExprCommand() | ||||||
|  | { | ||||||
|  |     mkFlag() | ||||||
|  |         .shortName('f') | ||||||
|  |         .longName("file") | ||||||
|  |         .label("file") | ||||||
|  |         .description("evaluate FILE rather than the default") | ||||||
|  |         .dest(&file); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Value * SourceExprCommand::getSourceExpr(EvalState & state) | Value * SourceExprCommand::getSourceExpr(EvalState & state) | ||||||
| { | { | ||||||
|     if (vSourceExpr) return vSourceExpr; |     if (vSourceExpr) return vSourceExpr; | ||||||
|  | @ -66,7 +76,7 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state) | ||||||
| ref<EvalState> SourceExprCommand::getEvalState() | ref<EvalState> SourceExprCommand::getEvalState() | ||||||
| { | { | ||||||
|     if (!evalState) |     if (!evalState) | ||||||
|         evalState = std::make_shared<EvalState>(Strings{}, getStore()); |         evalState = std::make_shared<EvalState>(searchPath, getStore()); | ||||||
|     return ref<EvalState>(evalState); |     return ref<EvalState>(evalState); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -120,9 +130,7 @@ struct InstallableValue : Installable | ||||||
| 
 | 
 | ||||||
|         auto v = toValue(*state); |         auto v = toValue(*state); | ||||||
| 
 | 
 | ||||||
|         // FIXME
 |         Bindings & autoArgs = *cmd.getAutoArgs(*state); | ||||||
|         std::map<string, string> autoArgs_; |  | ||||||
|         Bindings & autoArgs(*evalAutoArgs(*state, autoArgs_)); |  | ||||||
| 
 | 
 | ||||||
|         DrvInfos drvs; |         DrvInfos drvs; | ||||||
|         getDerivations(*state, *v, "", autoArgs, drvs, false); |         getDerivations(*state, *v, "", autoArgs, drvs, false); | ||||||
|  | @ -187,9 +195,7 @@ struct InstallableAttrPath : InstallableValue | ||||||
|     { |     { | ||||||
|         auto source = cmd.getSourceExpr(state); |         auto source = cmd.getSourceExpr(state); | ||||||
| 
 | 
 | ||||||
|         // FIXME
 |         Bindings & autoArgs = *cmd.getAutoArgs(state); | ||||||
|         std::map<string, string> autoArgs_; |  | ||||||
|         Bindings & autoArgs(*evalAutoArgs(state, autoArgs_)); |  | ||||||
| 
 | 
 | ||||||
|         Value * v = findAlongAttrPath(state, attrPath, autoArgs, *source); |         Value * v = findAlongAttrPath(state, attrPath, autoArgs, *source); | ||||||
|         state.forceValue(*v); |         state.forceValue(*v); | ||||||
|  | @ -203,14 +209,14 @@ std::string attrRegex = R"([A-Za-z_][A-Za-z0-9-_+]*)"; | ||||||
| static std::regex attrPathRegex(fmt(R"(%1%(\.%1%)*)", attrRegex)); | static std::regex attrPathRegex(fmt(R"(%1%(\.%1%)*)", attrRegex)); | ||||||
| 
 | 
 | ||||||
| static std::vector<std::shared_ptr<Installable>> parseInstallables( | static std::vector<std::shared_ptr<Installable>> parseInstallables( | ||||||
|     SourceExprCommand & cmd, ref<Store> store, Strings ss, bool useDefaultInstallables) |     SourceExprCommand & cmd, ref<Store> store, std::vector<std::string> ss, bool useDefaultInstallables) | ||||||
| { | { | ||||||
|     std::vector<std::shared_ptr<Installable>> result; |     std::vector<std::shared_ptr<Installable>> result; | ||||||
| 
 | 
 | ||||||
|     if (ss.empty() && useDefaultInstallables) { |     if (ss.empty() && useDefaultInstallables) { | ||||||
|         if (cmd.file == "") |         if (cmd.file == "") | ||||||
|             cmd.file = "."; |             cmd.file = "."; | ||||||
|         ss = Strings{""}; |         ss = {""}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (auto & s : ss) { |     for (auto & s : ss) { | ||||||
|  |  | ||||||
|  | @ -20,9 +20,16 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs | ||||||
| { | { | ||||||
|     NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix") |     NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix") | ||||||
|     { |     { | ||||||
|         mkFlag('h', "help", "show usage information", [&]() { showHelpAndExit(); }); |         mkFlag() | ||||||
|  |             .longName("help") | ||||||
|  |             .shortName('h') | ||||||
|  |             .description("show usage information") | ||||||
|  |             .handler([&]() { showHelpAndExit(); }); | ||||||
| 
 | 
 | ||||||
|         mkFlag(0, "help-config", "show configuration options", [=]() { |         mkFlag() | ||||||
|  |             .longName("help-config") | ||||||
|  |             .description("show configuration options") | ||||||
|  |             .handler([&]() { | ||||||
|                 std::cout << "The following configuration options are available:\n\n"; |                 std::cout << "The following configuration options are available:\n\n"; | ||||||
|                 Table2 tbl; |                 Table2 tbl; | ||||||
|                 for (const auto & s : settings._getSettings()) |                 for (const auto & s : settings._getSettings()) | ||||||
|  | @ -32,7 +39,10 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs | ||||||
|                 throw Exit(); |                 throw Exit(); | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|         mkFlag(0, "version", "show version information", std::bind(printVersion, programName)); |         mkFlag() | ||||||
|  |             .longName("version") | ||||||
|  |             .description("show version information") | ||||||
|  |             .handler([&]() { printVersion(programName); }); | ||||||
| 
 | 
 | ||||||
|         std::string cat = "config"; |         std::string cat = "config"; | ||||||
|         settings.convertToArgs(*this, cat); |         settings.convertToArgs(*this, cat); | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
| #include "eval-inline.hh" | #include "eval-inline.hh" | ||||||
| #include "store-api.hh" | #include "store-api.hh" | ||||||
| #include "common-opts.hh" | #include "common-eval-args.hh" | ||||||
| #include "get-drvs.hh" | #include "get-drvs.hh" | ||||||
| #include "derivations.hh" | #include "derivations.hh" | ||||||
| #include "affinity.hh" | #include "affinity.hh" | ||||||
|  | @ -44,7 +44,7 @@ struct NixRepl | ||||||
| 
 | 
 | ||||||
|     NixRepl(const Strings & searchPath, nix::ref<Store> store); |     NixRepl(const Strings & searchPath, nix::ref<Store> store); | ||||||
|     ~NixRepl(); |     ~NixRepl(); | ||||||
|     void mainLoop(const Strings & files); |     void mainLoop(const std::vector<std::string> & files); | ||||||
|     StringSet completePrefix(string prefix); |     StringSet completePrefix(string prefix); | ||||||
|     bool getLine(string & input, const std::string &prompt); |     bool getLine(string & input, const std::string &prompt); | ||||||
|     Path getDerivationPath(Value & v); |     Path getDerivationPath(Value & v); | ||||||
|  | @ -131,7 +131,7 @@ static void completionCallback(const char * s, linenoiseCompletions *lc) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void NixRepl::mainLoop(const Strings & files) | void NixRepl::mainLoop(const std::vector<std::string> & files) | ||||||
| { | { | ||||||
|     string error = ANSI_RED "error:" ANSI_NORMAL " "; |     string error = ANSI_RED "error:" ANSI_NORMAL " "; | ||||||
|     std::cout << "Welcome to Nix version " << nixVersion << ". Type :? for help." << std::endl << std::endl; |     std::cout << "Welcome to Nix version " << nixVersion << ". Type :? for help." << std::endl << std::endl; | ||||||
|  | @ -664,9 +664,9 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m | ||||||
|     return str; |     return str; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct CmdRepl : StoreCommand | struct CmdRepl : StoreCommand, MixEvalArgs | ||||||
| { | { | ||||||
|     Strings files; |     std::vector<std::string> files; | ||||||
| 
 | 
 | ||||||
|     CmdRepl() |     CmdRepl() | ||||||
|     { |     { | ||||||
|  | @ -682,8 +682,7 @@ struct CmdRepl : StoreCommand | ||||||
| 
 | 
 | ||||||
|     void run(ref<Store> store) override |     void run(ref<Store> store) override | ||||||
|     { |     { | ||||||
|         // FIXME: pass searchPath
 |         NixRepl repl(searchPath, openStore()); | ||||||
|         NixRepl repl({}, openStore()); |  | ||||||
|         repl.mainLoop(files); |         repl.mainLoop(files); | ||||||
|     } |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -20,7 +20,7 @@ extern char * * environ; | ||||||
| 
 | 
 | ||||||
| struct CmdRun : InstallablesCommand | struct CmdRun : InstallablesCommand | ||||||
| { | { | ||||||
|     Strings command = { "bash" }; |     std::vector<std::string> command = { "bash" }; | ||||||
|     StringSet keep, unset; |     StringSet keep, unset; | ||||||
|     bool ignoreEnvironment = false; |     bool ignoreEnvironment = false; | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +32,7 @@ struct CmdRun : InstallablesCommand | ||||||
|             .description("command and arguments to be executed; defaults to 'bash'") |             .description("command and arguments to be executed; defaults to 'bash'") | ||||||
|             .arity(ArityAny) |             .arity(ArityAny) | ||||||
|             .labels({"command", "args"}) |             .labels({"command", "args"}) | ||||||
|             .handler([&](Strings ss) { |             .handler([&](std::vector<std::string> ss) { | ||||||
|                 if (ss.empty()) throw UsageError("--command requires at least one argument"); |                 if (ss.empty()) throw UsageError("--command requires at least one argument"); | ||||||
|                 command = ss; |                 command = ss; | ||||||
|             }); |             }); | ||||||
|  | @ -49,7 +49,7 @@ struct CmdRun : InstallablesCommand | ||||||
|             .description("keep specified environment variable") |             .description("keep specified environment variable") | ||||||
|             .arity(1) |             .arity(1) | ||||||
|             .labels({"name"}) |             .labels({"name"}) | ||||||
|             .handler([&](Strings ss) { keep.insert(ss.front()); }); |             .handler([&](std::vector<std::string> ss) { keep.insert(ss.front()); }); | ||||||
| 
 | 
 | ||||||
|         mkFlag() |         mkFlag() | ||||||
|             .longName("unset") |             .longName("unset") | ||||||
|  | @ -57,7 +57,7 @@ struct CmdRun : InstallablesCommand | ||||||
|             .description("unset specified environment variable") |             .description("unset specified environment variable") | ||||||
|             .arity(1) |             .arity(1) | ||||||
|             .labels({"name"}) |             .labels({"name"}) | ||||||
|             .handler([&](Strings ss) { unset.insert(ss.front()); }); |             .handler([&](std::vector<std::string> ss) { unset.insert(ss.front()); }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string name() override |     std::string name() override | ||||||
|  | @ -126,7 +126,8 @@ struct CmdRun : InstallablesCommand | ||||||
|         setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1); |         setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1); | ||||||
| 
 | 
 | ||||||
|         std::string cmd = *command.begin(); |         std::string cmd = *command.begin(); | ||||||
|         Strings args = command; |         Strings args; | ||||||
|  |         for (auto & arg : command) args.push_back(arg); | ||||||
| 
 | 
 | ||||||
|         stopProgressBar(); |         stopProgressBar(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -38,12 +38,12 @@ struct CmdSearch : SourceExprCommand, MixJSON | ||||||
|             .longName("update-cache") |             .longName("update-cache") | ||||||
|             .shortName('u') |             .shortName('u') | ||||||
|             .description("update the package search cache") |             .description("update the package search cache") | ||||||
|             .handler([&](Strings ss) { writeCache = true; useCache = false; }); |             .handler([&]() { writeCache = true; useCache = false; }); | ||||||
| 
 | 
 | ||||||
|         mkFlag() |         mkFlag() | ||||||
|             .longName("no-cache") |             .longName("no-cache") | ||||||
|             .description("do not use or update the package search cache") |             .description("do not use or update the package search cache") | ||||||
|             .handler([&](Strings ss) { writeCache = false; useCache = false; }); |             .handler([&]() { writeCache = false; useCache = false; }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string name() override |     std::string name() override | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ struct CmdCopySigs : StorePathsCommand | ||||||
|             .labels({"store-uri"}) |             .labels({"store-uri"}) | ||||||
|             .description("use signatures from specified store") |             .description("use signatures from specified store") | ||||||
|             .arity(1) |             .arity(1) | ||||||
|             .handler([&](Strings ss) { substituterUris.push_back(ss.front()); }); |             .handler([&](std::vector<std::string> ss) { substituterUris.push_back(ss[0]); }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string name() override |     std::string name() override | ||||||
|  | @ -101,7 +101,12 @@ struct CmdSignPaths : StorePathsCommand | ||||||
| 
 | 
 | ||||||
|     CmdSignPaths() |     CmdSignPaths() | ||||||
|     { |     { | ||||||
|         mkFlag('k', "key-file", {"file"}, "file containing the secret signing key", &secretKeyFile); |         mkFlag() | ||||||
|  |             .shortName('k') | ||||||
|  |             .longName("key-file") | ||||||
|  |             .label("file") | ||||||
|  |             .description("file containing the secret signing key") | ||||||
|  |             .dest(&secretKeyFile); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::string name() override |     std::string name() override | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ struct CmdVerify : StorePathsCommand | ||||||
|             .labels({"store-uri"}) |             .labels({"store-uri"}) | ||||||
|             .description("use signatures from specified store") |             .description("use signatures from specified store") | ||||||
|             .arity(1) |             .arity(1) | ||||||
|             .handler([&](Strings ss) { substituterUris.push_back(ss.front()); }); |             .handler([&](std::vector<std::string> ss) { substituterUris.push_back(ss[0]); }); | ||||||
|         mkIntFlag('n', "sigs-needed", "require that each path has at least N valid signatures", &sigsNeeded); |         mkIntFlag('n', "sigs-needed", "require that each path has at least N valid signatures", &sigsNeeded); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue