use std::process::Stdio;
use gix_error::ExnMessageResult;
use bstr::{BStr, BString};
use crate::{
Driver, driver,
driver::{Operation, Process, State, process, substitute_f_parameter},
};
impl State {
pub fn maybe_launch_process(
&mut self,
driver: &Driver,
operation: Operation,
rela_path: &BStr,
) -> ExnMessageResult<Option<Process<'_>>> {
match driver.process.as_ref() {
Some(process) => {
let client = match self.running.remove(process) {
Some(c) => c,
None => {
let (child, cmd) = spawn_driver(process.clone(), &self.context)?;
use gix_error::{ResultExt, message};
process::Client::handshake(child, "git-filter", &[2], &["clean", "smudge", "delay"])
.or_raise(|| message!("Process handshake with command {cmd:?} failed"))?
}
};
self.running.insert(process.clone(), client);
let client = self.running.get_mut(process).expect("just inserted");
Ok(Some(Process::MultiFile {
client,
key: driver::Key(process.to_owned()),
}))
}
None => {
let cmd = match operation {
Operation::Clean => driver
.clean
.as_ref()
.map(|cmd| substitute_f_parameter(cmd.as_ref(), rela_path)),
Operation::Smudge => driver
.smudge
.as_ref()
.map(|cmd| substitute_f_parameter(cmd.as_ref(), rela_path)),
};
let cmd = match cmd {
Some(cmd) => cmd,
None => return Ok(None),
};
let (child, command) = spawn_driver(cmd, &self.context)?;
Ok(Some(Process::SingleFile { child, command }))
}
}
}
}
fn spawn_driver(
cmd: BString,
context: &gix_command::Context,
) -> ExnMessageResult<(std::process::Child, std::process::Command)> {
let mut cmd: std::process::Command = gix_command::prepare(gix_path::from_bstr(cmd).into_owned())
.command_may_be_shell_script()
.with_context(context.clone())
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.into();
gix_trace::debug!(cmd = ?cmd, "launching filter driver");
let child = match cmd.spawn() {
Ok(child) => child,
Err(err) => {
use gix_error::ErrorExt;
return Err(err.and_raise(gix_error::message!("Failed to spawn driver: {cmd:?}")));
}
};
Ok((child, cmd))
}