// Copyright (C) 2026 Doan Luu Duc Tai // // 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 . 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 { 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::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}") }