mk_lib/schema/
task_dependency.rs1use serde::Deserialize;
2
3use super::TaskContext;
4
5#[derive(Debug, Deserialize)]
9pub struct TaskDependencyArgs {
10 pub name: String,
12}
13
14#[derive(Debug, Deserialize)]
15#[serde(untagged)]
16pub enum TaskDependency {
17 String(String),
18 TaskDependency(Box<TaskDependencyArgs>),
19}
20
21impl TaskDependency {
22 pub fn run(&self, context: &TaskContext) -> anyhow::Result<()> {
23 match self {
24 TaskDependency::String(name) => self.execute(context, name),
25 TaskDependency::TaskDependency(args) => args.execute(context),
26 }
27 }
28
29 fn execute(&self, context: &TaskContext, task_name: &str) -> anyhow::Result<()> {
30 assert!(!task_name.is_empty());
31
32 let task = context
33 .task_root
34 .tasks
35 .get(task_name)
36 .ok_or_else(|| anyhow::anyhow!("Task not found"))?;
37
38 log::trace!("Task: {:?}", task);
39
40 {
41 let mut stack = context
42 .execution_stack
43 .lock()
44 .map_err(|e| anyhow::anyhow!("Failed to lock execution stack - {}", e))?;
45
46 if stack.contains(task_name) {
47 anyhow::bail!("Circular dependency detected - {}", task_name);
48 }
49
50 stack.insert(task_name.into());
51 }
52
53 let mut context = TaskContext::from_context(context);
54 task.run(&mut context)?;
55
56 Ok(())
57 }
58}
59
60impl TaskDependencyArgs {
61 pub fn execute(&self, context: &TaskContext) -> anyhow::Result<()> {
62 assert!(!self.name.is_empty());
63
64 let task_name: &str = &self.name;
65 let task = context
66 .task_root
67 .tasks
68 .get(task_name)
69 .ok_or_else(|| anyhow::anyhow!("Task not found"))?;
70
71 log::trace!("Task: {:?}", task);
72
73 {
74 let mut stack = context
75 .execution_stack
76 .lock()
77 .map_err(|e| anyhow::anyhow!("Failed to lock execution stack - {}", e))?;
78
79 if stack.contains(task_name) {
80 anyhow::bail!("Circular dependency detected - {}", task_name);
81 }
82
83 stack.insert(task_name.into());
84 }
85
86 let mut context = TaskContext::from_context(context);
87 task.run(&mut context)?;
88
89 Ok(())
90 }
91}
92
93#[cfg(test)]
94mod test {
95 use hashbrown::HashMap;
96 use std::sync::Arc;
97
98 use crate::schema::{
99 Task,
100 TaskRoot,
101 };
102
103 use super::*;
104
105 #[test]
106 fn test_task_dependency_1() -> anyhow::Result<()> {
107 let yaml = "
108 name: task1
109 ";
110
111 let task_dependency = serde_yaml::from_str::<TaskDependency>(yaml)?;
112 if let TaskDependency::TaskDependency(args) = task_dependency {
113 assert_eq!(args.name, "task1");
114 } else {
115 panic!("Expected TaskDependency::TaskDependency");
116 }
117
118 Ok(())
119 }
120
121 #[test]
122 fn test_task_dependency_2() -> anyhow::Result<()> {
123 let yaml = "\"task1\"";
124
125 let task_dependency = serde_yaml::from_str::<TaskDependency>(yaml)?;
126 if let TaskDependency::String(name) = task_dependency {
127 assert_eq!(name, "task1");
128 } else {
129 panic!("Expected TaskDependency::TaskString");
130 }
131
132 Ok(())
133 }
134
135 #[test]
136 fn test_task_dependency_3() -> anyhow::Result<()> {
137 let yaml = "\"\"";
138
139 let task_dependency = serde_yaml::from_str::<TaskDependency>(yaml)?;
140 if let TaskDependency::String(name) = task_dependency {
141 assert_eq!(name, "");
142 } else {
143 panic!("Expected TaskDependency::TaskString");
144 }
145
146 Ok(())
147 }
148
149 #[test]
150 fn test_task_dependency_4() -> anyhow::Result<()> {
151 let yaml = "
152 name:
153 ";
154
155 let task_dependency = serde_yaml::from_str::<TaskDependencyArgs>(yaml)?;
156 assert_eq!(task_dependency.name, "");
157
158 Ok(())
159 }
160
161 #[test]
162 fn test_task_dependency_5() -> anyhow::Result<()> {
163 let yaml = "
164 name: task_a
165 ";
166
167 let task_yaml = "
168 commands:
169 - command: echo 1
170 verbose: false
171 ";
172
173 let task = serde_yaml::from_str::<Task>(task_yaml)?;
174 let mut hm = HashMap::new();
175 hm.insert("task_a".into(), task);
176
177 let root = Arc::new(TaskRoot::from_hashmap(hm));
178 let task_dependency = serde_yaml::from_str::<TaskDependencyArgs>(yaml)?;
179 let result = task_dependency.execute(&TaskContext::empty_with_root(root));
180 assert!(result.is_ok());
181
182 Ok(())
183 }
184}