Skip to content

Commit bb00666

Browse files
feat: refactor and cleanup Adg
Signed-off-by: Andrew Lilley Brinker <[email protected]>
1 parent f653a09 commit bb00666

File tree

5 files changed

+135
-51
lines changed

5 files changed

+135
-51
lines changed

omnibor/src/adg.rs

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,6 @@
11
//! Operations and types for handling Artifact Dependency Graphs (ADGs).
2-
#![allow(unused)]
32
4-
use crate::{
5-
error::InputManifestError,
6-
hash_algorithm::HashAlgorithm,
7-
storage::{Match, Storage},
8-
ArtifactId,
9-
};
10-
use petgraph::{graph::NodeIndex, Graph};
3+
pub(crate) mod adg_internal;
4+
mod adg_node;
115

12-
// Convenience type for our internal dependency graph.
13-
pub(crate) type DepGraphInner<H> = Graph<AdgNode<H>, ()>;
14-
15-
/// The Artifact Dependency Graph.
16-
#[derive(Debug)]
17-
pub struct DepGraph<H>
18-
where
19-
H: HashAlgorithm,
20-
{
21-
graph: DepGraphInner<H>,
22-
}
23-
24-
impl<H> DepGraph<H>
25-
where
26-
H: HashAlgorithm,
27-
{
28-
pub(crate) fn from_graph(graph: DepGraphInner<H>) -> Self {
29-
Self { graph }
30-
}
31-
}
32-
33-
/// A node in the Artifact Dependency Graph.
34-
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
35-
pub struct AdgNode<H>
36-
where
37-
H: HashAlgorithm,
38-
{
39-
/// The Artifact ID of the node's artifact.
40-
pub id: ArtifactId<H>,
41-
}
6+
pub use adg_node::AdgNode;

omnibor/src/adg/adg_internal.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#![allow(unused)]
2+
3+
use crate::{
4+
adg::AdgNode,
5+
error::ArtifactIdError,
6+
hash_algorithm::HashAlgorithm,
7+
storage::{Match, Storage},
8+
ArtifactId, Identify,
9+
};
10+
use petgraph::{algo::astar, graph::NodeIndex, Graph};
11+
use std::ops::Not;
12+
13+
// Convenience type for our internal dependency graph.
14+
pub(crate) type AdgInner<H> = Graph<AdgNode<H>, ()>;
15+
16+
/// The Artifact Dependency Graph.
17+
#[derive(Debug)]
18+
pub struct Adg<H>
19+
where
20+
H: HashAlgorithm,
21+
{
22+
/// The internal graph type.
23+
graph: AdgInner<H>,
24+
/// The target artifact the ADG is describing.
25+
target: NodeIndex,
26+
}
27+
28+
impl<H> Adg<H>
29+
where
30+
H: HashAlgorithm,
31+
{
32+
// Actual construction is handled by the storage.
33+
pub(crate) fn new(graph: AdgInner<H>, target: NodeIndex) -> Self {
34+
Self { graph, target }
35+
}
36+
37+
/// Get the target artifact for this ADG.
38+
pub fn target(&self) -> ArtifactId<H> {
39+
self.graph[self.target].artifact_id()
40+
}
41+
42+
/// Get the path to a dependency, if present in the graph.
43+
pub fn dependency_path(&self, dep: ArtifactId<H>) -> Result<Vec<&AdgNode<H>>, ArtifactIdError> {
44+
let dep = dep.identify()?;
45+
46+
let search = astar(
47+
&self.graph,
48+
// Start from the target.
49+
self.target,
50+
// End when we find the dependency.
51+
|n| self.graph[n].artifact_id() == dep,
52+
// Each edge has weight 1.
53+
|_| 1,
54+
// We don't do estimation.
55+
|_| 0,
56+
);
57+
58+
match search {
59+
None => Ok(Vec::new()),
60+
Some((_, path)) => Ok(path.iter().map(|idx| &self.graph[*idx]).collect()),
61+
}
62+
}
63+
64+
/// Check if the ADG's target artifact depends on a specific artifact.
65+
pub fn depends_on(&self, dep: ArtifactId<H>) -> Result<bool, ArtifactIdError> {
66+
let dep = dep.identify()?;
67+
68+
// Rather than doing a graph algo, check if the dep is one of the nodes.
69+
Ok(self
70+
.graph
71+
.node_indices()
72+
.any(|idx| self.graph[idx].artifact_id() == dep))
73+
}
74+
}

