swh_graph/stdlib/
root_directory.rs1use anyhow::{bail, ensure, Result};
7
8use crate::graph::*;
9use crate::properties;
10use crate::NodeType;
11
12pub fn find_root_dir<G>(graph: &G, node: NodeId) -> Result<Option<NodeId>>
18where
19 G: SwhForwardGraph + SwhGraphWithProperties,
20 <G as SwhGraphWithProperties>::Maps: properties::Maps,
21{
22 match graph.properties().node_type(node) {
23 NodeType::Release => find_root_dir_from_rel(graph, node),
24 NodeType::Revision => find_root_dir_from_rev(graph, node),
25 ty => bail!("Expected node type release or revision, but got {ty} instead."),
26 }
27}
28
29fn find_root_dir_from_rel<G>(graph: &G, rel_id: NodeId) -> Result<Option<NodeId>>
30where
31 G: SwhForwardGraph + SwhGraphWithProperties,
32 <G as SwhGraphWithProperties>::Maps: properties::Maps,
33{
34 let props = graph.properties();
35 let rel_swhid = props.swhid(rel_id);
36
37 let mut root_dir = None;
38 let mut root_rev = None;
39 for succ in graph.successors(rel_id) {
40 let node_type = props.node_type(succ);
41 match node_type {
42 NodeType::Directory => {
43 ensure!(
44 root_dir.is_none(),
45 "{rel_swhid} has more than one directory successor",
46 );
47 root_dir = Some(succ);
48 }
49 NodeType::Revision => {
50 ensure!(
51 root_rev.is_none(),
52 "{rel_swhid} has more than one revision successor",
53 );
54 root_rev = Some(succ);
55 }
56 _ => (),
57 }
58 }
59
60 match (root_dir, root_rev) {
61 (Some(_), Some(_)) => {
62 bail!("{rel_swhid} has both a directory and a revision as successors",)
63 }
64 (None, Some(root_rev)) => {
65 let mut root_dir = None;
66 for succ in graph.successors(root_rev) {
67 if graph.properties().node_type(succ) == NodeType::Directory {
68 let rev_swhid = graph.properties().swhid(succ);
69 ensure!(
70 root_dir.is_none(),
71 "{rel_swhid} (via {rev_swhid}) has more than one directory successor",
72 );
73 root_dir = Some(succ);
74 }
75 }
76 Ok(root_dir)
77 }
78 (Some(root_dir), None) => Ok(Some(root_dir)),
79 (None, None) => Ok(None),
80 }
81}
82
83fn find_root_dir_from_rev<G>(graph: &G, rev_id: NodeId) -> Result<Option<NodeId>>
84where
85 G: SwhForwardGraph + SwhGraphWithProperties,
86 <G as SwhGraphWithProperties>::Maps: properties::Maps,
87{
88 let mut root_dir = None;
89 let props = graph.properties();
90 for succ in graph.successors(rev_id) {
91 let node_type = props.node_type(succ);
92 if node_type == NodeType::Directory {
93 let rev_swhid = props.swhid(succ);
94 ensure!(
95 root_dir.is_none(),
96 "{rev_swhid} has more than one directory successor",
97 );
98 root_dir = Some(succ);
99 }
100 }
101
102 Ok(root_dir)
103}