libutil: remove runProgram2 stdin functionality
this was only used in one place, and that place has been rewritten to use a temporary file instead. keeping this around is not very helpful at this time, and in any case we'd be better off rewriting subprocess handling in rust where we not only have a much safer library for such things but also async frameworks necessary for this easily available. Change-Id: I6f8641b756857c84ae2602cdf41f74ee7a1fda02
This commit is contained in:
parent
2bbdaf0b19
commit
d477b34d1d
5 changed files with 10 additions and 65 deletions
|
@ -242,8 +242,7 @@ NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, ref<EvalS
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void runNix(Path program, const Strings & args,
|
void runNix(Path program, const Strings & args)
|
||||||
const std::optional<std::string> & input = {})
|
|
||||||
{
|
{
|
||||||
auto subprocessEnv = getEnv();
|
auto subprocessEnv = getEnv();
|
||||||
subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue();
|
subprocessEnv["NIX_CONFIG"] = globalConfig.toKeyValue();
|
||||||
|
@ -252,7 +251,6 @@ void runNix(Path program, const Strings & args,
|
||||||
.program = settings.nixBinDir+ "/" + program,
|
.program = settings.nixBinDir+ "/" + program,
|
||||||
.args = args,
|
.args = args,
|
||||||
.environment = subprocessEnv,
|
.environment = subprocessEnv,
|
||||||
.input = input,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -358,7 +358,7 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
args.push_back(destDir);
|
args.push_back(destDir);
|
||||||
|
|
||||||
runProgram("git", true, args, {}, true);
|
runProgram("git", true, args, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Path> getSourcePath(const Input & input) const override
|
std::optional<Path> getSourcePath(const Input & input) const override
|
||||||
|
@ -589,7 +589,7 @@ struct GitInputScheme : InputScheme
|
||||||
: ref == "HEAD"
|
: ref == "HEAD"
|
||||||
? *ref
|
? *ref
|
||||||
: "refs/heads/" + *ref;
|
: "refs/heads/" + *ref;
|
||||||
runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) }, {}, true);
|
runProgram("git", true, { "-C", repoDir, "--git-dir", gitDir, "fetch", "--quiet", "--force", "--", actualUrl, fmt("%s:%s", fetchRef, fetchRef) }, true);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
if (!pathExists(localRefFile)) throw;
|
if (!pathExists(localRefFile)) throw;
|
||||||
warn("could not update local clone of Git repository '%s'; continuing with the most recent version", actualUrl);
|
warn("could not update local clone of Git repository '%s'; continuing with the most recent version", actualUrl);
|
||||||
|
@ -656,7 +656,7 @@ struct GitInputScheme : InputScheme
|
||||||
// everything to ensure we get the rev.
|
// everything to ensure we get the rev.
|
||||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("making temporary clone of '%s'", repoDir));
|
Activity act(*logger, lvlTalkative, actUnknown, fmt("making temporary clone of '%s'", repoDir));
|
||||||
runProgram("git", true, { "-C", tmpDir, "fetch", "--quiet", "--force",
|
runProgram("git", true, { "-C", tmpDir, "fetch", "--quiet", "--force",
|
||||||
"--update-head-ok", "--", repoDir, "refs/*:refs/*" }, {}, true);
|
"--update-head-ok", "--", repoDir, "refs/*:refs/*" }, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
runProgram("git", true, { "-C", tmpDir, "checkout", "--quiet", input.getRev()->gitRev() });
|
runProgram("git", true, { "-C", tmpDir, "checkout", "--quiet", input.getRev()->gitRev() });
|
||||||
|
@ -683,7 +683,7 @@ struct GitInputScheme : InputScheme
|
||||||
|
|
||||||
{
|
{
|
||||||
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching submodules of '%s'", actualUrl));
|
Activity act(*logger, lvlTalkative, actUnknown, fmt("fetching submodules of '%s'", actualUrl));
|
||||||
runProgram("git", true, { "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" }, {}, true);
|
runProgram("git", true, { "-C", tmpDir, "submodule", "--quiet", "update", "--init", "--recursive" }, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
filter = isNotDotGitDirectory;
|
filter = isNotDotGitDirectory;
|
||||||
|
|
|
@ -28,10 +28,9 @@ static RunOptions hgOptions(const Strings & args)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runProgram wrapper that uses hgOptions instead of stock RunOptions.
|
// runProgram wrapper that uses hgOptions instead of stock RunOptions.
|
||||||
static std::string runHg(const Strings & args, const std::optional<std::string> & input = {})
|
static std::string runHg(const Strings & args)
|
||||||
{
|
{
|
||||||
RunOptions opts = hgOptions(args);
|
RunOptions opts = hgOptions(args);
|
||||||
opts.input = input;
|
|
||||||
|
|
||||||
auto res = runProgram(std::move(opts));
|
auto res = runProgram(std::move(opts));
|
||||||
|
|
||||||
|
|
|
@ -230,10 +230,9 @@ Pid startProcess(std::function<void()> fun, const ProcessOptions & options)
|
||||||
return Pid{pid};
|
return Pid{pid};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string runProgram(Path program, bool searchPath, const Strings & args,
|
std::string runProgram(Path program, bool searchPath, const Strings & args, bool isInteractive)
|
||||||
const std::optional<std::string> & input, bool isInteractive)
|
|
||||||
{
|
{
|
||||||
auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .input = input, .isInteractive = isInteractive});
|
auto res = runProgram(RunOptions {.program = program, .searchPath = searchPath, .args = args, .isInteractive = isInteractive});
|
||||||
|
|
||||||
if (!statusOk(res.first))
|
if (!statusOk(res.first))
|
||||||
throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first));
|
throw ExecError(res.first, "program '%1%' %2%", program, statusToString(res.first));
|
||||||
|
@ -262,20 +261,9 @@ void runProgram2(const RunOptions & options)
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
assert(!(options.standardIn && options.input));
|
|
||||||
|
|
||||||
std::unique_ptr<Source> source_;
|
|
||||||
Source * source = options.standardIn;
|
|
||||||
|
|
||||||
if (options.input) {
|
|
||||||
source_ = std::make_unique<StringSource>(*options.input);
|
|
||||||
source = source_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a pipe. */
|
/* Create a pipe. */
|
||||||
Pipe out, in;
|
Pipe out;
|
||||||
if (options.standardOut) out.create();
|
if (options.standardOut) out.create();
|
||||||
if (source) in.create();
|
|
||||||
|
|
||||||
ProcessOptions processOptions;
|
ProcessOptions processOptions;
|
||||||
|
|
||||||
|
@ -298,8 +286,6 @@ void runProgram2(const RunOptions & options)
|
||||||
if (options.mergeStderrToStdout)
|
if (options.mergeStderrToStdout)
|
||||||
if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
|
if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
|
||||||
throw SysError("cannot dup stdout into stderr");
|
throw SysError("cannot dup stdout into stderr");
|
||||||
if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1)
|
|
||||||
throw SysError("dupping stdin");
|
|
||||||
|
|
||||||
if (options.chdir && chdir((*options.chdir).c_str()) == -1)
|
if (options.chdir && chdir((*options.chdir).c_str()) == -1)
|
||||||
throw SysError("chdir failed");
|
throw SysError("chdir failed");
|
||||||
|
@ -328,47 +314,12 @@ void runProgram2(const RunOptions & options)
|
||||||
|
|
||||||
out.writeSide.close();
|
out.writeSide.close();
|
||||||
|
|
||||||
std::thread writerThread;
|
|
||||||
|
|
||||||
std::promise<void> promise;
|
|
||||||
|
|
||||||
Finally doJoin([&]() {
|
|
||||||
if (writerThread.joinable())
|
|
||||||
writerThread.join();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
if (source) {
|
|
||||||
in.readSide.close();
|
|
||||||
writerThread = std::thread([&]() {
|
|
||||||
try {
|
|
||||||
std::vector<char> buf(8 * 1024);
|
|
||||||
while (true) {
|
|
||||||
size_t n;
|
|
||||||
try {
|
|
||||||
n = source->read(buf.data(), buf.size());
|
|
||||||
} catch (EndOfFile &) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
writeFull(in.writeSide.get(), {buf.data(), n});
|
|
||||||
}
|
|
||||||
promise.set_value();
|
|
||||||
} catch (...) {
|
|
||||||
promise.set_exception(std::current_exception());
|
|
||||||
}
|
|
||||||
in.writeSide.close();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.standardOut)
|
if (options.standardOut)
|
||||||
drainFD(out.readSide.get(), *options.standardOut);
|
drainFD(out.readSide.get(), *options.standardOut);
|
||||||
|
|
||||||
/* Wait for the child to finish. */
|
/* Wait for the child to finish. */
|
||||||
int status = pid.wait();
|
int status = pid.wait();
|
||||||
|
|
||||||
/* Wait for the writer thread to finish. */
|
|
||||||
if (source) promise.get_future().get();
|
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
throw ExecError(status, "program '%1%' %2%", options.program, statusToString(status));
|
throw ExecError(status, "program '%1%' %2%", options.program, statusToString(status));
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,8 +71,7 @@ Pid startProcess(std::function<void()> fun, const ProcessOptions & options = Pro
|
||||||
* shell backtick operator).
|
* shell backtick operator).
|
||||||
*/
|
*/
|
||||||
std::string runProgram(Path program, bool searchPath = false,
|
std::string runProgram(Path program, bool searchPath = false,
|
||||||
const Strings & args = Strings(),
|
const Strings & args = Strings(), bool isInteractive = false);
|
||||||
const std::optional<std::string> & input = {}, bool isInteractive = false);
|
|
||||||
|
|
||||||
struct RunOptions
|
struct RunOptions
|
||||||
{
|
{
|
||||||
|
@ -83,8 +82,6 @@ struct RunOptions
|
||||||
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;
|
||||||
std::optional<std::string> input;
|
|
||||||
Source * standardIn = nullptr;
|
|
||||||
Sink * standardOut = nullptr;
|
Sink * standardOut = nullptr;
|
||||||
bool mergeStderrToStdout = false;
|
bool mergeStderrToStdout = false;
|
||||||
bool isInteractive = false;
|
bool isInteractive = false;
|
||||||
|
|
Loading…
Reference in a new issue