omnibor/src/adg/adg_node.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#![allow(unused)]
2+
3+
use crate::{
4+
error::{ArtifactIdError, InputManifestError},
5+
hash_algorithm::HashAlgorithm,
6+
storage::{Match, Storage},
7+
ArtifactId, Identify,
8+
};
9+
use petgraph::{algo::astar, graph::NodeIndex, Graph};
10+
11+
/// A node in the Artifact Dependency Graph.
12+
#[derive(Debug, PartialEq, Eq, Copy, PartialOrd, Ord)]
13+
pub struct AdgNode<H>
14+
where
15+
H: HashAlgorithm,
16+
{
17+
/// The Artifact ID of the node's artifact.
18+
artifact_id: ArtifactId<H>,
19+
}
20+
21+
impl<H> AdgNode<H>
22+
where
23+
H: HashAlgorithm,
24+
{
25+
pub(crate) fn new(artifact_id: ArtifactId<H>) -> Self {
26+
AdgNode { artifact_id }
27+
}
28+
29+
/// Get the Artifact ID for the node.
30+
pub fn artifact_id(&self) -> ArtifactId<H> {
31+
self.artifact_id
32+
}
33+
}
34+
35+
impl<H> Clone for AdgNode<H>
36+
where
37+
H: HashAlgorithm,
38+
{
39+
fn clone(&self) -> Self {
40+
AdgNode {
41+
artifact_id: self.artifact_id,
42+
}
43+
}
44+
}

omnibor/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ pub mod hash_algorithm;
517517
pub mod hash_provider;
518518
pub mod storage;
519519

520+
pub use crate::adg::adg_internal::Adg;
520521
pub use crate::artifact_id::ArtifactId;
521522
pub use crate::artifact_id::Identify;
522523
pub use crate::artifact_id::IdentifyAsync;

omnibor/src/storage.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ pub use crate::storage::in_memory_storage::InMemoryStorage;
2323
pub use crate::storage::query::Match;
2424

2525
use crate::{
26-
adg::{AdgNode, DepGraph, DepGraphInner},
26+
adg::{adg_internal::AdgInner, AdgNode},
2727
artifact_id::ArtifactId,
2828
error::InputManifestError,
2929
hash_algorithm::HashAlgorithm,
3030
input_manifest::InputManifest,
31-
Identify,
31+
Adg, Identify,
3232
};
3333

3434
/// Represents the interface for storing and querying manifests.
@@ -78,13 +78,13 @@ pub trait Storage<H: HashAlgorithm> {
7878
I: Identify<H>;
7979

8080
/// Get the Artifact Dependency Graph of the target.
81-
fn get_adg<I>(&self, target_aid: I) -> Result<DepGraph<H>, InputManifestError>
81+
fn get_adg<I>(&self, target_aid: I) -> Result<Adg<H>, InputManifestError>
8282
where
8383
I: Identify<H>,
8484
{
8585
let target_aid = target_aid.identify()?;
86-
let graph = build_graph(target_aid, self)?;
87-
Ok(DepGraph::from_graph(graph))
86+
let (graph, root) = build_graph(target_aid, self)?;
87+
Ok(Adg::new(graph, root))
8888
}
8989
}
9090

@@ -137,29 +137,29 @@ impl<H: HashAlgorithm, S: Storage<H>> Storage<H> for &mut S {
137137
fn build_graph<H, S>(
138138
target_aid: ArtifactId<H>,
139139
storage: &S,
140-
) -> Result<DepGraphInner<H>, InputManifestError>
140+
) -> Result<(AdgInner<H>, NodeIndex), InputManifestError>
141141
where
142142
H: HashAlgorithm,
143143
S: Storage<H> + ?Sized,
144144
{
145145
let mut graph = Graph::new();
146-
populate_graph(&mut graph, target_aid, None, storage)?;
147-
Ok(graph)
146+
let root = populate_graph(&mut graph, target_aid, None, storage)?;
147+
Ok((graph, root))
148148
}
149149

150150
/// Build one layer of the ADG, recursing down for further layers.
151151
fn populate_graph<H, S>(
152-
graph: &mut DepGraphInner<H>,
152+
graph: &mut AdgInner<H>,
153153
target_aid: ArtifactId<H>,
154154
parent_idx: Option<NodeIndex>,
155155
storage: &S,
156-
) -> Result<(), InputManifestError>
156+
) -> Result<NodeIndex, InputManifestError>
157157
where
158158
H: HashAlgorithm,
159159
S: Storage<H> + ?Sized,
160160
{
161161
// Add current node to the graph.
162-
let self_idx = graph.add_node(AdgNode { id: target_aid });
162+
let self_idx = graph.add_node(AdgNode::new(target_aid));
163163

164164
// If there's a parent, add an edge from the parent to the current node.
165165
if let Some(parent_idx) = parent_idx {
@@ -169,9 +169,9 @@ where
169169
// If there's a manifest for current node, recurse for each child.
170170
if let Some(manifest) = storage.get_manifest(Match::target(target_aid))? {
171171
for input in manifest.inputs() {
172-
populate_graph(graph, input.artifact(), Some(self_idx), storage)?;
172+
let _ = populate_graph(graph, input.artifact(), Some(self_idx), storage)?;
173173
}
174174
}
175175

176-
Ok(())
176+
Ok(self_idx)
177177
}

0 commit comments

Comments
 (0)