Skip to content

Commit

Permalink
Auto merge of rust-lang#9520 - weihanglo:tree-prune, r=ehuss
Browse files Browse the repository at this point in the history
Add `--prune` option for cargo-tree

Part of rust-lang#8105

Prune the given package from the display of the dependency tree. Also providing a nice suggestion if the package is not within the resolved dependency graph.
  • Loading branch information
bors committed Jun 9, 2021
2 parents e21e03f + c685c13 commit aa8b092
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 19 deletions.
8 changes: 8 additions & 0 deletions src/bin/cargo/commands/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -152,6 +157,8 @@ 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");

let packages = args.packages_from_flags()?;
let mut invert = args
.values_of("invert")
Expand Down Expand Up @@ -197,6 +204,7 @@ subtree of the package given to -p.\n\
target,
edge_kinds,
invert,
pkgs_to_prune,
prefix,
no_dedupe,
duplicates: args.is_present("duplicates"),
Expand Down
70 changes: 51 additions & 19 deletions src/cargo/ops/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub struct TreeOptions {
/// The dependency kinds to display.
pub edge_kinds: HashSet<EdgeKind>,
pub invert: Vec<String>,
/// The packages to prune from the display of the dependency tree.
pub pkgs_to_prune: Vec<String>,
/// The style of prefix for each line.
pub prefix: Prefix,
/// If `true`, duplicates will be repeated.
Expand Down Expand Up @@ -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::<CargoResult<Vec<PackageIdSpec>>>()?;

print(ws.config(), opts, root_indexes, &pkgs_to_prune, &graph)?;
Ok(())
}

Expand All @@ -208,6 +222,7 @@ fn print(
config: &Config,
opts: &TreeOptions,
roots: Vec<usize>,
pkgs_to_prune: &[PackageIdSpec],
graph: &Graph<'_>,
) -> CargoResult<()> {
let format = Pattern::new(&opts.format)
Expand Down Expand Up @@ -240,6 +255,7 @@ fn print(
root_index,
&format,
symbols,
pkgs_to_prune,
opts.prefix,
opts.no_dedupe,
opts.max_display_depth,
Expand All @@ -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,
Expand Down Expand Up @@ -319,6 +336,7 @@ fn print_node<'a>(
node_index,
format,
symbols,
pkgs_to_prune,
prefix,
no_dedupe,
max_display_depth,
Expand All @@ -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,
Expand Down Expand Up @@ -371,6 +390,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| {
Expand All @@ -386,26 +410,34 @@ fn print_dependencies<'a>(
true
}
})
.filter(|dep| {
// Filter out packages to prune.
match graph.node(**dep) {
Node::Package { package_id, .. } => {
!pkgs_to_prune.iter().any(|spec| spec.matches(*package_id))
}
_ => true,
}
})
.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,
pkgs_to_prune,
prefix,
no_dedupe,
max_display_depth,
no_proc_macro,
visited_deps,
levels_continue,
print_stack,
);
levels_continue.pop();
}
}
4 changes: 4 additions & 0 deletions src/doc/man/cargo-tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
3 changes: 3 additions & 0 deletions src/doc/man/generated_txt/cargo-tree.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions src/doc/src/commands/cargo-tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ flag can be used to display the package's reverse dependencies only with the
subtree of the package given to <code>-p</code>.</dd>


<dt class="option-term" id="option-cargo-tree---prune"><a class="option-anchor" href="#option-cargo-tree---prune"></a><code>--prune</code> <em>spec</em></dt>
<dd class="option-desc">Prune the given package from the display of the dependency tree.</dd>


<dt class="option-term" id="option-cargo-tree---depth"><a class="option-anchor" href="#option-cargo-tree---depth"></a><code>--depth</code> <em>depth</em></dt>
<dd class="option-desc">Maximum display depth of the dependency tree. A depth of 1 displays the direct
dependencies, for example.</dd>
Expand Down
5 changes: 5 additions & 0 deletions src/etc/man/cargo-tree.1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
78 changes: 78 additions & 0 deletions tests/testsuite/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
<tab>Did you mean `bdep`?
",
)
.with_status(101)
.run();
}

0 comments on commit aa8b092

Please sign in to comment.