diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/archive.cc | 2 | ||||
-rw-r--r-- | src/libutil/archive.hh | 7 | ||||
-rw-r--r-- | src/libutil/hash.hh | 2 | ||||
-rw-r--r-- | src/libutil/util.cc | 41 | ||||
-rw-r--r-- | src/libutil/util.hh | 23 |
5 files changed, 50 insertions, 25 deletions
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index ea1deb924..f71229d8f 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -29,7 +29,7 @@ const std::string narVersionMagic1 = "nix-archive-1"; static string caseHackSuffix = "~nix~case~hack~"; -PathFilter defaultPathFilter; +PathFilter defaultPathFilter = [](const Path &) { return true; }; static void dumpContents(const Path & path, size_t size, diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh index 607ebf8b2..8a15e849c 100644 --- a/src/libutil/archive.hh +++ b/src/libutil/archive.hh @@ -44,13 +44,6 @@ namespace nix { `+' denotes string concatenation. */ -struct PathFilter -{ - virtual ~PathFilter() { } - virtual bool operator () (const Path & path) { return true; } -}; - -extern PathFilter defaultPathFilter; void dumpPath(const Path & path, Sink & sink, PathFilter & filter = defaultPathFilter); diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh index d83049b02..fd7a61df8 100644 --- a/src/libutil/hash.hh +++ b/src/libutil/hash.hh @@ -93,8 +93,6 @@ Hash hashFile(HashType ht, const Path & path); /* Compute the hash of the given path. The hash is defined as (essentially) hashString(ht, dumpPath(path)). */ -struct PathFilter; -extern PathFilter defaultPathFilter; typedef std::pair<Hash, unsigned long long> HashResult; HashResult hashPath(HashType ht, const Path & path, PathFilter & filter = defaultPathFilter); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 9346d5dc4..f56153cd4 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -896,31 +896,45 @@ std::vector<char *> stringsToCharPtrs(const Strings & ss) string runProgram(Path program, bool searchPath, const Strings & args, const std::experimental::optional<std::string> & input) { + RunOptions opts(program, args); + opts.searchPath = searchPath; + opts.input = input; + + auto res = runProgram(opts); + + if (!statusOk(res.first)) + throw ExecError(res.first, fmt("program '%1%' %2%", program, statusToString(res.first))); + + return res.second; +} + +std::pair<int, std::string> runProgram(const RunOptions & options) +{ checkInterrupt(); /* Create a pipe. */ Pipe out, in; out.create(); - if (input) in.create(); + if (options.input) in.create(); /* Fork. */ Pid pid = startProcess([&]() { if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) throw SysError("dupping stdout"); - if (input && dup2(in.readSide.get(), STDIN_FILENO) == -1) + if (options.input && dup2(in.readSide.get(), STDIN_FILENO) == -1) throw SysError("dupping stdin"); - Strings args_(args); - args_.push_front(program); + Strings args_(options.args); + args_.push_front(options.program); restoreSignals(); - if (searchPath) - execvp(program.c_str(), stringsToCharPtrs(args_).data()); + if (options.searchPath) + execvp(options.program.c_str(), stringsToCharPtrs(args_).data()); else - execv(program.c_str(), stringsToCharPtrs(args_).data()); + execv(options.program.c_str(), stringsToCharPtrs(args_).data()); - throw SysError(format("executing '%1%'") % program); + throw SysError("executing '%1%'", options.program); }); out.writeSide = -1; @@ -935,11 +949,11 @@ string runProgram(Path program, bool searchPath, const Strings & args, }); - if (input) { + if (options.input) { in.readSide = -1; writerThread = std::thread([&]() { try { - writeFull(in.writeSide.get(), *input); + writeFull(in.writeSide.get(), *options.input); promise.set_value(); } catch (...) { promise.set_exception(std::current_exception()); @@ -952,14 +966,11 @@ string runProgram(Path program, bool searchPath, const Strings & args, /* Wait for the child to finish. */ int status = pid.wait(); - if (!statusOk(status)) - throw ExecError(status, format("program '%1%' %2%") - % program % statusToString(status)); /* Wait for the writer thread to finish. */ - if (input) promise.get_future().get(); + if (options.input) promise.get_future().get(); - return result; + return {status, result}; } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index fccf5d854..a3494e09b 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -245,6 +245,23 @@ string runProgram(Path program, bool searchPath = false, const Strings & args = Strings(), const std::experimental::optional<std::string> & input = {}); +struct RunOptions +{ + Path program; + bool searchPath = true; + Strings args; + std::experimental::optional<std::string> input; + 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); + + class ExecError : public Error { public: @@ -481,4 +498,10 @@ struct MaintainCount std::pair<unsigned short, unsigned short> getWindowSize(); +/* Used in various places. */ +typedef std::function<bool(const Path & path)> PathFilter; + +extern PathFilter defaultPathFilter; + + } |