diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-27 18:08:55 +0100 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2021-01-27 18:08:55 +0100 |
commit | 81fccdc0ec42a97f8c3e4fa905af7759742a73f9 (patch) | |
tree | e028598e57cd09882d5da1de0ed3ce2a2426adff /src | |
parent | b20fb6f26e14bcd21266e9436d72d94b84978dce (diff) | |
download | rebel-81fccdc0ec42a97f8c3e4fa905af7759742a73f9.tar rebel-81fccdc0ec42a97f8c3e4fa905af7759742a73f9.zip |
resolve: better error output
Show the whole dependency chain that led to an error.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 9 | ||||
-rw-r--r-- | src/resolve.rs | 71 |
2 files changed, 47 insertions, 33 deletions
diff --git a/src/main.rs b/src/main.rs index b572afc..5dfe079 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod types; use resolve::Result; use types::*; -fn main() -> Result<()> { +fn main() { let recipes = recipe::read_recipes(Path::new("examples")).unwrap(); let mut tasks: TaskMap = TaskMap::default(); @@ -21,7 +21,10 @@ fn main() -> Result<()> { let mut rsv = resolve::Resolver::new(&tasks); - rsv.add_goal(&"ls:build".to_string())?; + if let Result::Err(error) = rsv.add_goal(&"ls:build".to_string()) { + eprintln!("{}", error); + std::process::exit(1); + } let taskset = rsv.to_taskset(); let (runnable, queued): (HashSet<TaskRef>, HashSet<TaskRef>) = taskset @@ -34,6 +37,4 @@ fn main() -> Result<()> { for t in &queued { println!("Queued: {} ({:?})", t, tasks.get(t).unwrap().run); } - - Ok(()) } diff --git a/src/resolve.rs b/src/resolve.rs index ab2eef3..d7ce52d 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -5,22 +5,47 @@ use crate::types::*; #[derive(Debug)] pub enum Error { - TaskNotFound(TaskRef), - DependencyCycle { tasks: Vec<TaskRef>, complete: bool }, + TaskNotFound(Vec<TaskRef>), + DependencyCycle(Vec<TaskRef>), +} + +impl Error { + fn extend(&mut self, task: TaskRef) { + let tasks = match self { + Error::TaskNotFound(ref mut tasks) => tasks, + Error::DependencyCycle(ref mut tasks) => tasks, + }; + tasks.push(task); + } + + fn write_tasks(f: &mut fmt::Formatter, tasks: &Vec<TaskRef>) -> fmt::Result { + let mut first = true; + for task in tasks.iter().rev() { + if !first { + write!(f, " -> ")?; + } + write!(f, "{}", task)?; + + first = false; + } + + Ok(()) + } } 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 { tasks, complete } => { - write!(f, "Dependency Cycle: {:?}", tasks)?; - if !complete { - write!(f, " (incomplete)")?; - } - Ok(()) + let tasks = match self { + Error::TaskNotFound(tasks) => { + write!(f, "Task not found: ")?; + tasks } - } + Error::DependencyCycle(tasks) => { + write!(f, "Dependency Cycle: ")?; + tasks + } + }; + Error::write_tasks(f, tasks) } } @@ -50,17 +75,14 @@ impl<'a> Resolver<'a> { pub fn add_goal(&mut self, task: &TaskRef) -> Result<()> { match self.resolve_state.get(task) { Some(ResolveState::Resolving) => { - return Err(Error::DependencyCycle { - tasks: vec![task.clone()], - complete: false, - }) + return Err(Error::DependencyCycle(vec![task.clone()])) } Some(ResolveState::Resolved) => return Ok(()), None => (), } let task_def = match self.tasks.get(task) { - None => return Err(Error::TaskNotFound(task.clone())), + None => return Err(Error::TaskNotFound(vec![task.clone()])), Some(task_def) => task_def, }; @@ -68,22 +90,13 @@ impl<'a> Resolver<'a> { .insert(task.clone(), ResolveState::Resolving); for dep in &task_def.depends { - let mut res = self.add_goal(dep); - if let Err(ref mut error) = res { + let res = self.add_goal(dep); + if let Err(mut error) = res { self.resolve_state.remove(task); - if let Error::DependencyCycle { - ref mut tasks, - complete: ref mut complete @ false, - } = error - { - tasks.push(task.clone()); - if tasks[0] == task.as_str() { - *complete = true - } - } + error.extend(task.clone()); - return res; + return Err(error); } } |