use std::{
fs::File,
path::{
Path,
PathBuf,
},
process::Command as ProcessCommand,
};
use super::process_setup::{
configure_environment,
configure_stdin,
open_output_file,
};
use crate::{
Command,
CommandError,
OutputStream,
};
pub(crate) struct PreparedCommand {
pub(crate) command_text: String,
pub(crate) process_command: ProcessCommand,
pub(crate) stdin_bytes: Option<Vec<u8>>,
pub(crate) stdout_file: Option<File>,
pub(crate) stderr_file: Option<File>,
pub(crate) stdout_file_path: Option<PathBuf>,
pub(crate) stderr_file_path: Option<PathBuf>,
}
impl PreparedCommand {
pub(crate) fn prepare(
command: Command,
default_working_directory: Option<&Path>,
stdout_file_path: Option<&Path>,
stderr_file_path: Option<&Path>,
) -> Result<Self, CommandError> {
let command_text = command.display_command();
let mut process_command = ProcessCommand::new(command.program());
process_command.args(command.arguments());
process_command.stdout(std::process::Stdio::piped());
process_command.stderr(std::process::Stdio::piped());
if let Some(working_directory) = command
.working_directory_override()
.or(default_working_directory)
{
process_command.current_dir(working_directory);
}
configure_environment(&command, &mut process_command);
let stdin = command.into_stdin_configuration();
let stdin_bytes = configure_stdin(&command_text, stdin, &mut process_command)?;
let stdout_file = open_output_file(&command_text, OutputStream::Stdout, stdout_file_path)?;
let stderr_file = open_output_file(&command_text, OutputStream::Stderr, stderr_file_path)?;
Ok(Self {
command_text,
process_command,
stdin_bytes,
stdout_file,
stderr_file,
stdout_file_path: stdout_file_path.map(Path::to_path_buf),
stderr_file_path: stderr_file_path.map(Path::to_path_buf),
})
}
}