From a4d7f4cad88472dbcf5b4dd433cfef5f9624d7e8 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 4 Apr 2024 20:04:30 +0200 Subject: driver: resolve: limit number of reported errors Reporting all dependency cycles may lead to a large number of errors in some cases, resulting in a long wait just for collecting the error data. --- crates/driver/src/resolve.rs | 59 ++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/crates/driver/src/resolve.rs b/crates/driver/src/resolve.rs index d03f26d..c13fcd2 100644 --- a/crates/driver/src/resolve.rs +++ b/crates/driver/src/resolve.rs @@ -7,7 +7,7 @@ use common::types::TaskID; use crate::args::TaskArgs; use crate::context::{self, Context, OutputRef, TaskRef}; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct DepChain<'ctx>(pub Vec>); impl<'ctx> fmt::Display for DepChain<'ctx> { @@ -48,11 +48,14 @@ impl<'ctx> From<&'ctx TaskID> for DepChain<'ctx> { } } +const MAX_ERRORS: usize = 100; + #[derive(Debug)] pub enum ErrorKind<'ctx> { Context(context::Error<'ctx>), OutputNotFound(&'ctx str), DependencyCycle, + TooManyErrors, } #[derive(Debug)] @@ -76,6 +79,13 @@ impl<'ctx> Error<'ctx> { } } + fn too_many_errors() -> Self { + Error { + dep_chain: DepChain::default(), + kind: ErrorKind::TooManyErrors, + } + } + fn extend(&mut self, task: &TaskRef<'ctx>) { self.dep_chain.0.push(task.clone()); } @@ -94,6 +104,9 @@ impl<'ctx> fmt::Display for Error<'ctx> { ErrorKind::DependencyCycle => { write!(f, "Dependency Cycle: ")?; } + ErrorKind::TooManyErrors => { + write!(f, "Too many errors, stopping.")?; + } } dep_chain.fmt(f) } @@ -254,33 +267,43 @@ impl<'ctx> Resolver<'ctx> { .insert(task.clone(), ResolveState::Resolving); let mut ret = Vec::new(); - let mut handle_errors = |errors: Vec>| { + let mut handle_errors = |errors: Vec>| -> Result<(), ()> { for mut error in errors { error.extend(task); ret.push(error); + + if ret.len() > MAX_ERRORS { + ret.push(Error::too_many_errors()); + return Err(()); + } } + Ok(()) }; - match self.ctx.get_inherit_depend(task) { - Ok(Some(inherit)) => { - handle_errors(self.add_task(&inherit, None)); - } - Ok(None) => {} - Err(err) => { - handle_errors(vec![err.into()]); + let _ = (|| -> Result<(), ()> { + match self.ctx.get_inherit_depend(task) { + Ok(Some(inherit)) => { + handle_errors(self.add_task(&inherit, None))?; + } + Ok(None) => {} + Err(err) => { + handle_errors(vec![err.into()])?; + } } - } - match get_dependent_outputs(self.ctx, task) { - Ok(rdeps) => { - for rdep in rdeps { - handle_errors(self.add_task(&rdep.task, Some(rdep.output))); + match get_dependent_outputs(self.ctx, task) { + Ok(rdeps) => { + for rdep in rdeps { + handle_errors(self.add_task(&rdep.task, Some(rdep.output)))?; + } + } + Err(errors) => { + handle_errors(errors)?; } } - Err(errors) => { - handle_errors(errors); - } - } + + Ok(()) + })(); if ret.is_empty() { *self -- cgit v1.2.3