1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-25 10:41:16 +02:00

refactor: RAII logger suspension

This commit is contained in:
Robert Hensing 2025-03-04 19:10:33 +01:00
parent 880489051a
commit 30694b5d8a
7 changed files with 46 additions and 35 deletions

View file

@ -102,8 +102,7 @@ struct NixRepl
unsigned int maxDepth = std::numeric_limits<unsigned int>::max()) unsigned int maxDepth = std::numeric_limits<unsigned int>::max())
{ {
// Hide the progress bar during printing because it might interfere // Hide the progress bar during printing because it might interfere
logger->pause(); auto suspension = logger->suspend();
Finally resumeLoggerDefer([]() { logger->resume(); });
::nix::printValue(*state, str, v, PrintOptions { ::nix::printValue(*state, str, v, PrintOptions {
.ansiColors = true, .ansiColors = true,
.force = true, .force = true,
@ -180,18 +179,20 @@ ReplExitStatus NixRepl::mainLoop()
while (true) { while (true) {
// Hide the progress bar while waiting for user input, so that it won't interfere. // Hide the progress bar while waiting for user input, so that it won't interfere.
logger->pause(); {
// When continuing input from previous lines, don't print a prompt, just align to the same auto suspension = logger->suspend();
// number of chars as the prompt. // When continuing input from previous lines, don't print a prompt, just align to the same
if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) { // number of chars as the prompt.
// Ctrl-D should exit the debugger. if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
state->debugStop = false; // Ctrl-D should exit the debugger.
logger->cout(""); state->debugStop = false;
// TODO: Should Ctrl-D exit just the current debugger session or logger->cout("");
// the entire program? // TODO: Should Ctrl-D exit just the current debugger session or
return ReplExitStatus::QuitAll; // the entire program?
return ReplExitStatus::QuitAll;
}
// `suspension` resumes the logger
} }
logger->resume();
try { try {
switch (processLine(input)) { switch (processLine(input)) {
case ProcessLineResult::Quit: case ProcessLineResult::Quit:
@ -694,10 +695,9 @@ ProcessLineResult NixRepl::processLine(std::string line)
} else { } else {
Value v; Value v;
evalString(line, v); evalString(line, v);
logger->pause(); auto suspension = logger->suspend();
printValue(std::cout, v, 1); printValue(std::cout, v, 1);
std::cout << std::endl; std::cout << std::endl;
logger->resume();
} }
} }

View file

@ -351,8 +351,7 @@ struct GitInputScheme : InputScheme
if (commitMsg) { if (commitMsg) {
// Pause the logger to allow for user input (such as a gpg passphrase) in `git commit` // Pause the logger to allow for user input (such as a gpg passphrase) in `git commit`
logger->pause(); auto suspension = logger->suspend();
Finally restoreLogger([]() { logger->resume(); });
runProgram("git", true, runProgram("git", true,
{ "-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" }, { "-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" },
*commitMsg); *commitMsg);

View file

@ -117,10 +117,10 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(
ProcessOptions options; ProcessOptions options;
options.dieWithParent = false; options.dieWithParent = false;
std::unique_ptr<Logger::Suspension> loggerSuspension;
if (!fakeSSH && !useMaster) { if (!fakeSSH && !useMaster) {
logger->pause(); loggerSuspension = std::make_unique<Logger::Suspension>(logger->suspend());
} }
Finally cleanup = [&]() { logger->resume(); };
conn->sshPid = startProcess([&]() { conn->sshPid = startProcess([&]() {
restoreProcessContext(); restoreProcessContext();
@ -199,8 +199,7 @@ Path SSHMaster::startMaster()
ProcessOptions options; ProcessOptions options;
options.dieWithParent = false; options.dieWithParent = false;
logger->pause(); auto suspension = logger->suspend();
Finally cleanup = [&]() { logger->resume(); };
if (isMasterRunning()) if (isMasterRunning())
return state->socketPath; return state->socketPath;

View file

@ -43,6 +43,19 @@ void Logger::writeToStdout(std::string_view s)
writeFull(standard_out, "\n"); writeFull(standard_out, "\n");
} }
Logger::Suspension Logger::suspend()
{
pause();
return Suspension { ._finalize = {[this](){this->resume();}} };
}
std::optional<Logger::Suspension> Logger::suspendIf(bool cond)
{
if (cond)
return suspend();
return {};
}
class SimpleLogger : public Logger class SimpleLogger : public Logger
{ {
public: public:

View file

@ -4,6 +4,7 @@
#include "error.hh" #include "error.hh"
#include "config.hh" #include "config.hh"
#include "file-descriptor.hh" #include "file-descriptor.hh"
#include "finally.hh"
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
@ -75,6 +76,17 @@ public:
virtual void stop() { }; virtual void stop() { };
/**
* Guard object to resume the logger when done.
*/
struct Suspension {
Finally<std::function<void()>> _finalize;
};
Suspension suspend();
std::optional<Suspension> suspendIf(bool cond);
virtual void pause() { }; virtual void pause() { };
virtual void resume() { }; virtual void resume() { };

View file

@ -306,15 +306,7 @@ void runProgram2(const RunOptions & options)
// case), so we can't use it if we alter the environment // case), so we can't use it if we alter the environment
processOptions.allowVfork = !options.environment; processOptions.allowVfork = !options.environment;
std::optional<Finally<std::function<void()>>> resumeLoggerDefer; auto suspension = logger->suspendIf(options.isInteractive);
if (options.isInteractive) {
logger->pause();
resumeLoggerDefer.emplace(
[]() {
logger->resume();
}
);
}
/* Fork. */ /* Fork. */
Pid pid = startProcess([&] { Pid pid = startProcess([&] {

View file

@ -312,11 +312,7 @@ void runProgram2(const RunOptions & options)
// TODO: Implement shebang / program interpreter lookup on Windows // TODO: Implement shebang / program interpreter lookup on Windows
auto interpreter = getProgramInterpreter(realProgram); auto interpreter = getProgramInterpreter(realProgram);
std::optional<Finally<std::function<void()>>> resumeLoggerDefer; auto suspension = logger->suspendIf(options.isInteractive);
if (options.isInteractive) {
logger->pause();
resumeLoggerDefer.emplace([]() { logger->resume(); });
}
Pid pid = spawnProcess(interpreter.has_value() ? *interpreter : realProgram, options, out, in); Pid pid = spawnProcess(interpreter.has_value() ? *interpreter : realProgram, options, out, in);