Parcourir la source

feat(core): add `output` and `status` APIs to the `Command` struct (#1668)

Lucas Fernandes Nogueira il y a 4 ans
Parent
commit
d92fde7505
2 fichiers modifiés avec 83 ajouts et 0 suppressions
  1. 5 0
      .changes/command-status-and-output.md
  2. 78 0
      core/tauri/src/api/process.rs

+ 5 - 0
.changes/command-status-and-output.md

@@ -0,0 +1,5 @@
+---
+"tauri": patch
+---
+
+Adds `status` and `output` APIs to the `tauri::api::process::Command` struct.

+ 78 - 0
core/tauri/src/api/process.rs

@@ -134,6 +134,33 @@ impl CommandChild {
   }
 }
 
+/// Describes the result of a process after it has terminated.
+pub struct ExitStatus {
+  code: Option<i32>,
+}
+
+impl ExitStatus {
+  /// Returns the exit code of the process, if any.
+  pub fn code(&self) -> Option<i32> {
+    self.code
+  }
+
+  /// Was termination successful? Signal termination is not considered a success, and success is defined as a zero exit status.
+  pub fn success(&self) -> bool {
+    self.code == Some(0)
+  }
+}
+
+/// The output of a finished process.
+pub struct Output {
+  /// The status (exit code) of the process.
+  pub status: ExitStatus,
+  /// The data that the process wrote to stdout.
+  pub stdout: String,
+  /// The data that the process wrote to stderr.
+  pub stderr: String,
+}
+
 #[cfg(not(windows))]
 fn relative_command_path(command: String) -> crate::Result<String> {
   match std::env::current_exe()?.parent() {
@@ -281,6 +308,57 @@ impl Command {
       },
     ))
   }
+
+  /// Executes a command as a child process, waiting for it to finish and collecting its exit status.
+  /// Stdin, stdout and stderr are ignored.
+  pub fn status(self) -> crate::api::Result<ExitStatus> {
+    let (mut rx, _child) = self.spawn()?;
+    let code = crate::async_runtime::block_on(async move {
+      let mut code = None;
+      while let Some(event) = rx.recv().await {
+        if let CommandEvent::Terminated(payload) = event {
+          code = payload.code;
+        }
+      }
+      code
+    });
+    Ok(ExitStatus { code })
+  }
+
+  /// Executes the command as a child process, waiting for it to finish and collecting all of its output.
+  /// Stdin is ignored.
+  pub fn output(self) -> crate::api::Result<Output> {
+    let (mut rx, _child) = self.spawn()?;
+
+    let output = crate::async_runtime::block_on(async move {
+      let mut code = None;
+      let mut stdout = String::new();
+      let mut stderr = String::new();
+      while let Some(event) = rx.recv().await {
+        match event {
+          CommandEvent::Terminated(payload) => {
+            code = payload.code;
+          }
+          CommandEvent::Stdout(line) => {
+            stdout.push_str(line.as_str());
+            stdout.push('\n');
+          }
+          CommandEvent::Stderr(line) => {
+            stderr.push_str(line.as_str());
+            stderr.push('\n');
+          }
+          CommandEvent::Error(_) => {}
+        }
+      }
+      Output {
+        status: ExitStatus { code },
+        stdout,
+        stderr,
+      }
+    });
+
+    Ok(output)
+  }
 }
 
 // tests for the commands functions.