A library for writing host-specific, single-binary configuration management and deployment tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
4.7 KiB

7 years ago
7 years ago
7 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
6 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
5 years ago
5 years ago
7 years ago
5 years ago
7 years ago
7 years ago
7 years ago
7 years ago
5 years ago
7 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
7 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
5 years ago
5 years ago
7 years ago
5 years ago
7 years ago
5 years ago
5 years ago
5 years ago
7 years ago
5 years ago
7 years ago
  1. use std::error::Error;
  2. use std::fmt;
  3. use resources::Resource;
  4. use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  5. pub struct Hook<A, B>
  6. where
  7. A: Symbol,
  8. B: Symbol,
  9. {
  10. a: A,
  11. b: B,
  12. }
  13. // A and B are executed if either A or B are not reached
  14. impl<A, B> Hook<A, B>
  15. where
  16. A: Symbol,
  17. B: Symbol,
  18. {
  19. pub fn new(a: A, b: B) -> Self {
  20. Hook { a, b }
  21. }
  22. }
  23. impl<A, B> Symbol for Hook<A, B>
  24. where
  25. A: Symbol,
  26. B: Symbol,
  27. {
  28. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  29. self.a.target_reached().and_then(|reached| {
  30. if reached {
  31. self.b.target_reached()
  32. } else {
  33. Ok(reached)
  34. }
  35. })
  36. }
  37. fn execute(&self) -> Result<(), Box<dyn Error>> {
  38. try!(self.a.execute());
  39. self.b.execute()
  40. }
  41. fn get_prerequisites(&self) -> Vec<Resource> {
  42. let mut r = vec![];
  43. r.extend(self.a.get_prerequisites().into_iter());
  44. r.extend(self.b.get_prerequisites().into_iter());
  45. r
  46. }
  47. fn provides(&self) -> Option<Vec<Resource>> {
  48. let mut r = vec![];
  49. if let Some(provides) = self.a.provides() {
  50. r.extend(provides.into_iter());
  51. }
  52. if let Some(provides) = self.b.provides() {
  53. r.extend(provides.into_iter());
  54. }
  55. if r.is_empty() {
  56. None
  57. } else {
  58. Some(r)
  59. }
  60. }
  61. fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box<dyn Action + 'a> {
  62. Box::new(SymbolAction::new(runner, self))
  63. }
  64. fn into_action<'a>(self: Box<Self>, runner: &'a dyn SymbolRunner) -> Box<dyn Action + 'a>
  65. where
  66. Self: 'a,
  67. {
  68. Box::new(OwnedSymbolAction::new(runner, *self))
  69. }
  70. }
  71. impl<A, B> fmt::Display for Hook<A, B>
  72. where
  73. A: Symbol,
  74. B: Symbol,
  75. {
  76. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
  77. write!(f, "Hook {} and then {}", self.a, self.b)
  78. }
  79. }
  80. #[cfg(test)]
  81. mod test {
  82. use std::error::Error;
  83. use std::fmt;
  84. use symbols::hook::Hook;
  85. use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
  86. struct ErrSymbol(String);
  87. impl Symbol for ErrSymbol {
  88. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  89. Err(self.0.clone().into())
  90. }
  91. fn execute(&self) -> Result<(), Box<dyn Error>> {
  92. Err(self.0.clone().into())
  93. }
  94. fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box<dyn Action + 'a> {
  95. Box::new(SymbolAction::new(runner, self))
  96. }
  97. fn into_action<'a>(self: Box<Self>, runner: &'a dyn SymbolRunner) -> Box<dyn Action + 'a>
  98. where
  99. Self: 'a,
  100. {
  101. Box::new(OwnedSymbolAction::new(runner, *self))
  102. }
  103. }
  104. impl fmt::Display for ErrSymbol {
  105. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
  106. write!(f, "")
  107. }
  108. }
  109. struct OkSymbol(bool);
  110. impl Symbol for OkSymbol {
  111. fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  112. Ok(self.0)
  113. }
  114. fn execute(&self) -> Result<(), Box<dyn Error>> {
  115. Ok(())
  116. }
  117. fn as_action<'a>(&'a self, runner: &'a dyn SymbolRunner) -> Box<dyn Action + 'a> {
  118. Box::new(SymbolAction::new(runner, self))
  119. }
  120. fn into_action<'a>(self: Box<Self>, runner: &'a dyn SymbolRunner) -> Box<dyn Action + 'a>
  121. where
  122. Self: 'a,
  123. {
  124. Box::new(OwnedSymbolAction::new(runner, *self))
  125. }
  126. }
  127. impl fmt::Display for OkSymbol {
  128. fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
  129. write!(f, "")
  130. }
  131. }
  132. #[test]
  133. fn first_target_reached_fails() {
  134. let res = Hook::new(ErrSymbol("first".into()), ErrSymbol("second".into())).target_reached();
  135. assert_eq!(res.unwrap_err().description(), "first");
  136. }
  137. #[test]
  138. fn first_target_not_reached() {
  139. let res = Hook::new(OkSymbol(false), ErrSymbol("second".into())).target_reached();
  140. assert_eq!(res.unwrap(), false);
  141. }
  142. #[test]
  143. fn second_target_reached_fails() {
  144. let res = Hook::new(OkSymbol(true), ErrSymbol("second".into())).target_reached();
  145. assert_eq!(res.unwrap_err().description(), "second");
  146. }
  147. #[test]
  148. fn second_target_not_reached() {
  149. let res = Hook::new(OkSymbol(true), OkSymbol(false)).target_reached();
  150. assert_eq!(res.unwrap(), false);
  151. }
  152. #[test]
  153. fn everything_reached() {
  154. let res = Hook::new(OkSymbol(true), OkSymbol(true)).target_reached();
  155. assert_eq!(res.unwrap(), true);
  156. }
  157. #[test]
  158. fn first_execute_fails() {
  159. let res = Hook::new(ErrSymbol("first".into()), ErrSymbol("second".into())).execute();
  160. assert_eq!(res.unwrap_err().description(), "first");
  161. }
  162. #[test]
  163. fn second_execute_fails() {
  164. let res = Hook::new(OkSymbol(true), ErrSymbol("second".into())).execute();
  165. assert_eq!(res.unwrap_err().description(), "second");
  166. }
  167. #[test]
  168. fn everything_executes() {
  169. let res = Hook::new(OkSymbol(true), OkSymbol(true)).execute();
  170. assert_eq!(res.unwrap(), ());
  171. }
  172. }