Skip to content

Commit aa8b092

Browse files
committed
Auto merge of #9520 - weihanglo:tree-prune, r=ehuss
Add `--prune` option for cargo-tree Part of #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.
2 parents e21e03f + c685c13 commit aa8b092

File tree

7 files changed

+153
-19
lines changed

7 files changed

+153
-19
lines changed

src/bin/cargo/commands/tree.rs

+8
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ pub fn cli() -> App {
5656
)
5757
.short("i"),
5858
)
59+
.arg(multi_opt(
60+
"prune",
61+
"SPEC",
62+
"Prune the given package from the display of the dependency tree",
63+
))
5964
.arg(opt("depth", "Maximum display depth of the dependency tree").value_name("DEPTH"))
6065
// Deprecated, use --prefix=none instead.
6166
.arg(Arg::with_name("no-indent").long("no-indent").hidden(true))
@@ -152,6 +157,8 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
152157
let (edge_kinds, no_proc_macro) = parse_edge_kinds(config, args)?;
153158
let graph_features = edge_kinds.contains(&EdgeKind::Feature);
154159

160+
let pkgs_to_prune = args._values_of("prune");
161+
155162
let packages = args.packages_from_flags()?;
156163
let mut invert = args
157164
.values_of("invert")
@@ -197,6 +204,7 @@ subtree of the package given to -p.\n\
197204
target,
198205
edge_kinds,
199206
invert,
207+
pkgs_to_prune,
200208
prefix,
201209
no_dedupe,
202210
duplicates: args.is_present("duplicates"),

src/cargo/ops/tree/mod.rs

+51-19
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ pub struct TreeOptions {
2727
/// The dependency kinds to display.
2828
pub edge_kinds: HashSet<EdgeKind>,
2929
pub invert: Vec<String>,
30+
/// The packages to prune from the display of the dependency tree.
31+
pub pkgs_to_prune: Vec<String>,
3032
/// The style of prefix for each line.
3133
pub prefix: Prefix,
3234
/// If `true`, duplicates will be repeated.
@@ -199,7 +201,19 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
199201
graph.invert();
200202
}
201203

202-
print(ws.config(), opts, root_indexes, &graph)?;
204+
// Packages to prune.
205+
let pkgs_to_prune = opts
206+
.pkgs_to_prune
207+
.iter()
208+
.map(|p| PackageIdSpec::parse(p))
209+
.map(|r| {
210+
// Provide a error message if pkgid is not within the resolved
211+
// dependencies graph.
212+
r.and_then(|spec| spec.query(ws_resolve.targeted_resolve.iter()).and(Ok(spec)))
213+
})
214+
.collect::<CargoResult<Vec<PackageIdSpec>>>()?;
215+
216+
print(ws.config(), opts, root_indexes, &pkgs_to_prune, &graph)?;
203217
Ok(())
204218
}
205219

@@ -208,6 +222,7 @@ fn print(
208222
config: &Config,
209223
opts: &TreeOptions,
210224
roots: Vec<usize>,
225+
pkgs_to_prune: &[PackageIdSpec],
211226
graph: &Graph<'_>,
212227
) -> CargoResult<()> {
213228
let format = Pattern::new(&opts.format)
@@ -240,6 +255,7 @@ fn print(
240255
root_index,
241256
&format,
242257
symbols,
258+
pkgs_to_prune,
243259
opts.prefix,
244260
opts.no_dedupe,
245261
opts.max_display_depth,
@@ -260,6 +276,7 @@ fn print_node<'a>(
260276
node_index: usize,
261277
format: &Pattern,
262278
symbols: &Symbols,
279+
pkgs_to_prune: &[PackageIdSpec],
263280
prefix: Prefix,
264281
no_dedupe: bool,
265282
max_display_depth: u32,
@@ -319,6 +336,7 @@ fn print_node<'a>(
319336
node_index,
320337
format,
321338
symbols,
339+
pkgs_to_prune,
322340
prefix,
323341
no_dedupe,
324342
max_display_depth,
@@ -339,6 +357,7 @@ fn print_dependencies<'a>(
339357
node_index: usize,
340358
format: &Pattern,
341359
symbols: &Symbols,
360+
pkgs_to_prune: &[PackageIdSpec],
342361
prefix: Prefix,
343362
no_dedupe: bool,
344363
max_display_depth: u32,
@@ -371,6 +390,11 @@ fn print_dependencies<'a>(
371390
}
372391
}
373392

393+
// Current level exceeds maximum display depth. Skip.
394+
if levels_continue.len() + 1 > max_display_depth as usize {
395+
return;
396+
}
397+
374398
let mut it = deps
375399
.iter()
376400
.filter(|dep| {
@@ -386,26 +410,34 @@ fn print_dependencies<'a>(
386410
true
387411
}
388412
})
413+
.filter(|dep| {
414+
// Filter out packages to prune.
415+
match graph.node(**dep) {
416+
Node::Package { package_id, .. } => {
417+
!pkgs_to_prune.iter().any(|spec| spec.matches(*package_id))
418+
}
419+
_ => true,
420+
}
421+
})
389422
.peekable();
390423

