Skip to content

Commit

Permalink
[guppy] add support for postfilters
Browse files Browse the repository at this point in the history
Use it in `cargo-guppy` to implement filtering for
third-party deps.
  • Loading branch information
sunshowers committed May 27, 2020
1 parent 47c0a1f commit 592d4b5
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 65 deletions.
41 changes: 27 additions & 14 deletions cargo-guppy/src/core.rs
Expand Up @@ -5,6 +5,7 @@

use anyhow::{anyhow, ensure};
use clap::arg_enum;
use guppy::graph::cargo::{CargoPostfilter, CargoResolvePhase};
use guppy::graph::{
DependencyDirection, DependencyReq, EnabledTernary, PackageGraph, PackageLink, PackageQuery,
};
Expand All @@ -13,7 +14,7 @@ use std::collections::HashSet;
use structopt::StructOpt;

arg_enum! {
#[derive(Debug)]
#[derive(Copy, Clone, Debug)]
pub enum Kind {
All,
Workspace,
Expand All @@ -22,6 +23,25 @@ arg_enum! {
}
}

impl Kind {
/// Returns true if this link should be traversed.
pub fn should_traverse(self, link: &PackageLink<'_>) -> bool {
// NOTE: We always retain all workspace deps in the graph, otherwise
// we'll get a disconnected graph.
match self {
Kind::All | Kind::ThirdParty => true,
Kind::DirectThirdParty => link.from().in_workspace(),
Kind::Workspace => link.from().in_workspace() && link.to().in_workspace(),
}
}
}

impl<'g> CargoPostfilter<'g> for Kind {
fn accept_package(&mut self, _phase: CargoResolvePhase<'_, '_>, link: PackageLink<'_>) -> bool {
self.should_traverse(&link)
}
}

#[derive(Debug, StructOpt)]
pub struct QueryOptions {
/// Query reverse transitive dependencies (default: forward)
Expand Down Expand Up @@ -67,6 +87,10 @@ pub struct BaseFilterOptions {
/// Omit edges that point into a given package; useful for seeing how
/// removing a dependency affects the graph
pub omit_edges_into: Vec<String>,

#[structopt(long, short, possible_values = &Kind::variants(), case_insensitive = true, default_value = "all")]
/// Kind of crates to select
pub kind: Kind,
}

impl BaseFilterOptions {
Expand All @@ -85,10 +109,6 @@ pub struct FilterOptions {
#[structopt(flatten)]
pub base_opts: BaseFilterOptions,

#[structopt(long, short, possible_values = &Kind::variants(), case_insensitive = true, default_value = "all")]
/// Kind of crates to select
pub kind: Kind,

#[structopt(long, rename_all = "kebab-case")]
/// Include dev dependencies
pub include_dev: bool,
Expand Down Expand Up @@ -119,15 +139,8 @@ impl FilterOptions {
};

move |_, link| {
let (from, to) = link.endpoints();
// filter by the kind of dependency (--kind)
// NOTE: We always retain all workspace deps in the graph, otherwise
// we'll get a disconnected graph.
let include_kind = match self.kind {
Kind::All | Kind::ThirdParty => true,
Kind::DirectThirdParty => from.in_workspace(),
Kind::Workspace => from.in_workspace() && to.in_workspace(),
};
let include_kind = self.base_opts.kind.should_traverse(&link);

let include_type = if let Some(platform) = &platform {
// filter out irrelevant dependencies for a specific target (--target)
Expand All @@ -140,7 +153,7 @@ impl FilterOptions {
};

// filter out provided edge targets (--omit-edges-into)
let include_edge = !omitted_package_ids.contains(to.id());
let include_edge = !omitted_package_ids.contains(link.to().id());

include_kind && include_type && include_edge
}
Expand Down
29 changes: 18 additions & 11 deletions cargo-guppy/src/lib.rs
Expand Up @@ -123,8 +123,9 @@ pub fn cmd_resolve_cargo(opts: &ResolveCargoOptions) -> Result<(), anyhow::Error
let host_platform = triple_to_platform(opts.host_platform.as_deref(), || None)?;
let mut command = opts.metadata_opts.make_command();
let pkg_graph = command.build_graph()?;
let mut kind_postfilter = opts.base_filter_opts.kind;

let cargo_opts = CargoOptions::new()
let mut cargo_opts = CargoOptions::new_postfilter(&mut kind_postfilter)
.with_dev_deps(opts.include_dev)
.with_target_platform(target_platform.as_ref())
.with_host_platform(host_platform.as_ref())
Expand All @@ -133,19 +134,25 @@ pub fn cmd_resolve_cargo(opts: &ResolveCargoOptions) -> Result<(), anyhow::Error
let cargo_set = opts
.pf
.make_feature_query(&pkg_graph)?
.resolve_cargo(&cargo_opts)?;
.resolve_cargo(&mut cargo_opts)?;

fn print_packages(feature_set: &FeatureSet) {
let print_packages = |feature_set: &FeatureSet| {
for feature_list in feature_set.packages_with_features(DependencyDirection::Forward) {
let package = feature_list.package();
println!(
"{} {}: {}",
package.name(),
package.version(),
feature_list.display_features()
);
let show_package = match opts.base_filter_opts.kind {
Kind::All | Kind::Workspace => true,
Kind::DirectThirdParty | Kind::ThirdParty => !package.in_workspace(),
};
if show_package {
println!(
"{} {}: {}",
package.name(),
package.version(),
feature_list.display_features()
);
}
}
}
};

match opts.build_kind {
BuildKind::All => {
Expand Down Expand Up @@ -204,7 +211,7 @@ pub fn cmd_select(options: &CmdSelectOptions) -> Result<(), anyhow::Error> {
let direct_dep = package
.reverse_direct_links()
.any(|link| link.from().in_workspace() && !link.to().in_workspace());
let show_package = match options.filter_opts.kind {
let show_package = match options.filter_opts.base_opts.kind {
Kind::All => true,
Kind::Workspace => in_workspace,
Kind::DirectThirdParty => direct_dep,
Expand Down

0 comments on commit 592d4b5

Please sign in to comment.