aboutsummaryrefslogtreecommitdiff
path: root/src/process.rs
diff options
context:
space:
mode:
authorDoan Luu Duc Tai <doan@luuduct.ai>2026-10-30 14:00:58 -0500
committerDoan Luu Duc Tai <doan@luuduct.ai>2026-10-30 14:00:58 -0500
commit19a0280d7dabd4ca637d8070cc7d3691a0e85bd1 (patch)
treede4591ed54ef860f04dd88bb3aae51dee51237a7 /src/process.rs
parent006a1e94075e90fccfe248cd66bf7d0586a86279 (diff)
Manage the portable stack with Rust and rootless Podman
Diffstat (limited to 'src/process.rs')
-rw-r--r--src/process.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/process.rs b/src/process.rs
new file mode 100644
index 0000000..eb48bc8
--- /dev/null
+++ b/src/process.rs
@@ -0,0 +1,70 @@
+// Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+use std::fmt;
+use std::io::{self, Write};
+use std::process::{Command, Output};
+
+use anyhow::{Context, Result, bail};
+
+pub(crate) fn capture(command: &mut Command) -> Result<Output> {
+ let output = command.output().with_context(|| {
+ format!(
+ "Could not start {}",
+ command.get_program().to_string_lossy()
+ )
+ })?;
+ if !output.status.success() {
+ bail!(
+ "{} failed ({}): {}",
+ command.get_program().to_string_lossy(),
+ output.status,
+ String::from_utf8_lossy(&output.stderr).trim()
+ );
+ }
+ Ok(output)
+}
+
+pub(crate) fn text(command: &mut Command) -> Result<String> {
+ String::from_utf8(capture(command)?.stdout).context("Command returned non-UTF-8 output")
+}
+
+pub(crate) fn run(command: &mut Command) -> Result<()> {
+ let status = command.status().with_context(|| {
+ format!(
+ "Could not start {}",
+ command.get_program().to_string_lossy()
+ )
+ })?;
+ if !status.success() {
+ bail!(
+ "{} failed ({status})",
+ command.get_program().to_string_lossy()
+ );
+ }
+ Ok(())
+}
+
+pub(crate) fn available(command: &mut Command) -> bool {
+ command.output().is_ok_and(|output| output.status.success())
+}
+
+pub(crate) fn line(message: fmt::Arguments<'_>) -> Result<()> {
+ writeln!(io::stdout().lock(), "{message}").context("Could not write command output")
+}
+
+pub(crate) fn error(message: fmt::Arguments<'_>) -> io::Result<()> {
+ writeln!(io::stderr().lock(), "{message}")
+}