391424
while let Some(dependency) = it.next() {
392-
if levels_continue.len() + 1 <= max_display_depth as usize {
393-
levels_continue.push(it.peek().is_some());
394-
print_node(
395-
config,
396-
graph,
397-
*dependency,
398-
format,
399-
symbols,
400-
prefix,
401-
no_dedupe,
402-
max_display_depth,
403-
no_proc_macro,
404-
visited_deps,
405-
levels_continue,
406-
print_stack,
407-
);
408-
levels_continue.pop();
409-
}
425+
levels_continue.push(it.peek().is_some());
426+
print_node(
427+
config,
428+
graph,
429+
*dependency,
430+
format,
431+
symbols,
432+
pkgs_to_prune,
433+
prefix,
434+
no_dedupe,
435+
max_display_depth,
436+
no_proc_macro,
437+
visited_deps,
438+
levels_continue,
439+
print_stack,
440+
);
441+
levels_continue.pop();
410442
}
411443
}

src/doc/man/cargo-tree.md

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ flag can be used to display the package's reverse dependencies only with the
7171
subtree of the package given to `-p`.
7272
{{/option}}
7373

74+
{{#option "`--prune` _spec_" }}
75+
Prune the given package from the display of the dependency tree.
76+
{{/option}}
77+
7478
{{#option "`--depth` _depth_" }}
7579
Maximum display depth of the dependency tree. A depth of 1 displays the direct
7680
dependencies, for example.

src/doc/man/generated_txt/cargo-tree.txt

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ OPTIONS
5959
package's reverse dependencies only with the subtree of the package
6060
given to -p.
6161

62+
--prune spec
63+
Prune the given package from the display of the dependency tree.
64+
6265
--depth depth
6366
Maximum display depth of the dependency tree. A depth of 1 displays
6467
the direct dependencies, for example.

src/doc/src/commands/cargo-tree.md

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ flag can be used to display the package's reverse dependencies only with the
7171
subtree of the package given to <code>-p</code>.</dd>
7272

7373

74+
<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>
75+
<dd class="option-desc">Prune the given package from the display of the dependency tree.</dd>
76+
77+
7478
<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>
7579
<dd class="option-desc">Maximum display depth of the dependency tree. A depth of 1 displays the direct
7680
dependencies, for example.</dd>

src/etc/man/cargo-tree.1

+5
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ flag can be used to display the package's reverse dependencies only with the
6969
subtree of the package given to \fB\-p\fR\&.
7070
.RE
7171
.sp
72+
\fB\-\-prune\fR \fIspec\fR
73+
.RS 4
74+
Prune the given package from the display of the dependency tree.
75+
.RE
76+
.sp
7277
\fB\-\-depth\fR \fIdepth\fR
7378
.RS 4
7479
Maximum display depth of the dependency tree. A depth of 1 displays the direct

tests/testsuite/tree.rs

+78
Original file line numberDiff line numberDiff line change
@@ -1720,3 +1720,81 @@ c v1.0.0
17201720
)
17211721
.run();
17221722
}
1723+
1724+
#[cargo_test]
1725+
fn prune() {
1726+
let p = make_simple_proj();
1727+
1728+
p.cargo("tree --prune c")
1729+
.with_stdout(
1730+
"\
1731+
foo v0.1.0 ([..]/foo)
1732+
└── a v1.0.0
1733+
└── b v1.0.0
1734+
[build-dependencies]
1735+
└── bdep v1.0.0
1736+
└── b v1.0.0 (*)
1737+
[dev-dependencies]
1738+
└── devdep v1.0.0
1739+
└── b v1.0.0 (*)
1740+
",
1741+
)
1742+
.run();
1743+
1744+
// multiple prune
1745+
p.cargo("tree --prune c --prune bdep")
1746+
.with_stdout(
1747+
"\
1748+
foo v0.1.0 ([..]/foo)
1749+
└── a v1.0.0
1750+
└── b v1.0.0
1751+
[build-dependencies]
1752+
[dev-dependencies]
1753+
└── devdep v1.0.0
1754+
└── b v1.0.0 (*)
1755+
",
1756+
)
1757+
.run();
1758+
1759+
// with edge-kinds
1760+
p.cargo("tree --prune c -e normal")
1761+
.with_stdout(
1762+
"\
1763+
foo v0.1.0 ([..]/foo)
1764+
└── a v1.0.0
1765+
└── b v1.0.0
1766+
",
1767+
)
1768+
.run();
1769+
1770+
// pruning self does not works
1771+
p.cargo("tree --prune foo")
1772+
.with_stdout(
1773+
"\
1774+
foo v0.1.0 ([..]/foo)
1775+
├── a v1.0.0
1776+
│ └── b v1.0.0
1777+
│ └── c v1.0.0
1778+
└── c v1.0.0
1779+
[build-dependencies]
1780+
└── bdep v1.0.0
1781+
└── b v1.0.0 (*)
1782+
[dev-dependencies]
1783+
└── devdep v1.0.0
1784+
└── b v1.0.0 (*)
1785+
",
1786+
)
1787+
.run();
1788+
1789+
// dep not exist
1790+
p.cargo("tree --prune no-dep")
1791+
.with_stderr(
1792+
"\
1793+
[ERROR] package ID specification `no-dep` did not match any packages
1794+
1795+
<tab>Did you mean `bdep`?
1796+
",
1797+
)
1798+
.with_status(101)
1799+
.run();
1800+
}

0 commit comments

Comments
 (0)