rivox 1.0.0

Universal polyglot build coordination layer for Python, Rust, and Node monorepos
Documentation
use super::SandboxExecutor;
use anyhow::{Context, Result};
use std::path::Path;
use std::process::{Command, Output};

pub struct LinuxSandbox;

impl SandboxExecutor for LinuxSandbox {
    fn name(&self) -> &'static str {
        "linux-namespaces-bwrap"
    }

    fn execute(
        &self,
        command: &str,
        args: &[&str],
        work_dir: &Path,
        allow_network: bool,
    ) -> Result<Output> {
        let bwrap_path = Path::new("/usr/bin/bwrap");

        if bwrap_path.exists() {
            let mut bwrap_cmd = Command::new(bwrap_path);
            bwrap_cmd
                .arg("--ro-bind")
                .arg("/")
                .arg("/")
                .arg("--dev")
                .arg("/dev")
                .arg("--proc")
                .arg("/proc")
                .arg("--bind")
                .arg(work_dir)
                .arg(work_dir)
                .current_dir(work_dir);

            if !allow_network {
                bwrap_cmd.arg("--unshare-net");
            }

            bwrap_cmd.arg(command).args(args);

            let output = bwrap_cmd
                .output()
                .with_context(|| format!("Linux bubblewrap sandbox failed for {}", command))?;

            return Ok(output);
        }

        // Fallback execution when bwrap binary is absent
        let mut cmd = Command::new(command);
        cmd.args(args).current_dir(work_dir);

        if !allow_network {
            cmd.env("RIVOX_SANDBOX_NETWORK", "0");
        }

        let output = cmd.output().with_context(|| {
            format!(
                "Linux sandbox fallback failed executing {} in {}",
                command,
                work_dir.display()
            )
        })?;

        Ok(output)
    }
}