mirror of
https://github.com/NixOS/nix.git
synced 2025-12-22 17:01:08 +01:00
Make the pager a logger wrapper
Rewrite the pager mechanism to make it a (parametrized) instance of `Logger` rather than being a standalone thing. The main interest of this is that we have more control over when to actually start it and make the inner pager more quiet (only when `writeToStdout` is called)
This commit is contained in:
parent
5c91f2e5d7
commit
52a4ccc1bd
14 changed files with 156 additions and 66 deletions
|
|
@ -29,6 +29,7 @@ extern "C" {
|
||||||
#include "attr-path.hh"
|
#include "attr-path.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "log-store.hh"
|
#include "log-store.hh"
|
||||||
|
#include "loggers.hh"
|
||||||
#include "common-eval-args.hh"
|
#include "common-eval-args.hh"
|
||||||
#include "get-drvs.hh"
|
#include "get-drvs.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#include "loggers.hh"
|
#include "loggers.hh"
|
||||||
#include "progress-bar.hh"
|
#include "progress-bar.hh"
|
||||||
|
#include "paged-logger.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
@ -53,4 +54,14 @@ void createDefaultLogger() {
|
||||||
logger = makeDefaultLogger();
|
logger = makeDefaultLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RunPager::RunPager()
|
||||||
|
: previousLogger(logger)
|
||||||
|
{
|
||||||
|
logger = new PagedLogger(previousLogger);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunPager::~RunPager() {
|
||||||
|
logger = previousLogger;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
///@file
|
///@file
|
||||||
|
|
||||||
|
#include "logging.hh"
|
||||||
#include "types.hh"
|
#include "types.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
@ -18,4 +19,13 @@ void setLogFormat(const LogFormat & logFormat);
|
||||||
|
|
||||||
void createDefaultLogger();
|
void createDefaultLogger();
|
||||||
|
|
||||||
|
class RunPager{
|
||||||
|
private:
|
||||||
|
Logger* previousLogger;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RunPager();
|
||||||
|
~RunPager();
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
90
src/libmain/paged-logger.cc
Normal file
90
src/libmain/paged-logger.cc
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#include "paged-logger.hh"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
PagedLogger::PagedLogger(Logger * previousLogger)
|
||||||
|
: innerLogger(previousLogger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PagedLogger::~PagedLogger()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (pid != -1) {
|
||||||
|
std::cout.flush();
|
||||||
|
dup2(stdout, STDOUT_FILENO);
|
||||||
|
pid.wait();
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
ignoreException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PagedLogger::startPager() {
|
||||||
|
if (pagerStarted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
innerLogger = makeSimpleLogger(false);
|
||||||
|
pagerStarted = true;
|
||||||
|
if (!isatty(STDOUT_FILENO)) return;
|
||||||
|
char * pager = getenv("NIX_PAGER");
|
||||||
|
if (!pager) pager = getenv("PAGER");
|
||||||
|
if (pager && ((std::string) pager == "" || (std::string) pager == "cat")) return;
|
||||||
|
|
||||||
|
Pipe toPager;
|
||||||
|
toPager.create();
|
||||||
|
|
||||||
|
pid = startProcess([&]() {
|
||||||
|
if (dup2(toPager.readSide.get(), STDIN_FILENO) == -1)
|
||||||
|
throw SysError("dupping stdin");
|
||||||
|
if (!getenv("LESS"))
|
||||||
|
setenv("LESS", "FRSXMK", 1);
|
||||||
|
restoreProcessContext();
|
||||||
|
if (pager)
|
||||||
|
execl("/bin/sh", "sh", "-c", pager, nullptr);
|
||||||
|
execlp("pager", "pager", nullptr);
|
||||||
|
execlp("less", "less", nullptr);
|
||||||
|
execlp("more", "more", nullptr);
|
||||||
|
throw SysError("executing '%1%'", pager);
|
||||||
|
});
|
||||||
|
|
||||||
|
pid.setKillSignal(SIGINT);
|
||||||
|
|
||||||
|
pid.setKillSignal(SIGINT);
|
||||||
|
stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
|
||||||
|
if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1)
|
||||||
|
throw SysError("dupping stdout");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PagedLogger::writeToStdout(std::string_view s)
|
||||||
|
{
|
||||||
|
startPager();
|
||||||
|
innerLogger->writeToStdout(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PagedLogger::stop() { return innerLogger->stop(); }
|
||||||
|
bool PagedLogger::isVerbose() { return false; }
|
||||||
|
void PagedLogger::log(Verbosity lvl, const std::string_view s)
|
||||||
|
{ innerLogger->log(lvl, s); }
|
||||||
|
void PagedLogger::logEI(const ErrorInfo & ei) { innerLogger->logEI(ei); }
|
||||||
|
void PagedLogger::warn(const std::string & msg)
|
||||||
|
{ innerLogger->warn(msg); }
|
||||||
|
void PagedLogger::startActivity(
|
||||||
|
ActivityId act,
|
||||||
|
Verbosity lvl,
|
||||||
|
ActivityType type,
|
||||||
|
const std::string & s,
|
||||||
|
const Fields & fields,
|
||||||
|
ActivityId parent)
|
||||||
|
{ innerLogger->startActivity(act, lvl, type, s, fields, parent); }
|
||||||
|
void PagedLogger::stopActivity(ActivityId act)
|
||||||
|
{ innerLogger->stopActivity(act); }
|
||||||
|
void PagedLogger::result(ActivityId act, ResultType type, const Fields & fields)
|
||||||
|
{ innerLogger->result(act, type, fields); }
|
||||||
|
std::optional<char> PagedLogger::ask(std::string_view s)
|
||||||
|
{ return innerLogger->ask(s); }
|
||||||
|
|
||||||
|
}
|
||||||
34
src/libmain/paged-logger.hh
Normal file
34
src/libmain/paged-logger.hh
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "logging.hh"
|
||||||
|
#include "util.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
class PagedLogger : public Logger {
|
||||||
|
Logger * innerLogger;
|
||||||
|
bool pagerStarted = false;
|
||||||
|
Pid pid;
|
||||||
|
int stdout;
|
||||||
|
|
||||||
|
void startPager();
|
||||||
|
|
||||||
|
public:
|
||||||
|
PagedLogger(Logger * previousLogger);
|
||||||
|
|
||||||
|
~PagedLogger();
|
||||||
|
|
||||||
|
void writeToStdout(std::string_view s) override;
|
||||||
|
|
||||||
|
// All these methods are just forwarded to the inner logger
|
||||||
|
|
||||||
|
void stop() override;
|
||||||
|
bool isVerbose() override;
|
||||||
|
void log(Verbosity lvl, std::string_view s) override;
|
||||||
|
void logEI(const ErrorInfo &ei) override;
|
||||||
|
void warn(const std::string &msg) override;
|
||||||
|
void startActivity(ActivityId act, Verbosity lvl, ActivityType type, const std::string &s, const Fields &fields, ActivityId parent) override;
|
||||||
|
void stopActivity(ActivityId act) override;
|
||||||
|
void result(ActivityId act, ResultType type, const Fields &fields) override;
|
||||||
|
std::optional<char> ask(std::string_view s) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
@ -351,55 +350,6 @@ int handleExceptions(const std::string & programName, std::function<void()> fun)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RunPager::RunPager()
|
|
||||||
{
|
|
||||||
if (!isatty(STDOUT_FILENO)) return;
|
|
||||||
char * pager = getenv("NIX_PAGER");
|
|
||||||
if (!pager) pager = getenv("PAGER");
|
|
||||||
if (pager && ((std::string) pager == "" || (std::string) pager == "cat")) return;
|
|
||||||
|
|
||||||
stopProgressBar();
|
|
||||||
|
|
||||||
Pipe toPager;
|
|
||||||
toPager.create();
|
|
||||||
|
|
||||||
pid = startProcess([&]() {
|
|
||||||
if (dup2(toPager.readSide.get(), STDIN_FILENO) == -1)
|
|
||||||
throw SysError("dupping stdin");
|
|
||||||
if (!getenv("LESS"))
|
|
||||||
setenv("LESS", "FRSXMK", 1);
|
|
||||||
restoreProcessContext();
|
|
||||||
if (pager)
|
|
||||||
execl("/bin/sh", "sh", "-c", pager, nullptr);
|
|
||||||
execlp("pager", "pager", nullptr);
|
|
||||||
execlp("less", "less", nullptr);
|
|
||||||
execlp("more", "more", nullptr);
|
|
||||||
throw SysError("executing '%1%'", pager);
|
|
||||||
});
|
|
||||||
|
|
||||||
pid.setKillSignal(SIGINT);
|
|
||||||
stdout = fcntl(STDOUT_FILENO, F_DUPFD_CLOEXEC, 0);
|
|
||||||
if (dup2(toPager.writeSide.get(), STDOUT_FILENO) == -1)
|
|
||||||
throw SysError("dupping stdout");
|
|
||||||
setLogFormat(LogFormat::raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RunPager::~RunPager()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (pid != -1) {
|
|
||||||
std::cout.flush();
|
|
||||||
dup2(stdout, STDOUT_FILENO);
|
|
||||||
pid.wait();
|
|
||||||
}
|
|
||||||
} catch (...) {
|
|
||||||
ignoreException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PrintFreed::~PrintFreed()
|
PrintFreed::~PrintFreed()
|
||||||
{
|
{
|
||||||
if (show)
|
if (show)
|
||||||
|
|
|
||||||
|
|
@ -84,21 +84,6 @@ struct LegacyArgs : public MixCommonArgs
|
||||||
*/
|
*/
|
||||||
void showManPage(const std::string & name);
|
void showManPage(const std::string & name);
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor of this class starts a pager if stdout is a
|
|
||||||
* terminal and $PAGER is set. Stdout is redirected to the pager.
|
|
||||||
*/
|
|
||||||
class RunPager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RunPager();
|
|
||||||
~RunPager();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Pid pid;
|
|
||||||
int stdout;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern volatile ::sig_atomic_t blockInt;
|
extern volatile ::sig_atomic_t blockInt;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "value-to-json.hh"
|
#include "value-to-json.hh"
|
||||||
#include "xml-writer.hh"
|
#include "xml-writer.hh"
|
||||||
#include "legacy.hh"
|
#include "legacy.hh"
|
||||||
|
#include "loggers.hh"
|
||||||
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "graphml.hh"
|
#include "graphml.hh"
|
||||||
#include "legacy.hh"
|
#include "legacy.hh"
|
||||||
#include "path-with-outputs.hh"
|
#include "path-with-outputs.hh"
|
||||||
|
#include "loggers.hh"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
#include "flake/flake.hh"
|
#include "flake/flake.hh"
|
||||||
#include "get-drvs.hh"
|
#include "get-drvs.hh"
|
||||||
|
#include "loggers.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "outputs-spec.hh"
|
#include "outputs-spec.hh"
|
||||||
|
|
@ -1130,7 +1131,9 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
||||||
Activity act(*logger, lvlInfo, actUnknown,
|
Activity act(*logger, lvlInfo, actUnknown,
|
||||||
fmt("evaluating '%s'", concatStringsSep(".", attrPathS)));
|
fmt("evaluating '%s'", concatStringsSep(".", attrPathS)));
|
||||||
|
|
||||||
std::optional<RunPager> pager = json ? std::nullopt : std::optional<RunPager>(RunPager());
|
std::optional<RunPager> pager = json
|
||||||
|
? std::nullopt
|
||||||
|
: std::make_optional<RunPager>();
|
||||||
try {
|
try {
|
||||||
auto recurse = [&]()
|
auto recurse = [&]()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "log-store.hh"
|
#include "log-store.hh"
|
||||||
#include "progress-bar.hh"
|
#include "progress-bar.hh"
|
||||||
|
#include "loggers.hh"
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "command.hh"
|
#include "command.hh"
|
||||||
#include "installable-value.hh"
|
#include "installable-value.hh"
|
||||||
|
#include "loggers.hh"
|
||||||
#include "repl.hh"
|
#include "repl.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include "eval-cache.hh"
|
#include "eval-cache.hh"
|
||||||
#include "attr-path.hh"
|
#include "attr-path.hh"
|
||||||
#include "hilite.hh"
|
#include "hilite.hh"
|
||||||
|
#include "loggers.hh"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "progress-bar.hh"
|
#include "progress-bar.hh"
|
||||||
#include "fs-accessor.hh"
|
#include "fs-accessor.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
|
#include "loggers.cc"
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue