1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use petgraph::{
algo::{toposort, Cycle},
graphmap::DiGraphMap,
};
use serde::Deserialize;
use std::borrow::Cow;
#[derive(Debug, Deserialize)]
pub struct TemplateConfig<'a> {
#[serde(borrow)]
pub features: Vec<Feature<'a>>,
}
impl<'a> TemplateConfig<'a> {
pub fn do_topological_sort_of_features(&self) -> Result<Vec<&str>, Cycle<&str>> {
let mut g = DiGraphMap::new();
for feature in &self.features {
g.add_node(feature.name);
if let Some(include) = &feature.include {
for workflow in include {
g.add_edge(feature.name, workflow, 1);
}
}
}
toposort(&g, None)
}
pub fn feature(&self, name: &str) -> Option<&Feature<'a>> {
self.features.iter().find(|&f| f.name == name)
}
}
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)]
pub struct Feature<'a> {
pub name: &'a str,
#[serde(borrow)]
pub files: Option<Vec<&'a str>>,
pub include: Option<Vec<&'a str>>,
}
impl<'a> Feature<'a> {
pub fn files_to_include(&self) -> Vec<&'a str> {
let mut vec = Vec::new();
if let Some(files) = &self.files {
vec.extend(files);
}
vec
}
pub fn get_features_for_feature<'b>(
&'b self,
all_features: &'b [&'b Feature<'b>],
) -> Cow<'b, [&'b Feature<'b>]> {
if let Some(includes) = &self.include {
println!("{} includes: {:?}", self.name, self.include);
let features_part_of_this_feature = all_features
.iter()
.filter(|feat| includes.contains(&feat.name))
.copied()
.collect::<Vec<_>>();
println!("first: {:?}", &features_part_of_this_feature);
let mut features = Vec::new();
for &feat in features_part_of_this_feature.iter() {
println!("recursive call for {}", feat.name);
let f = feat.get_features_for_feature(all_features);
println!("after recursive call: {:?}", f);
match f {
Cow::Owned(feature_vec) => {
println!("owned");
features.extend(feature_vec.into_iter());
println!("features: {:?}", &features);
}
Cow::Borrowed(feature_slice) => {
println!("borrowed");
features.extend(feature_slice.iter().copied());
println!("features: {:?}", &features);
}
}
println!("features after match: {:?}", &features);
}
features.push(self);
return Cow::Owned(features);
}
let self_index = all_features
.iter()
.position(|feat| feat.name == self.name)
.unwrap();
println!("index: {}", self_index);
println!("Returning self index");
let value = &all_features[self_index..=self_index];
println!("value: {:?}", &value);
Cow::Borrowed(value)
}
}