From fbdd6df1856483b3de1199ed810de6701690fc84 Mon Sep 17 00:00:00 2001 From: Itamar Date: Fri, 7 Jan 2022 16:17:19 +0200 Subject: [PATCH] LibCore: Make Core::command return CommandResult struct Previously, Core::command only returned a String which contained the data from stdout. The CommandResult struct contains the exit code as well as the data from stdout and stderr. --- Userland/DevTools/HackStudio/Git/GitRepo.cpp | 5 +++- Userland/Libraries/LibCore/Command.cpp | 31 ++++++++++---------- Userland/Libraries/LibCore/Command.h | 11 +++++-- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/Userland/DevTools/HackStudio/Git/GitRepo.cpp b/Userland/DevTools/HackStudio/Git/GitRepo.cpp index f91007e79c..aee1ac9b6b 100644 --- a/Userland/DevTools/HackStudio/Git/GitRepo.cpp +++ b/Userland/DevTools/HackStudio/Git/GitRepo.cpp @@ -80,7 +80,10 @@ String GitRepo::command(Vector const& command_parts) const String GitRepo::command_wrapper(Vector const& command_parts, String const& chdir) { - return Core::command("git", command_parts, LexicalPath(chdir)); + auto result = Core::command("git", command_parts, LexicalPath(chdir)); + if (result.is_error() || result.value().exit_code != 0) + return {}; + return result.value().stdout; } bool GitRepo::git_is_installed() diff --git a/Userland/Libraries/LibCore/Command.cpp b/Userland/Libraries/LibCore/Command.cpp index 7d04978e45..b1e3a9e9de 100644 --- a/Userland/Libraries/LibCore/Command.cpp +++ b/Userland/Libraries/LibCore/Command.cpp @@ -18,27 +18,26 @@ namespace Core { // Only supported in serenity mode because we use `posix_spawn_file_actions_addchdir` #ifdef __serenity__ -String command(const String& command_string, Optional chdir) +ErrorOr command(String const& command_string, Optional chdir) { auto parts = command_string.split(' '); if (parts.is_empty()) - return {}; + return Error::from_string_literal("empty command"sv); auto program = parts[0]; parts.remove(0); return command(program, parts, chdir); } -String command(const String& program, const Vector& arguments, Optional chdir) +ErrorOr command(String const& program, Vector const& arguments, Optional chdir) { int stdout_pipe[2] = {}; int stderr_pipe[2] = {}; if (pipe2(stdout_pipe, O_CLOEXEC)) { - perror("pipe2"); - VERIFY_NOT_REACHED(); + return Error::from_errno(errno); } if (pipe2(stderr_pipe, O_CLOEXEC)) { perror("pipe2"); - VERIFY_NOT_REACHED(); + return Error::from_errno(errno); } auto close_pipes = ScopeGuard([stderr_pipe, stdout_pipe] { @@ -68,9 +67,6 @@ String command(const String& program, const Vector& arguments, Optional< perror("posix_spawn"); VERIFY_NOT_REACHED(); } - int wstatus; - waitpid(pid, &wstatus, 0); - posix_spawn_file_actions_destroy(&action); // close the write-ends so reading wouldn't block close(stdout_pipe[1]); @@ -84,18 +80,21 @@ String command(const String& program, const Vector& arguments, Optional< } return String::copy(result_file->read_all()); }; + auto stdout = read_all_from_pipe(stdout_pipe); + auto stderr = read_all_from_pipe(stderr_pipe); - if (WEXITSTATUS(wstatus) != 0) { + int wstatus { 0 }; + waitpid(pid, &wstatus, 0); + posix_spawn_file_actions_destroy(&action); + int exit_code = WEXITSTATUS(wstatus); + + if (exit_code != 0) { # ifdef DBG_FAILED_COMMANDS - dbgln("command failed. stderr: {}", read_all_from_pipe(stderr_pipe)); + dbgln("command failed. stderr: {}", ); # endif - return {}; } - auto result = read_all_from_pipe(stdout_pipe); - if (result.is_null()) - return ""; - return result; + return CommandResult { WEXITSTATUS(wstatus), stdout, stderr }; } #endif diff --git a/Userland/Libraries/LibCore/Command.h b/Userland/Libraries/LibCore/Command.h index e850f6e373..8a19986c37 100644 --- a/Userland/Libraries/LibCore/Command.h +++ b/Userland/Libraries/LibCore/Command.h @@ -14,7 +14,14 @@ namespace Core { // If the executed command fails, the returned String will be in the null state. -String command(const String& program, const Vector& arguments, Optional chdir); -String command(const String& command_string, Optional chdir); + +struct CommandResult { + int exit_code { 0 }; + String stdout; + String stderr; +}; + +ErrorOr command(String const& program, Vector const& arguments, Optional chdir); +ErrorOr command(String const& command_string, Optional chdir); }