diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-26 22:04:18 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-26 22:04:18 +0100 |
commit | e48108cdef9555565d0715f4b6f39228cfc45376 (patch) | |
tree | cc4d1bf88a2a7d407dda841108ea30778bece53d /src/main.rs | |
parent | 9e60d16555765a6cfc053798f56e5b914ea1834e (diff) | |
download | rebel-e48108cdef9555565d0715f4b6f39228cfc45376.tar rebel-e48108cdef9555565d0715f4b6f39228cfc45376.zip |
Rewrite dependency resolution to reuse solutions
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 84 |
1 files changed, 17 insertions, 67 deletions
diff --git a/src/main.rs b/src/main.rs index 8c5708f..b572afc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,88 +1,38 @@ -use im::{HashMap, HashSet}; -use std::{fmt, path::Path, rc::Rc}; +use std::collections::HashSet; +use std::path::Path; mod recipe; +mod resolve; +mod types; -#[derive(Debug)] -enum Error { - TaskNotFound(String), - DependencyCycle(String), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Error::TaskNotFound(id) => write!(f, "Task not found: {}", id), - Error::DependencyCycle(id) => write!(f, "DependencyCycle: {}", id), - } - } -} - -impl std::error::Error for Error {} - -type Result<T> = std::result::Result<T, Error>; - -#[derive(Default)] -struct Context { - tasks: HashMap<String, Rc<recipe::Task>>, -} - -impl Context { - fn collect_subtasks<'a>( - &'a self, - queued: &HashSet<&'a str>, - id: &str, - ) -> Result<HashSet<&'a str>> { - let (task_id, task) = match self.tasks.get_key_value(id) { - Some(t) => t, - None => { - return Err(Error::TaskNotFound(id.to_string())); - } - }; - - if queued.contains(id) { - return Err(Error::DependencyCycle(id.to_string())); - } - - let queued_sub = queued.update(task_id); - - let mut subtasks: HashSet<&'a str> = HashSet::new(); - subtasks.insert(task_id); - - for dep in &task.depends { - let deptasks = self.collect_subtasks(&queued_sub, dep)?; - subtasks = subtasks.union(deptasks); - } - - Ok(subtasks) - } - - fn collect_tasks(&self, id: &str) -> Result<HashSet<&str>> { - self.collect_subtasks(&HashSet::new(), id) - } -} +use resolve::Result; +use types::*; fn main() -> Result<()> { let recipes = recipe::read_recipes(Path::new("examples")).unwrap(); - let mut ctx = Context::default(); + let mut tasks: TaskMap = TaskMap::default(); for (recipe_name, recipe) in recipes { for (task_name, task) in recipe.tasks { let full_name = format!("{}:{}", recipe_name, task_name); - ctx.tasks.insert(full_name, Rc::new(task)); + tasks.0.insert(full_name, task); } } - let queue = ctx.collect_tasks("ls:build")?; - let (runnable, queued): (HashSet<&str>, HashSet<&str>) = queue + let mut rsv = resolve::Resolver::new(&tasks); + + rsv.add_goal(&"ls:build".to_string())?; + let taskset = rsv.to_taskset(); + + let (runnable, queued): (HashSet<TaskRef>, HashSet<TaskRef>) = taskset .into_iter() - .partition(|id| ctx.tasks.get(*id).unwrap().depends.is_empty()); + .partition(|id| tasks.get(id).unwrap().depends.is_empty()); for t in &runnable { - println!("Runnable: {} ({:?})", t, ctx.tasks.get(*t).unwrap().run); + println!("Runnable: {} ({:?})", t, tasks.get(t).unwrap().run); } for t in &queued { - println!("Queued: {} ({:?})", t, ctx.tasks.get(*t).unwrap().run); + println!("Queued: {} ({:?})", t, tasks.get(t).unwrap().run); } Ok(()) |