Skip to content

Commit

Permalink
Add support for filtering built graphs (#59)
Browse files Browse the repository at this point in the history
* Add support for filtering built graphs

* Fixup

* Update CHANGELOG
  • Loading branch information
Jake-Shadle committed Sep 3, 2023
1 parent 504006f commit b7e4dbf
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- next-header -->
## [Unreleased] - ReleaseDate
### Added
- [PR#59](https://github.com/EmbarkStudios/krates/pull/59) added `Krates::krates_filtered`, allowing filtering of crates based upon their edge kinds.

## [0.15.0] - 2023-08-23
### Changed
- [PR#58](https://github.com/EmbarkStudios/krates/pull/58) removed the `prefer-index` feature, which brought in `tame-index`, in favor of just letting the user provide a callback that can be used to gather index information, freeing this crate from dependency issues and allowing downstream crates more flexibility.
Expand Down
4 changes: 3 additions & 1 deletion src/builder/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ pub(super) fn fix_features(index: &CachingIndex, krate: &mut cargo_metadata::Pac
return;
}

let Some(features) = index.index_krate_features(&krate.name, &krate.version) else { return; };
let Some(features) = index.index_krate_features(&krate.name, &krate.version) else {
return;
};

for (ikey, ivalue) in features {
if !krate.features.contains_key(ikey) {
Expand Down
62 changes: 61 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ impl<N, E> Krates<N, E> {

while let Some(nid) = stack.pop() {
for edge in graph.edges_directed(nid, Direction::Incoming) {
match &self.graph[edge.source()] {
match &graph[edge.source()] {
Node::Krate { krate, .. } => {
if visited.insert(edge.source()) {
direct_dependents.push(DirectDependent {
Expand Down Expand Up @@ -435,6 +435,66 @@ impl KrateDetails for cm::Package {
}
}

impl<N> Krates<N, Edge>
where
N: std::fmt::Debug,
{
/// Removes all of the crates that are only referenced via the specified
/// dependency kind.
///
/// This gives the same output as if the graph had been built by using
/// [`ignore_kind`](crate::Builder::ignore_kind) with [`Scope::all`](crate::Scope::All)
pub fn krates_filtered(&self, filter: DepKind) -> Vec<&N> {
let graph = self.graph();
let mut filtered: std::collections::BTreeMap<_, _> = self
.workspace_members()
.filter_map(|n| {
let Node::Krate { id, krate, .. } = n else {
return None;
};
Some((id, krate))
})
.collect();
let mut stack: Vec<_> = self
.workspace_members
.iter()
.filter_map(|pid| self.nid_for_kid(pid))
.collect();
let mut visited = std::collections::BTreeSet::new();

while let Some(nid) = stack.pop() {
for edge in graph.edges_directed(nid, Direction::Outgoing) {
match edge.weight() {
Edge::Dep { kind, .. } | Edge::DepFeature { kind, .. } => {
if *kind == filter {
continue;
}
}
Edge::Feature => {}
};

match &graph[edge.target()] {
Node::Krate { id, krate, .. } => {
if visited.insert(edge.target()) {
stack.push(edge.target());
filtered.insert(id, krate);
}
}
Node::Feature { .. } => {
if visited.insert(edge.target()) {
stack.push(edge.target());
}
}
}
}

visited.insert(nid);
}

filtered.into_values().collect()
}
}

/// If the node type N supports [`KrateDetails`], we can also iterator over krates
/// of a given name and or version
impl<N, E> Krates<N, E>
Expand Down
4 changes: 2 additions & 2 deletions tests/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn ignores_non_linux() {
fn ignores_non_tier1() {
let mut kb = krates::Builder::new();

let targets = vec![
let targets = [
targets::get_builtin_target_by_triple("i686-pc-windows-gnu").unwrap(),
targets::get_builtin_target_by_triple("i686-pc-windows-msvc").unwrap(),
targets::get_builtin_target_by_triple("i686-unknown-linux-gnu").unwrap(),
Expand All @@ -44,7 +44,7 @@ fn ignores_non_tier1() {
fn ignores_non_wasm() {
let mut kb = krates::Builder::new();

let targets = vec![targets::get_builtin_target_by_triple("wasm32-unknown-unknown").unwrap()];
let targets = [targets::get_builtin_target_by_triple("wasm32-unknown-unknown").unwrap()];

kb.include_targets(targets.iter().map(|ti| (ti.triple.clone(), vec![])));

Expand Down
41 changes: 41 additions & 0 deletions tests/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,44 @@ fn only_b() {
let grafs = build("all-features.json", kb).unwrap();
insta::assert_snapshot!(grafs.dotgraph());
}

#[test]
fn filters_after_build() {
{
let mut kb = krates::Builder::new();
kb.ignore_kind(krates::DepKind::Dev, krates::Scope::NonWorkspace);

let grafs = build("all-features.json", kb).unwrap();

let filtered = grafs.actual.krates_filtered(krates::DepKind::Dev);

let mut kb = krates::Builder::new();
kb.ignore_kind(krates::DepKind::Dev, krates::Scope::All);

let grafs = build("all-features.json", kb).unwrap();

let expected = format!("{:#?}", grafs.actual.krates().collect::<Vec<_>>());
let actual = format!("{filtered:#?}");

similar_asserts::assert_eq!(expected, actual);
}

{
let mut kb = krates::Builder::new();
kb.ignore_kind(krates::DepKind::Build, krates::Scope::NonWorkspace);

let grafs = build("all-features.json", kb).unwrap();

let filtered = grafs.actual.krates_filtered(krates::DepKind::Build);

let mut kb = krates::Builder::new();
kb.ignore_kind(krates::DepKind::Build, krates::Scope::All);

let grafs = build("all-features.json", kb).unwrap();

let expected = format!("{:#?}", grafs.actual.krates().collect::<Vec<_>>());
let actual = format!("{filtered:#?}");

similar_asserts::assert_eq!(expected, actual);
}
}
1 change: 1 addition & 0 deletions tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::{fmt, path::Path};

#[derive(Debug, PartialEq)]
pub struct JustId(pub krates::Kid);

pub type Graph = krates::Krates<JustId>;
Expand Down

0 comments on commit b7e4dbf

Please sign in to comment.