From 4c4ae887b871ace7bc8528bc3dcf4fe85a92ff09 Mon Sep 17 00:00:00 2001 From: Konstantin Vukolov Date: Thu, 18 May 2023 13:18:34 +0300 Subject: [PATCH] Add option isInteractive --- src/libfetchers/git.cc | 21 +++++++-------------- src/libutil/util.cc | 14 ++++++++++++-- src/libutil/util.hh | 3 ++- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/libfetchers/git.cc b/src/libfetchers/git.cc index 7ec6efa4d..7df467feb 100644 --- a/src/libfetchers/git.cc +++ b/src/libfetchers/git.cc @@ -22,14 +22,6 @@ namespace nix::fetchers { namespace { -template -auto runProgramWithCredentialsInput(Args... args) -{ - logger->pause(); - Finally defer([]{ logger->resume(); }); - return runProgram(std::forward(args)...); -} - // Explicit initial branch of our bare repo to suppress warnings from new version of git. // The value itself does not matter, since we always fetch a specific revision or branch. // It is set with `-c init.defaultBranch=` instead of `--initial-branch=` to stay compatible with @@ -67,10 +59,11 @@ Path getCachePath(std::string_view key) // ... std::optional readHead(const Path & path) { - auto [status, output] = runProgramWithCredentialsInput(RunOptions { + auto [status, output] = runProgram(RunOptions { .program = "git", // FIXME: use 'HEAD' to avoid returning all refs .args = {"ls-remote", "--symref", path}, + .isInteractive = true, }); if (status != 0) return std::nullopt; @@ -359,7 +352,7 @@ struct GitInputScheme : InputScheme args.push_back(destDir); - runProgramWithCredentialsInput("git", true, args); + runProgram("git", true, args, {}, true); } std::optional getSourcePath(const Input & input) override @@ -564,7 +557,7 @@ struct GitInputScheme : InputScheme : ref == "HEAD" ? *ref : "refs/heads/" + *ref; - runProgramWithCredentialsInput("git", true, Strings { "-C", repoDir, "--git-dir", gitDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) }); + runProgram("git", true, Strings { "-C", repoDir, "--git-dir", gitDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) }, {}, true); } catch (Error & e) { if (!pathExists(localRefFile)) throw; warn("could not update local clone of Git repository '%s'; continuing with the most recent version", actualUrl); @@ -630,8 +623,8 @@ struct GitInputScheme : InputScheme // exists, see FIXME above) so use a big hammer and fetch // everything to ensure we get the rev. Activity act(*logger, lvlTalkative, actUnknown, fmt("making temporary clone of '%s'", repoDir)); - runProgramWithCredentialsInput("git", true, Strings { "-C", tmpDir, "fetch", "--quiet", "--force", - "--update-head-ok", "--", repoDir, "refs/*:refs/*" }); + runProgram("git", true, Strings { "-C", tmpDir, "fetch", "--quiet", "--force", + "--update-head-ok", "--", repoDir, "refs/*:refs/*" }, {}, true); } runProgram("git", true, { "-C", tmpDir, "checkout", "--quiet", input.getRev()->gitRev() }); @@ -658,7 +651,7 @@ struct GitInputScheme : InputScheme { Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching submodules of '%s'", actualUrl)); - runProgramWithCredentialsInput("git", true, Strings{ "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" }); + runProgram("git", true, Strings{ "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" }, {}, true); } filter = isNotDotGitDirectory; diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 21d1c8dcd..3a8309149 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1141,9 +1141,9 @@ std::vector stringsToCharPtrs(const Strings & ss) } std::string runProgram(Path program, bool searchPath, const Strings & args, - const std::optional & input) + const std::optional & input, bool isInteractive) { - auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .input = input}); + auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .input = input, .isInteractive = isInteractive}); if (!statusOk(res.first)) throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first)); @@ -1193,6 +1193,16 @@ void runProgram2(const RunOptions & options) // case), so we can't use it if we alter the environment processOptions.allowVfork = !options.environment; + std::optional>> resumeLoggerDefer; + if (options.isInteractive) { + logger->pause(); + resumeLoggerDefer.emplace( + []() { + logger->resume(); + } + ); + } + /* Fork. */ Pid pid = startProcess([&]() { if (options.environment) diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 040fed68f..a7907cd14 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -415,7 +415,7 @@ pid_t startProcess(std::function fun, const ProcessOptions & options = P */ std::string runProgram(Path program, bool searchPath = false, const Strings & args = Strings(), - const std::optional & input = {}); + const std::optional & input = {}, bool isInteractive = false); struct RunOptions { @@ -430,6 +430,7 @@ struct RunOptions Source * standardIn = nullptr; Sink * standardOut = nullptr; bool mergeStderrToStdout = false; + bool isInteractive = false; }; std::pair runProgram(RunOptions && options);