2323
2424#include < array>
2525#include < cstring>
26+ #include < format>
2627#include < iostream>
2728#include < print>
29+ #include < stdexcept>
2830
2931#include < sys/wait.h>
3032
31- #include " iceberg/result.h"
32-
3333namespace iceberg {
3434
3535Command::Command (std::string program) : program_(std::move(program)) {}
3636
37- Command& Command::arg (std::string a) {
37+ Command& Command::Arg (std::string a) {
3838 args_.push_back (std::move (a));
3939 return *this ;
4040}
4141
42- Command& Command::args (const std::vector<std::string>& as) {
42+ Command& Command::Args (const std::vector<std::string>& as) {
4343 args_.insert (args_.end (), as.begin (), as.end ());
4444 return *this ;
4545}
4646
47- Command& Command::current_dir (const std::filesystem::path& path) {
47+ Command& Command::CurrentDir (const std::filesystem::path& path) {
4848 cwd_ = path;
4949 return *this ;
5050}
5151
52- Command& Command::env (const std::string& key, const std::string& val) {
52+ Command& Command::Env (const std::string& key, const std::string& val) {
5353 env_vars_[key] = val;
5454 return *this ;
5555}
@@ -64,7 +64,7 @@ void Command::RunCommand(const std::string& desc) const {
6464
6565 if (pid == -1 ) {
6666 std::println (stderr, " [ERROR] Fork failed: {}" , std::strerror (errno));
67- throw IOError ( " Fork failed: {}" , std::strerror (errno));
67+ throw std::runtime_error ( std::format ( " Fork failed: {}" , std::strerror (errno) ));
6868 }
6969
7070 // --- Child Process ---
@@ -102,7 +102,7 @@ void Command::RunCommand(const std::string& desc) const {
102102 int status = 0 ;
103103 if (waitpid (pid, &status, 0 ) == -1 ) {
104104 std::println (stderr, " [ERROR] waitpid failed: {}" , std::strerror (errno));
105- throw IOError ( " waitpid failed: {}" , std::strerror (errno));
105+ throw std::runtime_error ( std::format ( " waitpid failed: {}" , std::strerror (errno) ));
106106 }
107107
108108 int exit_code = -1 ;
@@ -117,94 +117,8 @@ void Command::RunCommand(const std::string& desc) const {
117117 return ;
118118 } else {
119119 std::println (stderr, " [ERROR] {} failed. Exit code: {}" , desc, exit_code);
120- throw IOError (" {} failed with exit code: {}" , desc, exit_code);
121- }
122- }
123-
124- std::string Command::GetCommandOutput (const std::string& desc) const {
125- std::println (" [INFO] Starting to capture {}, command: {} ..." , desc, program_);
126-
127- std::cout.flush ();
128- std::cerr.flush ();
129-
130- std::array<int , 2 > pipefd{-1 , -1 };
131- if (pipe (pipefd.data ()) == -1 ) {
132- throw IOError (" Pipe failed: {}" , std::strerror (errno));
133- }
134-
135- pid_t pid = fork ();
136- if (pid == -1 ) {
137- close (pipefd[0 ]);
138- close (pipefd[1 ]);
139- throw IOError (" Fork failed: {}" , std::strerror (errno));
140- }
141-
142- // --- Child Process ---
143- if (pid == 0 ) {
144- close (pipefd[0 ]);
145- if (dup2 (pipefd[1 ], STDOUT_FILENO) == -1 ) {
146- std::println (stderr, " dup2 failed: {}" , std::strerror (errno));
147- _exit (errno);
148- }
149- close (pipefd[1 ]);
150-
151- if (!cwd_.empty ()) {
152- std::error_code ec;
153- std::filesystem::current_path (cwd_, ec);
154- if (ec) {
155- std::println (stderr, " Failed to change directory to '{}': {}" , cwd_.string (),
156- ec.message ());
157- _exit (126 );
158- }
159- }
160-
161- for (const auto & [k, v] : env_vars_) {
162- setenv (k.c_str (), v.c_str (), 1 );
163- }
164-
165- std::vector<char *> argv;
166- argv.reserve (args_.size () + 2 );
167- argv.push_back (const_cast <char *>(program_.c_str ()));
168- for (const auto & arg : args_) {
169- argv.push_back (const_cast <char *>(arg.c_str ()));
170- }
171- argv.push_back (nullptr );
172-
173- execvp (program_.c_str (), argv.data ());
174- // reach here only if execvp fails
175- std::println (stderr, " execvp failed: {}" , std::strerror (errno));
176- _exit (127 );
177- }
178-
179- // --- Parent Process ---
180- close (pipefd[1 ]);
181-
182- std::string output;
183- std::array<char , 4096 > buffer;
184- ssize_t bytes_read;
185-
186- while ((bytes_read = read (pipefd[0 ], buffer.data (), buffer.size ())) > 0 ) {
187- output.append (buffer.data (), static_cast <size_t >(bytes_read));
188- }
189- close (pipefd[0 ]);
190-
191- int status = 0 ;
192- if (waitpid (pid, &status, 0 ) == -1 ) {
193- throw IOError (" waitpid failed: {}" , std::strerror (errno));
194- }
195-
196- int exit_code = -1 ;
197- if (WIFEXITED (status)) {
198- exit_code = WEXITSTATUS (status);
199- } else if (WIFSIGNALED (status)) {
200- exit_code = 128 + WTERMSIG (status);
201- }
202-
203- if (exit_code == 0 ) {
204- return output;
205- } else {
206- std::println (stderr, " [ERROR] {} failed. Exit code: {}" , desc, exit_code);
207- throw IOError (" {} failed with exit code: {}" , desc, exit_code);
120+ throw std::runtime_error (
121+ std::format (" {} failed with exit code: {}" , desc, exit_code));
208122 }
209123}
210124
0 commit comments