Skip to content

Commit

Permalink
Switched the dependency graph over to petgraph
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael-F-Bryan committed Jun 6, 2023
1 parent 330c33e commit 559d7c9
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 229 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 5 additions & 11 deletions lib/wasi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ wcgi-host = { version = "0.1.2", optional = true }
tower-http = { version = "0.4.0", features = ["trace", "util", "catch-panic", "cors"], optional = true }
tower = { version = "0.4.13", features = ["make", "util"], optional = true }
url = "2.3.1"
petgraph = "0.6.3"

[target.'cfg(not(target_arch = "riscv64"))'.dependencies.reqwest]
version = "0.11"
Expand Down Expand Up @@ -116,7 +117,7 @@ webc_runner_rt_wcgi = ["hyper", "wcgi", "wcgi-host", "tower", "tower-http"]
webc_runner_rt_emscripten = ["wasmer-emscripten"]

sys = ["webc/mmap", "time"]
sys-default = ["sys", "logging", "host-fs", "sys-poll", "sys-thread", "host-vnet", "host-threads", "host-reqwest" ]
sys-default = ["sys", "logging", "host-fs", "sys-poll", "sys-thread", "host-vnet", "host-threads", "host-reqwest"]
sys-poll = []
sys-thread = ["tokio/rt", "tokio/time", "tokio/rt-multi-thread"]

Expand All @@ -127,21 +128,14 @@ js = ["virtual-fs/no-time", "getrandom/js", "chrono"]
js-default = ["js"]
test-js = ["js", "wasmer/wat"]

host-vnet = [ "virtual-net/host-net" ]
host-vnet = ["virtual-net/host-net"]
host-threads = []
host-reqwest = ["reqwest"]
host-fs = ["virtual-fs/host-fs"]

logging = ["tracing/log"]
disable-all-logging = [
"tracing/release_max_level_off",
"tracing/max_level_off"
]
enable-serde = [
"typetag",
"virtual-fs/enable-serde",
"wasmer-wasix-types/enable-serde",
]
disable-all-logging = ["tracing/release_max_level_off", "tracing/max_level_off"]
enable-serde = ["typetag", "virtual-fs/enable-serde", "wasmer-wasix-types/enable-serde"]

