Skip to content

Commit d92fde7

Browse files
authored
feat(core): add output and status APIs to the Command struct (#1668)
1 parent 361456a commit d92fde7

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

.changes/command-status-and-output.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Adds `status` and `output` APIs to the `tauri::api::process::Command` struct.

core/tauri/src/api/process.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,33 @@ impl CommandChild {
134134
}
135135
}
136136

137+
/// Describes the result of a process after it has terminated.
138+
pub struct ExitStatus {
139+
code: Option<i32>,
140+
}
141+
142+
impl ExitStatus {
143+
/// Returns the exit code of the process, if any.
144+
pub fn code(&self) -> Option<i32> {
145+
self.code
146+
}
147+
148+
/// Was termination successful? Signal termination is not considered a success, and success is defined as a zero exit status.
149+
pub fn success(&self) -> bool {
150+
self.code == Some(0)
151+
}
152+
}
153+
154+
/// The output of a finished process.
155+
pub struct Output {
156+
/// The status (exit code) of the process.
157+
pub status: ExitStatus,
158+
/// The data that the process wrote to stdout.
159+
pub stdout: String,
160+
/// The data that the process wrote to stderr.
161+
pub stderr: String,
162+
}
163+
137164
#[cfg(not(windows))]
138165
fn relative_command_path(command: String) -> crate::Result<String> {
139166
match std::env::current_exe()?.parent() {
@@ -281,6 +308,57 @@ impl Command {
281308
},
282309
))
283310
}
311+
312+
/// Executes a command as a child process, waiting for it to finish and collecting its exit status.
313+
/// Stdin, stdout and stderr are ignored.
314+
pub fn status(self) -> crate::api::Result<ExitStatus> {
315+
let (mut rx, _child) = self.spawn()?;
316+
let code = crate::async_runtime::block_on(async move {
317+
let mut code = None;
318+
while let Some(event) = rx.recv().await {
319+
if let CommandEvent::Terminated(payload) = event {
320+
code = payload.code;
321+
}
322+
}
323+
code
324+
});
325+
Ok(ExitStatus { code })
326+
}
327+
328+
/// Executes the command as a child process, waiting for it to finish and collecting all of its output.
329+
/// Stdin is ignored.
330+
pub fn output(self) -> crate::api::Result<Output> {
331+
let (mut rx, _child) = self.spawn()?;
332+
333+
let output = crate::async_runtime::block_on(async move {
334+
let mut code = None;
335+
let mut stdout = String::new();
336+
let mut stderr = String::new();
337+
while let Some(event) = rx.recv().await {
338+
match event {
339+
CommandEvent::Terminated(payload) => {
340+
code = payload.code;
341+
}
342+
CommandEvent::Stdout(line) => {
343+
stdout.push_str(line.as_str());
344+
stdout.push('\n');
345+
}
346+
CommandEvent::Stderr(line) => {
347+
stderr.push_str(line.as_str());
348+
stderr.push('\n');
349+
}
350+
CommandEvent::Error(_) => {}
351+
}
352+
}
353+
Output {
354+
status: ExitStatus { code },
355+
stdout,
356+
stderr,
357+
}
358+
});
359+
360+
Ok(output)
361+
}
284362
}
285363

286364
// tests for the commands functions.

0 commit comments

Comments
 (0)