1use anyhow::{ensure, Result};
9
10use swh_graph::graph::*;
11use swh_graph::labels::{EdgeLabel, LabelNameId};
12use swh_graph::properties;
13use swh_graph::NodeType;
14
15pub const HEAD_REF_NAMES: [&str; 2] = ["refs/heads/main", "refs/heads/master"];
19
20pub fn find_head_rev<G>(graph: &G, snp: NodeId) -> Result<Option<NodeId>>
23where
24 G: SwhLabeledForwardGraph + SwhGraphWithProperties,
25 <G as SwhGraphWithProperties>::LabelNames: properties::LabelNames,
26 <G as SwhGraphWithProperties>::Maps: properties::Maps,
27{
28 let props = graph.properties();
29 let head_ref_name_ids: Vec<LabelNameId> = HEAD_REF_NAMES
30 .into_iter()
31 .filter_map(|name| props.label_name_id(name.as_bytes()).ok())
32 .collect();
36 find_head_rev_by_refs(graph, snp, &head_ref_name_ids)
37}
38
39pub fn find_head_rev_by_refs<G>(
48 graph: &G,
49 snp: NodeId,
50 ref_name_ids: &[LabelNameId],
51) -> Result<Option<NodeId>>
52where
53 G: SwhLabeledForwardGraph + SwhGraphWithProperties,
54 <G as SwhGraphWithProperties>::Maps: properties::Maps,
55 <G as SwhGraphWithProperties>::LabelNames: properties::LabelNames,
56{
57 let props = graph.properties();
58 let node_type = props.node_type(snp);
59 ensure!(
60 node_type == NodeType::Snapshot,
61 "Type of {snp} should be snp, but is {node_type} instead"
62 );
63 for (succ, labels) in graph.labeled_successors(snp) {
64 let node_type = props.node_type(succ);
65 if node_type != NodeType::Revision && node_type != NodeType::Release {
66 continue;
67 }
68 for label in labels {
69 if let EdgeLabel::Branch(branch) = label {
70 if ref_name_ids.contains(&branch.label_name_id()) {
71 return Ok(Some(succ));
72 }
73 }
74 }
75 }
76 Ok(None)
77}