1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::{Process, Program, Result};
use std::{fmt, path::PathBuf};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Command {
current_working_directory: Option<PathBuf>,
program: Program,
arguments: Vec<String>,
}
impl Command {
pub fn new(program: Program) -> Self {
Command {
current_working_directory: None,
program,
arguments: Vec::new(),
}
}
#[inline]
pub fn current_working_directory(&mut self, cwd: PathBuf) -> &mut Self {
self.current_working_directory = Some(cwd);
self
}
pub fn argument<S>(&mut self, argument: S) -> &mut Self
where
S: AsRef<str>,
{
self.arguments.push(argument.as_ref().to_owned());
self
}
pub fn arguments<I, S>(&mut self, arguments: I) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
self.arguments.extend(
arguments
.into_iter()
.map(|argument| argument.as_ref().to_owned()),
);
self
}
pub fn spawn(&self) -> Result<Process> {
Process::spawn(self.clone())
}
pub(super) fn process_command(&self) -> std::process::Command {
let mut cmd = std::process::Command::new(&self.program);
if let Some(current_working_directory) = &self.current_working_directory {
cmd.current_dir(current_working_directory);
}
cmd.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.args(self.arguments.iter());
cmd
}
}
impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(cwd) = &self.current_working_directory {
write!(f, "CWD={} ", cwd.display())?;
}
self.program.fmt(f)?;
for argument in self.arguments.iter() {
write!(f, " {}", argument)?;
}
Ok(())
}
}