diff --git a/src/libmain/common-args.cc b/src/libmain/common-args.cc index 51e199ea5..a0cccceb4 100644 --- a/src/libmain/common-args.cc +++ b/src/libmain/common-args.cc @@ -1,5 +1,6 @@ #include "common-args.hh" #include "globals.hh" +#include "loggers.hh" namespace nix { @@ -38,6 +39,14 @@ MixCommonArgs::MixCommonArgs(const string & programName) }}, }); + addFlag({ + .longName = "log-format", + .description = "Format of the logs. One of \"raw\", \"internal-json\", \"bar\" " + "or \"bar-with-logs\".", + .labels = {"format"}, + .handler = {[](std::string format) { setLogFormat(format); }}, + }); + addFlag({ .longName = "max-jobs", .shortName = 'j', diff --git a/src/libmain/loggers.cc b/src/libmain/loggers.cc new file mode 100644 index 000000000..d3d5b104b --- /dev/null +++ b/src/libmain/loggers.cc @@ -0,0 +1,47 @@ +#include "loggers.hh" +#include "../nix/progress-bar.hh" + +namespace nix { + +LogFormat defaultLogFormat = LogFormat::raw; + +LogFormat parseLogFormat(const string &logFormatStr) { + if (logFormatStr == "raw") + return LogFormat::raw; + else if (logFormatStr == "internal-json") + return LogFormat::internalJson; + else if (logFormatStr == "bar") + return LogFormat::bar; + else if (logFormatStr == "bar-with-logs") + return LogFormat::barWithLogs; + throw Error(format("option 'log-format' has an invalid value '%s'") % + logFormatStr); +} + +Logger *makeDefaultLogger() { + switch (defaultLogFormat) { + case LogFormat::raw: + return makeSimpleLogger(); + case LogFormat::internalJson: + return makeJSONLogger(*makeSimpleLogger()); + case LogFormat::bar: + return makeProgressBar(); + case LogFormat::barWithLogs: + return makeProgressBar(true); + } +} + +void setLogFormat(const string &logFormatStr) { + setLogFormat(parseLogFormat(logFormatStr)); +} + +void setLogFormat(const LogFormat &logFormat) { + defaultLogFormat = logFormat; + createDefaultLogger(); +} + +void createDefaultLogger() { + logger = makeDefaultLogger(); +} + +} diff --git a/src/libmain/loggers.hh b/src/libmain/loggers.hh new file mode 100644 index 000000000..f50cbb682 --- /dev/null +++ b/src/libmain/loggers.hh @@ -0,0 +1,19 @@ +#pragma once + +#include "types.hh" + +namespace nix { + +enum class LogFormat { + raw, + internalJson, + bar, + barWithLogs, +}; + +void setLogFormat(const string &logFormatStr); +void setLogFormat(const LogFormat &logFormat); + +void createDefaultLogger(); + +} diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 3cc4ef8f1..6aec16e58 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -18,7 +18,7 @@ void setCurActivity(const ActivityId activityId) curActivity = activityId; } -Logger * logger = makeDefaultLogger(); +Logger * logger = makeSimpleLogger(); void Logger::warn(const std::string & msg) { @@ -94,7 +94,7 @@ void writeToStderr(const string & s) } } -Logger * makeDefaultLogger() +Logger * makeSimpleLogger() { return new SimpleLogger(); } diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index 18c24d508..e319790fc 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -63,6 +63,8 @@ public: virtual ~Logger() { } + virtual void stop() { }; + virtual void log(Verbosity lvl, const FormatOrString & fs) = 0; void log(const FormatOrString & fs) @@ -141,7 +143,7 @@ struct PushActivity extern Logger * logger; -Logger * makeDefaultLogger(); +Logger * makeSimpleLogger(); Logger * makeJSONLogger(Logger & prevLogger); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 71db92d77..e0a99152b 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -989,7 +989,7 @@ pid_t startProcess(std::function fun, const ProcessOptions & options) { auto wrapper = [&]() { if (!options.allowVfork) - logger = makeDefaultLogger(); + logger = makeSimpleLogger(); try { #if __linux__ if (options.dieWithParent && prctl(PR_SET_PDEATHSIG, SIGKILL) == -1) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 0a058a31b..8649de5e9 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -472,6 +472,8 @@ static void _main(int argc, char * * argv) restoreSignals(); + logger->stop(); + execvp(shell->c_str(), argPtrs.data()); throw SysError("executing shell '%s'", *shell); @@ -521,6 +523,8 @@ static void _main(int argc, char * * argv) if (auto store2 = store.dynamic_pointer_cast()) store2->addPermRoot(store->parseStorePath(symlink.second), absPath(symlink.first), true); + logger->stop(); + for (auto & path : outPaths) std::cout << path << '\n'; } diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index d62febaff..f7b04eb2b 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1446,6 +1446,8 @@ static int _main(int argc, char * * argv) globals.state->printStats(); + logger->stop(); + return 0; } } diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 3a3060ad8..708591b14 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -1098,6 +1098,8 @@ static int _main(int argc, char * * argv) op(opFlags, opArgs); + logger->stop(); + return 0; } } diff --git a/src/nix/main.cc b/src/nix/main.cc index 1120ba5ef..203901168 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -10,6 +10,7 @@ #include "progress-bar.hh" #include "filetransfer.hh" #include "finally.hh" +#include "loggers.hh" #include #include @@ -90,7 +91,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs .longName = "print-build-logs", .shortName = 'L', .description = "print full build logs on stderr", - .handler = {&printBuildLogs, true}, + .handler = {[&]() {setLogFormat(LogFormat::barWithLogs); }}, }); addFlag({ @@ -165,6 +166,10 @@ void mainWrapped(int argc, char * * argv) verbosity = lvlWarn; settings.verboseBuild = false; + setLogFormat("bar"); + + Finally f([] { logger->stop(); }); + NixArgs args; args.parseCmdline(argvToStrings(argc, argv)); @@ -178,10 +183,6 @@ void mainWrapped(int argc, char * * argv) && args.command->first != "upgrade-nix") settings.requireExperimentalFeature("nix-command"); - Finally f([]() { stopProgressBar(); }); - - startProgressBar(args.printBuildLogs); - if (args.useNet && !haveInternet()) { warn("you don't have Internet access; disabling some network-dependent features"); args.useNet = false; diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index c67701098..828541bfe 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -106,7 +106,7 @@ public: updateThread.join(); } - void stop() + void stop() override { auto state(state_.lock()); if (!state->active) return; @@ -457,11 +457,17 @@ public: } }; +Logger *makeProgressBar(bool printBuildLogs) +{ + return new ProgressBar( + printBuildLogs, + isatty(STDERR_FILENO) && getEnv("TERM").value_or("dumb") != "dumb" + ); +} + void startProgressBar(bool printBuildLogs) { - logger = new ProgressBar( - printBuildLogs, - isatty(STDERR_FILENO) && getEnv("TERM").value_or("dumb") != "dumb"); + logger = makeProgressBar(printBuildLogs); } void stopProgressBar() diff --git a/src/nix/progress-bar.hh b/src/nix/progress-bar.hh index 4d61175c2..60d0a2076 100644 --- a/src/nix/progress-bar.hh +++ b/src/nix/progress-bar.hh @@ -4,6 +4,8 @@ namespace nix { +Logger* makeProgressBar(bool printBuildLogs = false); + void startProgressBar(bool printBuildLogs = false); void stopProgressBar();