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.

213 lines
5.1 KiB

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