2019-05-24 01:25:55 -07:00
|
|
|
use crate::common::*;
|
|
|
|
|
2020-01-07 18:05:48 -08:00
|
|
|
pub(crate) struct Env {
|
2019-05-24 01:25:55 -07:00
|
|
|
args: Vec<String>,
|
|
|
|
dir: Box<dyn AsRef<Path>>,
|
2020-01-04 18:58:42 -08:00
|
|
|
pub(crate) err: Box<dyn Write>,
|
2020-01-14 00:52:27 -08:00
|
|
|
pub(crate) _out: Box<dyn Write>,
|
2019-05-24 01:25:55 -07:00
|
|
|
}
|
|
|
|
|
2020-01-07 18:05:48 -08:00
|
|
|
impl Env {
|
2020-01-04 18:58:42 -08:00
|
|
|
pub(crate) fn main() -> Self {
|
2019-05-24 01:25:55 -07:00
|
|
|
let dir = match env::current_dir() {
|
|
|
|
Ok(dir) => dir,
|
|
|
|
Err(error) => panic!("Failed to get current directory: {}", error),
|
|
|
|
};
|
|
|
|
|
2020-01-14 00:52:27 -08:00
|
|
|
Self::new(dir, io::stdout(), io::stderr(), env::args())
|
2019-05-24 01:25:55 -07:00
|
|
|
}
|
|
|
|
|
2020-01-04 18:58:42 -08:00
|
|
|
pub(crate) fn run(&mut self) -> Result<(), Error> {
|
2019-05-24 01:25:55 -07:00
|
|
|
Opt::from_iter_safe(&self.args)?.run(self)
|
|
|
|
}
|
|
|
|
|
2020-01-14 00:52:27 -08:00
|
|
|
pub(crate) fn new<D, O, E, S, I>(dir: D, out: O, err: E, args: I) -> Self
|
2019-05-24 01:25:55 -07:00
|
|
|
where
|
|
|
|
D: AsRef<Path> + 'static,
|
2020-01-14 00:52:27 -08:00
|
|
|
O: Write + 'static,
|
2019-05-24 01:25:55 -07:00
|
|
|
E: Write + 'static,
|
|
|
|
S: Into<String>,
|
|
|
|
I: IntoIterator<Item = S>,
|
|
|
|
{
|
2020-01-04 18:58:42 -08:00
|
|
|
Self {
|
|
|
|
args: args.into_iter().map(Into::into).collect(),
|
2019-05-24 01:25:55 -07:00
|
|
|
dir: Box::new(dir),
|
|
|
|
err: Box::new(err),
|
2020-01-14 00:52:27 -08:00
|
|
|
_out: Box::new(out),
|
2019-05-24 01:25:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn status(&mut self) -> Result<(), i32> {
|
2020-01-14 00:52:27 -08:00
|
|
|
use structopt::clap::ErrorKind;
|
2019-05-24 01:25:55 -07:00
|
|
|
if let Err(error) = self.run() {
|
2020-01-14 00:52:27 -08:00
|
|
|
if let Error::Clap { source } = error {
|
|
|
|
write!(&mut self.err, "{}", source).ok();
|
|
|
|
match source.kind {
|
|
|
|
ErrorKind::VersionDisplayed | ErrorKind::HelpDisplayed => Ok(()),
|
|
|
|
_ => Err(EXIT_FAILURE),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
write!(&mut self.err, "error: {}", error).ok();
|
|
|
|
Err(EXIT_FAILURE)
|
|
|
|
}
|
2019-05-24 01:25:55 -07:00
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn resolve(&self, path: impl AsRef<Path>) -> PathBuf {
|
|
|
|
self.dir.as_ref().as_ref().join(path).clean()
|
|
|
|
}
|
|
|
|
}
|
2020-01-14 00:52:27 -08:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn error_message_on_stdout() {
|
|
|
|
let mut env = testing::env(
|
|
|
|
["torrent", "create", "--input", "foo", "--announce", "bar"]
|
|
|
|
.iter()
|
|
|
|
.cloned(),
|
|
|
|
);
|
|
|
|
fs::write(env.resolve("foo"), "").unwrap();
|
|
|
|
env.status().ok();
|
|
|
|
let err = env.err();
|
|
|
|
if !err.starts_with("error: Failed to parse announce URL:") {
|
|
|
|
panic!("Unexpected standard error output: {}", err);
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_eq!(env.out(), "");
|
|
|
|
}
|
|
|
|
}
|