diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-24 19:27:26 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-24 19:27:26 +0100 |
commit | 9e60d16555765a6cfc053798f56e5b914ea1834e (patch) | |
tree | 0ba9b72df22a17c4dbd363d195a2f14417362c24 /src/main.rs | |
parent | 01e3de22a53d30f21a829bf5d7cebc45c4d61ea8 (diff) | |
download | rebel-9e60d16555765a6cfc053798f56e5b914ea1834e.tar rebel-9e60d16555765a6cfc053798f56e5b914ea1834e.zip |
Read tasks from files
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 144 |
1 files changed, 68 insertions, 76 deletions
diff --git a/src/main.rs b/src/main.rs index 98d1b8d..8c5708f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,96 +1,88 @@ -use std::collections::{HashMap, HashSet}; -// use std::io::{self, Write}; -use std::io; -// use std::process::Command; - -struct Task { - // action: String, - deps: Vec<String>, +use im::{HashMap, HashSet}; +use std::{fmt, path::Path, rc::Rc}; + +mod recipe; + +#[derive(Debug)] +enum Error { + TaskNotFound(String), + DependencyCycle(String), } -// impl Task { -// fn run(&self) -> io::Result<()> { -// let output = Command::new("sh").arg("-c").arg(&self.action).output()?; - -// let stdout = io::stdout(); -// let mut handle = stdout.lock(); -// handle.write_all(&output.stdout)?; - -// Ok(()) -// } -// } - -fn collect_subtasks<'a>( - queued: &HashSet<&'a str>, - tasks: &'a HashMap<String, Task>, - id: &str, -) -> io::Result<HashSet<&'a str>> { - let (task_id, task) = match tasks.get_key_value(id) { - Some(t) => t, - None => { - return Err(io::Error::new(io::ErrorKind::NotFound, "Task not found")); +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), } - }; - - if queued.contains(id) { - return Err(io::Error::new( - io::ErrorKind::InvalidData, - "Dependency cycle", - )); } +} + +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())); + } + }; - let mut queued_sub = queued.clone(); - queued_sub.insert(task_id); + 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); + let mut subtasks: HashSet<&'a str> = HashSet::new(); + subtasks.insert(task_id); - for dep in &task.deps { - let deptasks = collect_subtasks(&queued_sub, tasks, dep)?; - subtasks = subtasks.union(&deptasks).copied().collect(); + for dep in &task.depends { + let deptasks = self.collect_subtasks(&queued_sub, dep)?; + subtasks = subtasks.union(deptasks); + } + + Ok(subtasks) } - Ok(subtasks) + fn collect_tasks(&self, id: &str) -> Result<HashSet<&str>> { + self.collect_subtasks(&HashSet::new(), id) + } } -fn collect_tasks<'a>(tasks: &'a HashMap<String, Task>, id: &str) -> io::Result<HashSet<&'a str>> { - collect_subtasks(&HashSet::new(), tasks, id) -} +fn main() -> Result<()> { + let recipes = recipe::read_recipes(Path::new("examples")).unwrap(); + + let mut ctx = Context::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)); + } + } -fn main() -> io::Result<()> { - let mut tasks = HashMap::new(); - tasks.insert( - String::from("ls"), - Task { - // action: String::from("ls"), - deps: vec!["foo".to_owned(), "bar".to_owned()], - }, - ); - tasks.insert( - String::from("foo"), - Task { - // action: String::from("echo foo"), - deps: vec!["bar".to_owned()], - }, - ); - tasks.insert( - String::from("bar"), - Task { - // action: String::from("echo bar"), - deps: vec![], - }, - ); - - let queue = collect_tasks(&tasks, "ls")?; - let (runnable, queued) = queue + let queue = ctx.collect_tasks("ls:build")?; + let (runnable, queued): (HashSet<&str>, HashSet<&str>) = queue .into_iter() - .partition::<HashSet<_>, _>(|id| tasks.get(*id).unwrap().deps.is_empty()); + .partition(|id| ctx.tasks.get(*id).unwrap().depends.is_empty()); for t in &runnable { - println!("Runnable: {}", t); + println!("Runnable: {} ({:?})", t, ctx.tasks.get(*t).unwrap().run); } for t in &queued { - println!("Queued: {}", t); + println!("Queued: {} ({:?})", t, ctx.tasks.get(*t).unwrap().run); } Ok(()) |