arcature-cli 2026.1.1

Developer lifecycle CLI for Arcature applications.
Documentation
use std::process::{Child, ExitStatus};

use super::ProcessError;

pub(crate) struct ChildGuard {
    child: Child,
    label: &'static str,
    reaped: bool,
}

impl ChildGuard {
    pub(crate) fn new(child: Child, label: &'static str) -> Self {
        Self {
            child,
            label,
            reaped: false,
        }
    }

    pub(crate) fn try_wait(&mut self) -> Result<Option<ExitStatus>, ProcessError> {
        let status = self.child.try_wait().map_err(|source| ProcessError::Wait {
            program: self.label.to_owned(),
            source,
        })?;
        if status.is_some() {
            self.reaped = true;
        }
        Ok(status)
    }

    pub(crate) fn terminate(&mut self) -> Result<(), ProcessError> {
        if self.try_wait()?.is_some() {
            return Ok(());
        }
        self.child
            .kill()
            .map_err(|source| ProcessError::Terminate {
                program: self.label,
                source,
            })?;
        self.child.wait().map_err(|source| ProcessError::Wait {
            program: self.label.to_owned(),
            source,
        })?;
        self.reaped = true;
        Ok(())
    }
}

impl Drop for ChildGuard {
    fn drop(&mut self) {
        if !self.reaped {
            let _ = self.child.kill();
            let _ = self.child.wait();
        }
    }
}