#include <string>
#include <vector>
+#include <msp/core/process.h>
#include <msp/fs/path.h>
+#include <msp/io/pipe.h>
#include "task.h"
+/**
+Runs an external command. A zero exit status is translated to a SUCCESS status
+for the task, and anything else is treated as an error. Output can optionally
+be captured.
+*/
class ExternalTask: public Task
{
+public:
+ enum StreamAction
+ {
+ PASSTHROUGH, //< Do not touch the stream
+ CAPTURE, //< Capture the stream
+ REDIRECT, //< Redirect the stream to/from a file
+ IGNORE //< Redirect the stream to oblivion
+ };
+
+ using Arguments = Msp::Process::Arguments;
+
+private:
+ Arguments argv;
+ Msp::FS::Path work_dir;
+ Msp::Process *process = 0;
+ int exit_code = -1;
+ StreamAction stdin_action = PASSTHROUGH;
+ Msp::FS::Path stdin_file;
+ StreamAction stdout_action = PASSTHROUGH;
+ Msp::FS::Path stdout_file;
+ StreamAction stderr_action = PASSTHROUGH;
+ Msp::IO::Pipe *capture_pipe = 0;
+ std::string output;
+
+public:
+ /** Creates an ExternalTask with an argument array and an optional working
+ directory. The first element of the argument array should be the command
+ name. If the working directory is not specified, no chdir is done. */
+ ExternalTask(const Arguments &, const Msp::FS::Path & = Msp::FS::Path());
+
+ ~ExternalTask();
+
+ std::string get_command() const override;
+ void start() override;
+ Status check() override;
+ Status wait() override;
private:
- int pid;
- int exit_code;
+ Status do_wait(bool);
public:
- ExternalTask(const std::vector<std::string> &, const Msp::FS::Path &);
+ /// Redirect stdin from a file. Has no effect after the task is started.
+ void set_stdin(const Msp::FS::Path &);
+
+ /// Sets destination for stdout. Has no effect after the task is started.
+ void set_stdout(StreamAction);
+
+ /// Redirect stdout to a file. Has no effect after the task is started.
+ void set_stdout(const Msp::FS::Path &);
+
+ /// Sets destination for stderr. Has no effect after the task is started.
+ void set_stderr(StreamAction);
+
+ /** Returns captured output, if any. This may be called while the task is
+ still running, but it will always return all output. */
+ const std::string &get_output() const { return output; }
- virtual void start();
- virtual Status check();
+ /** Executes a command and captures its output. If the command exits with
+ a nonzero status, an exception is thrown. */
+ static std::string run_and_capture_output(const Arguments &, const Msp::FS::Path & = Msp::FS::Path(), bool = false);
};
#endif