From 4be608a00286320ae57f95fc93988f48001b705a Mon Sep 17 00:00:00 2001 From: Adrian Heine Date: Tue, 7 Feb 2017 13:54:06 +0100 Subject: [PATCH] Remove symbol error type --- src/lib.rs | 4 +- src/schema.rs | 96 +++++++++------------ src/symbols/file.rs | 11 ++- src/symbols/git.rs | 10 +-- src/symbols/mod.rs | 6 +- src/symbols/nginx/server.rs | 5 +- src/symbols/npm.rs | 7 +- src/symbols/systemd/node_js_user_service.rs | 15 ++-- src/symbols/systemd/user_session.rs | 9 +- src/symbols/user.rs | 30 +++---- 10 files changed, 85 insertions(+), 108 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0e691f2..401006a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ // rustfmt #![deny(fat_ptr_transmutes, -trivial_casts, trivial_numeric_casts, unsafe_code, +trivial_numeric_casts, unsafe_code, unstable_features, unused_extern_crates, unused_import_braces, unused_qualifications, variant_size_differences @@ -12,7 +12,7 @@ unused_results )] /* -#![warn(missing_docs, +#![warn(missing_docs, trivial_casts, missing_copy_implementations, missing_debug_implementations )] diff --git a/src/schema.rs b/src/schema.rs index 1960d04..560e6e1 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -4,13 +4,13 @@ use std::fmt; use loggers::Logger; use symbols::Symbol; -#[derive(Debug,PartialEq)] -pub enum SymbolRunError { - Symbol(E), +#[derive(Debug)] +pub enum SymbolRunError { + Symbol(Box), ExecuteDidNotReach(()) } -impl Error for SymbolRunError { +impl Error for SymbolRunError { fn description(&self) -> &str { match self { &SymbolRunError::Symbol(_) => "Symbol execution error", @@ -19,13 +19,13 @@ impl Error for SymbolRunError { } fn cause(&self) -> Option<&Error> { match self { - &SymbolRunError::Symbol(ref e) => Some(e), + &SymbolRunError::Symbol(ref e) => Some(&**e), &SymbolRunError::ExecuteDidNotReach(_) => None } } } -impl fmt::Display for SymbolRunError { +impl fmt::Display for SymbolRunError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { &SymbolRunError::Symbol(ref e) => write!(f, "{}", e), @@ -34,22 +34,14 @@ impl fmt::Display for SymbolRunError { } } -impl From for SymbolRunError { - fn from(err: E) -> SymbolRunError { - SymbolRunError::Symbol(err) - } -} - pub trait SymbolRunner { - fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), SymbolRunError> - where S::Error: Error; + fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box>; } pub struct InitializingSymbolRunner; impl SymbolRunner for InitializingSymbolRunner { - fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), SymbolRunError> - where S::Error: Error + fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box> { let target_reached = try!(symbol.target_reached()); if target_reached { @@ -61,7 +53,7 @@ impl SymbolRunner for InitializingSymbolRunner { let target_reached = try!(symbol.target_reached()); logger.debug(format!("Symbol reports target_reached: {:?} (should be true)", target_reached).as_str()); if !target_reached { - return Err(SymbolRunError::ExecuteDidNotReach(())); + return Err(Box::new(SymbolRunError::ExecuteDidNotReach(()))); } } Ok(()) @@ -71,8 +63,7 @@ impl SymbolRunner for InitializingSymbolRunner { pub struct DrySymbolRunner; impl SymbolRunner for DrySymbolRunner { - fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), SymbolRunError> - where S::Error: Error + fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box> { let target_reached = try!(symbol.target_reached()); logger.debug(format!("Symbol reports target_reached: {:?}", target_reached).as_str()); @@ -95,7 +86,6 @@ mod test { use symbols::Symbol; use schema::SymbolRunner; use schema::InitializingSymbolRunner; - use schema::SymbolRunError; #[derive(Debug, PartialEq, Clone)] enum DummySymbolError { @@ -114,34 +104,29 @@ mod test { } } - #[derive(Debug)] - struct DummySymbol { - _target_reacheds: Vec>, - _cur_target_reached: RefCell, - _execute: Result<(), DummySymbolError>, + struct DummySymbol<'a> { + _execute: &'a Fn() -> Result<(), Box>, + _target_reached: &'a Fn() -> Result> } - impl Symbol for DummySymbol { - type Error = DummySymbolError; - fn target_reached(&self) -> Result { - let mut cur = self._cur_target_reached.borrow_mut(); - let ret = self._target_reacheds[*cur].clone(); - *cur = *cur + 1; - ret + impl<'a> Symbol for DummySymbol<'a> { + fn target_reached(&self) -> Result> { + (self._target_reached)() + } + fn execute(&self) -> Result<(), Box> { + (self._execute)() } - fn execute(&self) -> Result<(), Self::Error> { self._execute.clone() } } - impl fmt::Display for DummySymbol { + impl<'a> fmt::Display for DummySymbol<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Dummy symbol") } } - impl DummySymbol { - fn new(target_reached: Vec>, - execute: Result<(), DummySymbolError>) -> DummySymbol { - DummySymbol { _target_reacheds: target_reached, _cur_target_reached: RefCell::new(0), _execute: execute } + impl<'a> DummySymbol<'a> { + fn new(target_reached: &'a Fn() -> Result>, execute: &'a Fn() -> Result<(), Box>) -> DummySymbol<'a> { + DummySymbol { _target_reached: target_reached, _execute: execute } } } @@ -166,36 +151,37 @@ mod test { #[test] fn nothing_needed_to_be_done() { - let result: Result<(), SymbolRunError> = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(true)], Ok(())) ); - assert_eq!( - result, - Ok(()) - ); + let result = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| Ok(true), &|| Ok(())) ); + assert!(result.is_ok()); } #[test] fn everything_is_ok() { - let result: Result<(), SymbolRunError> = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(false), Ok(true)], Ok(())) ); - assert_eq!( - result, - Ok(()) - ); + let first = RefCell::new(true); + let result = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| { + let mut _first = first.borrow_mut(); + Ok(if *_first { + *_first = false; + true + } else { + false + }) + }, &|| Ok(())) ); + assert!(result.is_ok()); } #[test] fn executing_did_not_change_state() { - let result: Result<(), SymbolRunError> = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(false), Ok(false)], Ok(()))); + let result = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| Ok(false), &|| Ok(()))); assert_eq!( - result, - Err(SymbolRunError::ExecuteDidNotReach(())) + result.unwrap_err().description(), + "Target not reached after executing symbol" ); } #[test] fn executing_did_not_work() { - assert_eq!( - InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(vec![Ok(false)], Err(DummySymbolError::Error(()))) ), - Err(SymbolRunError::Symbol(DummySymbolError::Error(()))) - ); + let err = InitializingSymbolRunner.run_symbol( &mut DummyLogger::new(), &DummySymbol::new(&|| Ok(false), &|| Err(Box::new(DummySymbolError::Error(()))) )).unwrap_err(); + assert_eq!(err.description(), "Description"); } } diff --git a/src/symbols/file.rs b/src/symbols/file.rs index f586591..eff720b 100644 --- a/src/symbols/file.rs +++ b/src/symbols/file.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::error::Error; use std::fmt; use std::fs::File as FsFile; use std::io; @@ -23,16 +24,14 @@ impl File where C: Deref, D: AsRef + fmt::Display { } impl Symbol for File where C: Deref, D: AsRef + fmt::Display { - type Error = io::Error; - - fn target_reached(&self) -> Result { + fn target_reached(&self) -> Result> { let file = FsFile::open(self.path.as_ref()); // Check if file exists if let Err(e) = file { return if e.kind() == io::ErrorKind::NotFound { Ok(false) } else { - Err(e) + Err(Box::new(e)) }; } // Check if content is the same @@ -42,13 +41,13 @@ impl Symbol for File where C: Deref, D: AsRef + fmt match (file_content.next(), target_content.next()) { (None, None) => return Ok(true), (Some(Ok(a)), Some(b)) if a == b => {}, - (Some(Err(e)), _) => return Err(e), + (Some(Err(e)), _) => return Err(Box::new(e)), (_, _) => return Ok(false) } } } - fn execute(&self) -> Result<(), Self::Error> { + fn execute(&self) -> Result<(), Box> { let mut file = try!(FsFile::create(self.path.as_ref())); try!(file.write_all(self.content.as_bytes())); Ok(()) diff --git a/src/symbols/git.rs b/src/symbols/git.rs index 957f44a..bbac49e 100644 --- a/src/symbols/git.rs +++ b/src/symbols/git.rs @@ -1,3 +1,4 @@ +use std::error::Error; use std::fmt; use std::io; @@ -39,13 +40,12 @@ impl<'a> GitCheckout<'a> { } impl<'a> Symbol for GitCheckout<'a> { - type Error = io::Error; - fn target_reached(&self) -> Result { + fn target_reached(&self) -> Result> { if let Err(e) = metadata(self.target) { return if e.kind() == io::ErrorKind::NotFound { Ok(false) } else { - Err(e) + Err(Box::new(e)) }; } try!(self._run_in_target_repo(&["fetch", self.source, self.branch])); @@ -54,13 +54,13 @@ impl<'a> Symbol for GitCheckout<'a> { Ok(fetch_head == head) } - fn execute(&self) -> Result<(), Self::Error> { + fn execute(&self) -> Result<(), Box> { if let Err(e) = metadata(self.target) { return if e.kind() == io::ErrorKind::NotFound { try!(self.command_runner.run_with_args("git", &["clone", "-b", self.branch, self.source, self.target])); Ok(()) } else { - Err(e) + Err(Box::new(e)) }; } try!(self._run_in_target_repo(&["fetch", self.source, self.branch])); diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs index 0e397ed..d05c2cb 100644 --- a/src/symbols/mod.rs +++ b/src/symbols/mod.rs @@ -1,10 +1,10 @@ +use std::borrow::Cow; use std::error::Error; use std::fmt::Display; pub trait Symbol: Display { - type Error: Error; - fn target_reached(&self) -> Result; - fn execute(&self) -> Result<(), Self::Error>; + fn target_reached(&self) -> Result>; + fn execute(&self) -> Result<(), Box>; } pub mod file; diff --git a/src/symbols/nginx/server.rs b/src/symbols/nginx/server.rs index 703e3f4..27baf39 100644 --- a/src/symbols/nginx/server.rs +++ b/src/symbols/nginx/server.rs @@ -86,8 +86,7 @@ impl<'a> NginxServer<'a, String> { } impl<'a, C> Symbol for NginxServer<'a, C> where C: Deref { - type Error = NginxServerError<> as Symbol>::Error>; - fn target_reached(&self) -> Result { + fn target_reached(&self) -> Result> { if !try!(self.file.target_reached()) { return Ok(false); } @@ -95,7 +94,7 @@ impl<'a, C> Symbol for NginxServer<'a, C> where C: Deref { Ok(true) } - fn execute(&self) -> Result<(), Self::Error> { + fn execute(&self) -> Result<(), Box> { try!(self.file.execute()); try!(self.command_runner.run_with_args("systemctl", &["reload-or-restart", "nginx"])); Ok(()) diff --git a/src/symbols/npm.rs b/src/symbols/npm.rs index 80092df..61b9b3a 100644 --- a/src/symbols/npm.rs +++ b/src/symbols/npm.rs @@ -1,5 +1,5 @@ +use std::error::Error; use std::fmt; -use std::io; use command_runner::CommandRunner; use symbols::Symbol; @@ -25,13 +25,12 @@ impl<'a> fmt::Display for NpmInstall<'a> { } impl<'a> Symbol for NpmInstall<'a> { - type Error = io::Error; - fn target_reached(&self) -> Result { + fn target_reached(&self) -> Result> { let result = try!(self.command_runner.run_with_args("sh", &["-c", &format!("cd '{}' && npm ls", self.target)])); Ok(result.status.success() && !String::from_utf8(result.stdout).unwrap().contains("(empty)")) } - fn execute(&self) -> Result<(), Self::Error> { + fn execute(&self) -> Result<(), Box> { try!(self.command_runner.run_with_args("sh", &["-c", &format!("cd '{}' && npm install --production", self.target)])); Ok(()) } diff --git a/src/symbols/systemd/node_js_user_service.rs b/src/symbols/systemd/node_js_user_service.rs index 8e89bbd..4a19531 100644 --- a/src/symbols/systemd/node_js_user_service.rs +++ b/src/symbols/systemd/node_js_user_service.rs @@ -86,7 +86,7 @@ WantedBy=default.target } impl<'a, P, C> NodeJsSystemdUserService<'a, P, C> where P: AsRef + fmt::Display, C: Deref { - fn check_if_service(&self) -> Result::Error> { + fn check_if_service(&self) -> Result> { loop { // Check if service is registered let active_state = try!(self.command_runner.run_with_args("systemctl", &["--user", "show", "--property", "ActiveState", self.name])); @@ -97,7 +97,7 @@ impl<'a, P, C> NodeJsSystemdUserService<'a, P, C> where P: AsRef + fmt::Dis match String::from_utf8(active_state.stdout).unwrap().trim_right() { "ActiveState=activating" => sleep(Duration::from_millis(500)), "ActiveState=active" => return Ok(true), - "ActiveState=failed" => return Err(NodeJsSystemdUserServiceError::ActivationFailed(self.command_runner.run_with_args("journalctl", &["--user", &format!("--user-unit={}", self.name)]))), + "ActiveState=failed" => return Err(Box::new(NodeJsSystemdUserServiceError::ActivationFailed(self.command_runner.run_with_args("journalctl", &["--user", &format!("--user-unit={}", self.name)])) as NodeJsSystemdUserServiceError)), _ => return Ok(false) } } @@ -105,12 +105,11 @@ impl<'a, P, C> NodeJsSystemdUserService<'a, P, C> where P: AsRef + fmt::Dis } impl<'a, P, C> Symbol for NodeJsSystemdUserService<'a, P, C> where P: AsRef + fmt::Display, C: Deref { - type Error = NodeJsSystemdUserServiceError; - fn target_reached(&self) -> Result { + fn target_reached(&self) -> Result> { match self.file.target_reached() { Ok(false) => return Ok(false), Ok(true) => {}, - Err(e) => return Err(NodeJsSystemdUserServiceError::GenericError) + Err(e) => return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError)) } /* if !(try!(self.file.target_reached())) { @@ -120,7 +119,7 @@ impl<'a, P, C> Symbol for NodeJsSystemdUserService<'a, P, C> where P: AsRef self.check_if_service() } - fn execute(&self) -> Result<(), Self::Error> { + fn execute(&self) -> Result<(), Box> { try!(self.command_runner.run_with_args("mkdir", &["-p", &format!("{}/var", self.home)])); try!(self.command_runner.run_with_args("rm", &[&format!("{}/var/service.socket", self.home)])); @@ -129,12 +128,12 @@ impl<'a, P, C> Symbol for NodeJsSystemdUserService<'a, P, C> where P: AsRef // try!(create_dir_all(Path::new(&path).parent().unwrap())); match self.file.execute() { Ok(_) => {}, - Err(e) => return Err(NodeJsSystemdUserServiceError::GenericError) + Err(e) => return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError)) } try!(self.command_runner.run_with_args("systemctl", &["--user", "enable", self.name])); try!(self.command_runner.run_with_args("systemctl", &["--user", "start", self.name])); - if !(try!(self.check_if_service())) { return Err(NodeJsSystemdUserServiceError::GenericError); } + if !(try!(self.check_if_service())) { return Err(Box::new(NodeJsSystemdUserServiceError::GenericError as NodeJsSystemdUserServiceError)); } let file_name = format!("{}/var/service.socket", self.home); // try!(self.command_runner.run_with_args("chmod", &["666", &file_name])); diff --git a/src/symbols/systemd/user_session.rs b/src/symbols/systemd/user_session.rs index d705782..7f97f67 100644 --- a/src/symbols/systemd/user_session.rs +++ b/src/symbols/systemd/user_session.rs @@ -49,21 +49,20 @@ impl<'a> SystemdUserSession<'a> { } impl<'a> Symbol for SystemdUserSession<'a> { - type Error = SystemdUserSessionError; - fn target_reached(&self) -> Result { + fn target_reached(&self) -> Result> { let mut path = PathBuf::from("/var/lib/systemd/linger"); path.push(self.user_name); Ok(path.exists()) // Could also do `loginctl show-user ${self.user_name} | grep -F 'Linger=yes` } - fn execute(&self) -> Result<(), Self::Error> { + fn execute(&self) -> Result<(), Box> { match self.command_runner.run_with_args("loginctl", &["enable-linger", self.user_name]) { Ok(output) => { println!("{:?} {:?}", from_utf8(&output.stdout).unwrap(), from_utf8(&output.stderr).unwrap() ); match output.status.code() { Some(0) => Ok(()), - _ => Err(SystemdUserSessionError::GenericError) + _ => Err(Box::new(SystemdUserSessionError::GenericError as SystemdUserSessionError)) } }, - Err(e) => Err(SystemdUserSessionError::ExecError(e)) + Err(e) => Err(Box::new(SystemdUserSessionError::ExecError(e))) } } } diff --git a/src/symbols/user.rs b/src/symbols/user.rs index c397824..eaa8252 100644 --- a/src/symbols/user.rs +++ b/src/symbols/user.rs @@ -43,27 +43,24 @@ pub trait UserAdder { } #[derive(Debug, PartialEq)] -pub enum UserError { - GenericError, - ExecError(E) +pub enum UserError { + GenericError } -impl Error for UserError { +impl Error for UserError { fn description(&self) -> &str { match self { - &UserError::GenericError => "Could not find out if user exists", - &UserError::ExecError(_) => "Error executing symbol" + &UserError::GenericError => "Could not find out if user exists" } } fn cause(&self) -> Option<&Error> { match self { - &UserError::ExecError(ref e) => Some(e), _ => None } } } -impl fmt::Display for UserError { +impl fmt::Display for UserError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.cause() { Some(e) => write!(f, "{} (cause: {})", self.description(), e), @@ -94,22 +91,21 @@ impl<'a, E: Error, A: UserAdder> fmt::Display for User<'a, E, A> { } } -impl<'a, E: Error, A: UserAdder> Symbol for User<'a, E, A> { - type Error = UserError>; - fn target_reached(&self) -> Result { +impl<'a, E: 'static + Error, A: UserAdder> Symbol for User<'a, E, A> { + fn target_reached(&self) -> Result> { let output = self.command_runner.run_with_args("getent", &["passwd", self.user_name]); match output { Ok(output) => match output.status.code() { Some(2) => Ok(false), Some(0) => Ok(true), - _ => Err(UserError::GenericError) + _ => Err(Box::new(UserError::GenericError)) }, - Err(_) => Err(UserError::GenericError) + Err(e) => Err(Box::new(e)) } } - fn execute(&self) -> Result<(), Self::Error> { - self.user_adder.add_user(self.user_name).map_err(|e| UserError::ExecError(e)) + fn execute(&self) -> Result<(), Box> { + self.user_adder.add_user(self.user_name).map_err(|e| Box::new(e) as Box) } } @@ -192,12 +188,12 @@ mod test { #[test] fn test_target_reached_nonexisting() { let symbol = User { user_name: "nonexisting", command_runner: &StdCommandRunner, user_adder: &DummyUserAdder }; - assert_eq!(symbol.target_reached(), Ok(false)); + assert_eq!(symbol.target_reached().unwrap(), false); } #[test] fn test_target_reached_root() { let symbol = User { user_name: "root", command_runner: &StdCommandRunner, user_adder: &DummyUserAdder }; - assert_eq!(symbol.target_reached(), Ok(true)); + assert_eq!(symbol.target_reached().unwrap(), true); } }