aboutsummaryrefslogtreecommitdiff
path: root/src/nix/main.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix/main.cc')
-rw-r--r--src/nix/main.cc183
1 files changed, 135 insertions, 48 deletions
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 5056ceb78..06e221682 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -17,6 +17,10 @@
#include <netdb.h>
#include <netinet/in.h>
+#if __linux__
+#include <sys/resource.h>
+#endif
+
#include <nlohmann/json.hpp>
extern std::string chrootHelperName;
@@ -52,14 +56,18 @@ static bool haveInternet()
}
std::string programPath;
+char * * savedArgv;
+
+struct HelpRequested { };
struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
{
bool printBuildLogs = false;
bool useNet = true;
bool refresh = false;
+ bool showVersion = false;
- NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix")
+ NixArgs() : MultiCommand(RegisterCommand::getCommandsFor({})), MixCommonArgs("nix")
{
categories.clear();
categories[Command::catDefault] = "Main commands";
@@ -69,88 +77,137 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
addFlag({
.longName = "help",
- .description = "show usage information",
- .handler = {[&]() { if (!completions) showHelpAndExit(); }},
- });
-
- addFlag({
- .longName = "help-config",
- .description = "show configuration options",
- .handler = {[&]() {
- std::cout << "The following configuration options are available:\n\n";
- Table2 tbl;
- std::map<std::string, Config::SettingInfo> settings;
- globalConfig.getSettings(settings);
- for (const auto & s : settings)
- tbl.emplace_back(s.first, s.second.description);
- printTable(std::cout, tbl);
- throw Exit();
- }},
+ .description = "Show usage information.",
+ .handler = {[&]() { throw HelpRequested(); }},
});
addFlag({
.longName = "print-build-logs",
.shortName = 'L',
- .description = "print full build logs on stderr",
+ .description = "Print full build logs on standard error.",
+ .category = loggingCategory,
.handler = {[&]() {setLogFormat(LogFormat::barWithLogs); }},
});
addFlag({
.longName = "version",
- .description = "show version information",
- .handler = {[&]() { if (!completions) printVersion(programName); }},
+ .description = "Show version information.",
+ .handler = {[&]() { showVersion = true; }},
});
addFlag({
- .longName = "no-net",
- .description = "disable substituters and consider all previously downloaded files up-to-date",
+ .longName = "offline",
+ .aliases = {"no-net"}, // FIXME: remove
+ .description = "Disable substituters and consider all previously downloaded files up-to-date.",
.handler = {[&]() { useNet = false; }},
});
addFlag({
.longName = "refresh",
- .description = "consider all previously downloaded files out-of-date",
+ .description = "Consider all previously downloaded files out-of-date.",
.handler = {[&]() { refresh = true; }},
});
-
- deprecatedAliases.insert({"dev-shell", "develop"});
}
- void printFlags(std::ostream & out) override
+ std::map<std::string, std::vector<std::string>> aliases = {
+ {"add-to-store", {"store", "add-path"}},
+ {"cat-nar", {"nar", "cat"}},
+ {"cat-store", {"store", "cat"}},
+ {"copy-sigs", {"store", "copy-sigs"}},
+ {"dev-shell", {"develop"}},
+ {"diff-closures", {"store", "diff-closures"}},
+ {"dump-path", {"store", "dump-path"}},
+ {"hash-file", {"hash", "file"}},
+ {"hash-path", {"hash", "path"}},
+ {"ls-nar", {"nar", "ls"}},
+ {"ls-store", {"store", "ls"}},
+ {"make-content-addressable", {"store", "make-content-addressable"}},
+ {"optimise-store", {"store", "optimise"}},
+ {"ping-store", {"store", "ping"}},
+ {"sign-paths", {"store", "sign"}},
+ {"to-base16", {"hash", "to-base16"}},
+ {"to-base32", {"hash", "to-base32"}},
+ {"to-base64", {"hash", "to-base64"}},
+ {"verify", {"store", "verify"}},
+ };
+
+ bool aliasUsed = false;
+
+ Strings::iterator rewriteArgs(Strings & args, Strings::iterator pos) override
{
- Args::printFlags(out);
- std::cout <<
- "\n"
- "In addition, most configuration settings can be overriden using '--" ANSI_ITALIC "name value" ANSI_NORMAL "'.\n"
- "Boolean settings can be overriden using '--" ANSI_ITALIC "name" ANSI_NORMAL "' or '--no-" ANSI_ITALIC "name" ANSI_NORMAL "'. See 'nix\n"
- "--help-config' for a list of configuration settings.\n";
+ if (aliasUsed || command || pos == args.end()) return pos;
+ auto arg = *pos;
+ auto i = aliases.find(arg);
+ if (i == aliases.end()) return pos;
+ warn("'%s' is a deprecated alias for '%s'",
+ arg, concatStringsSep(" ", i->second));
+ pos = args.erase(pos);
+ for (auto j = i->second.rbegin(); j != i->second.rend(); ++j)
+ pos = args.insert(pos, *j);
+ aliasUsed = true;
+ return pos;
}
- void printHelp(const string & programName, std::ostream & out) override
+ std::string description() override
{
- MultiCommand::printHelp(programName, out);
+ return "a tool for reproducible and declarative configuration management";
+ }
-#if 0
- out << "\nFor full documentation, run 'man " << programName << "' or 'man " << programName << "-" ANSI_ITALIC "COMMAND" ANSI_NORMAL "'.\n";
-#endif
+ std::string doc() override
+ {
+ return
+ #include "nix.md"
+ ;
+ }
- std::cout << "\nNote: this program is " ANSI_RED "EXPERIMENTAL" ANSI_NORMAL " and subject to change.\n";
+ // Plugins may add new subcommands.
+ void pluginsInited() override
+ {
+ commands = RegisterCommand::getCommandsFor({});
}
+};
- void showHelpAndExit()
+static void showHelp(std::vector<std::string> subcommand)
+{
+ showManPage(subcommand.empty() ? "nix" : fmt("nix3-%s", concatStringsSep("-", subcommand)));
+}
+
+struct CmdHelp : Command
+{
+ std::vector<std::string> subcommand;
+
+ CmdHelp()
{
- printHelp(programName, std::cout);
- throw Exit();
+ expectArgs({
+ .label = "subcommand",
+ .handler = {&subcommand},
+ });
}
std::string description() override
{
- return "a tool for reproducible and declarative configuration management";
+ return "show help about `nix` or a particular subcommand";
+ }
+
+ std::string doc() override
+ {
+ return
+ #include "help.md"
+ ;
+ }
+
+ void run() override
+ {
+ showHelp(subcommand);
}
};
+static auto rCmdHelp = registerCommand<CmdHelp>("help");
+
void mainWrapped(int argc, char * * argv)
{
+ savedArgv = argv;
+
/* The chroot helper needs to be run before any threads have been
started. */
if (argc > 0 && argv[0] == chrootHelperName) {
@@ -169,7 +226,7 @@ void mainWrapped(int argc, char * * argv)
if (legacy) return legacy(argc, argv);
}
- verbosity = lvlWarn;
+ verbosity = lvlNotice;
settings.verboseBuild = false;
evalSettings.pureEval = true;
@@ -191,7 +248,7 @@ void mainWrapped(int argc, char * * argv)
auto builtins = state.baseEnv.values[0]->attrs;
for (auto & builtin : *builtins) {
auto b = nlohmann::json::object();
- if (builtin.value->type != tPrimOp) continue;
+ if (!builtin.value->isPrimOp()) continue;
auto primOp = builtin.value->primOp;
if (!primOp->doc) continue;
b["arity"] = primOp->arity;
@@ -214,15 +271,31 @@ void mainWrapped(int argc, char * * argv)
try {
args.parseCmdline(argvToStrings(argc, argv));
+ } catch (HelpRequested &) {
+ std::vector<std::string> subcommand;
+ MultiCommand * command = &args;
+ while (command) {
+ if (command && command->command) {
+ subcommand.push_back(command->command->first);
+ command = dynamic_cast<MultiCommand *>(&*command->command->second);
+ } else
+ break;
+ }
+ showHelp(subcommand);
+ return;
} catch (UsageError &) {
if (!completions) throw;
}
if (completions) return;
- initPlugins();
+ if (args.showVersion) {
+ printVersion(programName);
+ return;
+ }
- if (!args.command) args.showHelpAndExit();
+ if (!args.command)
+ throw UsageError("no subcommand specified");
if (args.command->first != "repl"
&& args.command->first != "doctor"
@@ -246,8 +319,11 @@ void mainWrapped(int argc, char * * argv)
fileTransferSettings.connectTimeout = 1;
}
- if (args.refresh)
+ if (args.refresh) {
settings.tarballTtl = 0;
+ settings.ttlNegativeNarInfoCache = 0;
+ settings.ttlPositiveNarInfoCache = 0;
+ }
args.command->second->prepare();
args.command->second->run();
@@ -257,6 +333,17 @@ void mainWrapped(int argc, char * * argv)
int main(int argc, char * * argv)
{
+ // Increase the default stack size for the evaluator and for
+ // libstdc++'s std::regex.
+ #if __linux__
+ rlim_t stackSize = 64 * 1024 * 1024;
+ struct rlimit limit;
+ if (getrlimit(RLIMIT_STACK, &limit) == 0 && limit.rlim_cur < stackSize) {
+ limit.rlim_cur = stackSize;
+ setrlimit(RLIMIT_STACK, &limit);
+ }
+ #endif
+
return nix::handleExceptions(argv[0], [&]() {
nix::mainWrapped(argc, argv);
});