summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/resolve.rs67
-rw-r--r--src/types.rs4
2 files changed, 68 insertions, 3 deletions
diff --git a/src/resolve.rs b/src/resolve.rs
index 14294d1..a01f5c5 100644
--- a/src/resolve.rs
+++ b/src/resolve.rs
@@ -64,6 +64,62 @@ enum ResolveState {
Resolved,
}
+pub fn runtime_depends<'a, I>(
+ tasks: &'a TaskMap,
+ deps: I,
+) -> Result<HashSet<&'a OutputRef>, Vec<Error>>
+where
+ I: IntoIterator<Item = &'a OutputRef>,
+{
+ fn add_dep<'a>(
+ ret: &mut HashSet<&'a OutputRef>,
+ tasks: &'a TaskMap,
+ dep: &'a OutputRef,
+ ) -> Vec<Error> {
+ if !ret.insert(dep) {
+ return Vec::new();
+ }
+
+ let task = &dep.task;
+ let task_def = match tasks.get(&task.id) {
+ Some(task) => task,
+ None => return vec![Error::TaskNotFound(DepChain(vec![task.clone()]))],
+ };
+
+ let output = match task_def.output.get(&dep.output) {
+ Some(output) => output,
+ None => {
+ return vec![Error::OutputNotFound(
+ DepChain(vec![task.clone()]),
+ dep.output.clone(),
+ )];
+ }
+ };
+
+ let mut errors = Vec::new();
+ for runtime_dep in &output.runtime_depends {
+ for mut error in add_dep(ret, tasks, runtime_dep) {
+ error.extend(task.clone());
+ errors.push(error);
+ }
+ }
+ errors
+ }
+
+ let mut ret = HashSet::new();
+ let mut errors = Vec::new();
+
+ for dep in deps {
+ errors.extend(add_dep(&mut ret, tasks, dep));
+ }
+
+ if !errors.is_empty() {
+ return Err(errors);
+ }
+
+ Ok(ret)
+}
+
#[derive(Debug)]
pub struct Resolver<'a> {
tasks: &'a TaskMap,
@@ -122,8 +178,15 @@ impl<'a> Resolver<'a> {
handle_errors(self.add_task(inherit, None));
}
- for dep in task_def.get_depend_outputs() {
- handle_errors(self.add_task(&dep.task, Some(&dep.output)));
+ match runtime_depends(self.tasks, task_def.get_depend_outputs()) {
+ Ok(rdeps) => {
+ for rdep in rdeps {
+ handle_errors(self.add_task(&rdep.task, Some(&rdep.output)));
+ }
+ }
+ Err(errors) => {
+ handle_errors(errors);
+ }
}
if ret.is_empty() {
diff --git a/src/types.rs b/src/types.rs
index af0fb92..0b85393 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -1,7 +1,7 @@
use serde::{Deserialize, Serialize};
use sha2::Sha256;
use std::{
- collections::{HashMap, HashSet},
+ collections::{BTreeSet, HashMap, HashSet},
fmt::Display,
};
@@ -107,6 +107,8 @@ fn default_output_name() -> String {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Output {
pub path: Option<String>,
+ #[serde(default)]
+ pub runtime_depends: BTreeSet<OutputRef>,
}
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]