summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-01-27 18:08:55 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-01-27 18:08:55 +0100
commit81fccdc0ec42a97f8c3e4fa905af7759742a73f9 (patch)
treee028598e57cd09882d5da1de0ed3ce2a2426adff /src
parentb20fb6f26e14bcd21266e9436d72d94b84978dce (diff)
downloadrebel-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.rs9
-rw-r--r--src/resolve.rs71
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);
}
}