[package.metadata.docs.rs]
features = ["wasmer/sys"]
10 changes: 6 additions & 4 deletions lib/wasi/src/runtime/package_loader/load_package_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,13 +215,15 @@ async fn fetch_dependencies(

let packages: FuturesUnordered<_> = packages
.into_iter()
.map(|id| async {
.filter_map(|id| {
let crate::runtime::resolver::Node { pkg, dist, .. } = &graph[&id];
let summary = PackageSummary {
pkg: graph.package_info[&id].clone(),
dist: graph.distribution[&id].clone(),
pkg: pkg.clone(),
dist: dist.clone()?,
};
loader.load(&summary).await.map(|webc| (id, webc))
Some((id, summary))
})
.map(|(id, summary)| async move { loader.load(&summary).await.map(|webc| (id, webc)) })
.collect();

let packages: HashMap<PackageId, Container> = packages.try_collect().await?;
Expand Down
4 changes: 2 additions & 2 deletions lib/wasi/src/runtime/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pub use self::{
},
multi_source_registry::MultiSource,
outputs::{
DependencyGraph, ItemLocation, PackageId, Resolution, ResolvedFileSystemMapping,
ResolvedPackage,
DependencyGraph, Edge, ItemLocation, Node, PackageId, Resolution,
ResolvedFileSystemMapping, ResolvedPackage,
},
resolve::resolve,
source::Source,
Expand Down
132 changes: 115 additions & 17 deletions lib/wasi/src/runtime/resolver/outputs.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use std::{
collections::{BTreeMap, HashMap},
collections::BTreeMap,
fmt::{self, Display, Formatter},
ops::Index,
path::PathBuf,
unreachable,
};

use petgraph::{graph::NodeIndex, visit::EdgeRef};
use semver::Version;

use crate::runtime::resolver::{DistributionInfo, PackageInfo};

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone)]
pub struct Resolution {
pub package: ResolvedPackage,
pub graph: DependencyGraph,
Expand All @@ -24,7 +25,7 @@ pub struct ItemLocation {
}

/// An identifier for a package within a dependency graph.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PackageId {
pub package_name: String,
pub version: Version,
Expand All @@ -40,25 +41,122 @@ impl Display for PackageId {
}
}

/// A dependency graph.
#[derive(Debug, Clone, PartialEq, Eq)]
/// An acyclic, directed dependency graph.
#[derive(Debug, Clone)]
pub struct DependencyGraph {
pub root: PackageId,
pub dependencies: HashMap<PackageId, HashMap<String, PackageId>>,
pub package_info: HashMap<PackageId, PackageInfo>,
pub distribution: HashMap<PackageId, DistributionInfo>,
root: NodeIndex,
graph: petgraph::graph::DiGraph<Node, Edge>,
packages: BTreeMap<PackageId, NodeIndex>,
}

impl DependencyGraph {
pub fn root_info(&self) -> &PackageInfo {
match self.package_info.get(&self.root) {
Some(info) => info,
None => unreachable!(
"The dependency graph should always have package info for the root package, {}",
self.root
),
pub(crate) fn new(
root: NodeIndex,
graph: petgraph::graph::DiGraph<Node, Edge>,
packages: BTreeMap<PackageId, NodeIndex>,
) -> Self {
DependencyGraph {
root,
graph,
packages,
}
}

pub fn root_info(&self) -> &PackageInfo {
let Node { pkg, .. } = &self.graph[self.root];
pkg
}

pub fn root(&self) -> NodeIndex {
self.root
}

pub fn graph(&self) -> &petgraph::graph::DiGraph<Node, Edge> {
&self.graph
}

/// Get a mapping from [`PackageId`]s to [`NodeIndex`]s.
pub fn packages(&self) -> &BTreeMap<PackageId, NodeIndex> {
&self.packages
}

/// Get an iterator over all the packages in this dependency graph and their
/// dependency mappings.
pub fn iter_dependencies(
&self,
) -> impl Iterator<Item = (&'_ PackageId, BTreeMap<&'_ str, &'_ PackageId>)> + '_ {
self.packages.iter().map(move |(id, index)| {
let dependencies: BTreeMap<_, _> = self
.graph
.edges(*index)
.map(|edge_ref| {
(
edge_ref.weight().alias.as_str(),
&self.graph[edge_ref.target()].id,
)
})
.collect();
(id, dependencies)
})
}
}

impl Index<NodeIndex> for DependencyGraph {
type Output = Node;

#[track_caller]
fn index(&self, index: NodeIndex) -> &Self::Output {
&self.graph[index]
}
}

impl Index<&NodeIndex> for DependencyGraph {
type Output = Node;

#[track_caller]
fn index(&self, index: &NodeIndex) -> &Self::Output {
&self[*index]
}
}

impl Index<&PackageId> for DependencyGraph {
type Output = Node;

#[track_caller]
fn index(&self, index: &PackageId) -> &Self::Output {
let index = self.packages[index];
&self[index]
}
}

impl PartialEq for DependencyGraph {
fn eq(&self, other: &Self) -> bool {
let DependencyGraph {
root,
graph,
packages,
} = self;

root.index() == other.root.index()
&& *packages == other.packages
&& petgraph::algo::is_isomorphic_matching(graph, &other.graph, Node::eq, Edge::eq)
}
}

impl Eq for DependencyGraph {}

/// A node in the [`DependencyGraph`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Node {
pub id: PackageId,
pub pkg: PackageInfo,
pub dist: Option<DistributionInfo>,
}

/// An edge in the [`DependencyGraph`].
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Edge {
pub alias: String,
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
Loading

0 comments on commit 559d7c9

Please sign in to comment.