about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/archive.cc2
-rw-r--r--src/libutil/archive.hh7
-rw-r--r--src/libutil/hash.hh2
-rw-r--r--src/libutil/util.cc41
-rw-r--r--src/libutil/util.hh23
5 files changed, 50 insertions, 25 deletions
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index ea1deb924e67..f71229d8fdd6 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 607ebf8b28f9..8a15e849c7b8 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 d83049b02368..fd7a61df8e46 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 16c2c97aac9b..96c0cd78383d 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -895,31 +895,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;
@@ -934,11 +948,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());
@@ -951,14 +965,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 fccf5d854800..a3494e09b09b 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;
+
+
 }