/// Spawns the command process,
/// computes its output length and its hash and captures its standard error into a string.
/// Blocks until the child process terminates.
Spawns the command process,
computes its output length and its hash and captures its standard error into a string.
Blocks until the child process terminates.
Spawns the command process computes its output length and its hash and captures its standard error into a string . Blocks until the child process terminates .
fn execute(command: &mut Command, output_conf: &OutputConf) -> io::Result<Output> {
        let mut child = command.spawn()?;
        // We call 'take' to avoid borrowing `child` for longer than a single line.
        // We can't reference stdout/stderr directly, because a mutable borrow of a field
        // creates a mutable borrow of the containing struct, but later we need to mutably
        // borrow `child` again to wait on it.
        let child_out = child.stdout.take();
        let child_err = child.stderr.take();
        // Capture the stderr in background in order to avoid a deadlock when the child process
        // would block on writing to stdout, and this process would block on reading stderr
        // (or the other way round).
        // The other solution could be to use non-blocking I/O, but threads look simpler.
        let stderr_reaper = std::thread::spawn(move || {
            let mut str = String::new();
            let _ = child_err.unwrap().read_to_string(&mut str);
            str
        });
        let result = match output_conf {
            OutputConf::StdOut => {
                stream_hash(&mut child_out.unwrap(), FileLen::MAX, BUF_LEN, |_| {})
            }
            OutputConf::Named(output) => {
                stream_hash(&mut File::open(output)?, FileLen::MAX, BUF_LEN, |_| {})
            }
            OutputConf::InPlace(output) => {
                child.wait()?;
                stream_hash(&mut File::open(output)?, FileLen::MAX, BUF_LEN, |_| {})
            }
        }?;
        Ok(Output {
            output_len: result.0,
            output_hash: result.1,
            status: child.wait()?,
            stderr: stderr_reaper.join().unwrap(),
        })
    }
fn execute ( command : & mut Command , output_conf : & OutputConf ) -> io :: Result < Output > { let mut child = command . spawn ( ) ? ; // We call 'take' to avoid borrowing `child` for longer than a single line. // We can't reference stdout/stderr directly, because a mutable borrow of a field // creates a mutable borrow of the containing struct, but later we need to mutably // borrow `child` again to wait on it. let child_out = child . stdout . take ( ) ; let child_err = child . stderr . take ( ) ; // Capture the stderr in background in order to avoid a deadlock when the child process // would block on writing to stdout, and this process would block on reading stderr // (or the other way round). // The other solution could be to use non-blocking I/O, but threads look simpler. let stderr_reaper = std :: thread :: spawn ( move | | { let mut str = String :: new ( ) ; let _ = child_err . unwrap ( ) . read_to_string ( & mut str ) ; str } ) ; let result = match output_conf { OutputConf :: StdOut => { stream_hash ( & mut child_out . unwrap ( ) , FileLen :: MAX , BUF_LEN , | _ | { } ) } OutputConf :: Named ( output ) => { stream_hash ( & mut File :: open ( output ) ? , FileLen :: MAX , BUF_LEN , | _ | { } ) } OutputConf :: InPlace ( output ) => { child . wait ( ) ? ; stream_hash ( & mut File :: open ( output ) ? , FileLen :: MAX , BUF_LEN , | _ | { } ) } } ? ; Ok ( Output { output_len : result . 0 , output_hash : result . 1 , status : child . wait ( ) ? , stderr : stderr_reaper . join ( ) . unwrap ( ) , } ) }
Spawns the command process,
computes its output length and its hash and captures its standard error into a string.
Spawns the command process computes its output length and its hash and captures its standard error into a string .
command
&mut Command
output_conf
&OutputConf