Skip to main content

swh_graph_stdlib/
lib.rs

1// Copyright (C) 2024-2026  The Software Heritage developers
2// See the AUTHORS file at the top-level directory of this distribution
3// License: GNU General Public License version 3, or any later version
4// See top-level LICENSE file for more information
5
6//! Standard library to work on Software Heritage compressed graph in Rust
7
8use anyhow::{Result, ensure};
9
10use swh_graph::NodeType;
11use swh_graph::graph::*;
12use swh_graph::labels::{EdgeLabel, VisitStatus};
13use swh_graph::properties;
14
15/// Given a graph and an origin node in it, return the node id and timestamp
16/// (as a number of seconds since Epoch) of the most recent snapshot of that
17/// origin, if it exists.
18///
19/// Note: only visit with status `Full` are considered when selecting
20/// snapshots.
21pub fn find_latest_snp<G>(graph: &G, ori: NodeId) -> Result<Option<(NodeId, u64)>>
22where
23    G: SwhLabeledForwardGraph + SwhGraphWithProperties,
24    <G as SwhGraphWithProperties>::Maps: properties::Maps,
25{
26    let props = graph.properties();
27    let node_type = props.node_type(ori);
28    ensure!(
29        node_type == NodeType::Origin,
30        "Type of {ori} should be ori, but is {node_type} instead"
31    );
32    // Most recent snapshot thus far, as an optional (node_id, timestamp) pair
33    let mut latest_snp: Option<(usize, u64)> = None;
34    for (succ, labels) in graph.labeled_successors(ori) {
35        let node_type = props.node_type(succ);
36        if node_type != NodeType::Snapshot {
37            continue;
38        }
39        for label in labels {
40            if let EdgeLabel::Visit(visit) = label {
41                if visit.status() != VisitStatus::Full {
42                    continue;
43                }
44                let ts = visit.timestamp();
45                if let Some((_cur_snp, cur_ts)) = latest_snp {
46                    if ts > cur_ts {
47                        latest_snp = Some((succ, ts))
48                    }
49                } else {
50                    latest_snp = Some((succ, ts))
51                }
52            }
53        }
54    }
55    Ok(latest_snp)
56}
57
58pub mod collections;
59pub mod connectivity;
60pub mod labeling;
61
62pub mod fs;
63
64pub mod origins;
65
66#[cfg(feature = "unstable_project_ids")]
67pub mod project_ids;
68
69mod root_directory;
70pub use root_directory::find_root_dir;
71
72pub mod vcs;
73
74mod visit;
75pub use visit::*;
76
77pub mod diff;
78
79pub use deprecated::*;
80
81#[allow(deprecated)]
82mod deprecated {
83    use std::collections::HashMap;
84    use swh_graph::labels::{LabelNameId, Permission};
85
86    use super::*;
87
88    #[doc(hidden)]
89    #[deprecated(since = "10.3.0", note = "use swh_graph_stdlib::vcs::HEAD_REF_NAMES")]
90    pub const HEAD_REF_NAMES: [&str; 2] = vcs::HEAD_REF_NAMES;
91
92    #[doc(hidden)]
93    #[deprecated(since = "10.3.0", note = "use swh_graph_stdlib::vcs::find_head_rev")]
94    pub fn find_head_rev<G>(graph: &G, snp: NodeId) -> Result<Option<NodeId>>
95    where
96        G: SwhLabeledForwardGraph + SwhGraphWithProperties,
97        <G as SwhGraphWithProperties>::LabelNames: properties::LabelNames,
98        <G as SwhGraphWithProperties>::Maps: properties::Maps,
99    {
100        vcs::find_head_rev(graph, snp)
101    }
102
103    #[doc(hidden)]
104    #[deprecated(
105        since = "10.3.0",
106        note = "use swh_graph_stdlib::vcs::find_head_rev_by_refs"
107    )]
108    pub fn find_head_rev_by_refs<G>(
109        graph: &G,
110        snp: NodeId,
111        ref_name_ids: &[LabelNameId],
112    ) -> Result<Option<NodeId>>
113    where
114        G: SwhLabeledForwardGraph + SwhGraphWithProperties,
115        <G as SwhGraphWithProperties>::Maps: properties::Maps,
116        <G as SwhGraphWithProperties>::LabelNames: properties::LabelNames,
117    {
118        vcs::find_head_rev_by_refs(graph, snp, ref_name_ids)
119    }
120
121    #[doc(hidden)]
122    #[deprecated(since = "10.3.0", note = "use swh_graph_stdlib::fs::FsTree")]
123    #[derive(Debug, Default, PartialEq)]
124    pub enum FsTree {
125        #[default]
126        Content,
127        Directory(HashMap<Vec<u8>, (FsTree, Option<Permission>)>),
128        Revision(NodeId),
129    }
130
131    impl From<fs::FsTree> for FsTree {
132        fn from(tree: fs::FsTree) -> Self {
133            match tree {
134                fs::FsTree::Content => FsTree::Content,
135                fs::FsTree::Directory(entries) => FsTree::Directory(
136                    entries
137                        .into_iter()
138                        .map(|(name, (tree, perm))| (name, (tree.into(), perm)))
139                        .collect(),
140                ),
141                fs::FsTree::Revision(rev) => FsTree::Revision(rev),
142            }
143        }
144    }
145
146    #[doc(hidden)]
147    #[deprecated(since = "10.3.0", note = "use swh_graph_stdlib::fs::resolve_name")]
148    pub fn fs_resolve_name<G>(
149        graph: &G,
150        dir: NodeId,
151        name: impl AsRef<[u8]>,
152    ) -> Result<Option<NodeId>>
153    where
154        G: SwhLabeledForwardGraph + SwhGraphWithProperties,
155        <G as SwhGraphWithProperties>::LabelNames: properties::LabelNames,
156        <G as SwhGraphWithProperties>::Maps: properties::Maps,
157    {
158        fs::resolve_name(graph, dir, name)
159    }
160
161    pub fn fs_resolve_name_by_id<G>(
162        graph: &G,
163        dir: NodeId,
164        name: LabelNameId,
165    ) -> Result<Option<NodeId>>
166    where
167        G: SwhLabeledForwardGraph + SwhGraphWithProperties,
168        <G as SwhGraphWithProperties>::Maps: properties::Maps,
169    {
170        fs::resolve_name_by_id(graph, dir, name)
171    }
172
173    #[doc(hidden)]
174    #[deprecated(since = "10.3.0", note = "use swh_graph_stdlib::fs::resolve_path")]
175    pub fn fs_resolve_path<G>(
176        graph: &G,
177        dir: NodeId,
178        path: impl AsRef<[u8]>,
179    ) -> Result<Option<NodeId>>
180    where
181        G: SwhLabeledForwardGraph + SwhGraphWithProperties,
182        <G as SwhGraphWithProperties>::LabelNames: properties::LabelNames,
183        <G as SwhGraphWithProperties>::Maps: properties::Maps,
184    {
185        fs::resolve_path(graph, dir, path)
186    }
187
188    #[doc(hidden)]
189    #[deprecated(
190        since = "10.3.0",
191        note = "use swh_graph_stdlib::fs::resolve_path_by_id"
192    )]
193    pub fn fs_resolve_path_by_id<G>(
194        graph: &G,
195        dir: NodeId,
196        path: &[LabelNameId],
197    ) -> Result<Option<NodeId>>
198    where
199        G: SwhLabeledForwardGraph + SwhGraphWithProperties,
200        <G as SwhGraphWithProperties>::Maps: properties::Maps,
201    {
202        fs::resolve_path_by_id(graph, dir, path)
203    }
204
205    #[doc(hidden)]
206    #[deprecated(since = "10.3.0", note = "use swh_graph_stdlib::fs::ls_tree")]
207    pub fn fs_ls_tree<G>(graph: &G, dir: NodeId) -> Result<FsTree>
208    where
209        G: SwhLabeledForwardGraph + SwhGraphWithProperties,
210        <G as SwhGraphWithProperties>::LabelNames: properties::LabelNames,
211        <G as SwhGraphWithProperties>::Maps: properties::Maps,
212    {
213        fs::ls_tree(graph, dir).map(Into::into)
214    }
215}