RunOptions: Use designated initializers

Also get rid of _killStderr because it wasn't actually checked
anywhere.
This commit is contained in:
Eelco Dolstra 2021-09-13 23:22:09 +02:00
parent c3e9acd1c0
commit 4ed66735b6
7 changed files with 48 additions and 64 deletions

View file

@ -413,17 +413,14 @@ struct GitInputScheme : InputScheme
AutoDelete delTmpDir(tmpDir, true); AutoDelete delTmpDir(tmpDir, true);
PathFilter filter = defaultPathFilter; PathFilter filter = defaultPathFilter;
RunOptions checkCommitOpts( auto result = runProgram({
"git", .program = "git",
{ "-C", repoDir, "cat-file", "commit", input.getRev()->gitRev() } .args = { "-C", repoDir, "cat-file", "commit", input.getRev()->gitRev() },
); .mergeStderrToStdout = true
checkCommitOpts.searchPath = true; });
checkCommitOpts.mergeStderrToStdout = true;
auto result = runProgram(checkCommitOpts);
if (WEXITSTATUS(result.first) == 128 if (WEXITSTATUS(result.first) == 128
&& result.second.find("bad file") != std::string::npos && result.second.find("bad file") != std::string::npos)
) { {
throw Error( throw Error(
"Cannot find Git revision '%s' in ref '%s' of repository '%s'! " "Cannot find Git revision '%s' in ref '%s' of repository '%s'! "
"Please make sure that the " ANSI_BOLD "rev" ANSI_NORMAL " exists on the " "Please make sure that the " ANSI_BOLD "rev" ANSI_NORMAL " exists on the "
@ -455,9 +452,11 @@ struct GitInputScheme : InputScheme
// FIXME: should pipe this, or find some better way to extract a // FIXME: should pipe this, or find some better way to extract a
// revision. // revision.
auto source = sinkToSource([&](Sink & sink) { auto source = sinkToSource([&](Sink & sink) {
RunOptions gitOptions("git", { "-C", repoDir, "archive", input.getRev()->gitRev() }); runProgram2({
gitOptions.standardOut = &sink; .program = "git",
runProgram2(gitOptions); .args = { "-C", repoDir, "archive", input.getRev()->gitRev() },
.standardOut = &sink
});
}); });
unpackTarfile(*source, tmpDir); unpackTarfile(*source, tmpDir);

View file

@ -11,28 +11,27 @@ using namespace std::string_literals;
namespace nix::fetchers { namespace nix::fetchers {
namespace { static RunOptions hgOptions(const Strings & args)
RunOptions hgOptions(const Strings & args)
{ {
RunOptions opts("hg", args);
opts.searchPath = true;
auto env = getEnv(); auto env = getEnv();
// Set HGPLAIN: this means we get consistent output from hg and avoids leakage from a user or system .hgrc. // Set HGPLAIN: this means we get consistent output from hg and avoids leakage from a user or system .hgrc.
env["HGPLAIN"] = ""; env["HGPLAIN"] = "";
opts.environment = env;
return opts; return {
.program = "hg",
.searchPath = true,
.args = args,
.environment = env
};
} }
// runProgram wrapper that uses hgOptions instead of stock RunOptions. // runProgram wrapper that uses hgOptions instead of stock RunOptions.
string runHg(const Strings & args, const std::optional<std::string> & input = {}) static string runHg(const Strings & args, const std::optional<std::string> & input = {})
{ {
RunOptions opts = hgOptions(args); RunOptions opts = hgOptions(args);
opts.input = input; opts.input = input;
auto res = runProgram(opts); auto res = runProgram(std::move(opts));
if (!statusOk(res.first)) if (!statusOk(res.first))
throw ExecError(res.first, fmt("hg %1%", statusToString(res.first))); throw ExecError(res.first, fmt("hg %1%", statusToString(res.first)));
@ -40,8 +39,6 @@ string runHg(const Strings & args, const std::optional<std::string> & input = {}
return res.second; return res.second;
} }
}
struct MercurialInputScheme : InputScheme struct MercurialInputScheme : InputScheme
{ {
std::optional<Input> inputFromURL(const ParsedURL & url) override std::optional<Input> inputFromURL(const ParsedURL & url) override
@ -254,9 +251,7 @@ struct MercurialInputScheme : InputScheme
have to pull again. */ have to pull again. */
if (!(input.getRev() if (!(input.getRev()
&& pathExists(cacheDir) && pathExists(cacheDir)
&& runProgram( && runProgram(hgOptions({ "log", "-R", cacheDir, "-r", input.getRev()->gitRev(), "--template", "1" })).second == "1"))
hgOptions({ "log", "-R", cacheDir, "-r", input.getRev()->gitRev(), "--template", "1" })
.killStderr(true)).second == "1"))
{ {
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl)); Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching Mercurial repository '%s'", actualUrl));

View file

@ -774,9 +774,6 @@ void runPostBuildHook(
hookEnvironment.emplace("OUT_PATHS", chomp(concatStringsSep(" ", store.printStorePathSet(outputPaths)))); hookEnvironment.emplace("OUT_PATHS", chomp(concatStringsSep(" ", store.printStorePathSet(outputPaths))));
hookEnvironment.emplace("NIX_CONFIG", globalConfig.toKeyValue()); hookEnvironment.emplace("NIX_CONFIG", globalConfig.toKeyValue());
RunOptions opts(settings.postBuildHook, {});
opts.environment = hookEnvironment;
struct LogSink : Sink { struct LogSink : Sink {
Activity & act; Activity & act;
std::string currentLine; std::string currentLine;
@ -807,9 +804,12 @@ void runPostBuildHook(
}; };
LogSink sink(act); LogSink sink(act);
opts.standardOut = &sink; runProgram2({
opts.mergeStderrToStdout = true; .program = settings.postBuildHook,
runProgram2(opts); .environment = hookEnvironment,
.standardOut = &sink,
.mergeStderrToStdout = true,
});
} }
void DerivationGoal::buildDone() void DerivationGoal::buildDone()

View file

@ -66,12 +66,14 @@ void handleDiffHook(
auto diffHook = settings.diffHook; auto diffHook = settings.diffHook;
if (diffHook != "" && settings.runDiffHook) { if (diffHook != "" && settings.runDiffHook) {
try { try {
RunOptions diffHookOptions(diffHook,{tryA, tryB, drvPath, tmpDir}); auto diffRes = runProgram({
diffHookOptions.searchPath = true; .program = diffHook,
diffHookOptions.uid = uid; .searchPath = true,
diffHookOptions.gid = gid; .args = {tryA, tryB, drvPath, tmpDir},
diffHookOptions.chdir = "/"; .uid = uid,
auto diffRes = runProgram(diffHookOptions); .gid = gid,
.chdir = "/"
});
if (!statusOk(diffRes.first)) if (!statusOk(diffRes.first))
throw ExecError(diffRes.first, throw ExecError(diffRes.first,
"diff-hook program '%1%' %2%", "diff-hook program '%1%' %2%",

View file

@ -1034,17 +1034,10 @@ std::vector<char *> stringsToCharPtrs(const Strings & ss)
return res; return res;
} }
// Output = "standard out" output stream
string runProgram(Path program, bool searchPath, const Strings & args, string runProgram(Path program, bool searchPath, const Strings & args,
const std::optional<std::string> & input) const std::optional<std::string> & input)
{ {
RunOptions opts(program, args); auto res = runProgram({.program = program, .searchPath = searchPath, .args = args, .input = input});
opts.searchPath = searchPath;
// This allows you to refer to a program with a pathname relative to the
// PATH variable.
opts.input = input;
auto res = runProgram(opts);
if (!statusOk(res.first)) if (!statusOk(res.first))
throw ExecError(res.first, fmt("program '%1%' %2%", program, statusToString(res.first))); throw ExecError(res.first, fmt("program '%1%' %2%", program, statusToString(res.first)));
@ -1053,9 +1046,8 @@ string runProgram(Path program, bool searchPath, const Strings & args,
} }
// Output = error code + "standard out" output stream // Output = error code + "standard out" output stream
std::pair<int, std::string> runProgram(const RunOptions & options_) std::pair<int, std::string> runProgram(RunOptions && options)
{ {
RunOptions options(options_);
StringSink sink; StringSink sink;
options.standardOut = &sink; options.standardOut = &sink;

View file

@ -276,26 +276,20 @@ string runProgram(Path program, bool searchPath = false,
struct RunOptions struct RunOptions
{ {
Path program;
bool searchPath = true;
Strings args;
std::optional<uid_t> uid; std::optional<uid_t> uid;
std::optional<uid_t> gid; std::optional<uid_t> gid;
std::optional<Path> chdir; std::optional<Path> chdir;
std::optional<std::map<std::string, std::string>> environment; std::optional<std::map<std::string, std::string>> environment;
Path program;
bool searchPath = true;
Strings args;
std::optional<std::string> input; std::optional<std::string> input;
Source * standardIn = nullptr; Source * standardIn = nullptr;
Sink * standardOut = nullptr; Sink * standardOut = nullptr;
bool mergeStderrToStdout = false; bool mergeStderrToStdout = false;
bool _killStderr = false;
RunOptions(const Path & program, const Strings & args)
: program(program), args(args) { };
RunOptions & killStderr(bool v) { _killStderr = true; return *this; }
}; };
std::pair<int, std::string> runProgram(const RunOptions & options); std::pair<int, std::string> runProgram(RunOptions && options);
void runProgram2(const RunOptions & options); void runProgram2(const RunOptions & options);

View file

@ -110,11 +110,13 @@ string runNix(Path program, const Strings & args,
{ {
auto subprocessEnv = getEnv(); auto subprocessEnv = getEnv();
subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue(); subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue();
RunOptions opts(settings.nixBinDir+ "/" + program, args);
opts.input = input;
opts.environment = subprocessEnv;
auto res = runProgram(opts); auto res = runProgram({
.program = settings.nixBinDir+ "/" + program,
.args = args,
.environment = subprocessEnv,
.input = input,
});
if (!statusOk(res.first)) if (!statusOk(res.first))
throw ExecError(res.first, fmt("program '%1%' %2%", program, statusToString(res.first))); throw ExecError(res.first, fmt("program '%1%' %2%", program, statusToString(res.first)));