internal: Bring back JodChild into flychecking for cancellation

This commit is contained in:
Lukas Wirth 2022-06-13 13:34:07 +02:00
parent 7db73875ac
commit 6438ef9aa3
4 changed files with 117 additions and 64 deletions

View file

@ -5,54 +5,66 @@
use std::{
io,
process::{Command, Output, Stdio},
process::{ChildStderr, ChildStdout, Command, Output, Stdio},
};
use crate::JodChild;
pub fn streaming_output(
out: ChildStdout,
err: ChildStderr,
on_stdout_line: &mut dyn FnMut(&str),
on_stderr_line: &mut dyn FnMut(&str),
) -> io::Result<(Vec<u8>, Vec<u8>)> {
let mut stdout = Vec::new();
let mut stderr = Vec::new();
imp::read2(out, err, &mut |is_out, data, eof| {
let idx = if eof {
data.len()
} else {
match data.iter().rposition(|b| *b == b'\n') {
Some(i) => i + 1,
None => return,
}
};
{
// scope for new_lines
let new_lines = {
let dst = if is_out { &mut stdout } else { &mut stderr };
let start = dst.len();
let data = data.drain(..idx);
dst.extend(data);
&dst[start..]
};
for line in String::from_utf8_lossy(new_lines).lines() {
if is_out {
on_stdout_line(line);
} else {
on_stderr_line(line);
}
}
}
})?;
Ok((stdout, stderr))
}
pub fn spawn_with_streaming_output(
mut cmd: Command,
on_stdout_line: &mut dyn FnMut(&str),
on_stderr_line: &mut dyn FnMut(&str),
) -> io::Result<Output> {
let mut stdout = Vec::new();
let mut stderr = Vec::new();
let cmd = cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
let status = {
let mut child = cmd.spawn()?;
let out = child.stdout.take().unwrap();
let err = child.stderr.take().unwrap();
imp::read2(out, err, &mut |is_out, data, eof| {
let idx = if eof {
data.len()
} else {
match data.iter().rposition(|b| *b == b'\n') {
Some(i) => i + 1,
None => return,
}
};
{
// scope for new_lines
let new_lines = {
let dst = if is_out { &mut stdout } else { &mut stderr };
let start = dst.len();
let data = data.drain(..idx);
dst.extend(data);
&dst[start..]
};
for line in String::from_utf8_lossy(new_lines).lines() {
if is_out {
on_stdout_line(line);
} else {
on_stderr_line(line);
}
}
}
})?;
let _ = child.kill();
child.wait()?
};
let mut child = JodChild(cmd.spawn()?);
let (stdout, stderr) = streaming_output(
child.stdout.take().unwrap(),
child.stderr.take().unwrap(),
on_stdout_line,
on_stderr_line,
)?;
let status = child.wait()?;
Ok(Output { status, stdout, stderr })
}