Skip to content

Commit

Permalink
Add depth option
Browse files Browse the repository at this point in the history
  • Loading branch information
mwilliammyers committed Sep 29, 2019
1 parent 3703074 commit 2bb30ac
Showing 1 changed file with 62 additions and 17 deletions.
79 changes: 62 additions & 17 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use petgraph::graph::NodeIndex;
use petgraph::visit::EdgeRef;
use petgraph::EdgeDirection;
use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet};
use std::collections::{HashMap, VecDeque};
use std::path::PathBuf;
use std::str::{self, FromStr};
use std::rc::Rc;
Expand Down Expand Up @@ -64,6 +64,9 @@ struct Args {
#[structopt(long = "no-dev-dependencies")]
/// Skip dev dependencies.
no_dev_dependencies: bool,
#[structopt(long = "depth", short = "D", value_name = "DEPTH")]
/// Max display depth of the dependency tree
depth: Option<usize>,
#[structopt(long = "manifest-path", value_name = "PATH", parse(from_os_str))]
/// Path to Cargo.toml
manifest_path: Option<PathBuf>,
Expand All @@ -77,7 +80,7 @@ struct Args {
/// Display the dependencies as a list (rather than a tree), but prefixed with the depth
prefix_depth: bool,
#[structopt(long = "all", short = "a")]
/// Don't truncate dependencies that have already been displayed
/// Don't truncate dependencies that are farther down the dependency tree
all: bool,
#[structopt(long = "duplicate", short = "d")]
/// Show only dependencies which come in multiple versions (implies -i)
Expand Down Expand Up @@ -231,6 +234,7 @@ fn real_main(args: Args, config: &mut Config) -> CliResult {
package.package_id(),
target,
cfgs.as_ref().map(|r| &**r),
args.depth,
)?;

let direction = if args.invert || args.duplicates {
Expand All @@ -255,11 +259,15 @@ fn real_main(args: Args, config: &mut Config) -> CliResult {
if args.duplicates {
let dups = find_duplicates(&graph);
for dup in &dups {
print_tree(dup, &graph, &format, direction, symbols, prefix, args.all)?;
print_tree(
dup, &graph, &format, direction, symbols, prefix, args.all, args.depth,
)?;
println!();
}
} else {
print_tree(&root, &graph, &format, direction, symbols, prefix, args.all)?;
print_tree(
&root, &graph, &format, direction, symbols, prefix, args.all, args.depth,
)?;
}

Ok(())
Expand Down Expand Up @@ -349,6 +357,8 @@ fn resolve<'a, 'cfg>(
struct Node<'a> {
id: PackageId,
metadata: &'a ManifestMetadata,
depth_first_seen: usize,
is_duplicate: bool,
}

struct Graph<'a> {
Expand All @@ -362,6 +372,7 @@ fn build_graph<'a>(
root: PackageId,
target: Option<&str>,
cfgs: Option<&[Cfg]>,
max_depth: Option<usize>,
) -> CargoResult<Graph<'a>> {
let mut graph = Graph {
graph: petgraph::Graph::new(),
Expand All @@ -370,12 +381,23 @@ fn build_graph<'a>(
let node = Node {
id: root.clone(),
metadata: packages.get_one(root)?.manifest().metadata(),
depth_first_seen: 0,
is_duplicate: false,
};
graph.nodes.insert(root.clone(), graph.graph.add_node(node));

let mut pending = vec![root];
if let Some(depth) = max_depth {
if depth == 0 {
return Ok(graph);
}
}

let mut pending = VecDeque::new();
pending.push_back(root);

while let Some(pkg_id) = pending.pop() {
let mut current_depth: usize = 1;

while let Some(pkg_id) = pending.pop_front() {
let idx = graph.nodes[&pkg_id];
let pkg = packages.get_one(pkg_id)?;

Expand All @@ -395,19 +417,36 @@ fn build_graph<'a>(
};
for dep in it {
let dep_idx = match graph.nodes.entry(dep_id) {
Entry::Occupied(e) => *e.get(),
Entry::Occupied(e) => {
let key = *e.get();

let mut node = &mut graph.graph[key];
node.is_duplicate = true;

key
}
Entry::Vacant(e) => {
pending.push(dep_id);
if let Some(depth) = max_depth {
if current_depth < depth {
pending.push_back(dep_id);
}
} else {
pending.push_back(dep_id);
}

let node = Node {
id: dep_id,
metadata: packages.get_one(dep_id)?.manifest().metadata(),
depth_first_seen: current_depth,
is_duplicate: false,
};
*e.insert(graph.graph.add_node(node))
}
};
graph.graph.add_edge(idx, dep_idx, dep.kind());
}
}
current_depth += 1;
}

Ok(graph)
Expand All @@ -421,8 +460,8 @@ fn print_tree<'a>(
symbols: &Symbols,
prefix: Prefix,
all: bool,
max_depth: Option<usize>,
) -> CargoResult<()> {
let mut visited_deps = HashSet::new();
let mut levels_continue = vec![];

let package = match graph.nodes.get(package) {
Expand All @@ -436,10 +475,10 @@ fn print_tree<'a>(
format,
direction,
symbols,
&mut visited_deps,
&mut levels_continue,
prefix,
all,
max_depth,
);
Ok(())
}
Expand All @@ -450,12 +489,18 @@ fn print_dependency<'a>(
format: &Pattern,
direction: EdgeDirection,
symbols: &Symbols,
visited_deps: &mut HashSet<PackageId>,
levels_continue: &mut Vec<bool>,
prefix: Prefix,
all: bool,
max_depth: Option<usize>,
) {
let new = all || visited_deps.insert(package.id);
if let Some(depth) = max_depth {
if depth < levels_continue.len() {
return;
}
}

let new = all || (!package.is_duplicate || package.depth_first_seen >= levels_continue.len());
let star = if new { "" } else { " (*)" };

match prefix {
Expand Down Expand Up @@ -509,10 +554,10 @@ fn print_dependency<'a>(
format,
direction,
symbols,
visited_deps,
levels_continue,
prefix,
all,
max_depth,
);
print_dependency_kind(
Kind::Build,
Expand All @@ -521,10 +566,10 @@ fn print_dependency<'a>(
format,
direction,
symbols,
visited_deps,
levels_continue,
prefix,
all,
max_depth,
);
print_dependency_kind(
Kind::Development,
Expand All @@ -533,10 +578,10 @@ fn print_dependency<'a>(
format,
direction,
symbols,
visited_deps,
levels_continue,
prefix,
all,
max_depth,
);
}

Expand All @@ -547,10 +592,10 @@ fn print_dependency_kind<'a>(
format: &Pattern,
direction: EdgeDirection,
symbols: &Symbols,
visited_deps: &mut HashSet<PackageId>,
levels_continue: &mut Vec<bool>,
prefix: Prefix,
all: bool,
max_depth: Option<usize>,
) {
if deps.is_empty() {
return;
Expand Down Expand Up @@ -584,10 +629,10 @@ fn print_dependency_kind<'a>(
format,
direction,
symbols,
visited_deps,
levels_continue,
prefix,
all,
max_depth,
);
levels_continue.pop();
}
Expand Down

0 comments on commit 2bb30ac

Please sign in to comment.