From 8a747ab09c82c27bc9978f09364edfe8909aed8f Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 29 May 2021 09:41:17 +0800 Subject: [PATCH 1/6] refactor(cargo-tree): skip level earlier when exceeded --- src/cargo/ops/tree/mod.rs | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/cargo/ops/tree/mod.rs b/src/cargo/ops/tree/mod.rs index db5ee4ee202..d3b35862300 100644 --- a/src/cargo/ops/tree/mod.rs +++ b/src/cargo/ops/tree/mod.rs @@ -371,6 +371,11 @@ fn print_dependencies<'a>( } } + // Current level exceeds maximum display depth. Skip. + if levels_continue.len() + 1 > max_display_depth as usize { + return; + } + let mut it = deps .iter() .filter(|dep| { @@ -389,23 +394,21 @@ fn print_dependencies<'a>( .peekable(); while let Some(dependency) = it.next() { - if levels_continue.len() + 1 <= max_display_depth as usize { - levels_continue.push(it.peek().is_some()); - print_node( - config, - graph, - *dependency, - format, - symbols, - prefix, - no_dedupe, - max_display_depth, - no_proc_macro, - visited_deps, - levels_continue, - print_stack, - ); - levels_continue.pop(); - } + levels_continue.push(it.peek().is_some()); + print_node( + config, + graph, + *dependency, + format, + symbols, + prefix, + no_dedupe, + max_display_depth, + no_proc_macro, + visited_deps, + levels_continue, + print_stack, + ); + levels_continue.pop(); } } From b5998aeef4023e32afa0492a286f905abe51ffba Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 29 May 2021 09:47:19 +0800 Subject: [PATCH 2/6] feat(carog-tree): new `--prune` option --- src/bin/cargo/commands/tree.rs | 16 ++++++++++++++++ src/cargo/ops/tree/mod.rs | 35 +++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/bin/cargo/commands/tree.rs b/src/bin/cargo/commands/tree.rs index dfbded3463a..07b4b23afc2 100644 --- a/src/bin/cargo/commands/tree.rs +++ b/src/bin/cargo/commands/tree.rs @@ -56,6 +56,11 @@ pub fn cli() -> App { ) .short("i"), ) + .arg(multi_opt( + "prune", + "SPEC", + "Prune the given package from the display of the dependency tree", + )) .arg(opt("depth", "Maximum display depth of the dependency tree").value_name("DEPTH")) // Deprecated, use --prefix=none instead. .arg(Arg::with_name("no-indent").long("no-indent").hidden(true)) @@ -152,6 +157,16 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { let (edge_kinds, no_proc_macro) = parse_edge_kinds(config, args)?; let graph_features = edge_kinds.contains(&EdgeKind::Feature); + let pkgs_to_prune = args.values_of("prune").map_or_else( + || Vec::new(), + |ps| { + let mut specs = ps.map(|p| p.to_string()).collect::>(); + specs.sort_unstable(); + specs.dedup(); + specs + }, + ); + let packages = args.packages_from_flags()?; let mut invert = args .values_of("invert") @@ -197,6 +212,7 @@ subtree of the package given to -p.\n\ target, edge_kinds, invert, + pkgs_to_prune, prefix, no_dedupe, duplicates: args.is_present("duplicates"), diff --git a/src/cargo/ops/tree/mod.rs b/src/cargo/ops/tree/mod.rs index d3b35862300..56f4692ca48 100644 --- a/src/cargo/ops/tree/mod.rs +++ b/src/cargo/ops/tree/mod.rs @@ -27,6 +27,8 @@ pub struct TreeOptions { /// The dependency kinds to display. pub edge_kinds: HashSet, pub invert: Vec, + /// The packages to prune from the display of the dependency tree. + pub pkgs_to_prune: Vec, /// The style of prefix for each line. pub prefix: Prefix, /// If `true`, duplicates will be repeated. @@ -199,7 +201,19 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<() graph.invert(); } - print(ws.config(), opts, root_indexes, &graph)?; + // Packages to prune. + let pkgs_to_prune = opts + .pkgs_to_prune + .iter() + .map(|p| PackageIdSpec::parse(p)) + .map(|r| { + // Provide a error message if pkgid is not within the resolved + // dependencies graph. + r.and_then(|spec| spec.query(ws_resolve.targeted_resolve.iter()).and(Ok(spec))) + }) + .collect::>>()?; + + print(ws.config(), opts, root_indexes, &pkgs_to_prune, &graph)?; Ok(()) } @@ -208,6 +222,7 @@ fn print( config: &Config, opts: &TreeOptions, roots: Vec, + pkgs_to_prune: &[PackageIdSpec], graph: &Graph<'_>, ) -> CargoResult<()> { let format = Pattern::new(&opts.format) @@ -240,6 +255,7 @@ fn print( root_index, &format, symbols, + pkgs_to_prune, opts.prefix, opts.no_dedupe, opts.max_display_depth, @@ -260,6 +276,7 @@ fn print_node<'a>( node_index: usize, format: &Pattern, symbols: &Symbols, + pkgs_to_prune: &[PackageIdSpec], prefix: Prefix, no_dedupe: bool, max_display_depth: u32, @@ -319,6 +336,7 @@ fn print_node<'a>( node_index, format, symbols, + pkgs_to_prune, prefix, no_dedupe, max_display_depth, @@ -339,6 +357,7 @@ fn print_dependencies<'a>( node_index: usize, format: &Pattern, symbols: &Symbols, + pkgs_to_prune: &[PackageIdSpec], prefix: Prefix, no_dedupe: bool, max_display_depth: u32, @@ -391,6 +410,19 @@ fn print_dependencies<'a>( true } }) + .filter(|dep| { + // Filter out packages to prune. + if !pkgs_to_prune.is_empty() { + match graph.node(**dep) { + Node::Package { package_id, .. } => { + !pkgs_to_prune.iter().any(|spec| spec.matches(*package_id)) + } + _ => true, + } + } else { + true + } + }) .peekable(); while let Some(dependency) = it.next() { @@ -401,6 +433,7 @@ fn print_dependencies<'a>( *dependency, format, symbols, + pkgs_to_prune, prefix, no_dedupe, max_display_depth, From 64f5d1011351206716415e3140943f0c182a83e2 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 29 May 2021 11:22:53 +0800 Subject: [PATCH 3/6] test(carog-tree): new `--prune` option --- tests/testsuite/tree.rs | 78 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tests/testsuite/tree.rs b/tests/testsuite/tree.rs index c9a5441b627..acb727b64cf 100644 --- a/tests/testsuite/tree.rs +++ b/tests/testsuite/tree.rs @@ -1720,3 +1720,81 @@ c v1.0.0 ) .run(); } + +#[cargo_test] +fn prune() { + let p = make_simple_proj(); + + p.cargo("tree --prune c") + .with_stdout( + "\ +foo v0.1.0 ([..]/foo) +└── a v1.0.0 + └── b v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── b v1.0.0 (*) +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) +", + ) + .run(); + + // multiple prune + p.cargo("tree --prune c --prune bdep") + .with_stdout( + "\ +foo v0.1.0 ([..]/foo) +└── a v1.0.0 + └── b v1.0.0 +[build-dependencies] +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) +", + ) + .run(); + + // with edge-kinds + p.cargo("tree --prune c -e normal") + .with_stdout( + "\ +foo v0.1.0 ([..]/foo) +└── a v1.0.0 + └── b v1.0.0 +", + ) + .run(); + + // pruning self does not works + p.cargo("tree --prune foo") + .with_stdout( + "\ +foo v0.1.0 ([..]/foo) +├── a v1.0.0 +│ └── b v1.0.0 +│ └── c v1.0.0 +└── c v1.0.0 +[build-dependencies] +└── bdep v1.0.0 + └── b v1.0.0 (*) +[dev-dependencies] +└── devdep v1.0.0 + └── b v1.0.0 (*) +", + ) + .run(); + + // dep not exist + p.cargo("tree --prune no-dep") + .with_stderr( + "\ +[ERROR] package ID specification `no-dep` did not match any packages + +Did you mean `bdep`? +", + ) + .with_status(101) + .run(); +} From 07c40a7c86a93f6443283cd2104690d2f87c926d Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 29 May 2021 11:33:26 +0800 Subject: [PATCH 4/6] doc(carog-tree): new `--prune` option --- src/doc/man/cargo-tree.md | 4 ++++ src/doc/man/generated_txt/cargo-tree.txt | 3 +++ src/doc/src/commands/cargo-tree.md | 4 ++++ src/etc/man/cargo-tree.1 | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/src/doc/man/cargo-tree.md b/src/doc/man/cargo-tree.md index e4a1b616a97..e8d4397938b 100644 --- a/src/doc/man/cargo-tree.md +++ b/src/doc/man/cargo-tree.md @@ -71,6 +71,10 @@ flag can be used to display the package's reverse dependencies only with the subtree of the package given to `-p`. {{/option}} +{{#option "`--prune` _spec_" }} +Prune the given package from the display of the dependency tree. +{{/option}} + {{#option "`--depth` _depth_" }} Maximum display depth of the dependency tree. A depth of 1 displays the direct dependencies, for example. diff --git a/src/doc/man/generated_txt/cargo-tree.txt b/src/doc/man/generated_txt/cargo-tree.txt index 345a941d2ef..3928eca014b 100644 --- a/src/doc/man/generated_txt/cargo-tree.txt +++ b/src/doc/man/generated_txt/cargo-tree.txt @@ -59,6 +59,9 @@ OPTIONS package's reverse dependencies only with the subtree of the package given to -p. + --prune spec + Prune the given package from the display of the dependency tree. + --depth depth Maximum display depth of the dependency tree. A depth of 1 displays the direct dependencies, for example. diff --git a/src/doc/src/commands/cargo-tree.md b/src/doc/src/commands/cargo-tree.md index a085d63efaf..16b82f538fb 100644 --- a/src/doc/src/commands/cargo-tree.md +++ b/src/doc/src/commands/cargo-tree.md @@ -71,6 +71,10 @@ flag can be used to display the package's reverse dependencies only with the subtree of the package given to -p. +
--prune spec
+
Prune the given package from the display of the dependency tree.
+ +
--depth depth
Maximum display depth of the dependency tree. A depth of 1 displays the direct dependencies, for example.
diff --git a/src/etc/man/cargo-tree.1 b/src/etc/man/cargo-tree.1 index 48803dedc35..e2967e7c753 100644 --- a/src/etc/man/cargo-tree.1 +++ b/src/etc/man/cargo-tree.1 @@ -69,6 +69,11 @@ flag can be used to display the package's reverse dependencies only with the subtree of the package given to \fB\-p\fR\&. .RE .sp +\fB\-\-prune\fR \fIspec\fR +.RS 4 +Prune the given package from the display of the dependency tree. +.RE +.sp \fB\-\-depth\fR \fIdepth\fR .RS 4 Maximum display depth of the dependency tree. A depth of 1 displays the direct From 681c19438e1332caab31e1be69226669535de989 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 3 Jun 2021 06:52:01 +0800 Subject: [PATCH 5/6] refactor(cargo-tree): remove premature micro optimization Co-authored-by: Eric Huss --- src/cargo/ops/tree/mod.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/cargo/ops/tree/mod.rs b/src/cargo/ops/tree/mod.rs index 56f4692ca48..e9981b78650 100644 --- a/src/cargo/ops/tree/mod.rs +++ b/src/cargo/ops/tree/mod.rs @@ -412,15 +412,11 @@ fn print_dependencies<'a>( }) .filter(|dep| { // Filter out packages to prune. - if !pkgs_to_prune.is_empty() { - match graph.node(**dep) { - Node::Package { package_id, .. } => { - !pkgs_to_prune.iter().any(|spec| spec.matches(*package_id)) - } - _ => true, + match graph.node(**dep) { + Node::Package { package_id, .. } => { + !pkgs_to_prune.iter().any(|spec| spec.matches(*package_id)) } - } else { - true + _ => true, } }) .peekable(); From c685c139768091d7c972d1e16045c14532da01e8 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 3 Jun 2021 07:01:45 +0800 Subject: [PATCH 6/6] refactor(cargo-tree): simplify arg-parsing logic Co-authored-by: Eric Huss --- src/bin/cargo/commands/tree.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/bin/cargo/commands/tree.rs b/src/bin/cargo/commands/tree.rs index 07b4b23afc2..6b996d66fa2 100644 --- a/src/bin/cargo/commands/tree.rs +++ b/src/bin/cargo/commands/tree.rs @@ -157,15 +157,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { let (edge_kinds, no_proc_macro) = parse_edge_kinds(config, args)?; let graph_features = edge_kinds.contains(&EdgeKind::Feature); - let pkgs_to_prune = args.values_of("prune").map_or_else( - || Vec::new(), - |ps| { - let mut specs = ps.map(|p| p.to_string()).collect::>(); - specs.sort_unstable(); - specs.dedup(); - specs - }, - ); + let pkgs_to_prune = args._values_of("prune"); let packages = args.packages_from_flags()?; let mut invert = args