diff --git a/build.cc b/build.cc index 5199dc7..af93022 100644 --- a/build.cc +++ b/build.cc @@ -106,12 +106,10 @@ static void print_help(ostd::string_range arg0) { } static void exec_command(strvec const &args) { - ostd::subprocess p; - p.open_command(ostd::iter(args)); - if (int ret; (ret = p.close())) { - auto app = ostd::appender(); - ostd::format(app, "command failed with code %d", ret); - throw std::runtime_error{app.get()}; + if (int ret = ostd::subprocess{ostd::iter(args)}.close(); ret) { + throw std::runtime_error{ostd::format( + ostd::appender(), "command failed with code %d", ret + ).get()}; } } diff --git a/ostd/process.hh b/ostd/process.hh index c8aa4dd..5b08b2c 100644 --- a/ostd/process.hh +++ b/ostd/process.hh @@ -180,19 +180,57 @@ struct OSTD_EXPORT subprocess { */ file_stream err = file_stream{}; - /** @brief Initializes a default subprocess. - * - * No streams will be set to redirect. - */ - subprocess() noexcept {} - - /** @brief Initializes a subprocess with the given stream redirections.*/ + /** @brief Initializes the structure with the given stream redirections. */ subprocess( - process_stream in_use, process_stream out_use, process_stream err_use + process_stream in_use = process_stream::DEFAULT, + process_stream out_use = process_stream::DEFAULT, + process_stream err_use = process_stream::DEFAULT ) noexcept: use_in(in_use), use_out(out_use), use_err(err_use) {} + /** @brief Initializes the structure and opens a subprocess. + * + * This is similar to calling either open_command() or open_path() + * after constructing the object depending on `use_path`. It may + * throw the same exceptions as the respective two methods. + */ + template + subprocess( + string_range cmd, InputRange &&args, bool use_path = true, + process_stream in_use = process_stream::DEFAULT, + process_stream out_use = process_stream::DEFAULT, + process_stream err_use = process_stream::DEFAULT, + std::enable_if_t< + is_input_range, bool + > = true + ): + use_in(in_use), use_out(out_use), use_err(err_use) + { + open_full(cmd, std::forward(args), use_path); + } + + /** @brief Initializes the structure and opens a subprocess. + * + * This is similar to calling either open_command() or open_path() + * after constructing the object depending on `use_path`. It may + * throw the same exceptions as the respective two methods. + */ + template + subprocess( + InputRange &&args, bool use_path = true, + process_stream in_use = process_stream::DEFAULT, + process_stream out_use = process_stream::DEFAULT, + process_stream err_use = process_stream::DEFAULT, + std::enable_if_t< + is_input_range, bool + > = true + ): + use_in(in_use), use_out(out_use), use_err(err_use) + { + open_full(nullptr, std::forward(args), use_path); + } + /** @brief Moves the subprocess data. */ subprocess(subprocess &&i) noexcept: use_in(i.use_in), use_out(i.use_out), use_err(i.use_err),