nix: Respect -I, --arg, --argstr

Also, random cleanup to argument handling.
This commit is contained in:
Eelco Dolstra 2017-10-24 12:45:11 +02:00
parent 25f32625e2
commit 0d59f1ca49
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
26 changed files with 349 additions and 299 deletions

View 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);
}
}

View 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);
}

View file

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

View file

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

View file

@ -6,28 +6,30 @@ namespace nix {
MixCommonArgs::MixCommonArgs(const string & programName)
: programName(programName)
{
mkFlag('v', "verbose", "increase verbosity level", []() {
verbosity = (Verbosity) (verbosity + 1);
});
mkFlag()
.longName("verbose")
.shortName('v')
.description("increase verbosity level")
.handler([]() { verbosity = (Verbosity) (verbosity + 1); });
mkFlag(0, "quiet", "decrease verbosity level", []() {
verbosity = verbosity > lvlError ? (Verbosity) (verbosity - 1) : lvlError;
});
mkFlag()
.longName("quiet")
.description("decrease verbosity level")
.handler([]() { verbosity = verbosity > lvlError ? (Verbosity) (verbosity - 1) : lvlError; });
mkFlag(0, "debug", "enable debug output", []() {
verbosity = lvlDebug;
});
mkFlag()
.longName("debug")
.description("enable debug output")
.handler([]() { verbosity = lvlDebug; });
mkFlag()
.longName("option")
.labels({"name", "value"})
.description("set a Nix configuration option (overriding nix.conf)")
.arity(2)
.handler([](Strings ss) {
auto name = ss.front(); ss.pop_front();
auto value = ss.front();
.handler([](std::vector<std::string> ss) {
try {
settings.set(name, value);
settings.set(ss[0], ss[1]);
} catch (UsageError & e) {
warn(e.what());
}

View file

@ -1,4 +1,3 @@
#include "common-args.hh"
#include "globals.hh"
#include "shared.hh"
#include "store-api.hh"
@ -149,71 +148,78 @@ void initNix()
}
struct LegacyArgs : public MixCommonArgs
LegacyArgs::LegacyArgs(const std::string & programName,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg)
: MixCommonArgs(programName), parseArg(parseArg)
{
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg;
mkFlag()
.longName("no-build-output")
.shortName('Q')
.description("do not show build output")
.set(&settings.verboseBuild, false);
LegacyArgs(const std::string & programName,
std::function<bool(Strings::iterator & arg, const Strings::iterator & end)> parseArg)
: MixCommonArgs(programName), parseArg(parseArg)
{
mkFlag('Q', "no-build-output", "do not show build output",
&settings.verboseBuild, false);
mkFlag()
.longName("keep-failed")
.shortName('K')
.description("keep temporary directories of failed builds")
.set(&(bool&) settings.keepFailed, true);
mkFlag('K', "keep-failed", "keep temporary directories of failed builds",
&(bool&) settings.keepFailed);
mkFlag()
.longName("keep-going")
.shortName('k')
.description("keep going after a build fails")
.set(&(bool&) settings.keepGoing, true);
mkFlag('k', "keep-going", "keep going after a build fails",
&(bool&) settings.keepGoing);
mkFlag()
.longName("fallback")
.description("build from source if substitution fails")
.set(&(bool&) settings.tryFallback, true);
mkFlag(0, "fallback", "build from source if substitution fails", []() {
settings.tryFallback = true;
mkFlag1('j', "max-jobs", "jobs", "maximum number of parallel builds", [=](std::string s) {
settings.set("max-jobs", s);
});
auto intSettingAlias = [&](char shortName, const std::string & longName,
const std::string & description, const std::string & dest) {
mkFlag<unsigned int>(shortName, longName, description, [=](unsigned int n) {
settings.set(dest, std::to_string(n));
});
};
mkFlag1('j', "max-jobs", "jobs", "maximum number of parallel builds", [=](std::string s) {
settings.set("max-jobs", s);
});
intSettingAlias(0, "cores", "maximum number of CPU cores to use inside a build", "cores");
intSettingAlias(0, "max-silent-time", "number of seconds of silence before a build is killed", "max-silent-time");
intSettingAlias(0, "timeout", "number of seconds before a build is killed", "timeout");
auto intSettingAlias = [&](char shortName, const std::string & longName,
const std::string & description, const std::string & dest) {
mkFlag<unsigned int>(shortName, longName, description, [=](unsigned int n) {
settings.set(dest, std::to_string(n));
});
};
mkFlag(0, "readonly-mode", "do not write to the Nix store",
&settings.readOnlyMode);
intSettingAlias(0, "cores", "maximum number of CPU cores to use inside a build", "cores");
intSettingAlias(0, "max-silent-time", "number of seconds of silence before a build is killed", "max-silent-time");
intSettingAlias(0, "timeout", "number of seconds before a build is killed", "timeout");
mkFlag(0, "show-trace", "show Nix expression stack trace in evaluation errors",
&settings.showTrace);
mkFlag(0, "readonly-mode", "do not write to the Nix store",
&settings.readOnlyMode);
mkFlag(0, "no-gc-warning", "disable warning about not using '--add-root'",
&gcWarning, false);
}
mkFlag(0, "show-trace", "show Nix expression stack trace in evaluation errors",
&settings.showTrace);
mkFlag(0, "no-gc-warning", "disable warning about not using '--add-root'",
&gcWarning, false);
}
bool LegacyArgs::processFlag(Strings::iterator & pos, Strings::iterator end)
{
if (MixCommonArgs::processFlag(pos, end)) return true;
bool res = parseArg(pos, end);
if (res) ++pos;
return res;
}
bool processFlag(Strings::iterator & pos, Strings::iterator end) override
{
if (MixCommonArgs::processFlag(pos, end)) return true;
bool res = parseArg(pos, end);
if (res) ++pos;
return res;
}
bool processArgs(const Strings & args, bool finish) override
{
if (args.empty()) return true;
assert(args.size() == 1);
Strings ss(args);
auto pos = ss.begin();
if (!parseArg(pos, ss.end()))
throw UsageError(format("unexpected argument '%1%'") % args.front());
return true;
}
};
bool LegacyArgs::processArgs(const Strings & args, bool finish)
{
if (args.empty()) return true;
assert(args.size() == 1);
Strings ss(args);
auto pos = ss.begin();
if (!parseArg(pos, ss.end()))
throw UsageError(format("unexpected argument '%1%'") % args.front());
return true;
}
void parseCmdLine(int argc, char * * argv,

View file

@ -2,6 +2,7 @@
#include "util.hh"
#include "args.hh"
#include "common-args.hh"
#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. */
void showManPage(const string & name);

View file

@ -116,17 +116,17 @@ template<> void BaseSetting<SandboxMode>::convertToArg(Args & args, const std::s
args.mkFlag()
.longName(name)
.description("Enable sandboxing.")
.handler([=](Strings ss) { value = smEnabled; })
.handler([=](std::vector<std::string> ss) { value = smEnabled; })
.category(category);
args.mkFlag()
.longName("no-" + name)
.description("Disable sandboxing.")
.handler([=](Strings ss) { value = smDisabled; })
.handler([=](std::vector<std::string> ss) { value = smDisabled; })
.category(category);
args.mkFlag()
.longName("relaxed-" + name)
.description("Enable sandboxing, but allow builds to disable it.")
.handler([=](Strings ss) { value = smRelaxed; })
.handler([=](std::vector<std::string> ss) { value = smRelaxed; })
.category(category);
}

View file

@ -100,7 +100,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
auto process = [&](const std::string & name, const Flag & flag) -> bool {
++pos;
Strings args;
std::vector<std::string> args;
for (size_t n = 0 ; n < flag.arity; ++n) {
if (pos == end) {
if (flag.arity == ArityAny) break;
@ -109,7 +109,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end)
}
args.push_back(*pos++);
}
flag.handler(args);
flag.handler(std::move(args));
return true;
};
@ -144,7 +144,9 @@ bool Args::processArgs(const Strings & args, bool finish)
if ((exp.arity == 0 && finish) ||
(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();
res = true;
}
@ -155,13 +157,17 @@ bool Args::processArgs(const Strings & args, bool finish)
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);
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)

View file

@ -37,7 +37,7 @@ protected:
std::string description;
Strings labels;
size_t arity = 0;
std::function<void(Strings)> handler;
std::function<void(std::vector<std::string>)> handler;
std::string category;
};
@ -54,7 +54,7 @@ protected:
std::string label;
size_t arity; // 0 = any
bool optional;
std::function<void(Strings)> handler;
std::function<void(std::vector<std::string>)> handler;
};
std::list<ExpectedArg> expectedArgs;
@ -76,24 +76,35 @@ public:
FlagMaker & longName(const std::string & s) { flag->longName = s; return *this; };
FlagMaker & shortName(char s) { flag->shortName = 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 & 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; };
template<class T>
FlagMaker & dest(T * dest) {
FlagMaker & dest(T * dest)
{
flag->arity = 1;
flag->handler = [=](Strings ss) { *dest = ss.front(); };
flag->handler = [=](std::vector<std::string> ss) { *dest = ss[0]; };
return *this;
};
template<class T>
FlagMaker & set(T * dest, const T & val) {
FlagMaker & set(T * dest, const T & val)
{
flag->arity = 0;
flag->handler = [=](Strings ss) { *dest = val; };
flag->handler = [=](std::vector<std::string> ss) { *dest = val; };
return *this;
};
FlagMaker & mkHashTypeFlag(HashType * ht);
};
FlagMaker mkFlag();
@ -101,16 +112,6 @@ public:
/* Helper functions for constructing flags / positional
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,
const std::string & label, const std::string & description,
std::function<void(std::string)> fun)
@ -121,7 +122,7 @@ public:
.labels({label})
.description(description)
.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,
@ -130,17 +131,6 @@ public:
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>
void mkFlag(char shortName, const std::string & longName, const std::string & description,
T * dest, const T & value)
@ -149,7 +139,7 @@ public:
.shortName(shortName)
.longName(longName)
.description(description)
.handler([=](Strings ss) { *dest = value; });
.handler([=](std::vector<std::string> ss) { *dest = value; });
}
template<class I>
@ -171,10 +161,10 @@ public:
.labels({"N"})
.description(description)
.arity(1)
.handler([=](Strings ss) {
.handler([=](std::vector<std::string> ss) {
I n;
if (!string2Int(ss.front(), n))
throw UsageError(format("flag '--%1%' requires a integer argument") % longName);
if (!string2Int(ss[0], n))
throw UsageError("flag '--%s' requires a integer argument", longName);
fun(n);
});
}
@ -182,16 +172,16 @@ public:
/* Expect a string argument. */
void expectArg(const std::string & label, string * dest, bool optional = false)
{
expectedArgs.push_back(ExpectedArg{label, 1, optional, [=](Strings ss) {
*dest = ss.front();
expectedArgs.push_back(ExpectedArg{label, 1, optional, [=](std::vector<std::string> ss) {
*dest = ss[0];
}});
}
/* 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) {
*dest = ss;
expectedArgs.push_back(ExpectedArg{label, 0, false, [=](std::vector<std::string> ss) {
*dest = std::move(ss);
}});
}

View file

@ -152,7 +152,7 @@ void BaseSetting<T>::convertToArg(Args & args, const std::string & category)
.longName(name)
.description(description)
.arity(1)
.handler([=](Strings ss) { set(*ss.begin()); })
.handler([=](std::vector<std::string> ss) { set(ss[0]); })
.category(category);
}
@ -201,12 +201,12 @@ template<> void BaseSetting<bool>::convertToArg(Args & args, const std::string &
args.mkFlag()
.longName(name)
.description(description)
.handler([=](Strings ss) { value = true; })
.handler([=](std::vector<std::string> ss) { value = true; })
.category(category);
args.mkFlag()
.longName("no-" + name)
.description(description)
.handler([=](Strings ss) { value = false; })
.handler([=](std::vector<std::string> ss) { value = false; })
.category(category);
}

View file

@ -14,7 +14,7 @@
#include "eval.hh"
#include "eval-inline.hh"
#include "get-drvs.hh"
#include "common-opts.hh"
#include "common-eval-args.hh"
#include "attr-path.hh"
using namespace nix;
@ -80,8 +80,6 @@ void mainWrapped(int argc, char * * argv)
auto interactive = isatty(STDIN_FILENO) && isatty(STDERR_FILENO);
Strings attrPaths;
Strings left;
Strings searchPath;
std::map<string, string> autoArgs_;
RepairFlag repair = NoRepair;
Path gcRoot;
BuildMode buildMode = bmNormal;
@ -129,7 +127,12 @@ void mainWrapped(int argc, char * * argv)
} 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") {
deletePath(tmpDir);
showManPage(myName);
@ -153,12 +156,6 @@ void mainWrapped(int argc, char * * argv)
else if (*arg == "--out-link" || *arg == "-o")
outLink = getArg(*arg, arg, end);
else if (parseAutoArgs(arg, end, autoArgs_))
;
else if (parseSearchPathArg(arg, end, searchPath))
;
else if (*arg == "--add-root")
gcRoot = getArg(*arg, arg, end);
@ -237,15 +234,17 @@ void mainWrapped(int argc, char * * argv)
return true;
});
myArgs.parseCmdline(args);
if (packages && fromArgs)
throw UsageError("'-p' and '-E' are mutually exclusive");
auto store = openStore();
EvalState state(searchPath, store);
EvalState state(myArgs.searchPath, store);
state.repair = repair;
Bindings & autoArgs(*evalAutoArgs(state, autoArgs_));
Bindings & autoArgs = *myArgs.getAutoArgs(state);
if (packages) {
std::ostringstream joined;

View file

@ -1,5 +1,5 @@
#include "attr-path.hh"
#include "common-opts.hh"
#include "common-eval-args.hh"
#include "derivations.hh"
#include "eval.hh"
#include "get-drvs.hh"
@ -1309,8 +1309,7 @@ int main(int argc, char * * argv)
initNix();
initGC();
Strings opFlags, opArgs, searchPath;
std::map<string, string> autoArgs_;
Strings opFlags, opArgs;
Operation op = 0;
RepairFlag repair = NoRepair;
string file;
@ -1326,7 +1325,12 @@ int main(int argc, char * * argv)
globals.removeAll = 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;
if (*arg == "--help")
@ -1335,10 +1339,6 @@ int main(int argc, char * * argv)
op = opVersion;
else if (*arg == "--install" || *arg == "-i")
op = opInstall;
else if (parseAutoArgs(arg, end, autoArgs_))
;
else if (parseSearchPathArg(arg, end, searchPath))
;
else if (*arg == "--force-name") // undocumented flag for nix-install-package
globals.forceName = getArg(*arg, arg, end);
else if (*arg == "--uninstall" || *arg == "-e")
@ -1391,17 +1391,19 @@ int main(int argc, char * * argv)
return true;
});
myArgs.parseCmdline(argvToStrings(argc, argv));
if (!op) throw UsageError("no operation specified");
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;
if (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 == "")
globals.profile = getEnv("NIX_PROFILE", "");

View file

@ -8,7 +8,7 @@
#include "value-to-json.hh"
#include "util.hh"
#include "store-api.hh"
#include "common-opts.hh"
#include "common-eval-args.hh"
#include <map>
#include <iostream>
@ -89,7 +89,7 @@ int main(int argc, char * * argv)
initNix();
initGC();
Strings files, searchPath;
Strings files;
bool readStdin = false;
bool fromArgs = false;
bool findFile = false;
@ -100,10 +100,14 @@ int main(int argc, char * * argv)
bool strict = false;
Strings attrPaths;
bool wantsReadWrite = false;
std::map<string, string> autoArgs_;
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")
showManPage("nix-instantiate");
else if (*arg == "--version")
@ -122,10 +126,6 @@ int main(int argc, char * * argv)
findFile = true;
else if (*arg == "--attr" || *arg == "-A")
attrPaths.push_back(getArg(*arg, arg, end));
else if (parseAutoArgs(arg, end, autoArgs_))
;
else if (parseSearchPathArg(arg, end, searchPath))
;
else if (*arg == "--add-root")
gcRoot = getArg(*arg, arg, end);
else if (*arg == "--indirect")
@ -149,15 +149,17 @@ int main(int argc, char * * argv)
return true;
});
myArgs.parseCmdline(argvToStrings(argc, argv));
if (evalOnly && !wantsReadWrite)
settings.readOnlyMode = true;
auto store = openStore();
EvalState state(searchPath, store);
EvalState state(myArgs.searchPath, store);
state.repair = repair;
Bindings & autoArgs(*evalAutoArgs(state, autoArgs_));
Bindings & autoArgs = *myArgs.getAutoArgs(state);
if (attrPaths.empty()) attrPaths = {""};

View file

@ -4,7 +4,7 @@
#include "store-api.hh"
#include "eval.hh"
#include "eval-inline.hh"
#include "common-opts.hh"
#include "common-eval-args.hh"
#include "attr-path.hh"
#include <iostream>
@ -48,15 +48,18 @@ int main(int argc, char * * argv)
HashType ht = htSHA256;
std::vector<string> args;
Strings searchPath;
bool printPath = getEnv("PRINT_PATH") != "";
bool fromExpr = false;
string attrPath;
std::map<string, string> autoArgs_;
bool unpack = false;
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")
showManPage("nix-prefetch-url");
else if (*arg == "--version")
@ -77,10 +80,6 @@ int main(int argc, char * * argv)
unpack = true;
else if (*arg == "--name")
name = getArg(*arg, arg, end);
else if (parseAutoArgs(arg, end, autoArgs_))
;
else if (parseSearchPathArg(arg, end, searchPath))
;
else if (*arg != "" && arg->at(0) == '-')
return false;
else
@ -88,13 +87,15 @@ int main(int argc, char * * argv)
return true;
});
myArgs.parseCmdline(argvToStrings(argc, argv));
if (args.size() > 2)
throw UsageError("too many arguments");
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
expression. */

View file

@ -24,11 +24,11 @@ void Command::printHelp(const string & programName, std::ostream & out)
MultiCommand::MultiCommand(const 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);
auto i = commands.find(ss.front());
auto i = commands.find(ss[0]);
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;
}});
}

View file

@ -1,10 +1,12 @@
#pragma once
#include "args.hh"
#include "common-eval-args.hh"
namespace nix {
struct Value;
struct Bindings;
class EvalState;
/* 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;
SourceExprCommand()
{
mkFlag('f', "file", "file", "evaluate FILE rather than the default", &file);
}
SourceExprCommand();
/* Return a value representing the Nix expression from which we
are installing. This is either the file specified by --file,
@ -111,7 +110,7 @@ struct InstallablesCommand : virtual Args, SourceExprCommand
private:
Strings _installables;
std::vector<std::string> _installables;
};
struct InstallableCommand : virtual Args, SourceExprCommand

View file

@ -19,8 +19,16 @@ struct CmdCopy : StorePathsCommand
CmdCopy()
: StorePathsCommand(true)
{
mkFlag(0, "from", "store-uri", "URI of the source Nix store", &srcUri);
mkFlag(0, "to", "store-uri", "URI of the destination Nix store", &dstUri);
mkFlag()
.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()
.longName("no-check-sigs")

View file

@ -12,14 +12,16 @@ struct CmdHash : Command
Base base = Base16;
bool truncate = false;
HashType ht = htSHA512;
Strings paths;
std::vector<std::string> paths;
CmdHash(Mode mode) : mode(mode)
{
mkFlag(0, "base64", "print hash in base-64", &base, Base64);
mkFlag(0, "base32", "print hash in base-32 (Nix-specific)", &base, Base32);
mkFlag(0, "base16", "print hash in base-16", &base, Base16);
mkHashTypeFlag("type", &ht);
mkFlag()
.longName("type")
.mkHashTypeFlag(&ht);
expectArgs("paths", &paths);
}
@ -53,11 +55,13 @@ struct CmdToBase : Command
{
Base base;
HashType ht = htSHA512;
Strings args;
std::vector<std::string> args;
CmdToBase(Base base) : base(base)
{
mkHashTypeFlag("type", &ht);
mkFlag()
.longName("type")
.mkHashTypeFlag(&ht);
expectArgs("strings", &args);
}
@ -95,7 +99,7 @@ static int compatNixHash(int argc, char * * argv)
bool base32 = false;
bool truncate = false;
enum { opHash, opTo32, opTo16 } op = opHash;
Strings ss;
std::vector<std::string> ss;
parseCmdLine(argc, argv, [&](Strings::iterator & arg, const Strings::iterator & end) {
if (*arg == "--help")

View file

@ -1,6 +1,6 @@
#include "command.hh"
#include "attr-path.hh"
#include "common-opts.hh"
#include "common-eval-args.hh"
#include "derivations.hh"
#include "eval-inline.hh"
#include "eval.hh"
@ -12,6 +12,16 @@
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)
{
if (vSourceExpr) return vSourceExpr;
@ -66,7 +76,7 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state)
ref<EvalState> SourceExprCommand::getEvalState()
{
if (!evalState)
evalState = std::make_shared<EvalState>(Strings{}, getStore());
evalState = std::make_shared<EvalState>(searchPath, getStore());
return ref<EvalState>(evalState);
}
@ -120,9 +130,7 @@ struct InstallableValue : Installable
auto v = toValue(*state);
// FIXME
std::map<string, string> autoArgs_;
Bindings & autoArgs(*evalAutoArgs(*state, autoArgs_));
Bindings & autoArgs = *cmd.getAutoArgs(*state);
DrvInfos drvs;
getDerivations(*state, *v, "", autoArgs, drvs, false);
@ -187,9 +195,7 @@ struct InstallableAttrPath : InstallableValue
{
auto source = cmd.getSourceExpr(state);
// FIXME
std::map<string, string> autoArgs_;
Bindings & autoArgs(*evalAutoArgs(state, autoArgs_));
Bindings & autoArgs = *cmd.getAutoArgs(state);
Value * v = findAlongAttrPath(state, attrPath, autoArgs, *source);
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::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;
if (ss.empty() && useDefaultInstallables) {
if (cmd.file == "")
cmd.file = ".";
ss = Strings{""};
ss = {""};
}
for (auto & s : ss) {

View file

@ -20,19 +20,29 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
{
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", [=]() {
std::cout << "The following configuration options are available:\n\n";
Table2 tbl;
for (const auto & s : settings._getSettings())
if (!s.second.isAlias)
tbl.emplace_back(s.first, s.second.setting->description);
printTable(std::cout, tbl);
throw Exit();
});
mkFlag()
.longName("help-config")
.description("show configuration options")
.handler([&]() {
std::cout << "The following configuration options are available:\n\n";
Table2 tbl;
for (const auto & s : settings._getSettings())
if (!s.second.isAlias)
tbl.emplace_back(s.first, s.second.setting->description);
printTable(std::cout, tbl);
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";
settings.convertToArgs(*this, cat);

View file

@ -7,7 +7,7 @@
#include "eval.hh"
#include "eval-inline.hh"
#include "store-api.hh"
#include "common-opts.hh"
#include "common-eval-args.hh"
#include "get-drvs.hh"
#include "derivations.hh"
#include "affinity.hh"
@ -44,7 +44,7 @@ struct NixRepl
NixRepl(const Strings & searchPath, nix::ref<Store> store);
~NixRepl();
void mainLoop(const Strings & files);
void mainLoop(const std::vector<std::string> & files);
StringSet completePrefix(string prefix);
bool getLine(string & input, const std::string &prompt);
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 " ";
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;
}
struct CmdRepl : StoreCommand
struct CmdRepl : StoreCommand, MixEvalArgs
{
Strings files;
std::vector<std::string> files;
CmdRepl()
{
@ -682,8 +682,7 @@ struct CmdRepl : StoreCommand
void run(ref<Store> store) override
{
// FIXME: pass searchPath
NixRepl repl({}, openStore());
NixRepl repl(searchPath, openStore());
repl.mainLoop(files);
}
};

View file

@ -20,7 +20,7 @@ extern char * * environ;
struct CmdRun : InstallablesCommand
{
Strings command = { "bash" };
std::vector<std::string> command = { "bash" };
StringSet keep, unset;
bool ignoreEnvironment = false;
@ -32,7 +32,7 @@ struct CmdRun : InstallablesCommand
.description("command and arguments to be executed; defaults to 'bash'")
.arity(ArityAny)
.labels({"command", "args"})
.handler([&](Strings ss) {
.handler([&](std::vector<std::string> ss) {
if (ss.empty()) throw UsageError("--command requires at least one argument");
command = ss;
});
@ -49,7 +49,7 @@ struct CmdRun : InstallablesCommand
.description("keep specified environment variable")
.arity(1)
.labels({"name"})
.handler([&](Strings ss) { keep.insert(ss.front()); });
.handler([&](std::vector<std::string> ss) { keep.insert(ss.front()); });
mkFlag()
.longName("unset")
@ -57,7 +57,7 @@ struct CmdRun : InstallablesCommand
.description("unset specified environment variable")
.arity(1)
.labels({"name"})
.handler([&](Strings ss) { unset.insert(ss.front()); });
.handler([&](std::vector<std::string> ss) { unset.insert(ss.front()); });
}
std::string name() override
@ -126,7 +126,8 @@ struct CmdRun : InstallablesCommand
setenv("PATH", concatStringsSep(":", unixPath).c_str(), 1);
std::string cmd = *command.begin();
Strings args = command;
Strings args;
for (auto & arg : command) args.push_back(arg);
stopProgressBar();

View file

@ -38,12 +38,12 @@ struct CmdSearch : SourceExprCommand, MixJSON
.longName("update-cache")
.shortName('u')
.description("update the package search cache")
.handler([&](Strings ss) { writeCache = true; useCache = false; });
.handler([&]() { writeCache = true; useCache = false; });
mkFlag()
.longName("no-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

View file

@ -19,7 +19,7 @@ struct CmdCopySigs : StorePathsCommand
.labels({"store-uri"})
.description("use signatures from specified store")
.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
@ -101,7 +101,12 @@ struct CmdSignPaths : StorePathsCommand
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

View file

@ -25,7 +25,7 @@ struct CmdVerify : StorePathsCommand
.labels({"store-uri"})
.description("use signatures from specified store")
.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);
}