Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions src/libcmd/repl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,7 @@ struct NixRepl
unsigned int maxDepth = std::numeric_limits<unsigned int>::max())
{
// Hide the progress bar during printing because it might interfere
logger->pause();
Finally resumeLoggerDefer([]() { logger->resume(); });
auto suspension = logger->suspend();
::nix::printValue(*state, str, v, PrintOptions {
.ansiColors = true,
.force = true,
Expand Down Expand Up @@ -180,18 +179,20 @@ ReplExitStatus NixRepl::mainLoop()

while (true) {
// 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
// number of chars as the prompt.
if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
// Ctrl-D should exit the debugger.
state->debugStop = false;
logger->cout("");
// TODO: Should Ctrl-D exit just the current debugger session or
// the entire program?
return ReplExitStatus::QuitAll;
{
auto suspension = logger->suspend();
// When continuing input from previous lines, don't print a prompt, just align to the same
// number of chars as the prompt.
if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
// Ctrl-D should exit the debugger.
state->debugStop = false;
logger->cout("");
// TODO: Should Ctrl-D exit just the current debugger session or
// the entire program?
return ReplExitStatus::QuitAll;
}
// `suspension` resumes the logger
}
logger->resume();
try {
switch (processLine(input)) {
case ProcessLineResult::Quit:
Expand Down Expand Up @@ -586,6 +587,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
else if (command == ":p" || command == ":print") {
Value v;
evalString(arg, v);
auto suspension = logger->suspend();
if (v.type() == nString) {
std::cout << v.string_view();
} else {
Expand Down Expand Up @@ -694,6 +696,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
} else {
Value v;
evalString(line, v);
auto suspension = logger->suspend();
printValue(std::cout, v, 1);
std::cout << std::endl;
}
Expand Down
3 changes: 1 addition & 2 deletions src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,7 @@ struct GitInputScheme : InputScheme

if (commitMsg) {
// Pause the logger to allow for user input (such as a gpg passphrase) in `git commit`
logger->pause();
Finally restoreLogger([]() { logger->resume(); });
auto suspension = logger->suspend();
runProgram("git", true,
{ "-C", repoPath->string(), "--git-dir", repoInfo.gitDir, "commit", std::string(path.rel()), "-F", "-" },
*commitMsg);
Expand Down
33 changes: 25 additions & 8 deletions src/libmain/progress-bar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,13 @@ class ProgressBar : public Logger
uint64_t corruptedPaths = 0, untrustedPaths = 0;

bool active = true;
bool paused = false;
size_t suspensions = 0;
bool haveUpdate = true;

bool isPaused() const
{
return suspensions > 0;
}
};

/** Helps avoid unnecessary redraws, see `redraw()` */
Expand Down Expand Up @@ -130,18 +135,30 @@ class ProgressBar : public Logger

void pause() override {
auto state (state_.lock());
state->paused = true;
state->suspensions++;
if (state->suspensions > 1) {
// already paused
return;
}

if (state->active)
writeToStderr("\r\e[K");
}

void resume() override {
auto state (state_.lock());
state->paused = false;
if (state->active)
writeToStderr("\r\e[K");
state->haveUpdate = true;
updateCV.notify_one();
if (state->suspensions == 0) {
log(lvlError, "nix::ProgressBar: resume() called without a matching preceding pause(). This is a bug.");
return;
} else {
state->suspensions--;
}
if (state->suspensions == 0) {
if (state->active)
writeToStderr("\r\e[K");
state->haveUpdate = true;
updateCV.notify_one();
}
}

bool isVerbose() override
Expand Down Expand Up @@ -383,7 +400,7 @@ class ProgressBar : public Logger
auto nextWakeup = std::chrono::milliseconds::max();

state.haveUpdate = false;
if (state.paused || !state.active) return nextWakeup;
if (state.isPaused() || !state.active) return nextWakeup;

std::string line;

Expand Down
7 changes: 3 additions & 4 deletions src/libstore/ssh.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(
ProcessOptions options;
options.dieWithParent = false;

std::unique_ptr<Logger::Suspension> loggerSuspension;
if (!fakeSSH && !useMaster) {
logger->pause();
loggerSuspension = std::make_unique<Logger::Suspension>(logger->suspend());
}
Finally cleanup = [&]() { logger->resume(); };

conn->sshPid = startProcess([&]() {
restoreProcessContext();
Expand Down Expand Up @@ -199,8 +199,7 @@ Path SSHMaster::startMaster()
ProcessOptions options;
options.dieWithParent = false;

logger->pause();
Finally cleanup = [&]() { logger->resume(); };
auto suspension = logger->suspend();

if (isMasterRunning())
return state->socketPath;
Expand Down
13 changes: 13 additions & 0 deletions src/libutil/logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@ void Logger::writeToStdout(std::string_view s)
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
{
public:
Expand Down
12 changes: 12 additions & 0 deletions src/libutil/logging.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "error.hh"
#include "config.hh"
#include "file-descriptor.hh"
#include "finally.hh"

#include <nlohmann/json_fwd.hpp>

Expand Down Expand Up @@ -75,6 +76,17 @@ public:

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 resume() { };

Expand Down
10 changes: 1 addition & 9 deletions src/libutil/unix/processes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -306,15 +306,7 @@ void runProgram2(const RunOptions & options)
// case), so we can't use it if we alter the environment
processOptions.allowVfork = !options.environment;

std::optional<Finally<std::function<void()>>> resumeLoggerDefer;
if (options.isInteractive) {
logger->pause();
resumeLoggerDefer.emplace(
[]() {
logger->resume();
}
);
}
auto suspension = logger->suspendIf(options.isInteractive);

/* Fork. */
Pid pid = startProcess([&] {
Expand Down
6 changes: 1 addition & 5 deletions src/libutil/windows/processes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,7 @@ void runProgram2(const RunOptions & options)
// TODO: Implement shebang / program interpreter lookup on Windows
auto interpreter = getProgramInterpreter(realProgram);

std::optional<Finally<std::function<void()>>> resumeLoggerDefer;
if (options.isInteractive) {
logger->pause();
resumeLoggerDefer.emplace([]() { logger->resume(); });
}
auto suspension = logger->suspendIf(options.isInteractive);

Pid pid = spawnProcess(interpreter.has_value() ? *interpreter : realProgram, options, out, in);

Expand Down
Loading