dag: Accept multiple roots in `fold`, remove depth
This allows the fold to start anywhere in our DAG.
This commit is contained in:
parent
5c256c8bfb
commit
f760b1153f
|
|
@ -91,7 +91,7 @@ impl ChangeGraph {
|
||||||
let manifest = root_node.manifest.clone();
|
let manifest = root_node.manifest.clone();
|
||||||
let graph = self
|
let graph = self
|
||||||
.graph
|
.graph
|
||||||
.fold(&root, Dag::new(), |mut graph, _, change, _| {
|
.fold(&[root], Dag::new(), |mut graph, _, change| {
|
||||||
// Check the change signatures are valid.
|
// Check the change signatures are valid.
|
||||||
if !change.valid_signatures() {
|
if !change.valid_signatures() {
|
||||||
return ControlFlow::Break(graph);
|
return ControlFlow::Break(graph);
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ impl History {
|
||||||
F: for<'r> FnMut(A, &'r EntryId, &'r Entry) -> ControlFlow<A, A>,
|
F: for<'r> FnMut(A, &'r EntryId, &'r Entry) -> ControlFlow<A, A>,
|
||||||
{
|
{
|
||||||
self.graph
|
self.graph
|
||||||
.fold(&self.root, init, |acc, k, v, _| f(acc, k, v))
|
.fold(&[self.root], init, |acc, k, v| f(acc, k, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a topologically-sorted list of history entries.
|
/// Return a topologically-sorted list of history entries.
|
||||||
|
|
|
||||||
|
|
@ -187,21 +187,21 @@ impl<K: Ord + Copy, V> Dag<K, V> {
|
||||||
///
|
///
|
||||||
/// To continue traversing a branch, return [`ControlFlow::Continue`] from the
|
/// To continue traversing a branch, return [`ControlFlow::Continue`] from the
|
||||||
/// filter function. To stop traversal of a branch, return [`ControlFlow::Break`].
|
/// filter function. To stop traversal of a branch, return [`ControlFlow::Break`].
|
||||||
pub fn fold<A, F>(&self, root: &K, mut acc: A, mut filter: F) -> A
|
pub fn fold<A, F>(&self, roots: &[K], mut acc: A, mut filter: F) -> A
|
||||||
where
|
where
|
||||||
F: for<'r> FnMut(A, &'r K, &'r Node<K, V>, usize) -> ControlFlow<A, A>,
|
F: for<'r> FnMut(A, &'r K, &'r Node<K, V>) -> ControlFlow<A, A>,
|
||||||
{
|
{
|
||||||
let mut visited = BTreeSet::new();
|
let mut visited = BTreeSet::new();
|
||||||
let mut queue = VecDeque::<(K, usize)>::from([(*root, 0)]);
|
let mut queue = VecDeque::<K>::from_iter(roots.iter().cloned());
|
||||||
|
|
||||||
while let Some((next, depth)) = queue.pop_front() {
|
while let Some(next) = queue.pop_front() {
|
||||||
if !visited.insert(next) {
|
if !visited.insert(next) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(node) = self.graph.get(&next) {
|
if let Some(node) = self.graph.get(&next) {
|
||||||
match filter(acc, &next, node, depth) {
|
match filter(acc, &next, node) {
|
||||||
ControlFlow::Continue(a) => {
|
ControlFlow::Continue(a) => {
|
||||||
queue.extend(node.dependents.iter().map(|k| (*k, depth + 1)));
|
queue.extend(node.dependents.iter().cloned());
|
||||||
acc = a;
|
acc = a;
|
||||||
}
|
}
|
||||||
ControlFlow::Break(a) => {
|
ControlFlow::Break(a) => {
|
||||||
|
|
@ -497,59 +497,13 @@ mod tests {
|
||||||
dag.dependency("C1", "B2");
|
dag.dependency("C1", "B2");
|
||||||
dag.dependency("C1", "B3");
|
dag.dependency("C1", "B3");
|
||||||
|
|
||||||
let acc = dag.fold(&"R", Vec::new(), |mut acc, key, _, _| {
|
let acc = dag.fold(&["R"], Vec::new(), |mut acc, key, _| {
|
||||||
acc.push(*key);
|
acc.push(*key);
|
||||||
ControlFlow::Continue(acc)
|
ControlFlow::Continue(acc)
|
||||||
});
|
});
|
||||||
assert_eq!(acc, vec!["R", "A1", "A2", "A3", "B1", "B2", "B3", "C1"]);
|
assert_eq!(acc, vec!["R", "A1", "A2", "A3", "B1", "B2", "B3", "C1"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_fold_depth() {
|
|
||||||
let mut dag = Dag::new();
|
|
||||||
|
|
||||||
dag.node("R", ());
|
|
||||||
dag.node("A1", ());
|
|
||||||
dag.node("A2", ());
|
|
||||||
dag.node("A3", ());
|
|
||||||
dag.node("B1", ());
|
|
||||||
dag.node("B2", ());
|
|
||||||
dag.node("B3", ());
|
|
||||||
dag.node("C1", ());
|
|
||||||
|
|
||||||
dag.dependency("A1", "R");
|
|
||||||
dag.dependency("A2", "R");
|
|
||||||
dag.dependency("A3", "R");
|
|
||||||
|
|
||||||
dag.dependency("B1", "A1");
|
|
||||||
dag.dependency("B2", "A1");
|
|
||||||
dag.dependency("B3", "A2");
|
|
||||||
dag.dependency("B3", "A3");
|
|
||||||
|
|
||||||
dag.dependency("C1", "B1");
|
|
||||||
dag.dependency("C1", "B2");
|
|
||||||
dag.dependency("C1", "B3");
|
|
||||||
|
|
||||||
let acc = dag.fold(&"R", Vec::new(), |mut acc, key, _, depth| {
|
|
||||||
acc.push((*key, depth));
|
|
||||||
ControlFlow::Continue(acc)
|
|
||||||
});
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
acc,
|
|
||||||
vec![
|
|
||||||
("R", 0),
|
|
||||||
("A1", 1),
|
|
||||||
("A2", 1),
|
|
||||||
("A3", 1),
|
|
||||||
("B1", 2),
|
|
||||||
("B2", 2),
|
|
||||||
("B3", 2),
|
|
||||||
("C1", 3)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fold_reject() {
|
fn test_fold_reject() {
|
||||||
let mut dag = Dag::new();
|
let mut dag = Dag::new();
|
||||||
|
|
@ -571,7 +525,7 @@ mod tests {
|
||||||
let a1 = dag.get(&"A1").unwrap();
|
let a1 = dag.get(&"A1").unwrap();
|
||||||
assert_eq!(dag.descendants_of(a1), vec!["B1", "C1", "D1"]);
|
assert_eq!(dag.descendants_of(a1), vec!["B1", "C1", "D1"]);
|
||||||
|
|
||||||
let acc = dag.fold(&"R", Vec::new(), |mut acc, key, accept, _| {
|
let acc = dag.fold(&["R"], Vec::new(), |mut acc, key, accept| {
|
||||||
if !accept.value {
|
if !accept.value {
|
||||||
ControlFlow::Break(acc)
|
ControlFlow::Break(acc)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue