This repository has been archived by the owner on Jul 21, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27
/
rpmbuild.rs
139 lines (120 loc) · 3.72 KB
/
rpmbuild.rs
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! Wrapper for running the `rpmbuild` command
use crate::error::{Error, ErrorKind};
use std::{
ffi::OsStr,
io::{BufRead, BufReader},
path::PathBuf,
process::{Child, Command, Stdio},
};
/// Path to the `rpmbuild` command
pub const DEFAULT_RPMBUILD_PATH: &str = "/usr/bin/rpmbuild";
/// Version of rpmbuild supported by this tool
pub const SUPPORTED_RPMBUILD_VERSION: &str = " 4.";
/// Wrapper for the `rpmbuild` command
pub struct Rpmbuild {
/// Path to rpmbuild
pub path: PathBuf,
/// Are we in verbose mode?
pub verbose: bool,
}
impl Rpmbuild {
/// Prepare `rpmbuild`, checking the correct version is installed
pub fn new(verbose: bool) -> Result<Self, Error> {
let rpmbuild = Self {
path: DEFAULT_RPMBUILD_PATH.into(),
verbose,
};
// Make sure we have a valid version of rpmbuild
rpmbuild.version()?;
Ok(rpmbuild)
}
/// Get version of `rpmbuild`
pub fn version(&self) -> Result<String, Error> {
let output = Command::new(&self.path)
.args(&["--version"])
.output()
.map_err(|e| {
err!(
ErrorKind::Rpmbuild,
"error running {}: {}",
self.path.display(),
e
)
})?;
if !output.status.success() {
fail!(
ErrorKind::Rpmbuild,
"error running {} (exit status: {})",
&self.path.display(),
&output.status
);
}
let vers = String::from_utf8(output.stdout).map_err(|e| {
err!(
ErrorKind::Rpmbuild,
"error parsing rpmbuild output as UTF-8: {}",
e
)
})?;
if !vers.contains(SUPPORTED_RPMBUILD_VERSION) {
fail!(
ErrorKind::Rpmbuild,
"unexpected rpmbuild version string: {:?}",
vers
);
}
let parts: Vec<&str> = vers.split_whitespace().collect();
Ok(parts[2].to_owned())
}
/// Execute `rpmbuild` with the given arguments
pub fn exec<I, S>(&self, args: I) -> Result<(), Error>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
let mut rpmbuild = Command::new(&self.path)
.args(args)
.stdout(Stdio::piped())
.stderr(if self.verbose {
Stdio::inherit()
} else {
Stdio::null()
})
.spawn()
.map_err(|e| {
err!(
ErrorKind::Rpmbuild,
"error running {}: {}",
self.path.display(),
e
)
})?;
let output = self.read_rpmbuild_output(&mut rpmbuild)?;
let status = rpmbuild.wait()?;
if status.success() {
Ok(())
} else {
if !self.verbose {
eprintln!("{}", &output);
}
fail!(
ErrorKind::Rpmbuild,
"error running {} (exit status: {})",
self.path.display(),
status
);
}
}
/// Read stdout from rpmbuild, either displaying it or discarding it
fn read_rpmbuild_output(&self, subprocess: &mut Child) -> Result<String, Error> {
let mut reader = BufReader::new(subprocess.stdout.as_mut().unwrap());
let mut string = String::new();
while reader.read_line(&mut string)? != 0 {
if self.verbose {
status_ok!("rpmbuild", string.trim_end());
string.clear();
}
}
Ok(string)
}
}