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 "store-api.hh"
|
||||
#include "log-store.hh"
|
||||
#include "loggers.hh"
|
||||
#include "common-eval-args.hh"
|
||||
#include "get-drvs.hh"
|
||||
#include "derivations.hh"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "loggers.hh"
|
||||
#include "progress-bar.hh"
|
||||
#include "paged-logger.hh"
|
||||
#include "util.hh"
|
||||
|
||||
namespace nix {
|
||||
|
|
@ -53,4 +54,14 @@ void createDefaultLogger() {
|
|||
logger = makeDefaultLogger();
|
||||
}
|
||||
|
||||
RunPager::RunPager()
|
||||
: previousLogger(logger)
|
||||
{
|
||||
logger = new PagedLogger(previousLogger);
|
||||
}
|
||||
|
||||
RunPager::~RunPager() {
|
||||
logger = previousLogger;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "logging.hh"
|
||||
#include "types.hh"
|
||||
|
||||
namespace nix {
|
||||
|
|
@ -18,4 +19,13 @@ void setLogFormat(const LogFormat & logFormat);
|
|||
|
||||
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 <exception>
|
||||
#include <iostream>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -351,55 +350,6 @@ int handleExceptions(const std::string & programName, std::function<void()> fun)
|
|||
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()
|
||||
{
|
||||
if (show)
|
||||
|
|
|
|||
|
|
@ -84,21 +84,6 @@ struct LegacyArgs : public MixCommonArgs
|
|||
*/
|
||||
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;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "value-to-json.hh"
|
||||
#include "xml-writer.hh"
|
||||
#include "legacy.hh"
|
||||
#include "loggers.hh"
|
||||
|
||||
#include <cerrno>
|
||||
#include <ctime>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "graphml.hh"
|
||||
#include "legacy.hh"
|
||||
#include "path-with-outputs.hh"
|
||||
#include "loggers.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "eval-inline.hh"
|
||||
#include "flake/flake.hh"
|
||||
#include "get-drvs.hh"
|
||||
#include "loggers.hh"
|
||||
#include "store-api.hh"
|
||||
#include "derivations.hh"
|
||||
#include "outputs-spec.hh"
|
||||
|
|
@ -1130,7 +1131,9 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
|||
Activity act(*logger, lvlInfo, actUnknown,
|
||||
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 {
|
||||
auto recurse = [&]()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "store-api.hh"
|
||||
#include "log-store.hh"
|
||||
#include "progress-bar.hh"
|
||||
#include "loggers.hh"
|
||||
|
||||
using namespace nix;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "globals.hh"
|
||||
#include "command.hh"
|
||||
#include "installable-value.hh"
|
||||
#include "loggers.hh"
|
||||
#include "repl.hh"
|
||||
|
||||
namespace nix {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "eval-cache.hh"
|
||||
#include "attr-path.hh"
|
||||
#include "hilite.hh"
|
||||
#include "loggers.hh"
|
||||
|
||||
#include <regex>
|
||||
#include <fstream>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "progress-bar.hh"
|
||||
#include "fs-accessor.hh"
|
||||
#include "shared.hh"
|
||||
#include "loggers.cc"
|
||||
|
||||
#include <queue>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue