From 73b2184d24306697d2bee393da52ad1538512ab2 Mon Sep 17 00:00:00 2001 From: Adrian Heine Date: Wed, 10 May 2017 14:21:51 +0200 Subject: [PATCH] Update --- src/repository.rs | 33 +++----------------------- src/schema.rs | 46 +++++++++++++++++++++++++++++++++---- src/symbols/dir.rs | 16 ++++++++++++- src/symbols/git/checkout.rs | 10 ++++++++ src/symbols/hook.rs | 11 +++++++++ src/symbols/list.rs | 20 ++++++++++++++++ src/symbols/mod.rs | 3 +++ src/symbols/user.rs | 5 ++++ 8 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/repository.rs b/src/repository.rs index c980ee0..6dfd8b6 100644 --- a/src/repository.rs +++ b/src/repository.rs @@ -1,5 +1,4 @@ -use std::cell::RefCell; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use symbols::Symbol; use resources::Resource; @@ -15,11 +14,11 @@ impl<'a, C> SymbolRepository<'a> for C where C: Fn(&Resource) -> Option { - repositories: HashMap<&'static str, Box>> + repositories: HashMap<&'a str, Box + 'a>> } impl<'a> DispatchingSymbolRepository<'a> { - pub fn new(repositories: HashMap<&'static str, Box>>) -> DispatchingSymbolRepository<'a> { + pub fn new(repositories: HashMap<&'a str, Box + 'a>>) -> Self { DispatchingSymbolRepository { repositories: repositories } } } @@ -29,29 +28,3 @@ impl<'a> SymbolRepository<'a> for DispatchingSymbolRepository<'a> { self.repositories.get(resource.get_type()).and_then(|repo| repo.get_symbol(resource)) } } - -use std::marker::PhantomData; - -pub struct NonRepeatingSymbolRepository<'a, R> where R: SymbolRepository<'a> { - upstream: R, - done: RefCell>, - d: PhantomData> -} - -impl<'a, R> NonRepeatingSymbolRepository<'a, R> where R: SymbolRepository<'a> { - pub fn new(repository: R) -> Self { - NonRepeatingSymbolRepository { upstream: repository, done: RefCell::new(HashSet::new()), d: PhantomData } - } -} - -impl<'a, R> SymbolRepository<'a> for NonRepeatingSymbolRepository<'a, R> where R: SymbolRepository<'a> { - fn get_symbol(&self, resource: &Resource) -> Option> { - let mut done = self.done.borrow_mut(); - if done.contains(&resource) { - None - } else { - done.insert(resource.clone()); - self.upstream.get_symbol(resource) - } - } -} diff --git a/src/schema.rs b/src/schema.rs index 894e3ef..f1f93da 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -100,15 +100,51 @@ impl<'a, R> SymbolRunner for ReportingSymbolRunner<'a, R> where R: SymbolRunner } } -pub struct RequirementsResolvingSymbolRunner<'s, R: 's + SymbolRunner, G: 's + SymbolRepository<'s>>(&'s R, &'s G); +use std::cell::RefCell; +use std::collections::HashSet; +use resources::Resource; -impl<'s, R, G> RequirementsResolvingSymbolRunner<'s, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { - pub fn new(symbol_runner: &'s R, symbol_repo: &'s G) -> Self { - RequirementsResolvingSymbolRunner(symbol_runner, symbol_repo) +pub struct NonRepeatingSymbolRunner<'a, R> where R: 'a + SymbolRunner { + upstream: &'a R, + done: RefCell> +} + +impl<'a, R> NonRepeatingSymbolRunner<'a, R> where R: SymbolRunner { + pub fn new(symbol_runner: &'a R) -> Self { + NonRepeatingSymbolRunner{ upstream: symbol_runner, done: RefCell::new(HashSet::new()) } + } +} + +impl<'a, R> SymbolRunner for NonRepeatingSymbolRunner<'a, R> where R: SymbolRunner { + fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box> + { + if let Some(resources) = symbol.provides() { + let mut done = self.done.borrow_mut(); + let mut has_to_run = false; + for resource in resources { + if !done.contains(&resource) { + has_to_run = true; + done.insert(resource.clone()); + } + } + if !has_to_run { + return Ok(()); + } + } + self.upstream.run_symbol(logger, &*symbol) + } +} +use std::marker::PhantomData; + +pub struct RequirementsResolvingSymbolRunner<'a, 's, R: 'a + SymbolRunner, G: 'a + SymbolRepository<'s>>(&'a R, &'a G, PhantomData>); + +impl<'a, 's, R, G> RequirementsResolvingSymbolRunner<'a, 's, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { + pub fn new(symbol_runner: &'a R, symbol_repo: &'a G) -> Self { + RequirementsResolvingSymbolRunner(symbol_runner, symbol_repo, PhantomData) } } -impl<'s, R, G> SymbolRunner for RequirementsResolvingSymbolRunner<'s, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { +impl<'a, 's, R, G> SymbolRunner for RequirementsResolvingSymbolRunner<'a, 's, R, G> where R: SymbolRunner, G: SymbolRepository<'s> { fn run_symbol(&self, logger: &mut Logger, symbol: &S) -> Result<(), Box> { for resource in symbol.get_prerequisites() { diff --git a/src/symbols/dir.rs b/src/symbols/dir.rs index 3624738..ed6cbba 100644 --- a/src/symbols/dir.rs +++ b/src/symbols/dir.rs @@ -2,7 +2,9 @@ use std::error::Error; use std::fmt; use std::fs; use std::io; +use std::path::Path; +use resources::Resource; use symbols::Symbol; pub struct Dir where D: AsRef + fmt::Display { @@ -34,7 +36,19 @@ impl Symbol for Dir where D: AsRef + fmt::Display { } fn execute(&self) -> Result<(), Box> { - fs::create_dir_all(self.path.as_ref()).map_err(|e| Box::new(e) as Box) + fs::create_dir(self.path.as_ref()).map_err(|e| Box::new(e) as Box) + } + + fn get_prerequisites(&self) -> Vec { + if let Some(parent) = Path::new(self.path.as_ref()).parent() { + vec![ Resource::new("dir", parent.to_string_lossy()) ] + } else { + vec![] + } + } + + fn provides(&self) -> Option> { + Some(vec![ Resource::new("dir", self.path.to_string()) ]) } } diff --git a/src/symbols/git/checkout.rs b/src/symbols/git/checkout.rs index 9fd5324..6fea070 100644 --- a/src/symbols/git/checkout.rs +++ b/src/symbols/git/checkout.rs @@ -1,8 +1,10 @@ use std::error::Error; use std::fmt; use std::io; +use std::path::Path; use command_runner::CommandRunner; +use resources::Resource; use symbols::Symbol; pub struct GitCheckout<'a> { @@ -67,6 +69,14 @@ impl<'a> Symbol for GitCheckout<'a> { try!(self._run_in_target_repo(&["merge", "FETCH_HEAD"])); Ok(()) } + + fn get_prerequisites(&self) -> Vec { + vec![ Resource::new("dir", Path::new(self.target).parent().unwrap().to_string_lossy()) ] + } + + fn provides(&self) -> Option> { + Some(vec![ Resource::new("dir", self.target.to_string()) ]) + } } #[cfg(test)] diff --git a/src/symbols/hook.rs b/src/symbols/hook.rs index 61b5618..cac23db 100644 --- a/src/symbols/hook.rs +++ b/src/symbols/hook.rs @@ -31,6 +31,17 @@ impl Symbol for Hook where A: Symbol, B: Symbol { r.extend(self.b.get_prerequisites().into_iter()); r } + + fn provides(&self) -> Option> { + let mut r = vec![]; + if let Some(provides) = self.a.provides() { + r.extend(provides.into_iter()); + } + if let Some(provides) = self.b.provides() { + r.extend(provides.into_iter()); + } + if r.len() > 0 { Some(r) } else { None } + } } impl fmt::Display for Hook where A: Symbol, B: Symbol { diff --git a/src/symbols/list.rs b/src/symbols/list.rs index 056a418..badc2ce 100644 --- a/src/symbols/list.rs +++ b/src/symbols/list.rs @@ -32,6 +32,26 @@ impl<'a> Symbol for List<'a> { } Ok(()) } + + fn get_prerequisites(&self) -> Vec { + let mut r = vec![]; + for symbol in &self.symbols { + for req in symbol.get_prerequisites() { + if self.provides().map_or(true, |p| !p.contains(&req)) { r.push(req) } + } + } + r + } + + fn provides(&self) -> Option> { + let mut r = vec![]; + for symbol in &self.symbols { + if let Some(provides) = symbol.provides() { + r.extend(provides.into_iter()); + } + } + if r.len() > 0 { Some(r) } else { None } + } } impl<'a> fmt::Display for List<'a> { diff --git a/src/symbols/mod.rs b/src/symbols/mod.rs index b697443..13776da 100644 --- a/src/symbols/mod.rs +++ b/src/symbols/mod.rs @@ -8,6 +8,9 @@ pub trait Symbol: Display { fn get_prerequisites(&self) -> Vec { vec![] } + fn provides(&self) -> Option> { + None + } } pub mod acme; diff --git a/src/symbols/user.rs b/src/symbols/user.rs index 998790d..7342d77 100644 --- a/src/symbols/user.rs +++ b/src/symbols/user.rs @@ -4,6 +4,7 @@ use std::fmt; use std::io::Error as IoError; use command_runner::CommandRunner; +use resources::Resource; use symbols::Symbol; #[derive(Debug, PartialEq)] @@ -108,6 +109,10 @@ impl<'a, E: 'static + Error, A: UserAdder> Symbol for User<'a, E, A> { fn execute(&self) -> Result<(), Box> { self.user_adder.add_user(&*self.user_name).map_err(|e| Box::new(e) as Box) } + + fn provides(&self) -> Option> { + Some(vec![Resource::new("user", self.user_name.to_string())]) + } } pub struct SystemUserAdder<'a> {