Switch --invert to take the package name as an argument.

This commit is contained in:
Eric Huss 2020-04-03 19:52:21 -07:00
parent 96ff434cb9
commit 7c403447bd
8 changed files with 177 additions and 93 deletions

View file

@ -2,6 +2,7 @@ use crate::command_prelude::*;
use anyhow::{bail, format_err};
use cargo::core::dependency::DepKind;
use cargo::ops::tree::{self, EdgeKind};
use cargo::ops::Packages;
use cargo::util::CargoResult;
use std::collections::HashSet;
use std::str::FromStr;
@ -40,7 +41,14 @@ pub fn cli() -> App {
)
.short("e"),
)
.arg(opt("invert", "Invert the tree direction").short("i"))
.arg(
optional_multi_opt(
"invert",
"SPEC",
"Invert the tree direction and focus on the given package",
)
.short("i"),
)
.arg(Arg::with_name("no-indent").long("no-indent").hidden(true))
.arg(
Arg::with_name("prefix-depth")
@ -119,6 +127,37 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
let edge_kinds = parse_edge_kinds(config, args)?;
let graph_features = edge_kinds.contains(&EdgeKind::Feature);
let packages = args.packages_from_flags()?;
let mut invert = args
.values_of("invert")
.map_or_else(|| Vec::new(), |is| is.map(|s| s.to_string()).collect());
if args.is_present_with_zero_values("invert") {
match &packages {
Packages::Packages(ps) => {
// Backwards compatibility with old syntax of `cargo tree -i -p foo`.
invert.extend(ps.clone());
}
_ => {
return Err(format_err!(
"The `-i` flag requires a package name.\n\
\n\
The `-i` flag is used to inspect the reverse dependencies of a specific\n\
package. It will invert the tree and display the packages that depend on the\n\
given package.\n\
\n\
Note that in a workspace, by default it will only display the package's\n\
reverse dependencies inside the tree of the workspace member in the current\n\
directory. The --workspace flag can be used to extend it so that it will show\n\
the package's reverse dependencies across the entire workspace. The -p flag\n\
can be used to display the package's reverse dependencies only with the\n\
subtree of the package given to -p.\n\
"
)
.into());
}
}
}
let ws = args.workspace(config)?;
let charset = tree::Charset::from_str(args.value_of("charset").unwrap())
.map_err(|e| anyhow::anyhow!("{}", e))?;
@ -126,10 +165,10 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
features: values(args, "features"),
all_features: args.is_present("all-features"),
no_default_features: args.is_present("no-default-features"),
packages: args.packages_from_flags()?,
packages,
target,
edge_kinds,
invert: args.is_present("invert"),
invert,
prefix,
no_dedupe: args.is_present("no-dedupe"),
duplicates: args.is_present("duplicates"),

View file

@ -4,7 +4,7 @@ use self::format::Pattern;
use crate::core::compiler::{CompileKind, RustcTargetData};
use crate::core::dependency::DepKind;
use crate::core::resolver::{HasDevUnits, ResolveOpts};
use crate::core::{Package, PackageId, Workspace};
use crate::core::{Package, PackageId, PackageIdSpec, Workspace};
use crate::ops::{self, Packages};
use crate::util::CargoResult;
use anyhow::{bail, Context};
@ -27,7 +27,7 @@ pub struct TreeOptions {
pub target: Target,
/// The dependency kinds to display.
pub edge_kinds: HashSet<EdgeKind>,
pub invert: bool,
pub invert: Vec<String>,
/// The style of prefix for each line.
pub prefix: Prefix,
/// If `true`, duplicates will be repeated.
@ -177,7 +177,15 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
opts,
)?;
let root_ids = ws_resolve.targeted_resolve.specs_to_ids(&specs)?;
let root_specs = if opts.invert.is_empty() {
specs
} else {
opts.invert
.iter()
.map(|p| PackageIdSpec::parse(p))
.collect::<CargoResult<Vec<PackageIdSpec>>>()?
};
let root_ids = ws_resolve.targeted_resolve.specs_to_ids(&root_specs)?;
let root_indexes = graph.indexes_from_ids(&root_ids);
let root_indexes = if opts.duplicates {
@ -188,7 +196,7 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
root_indexes
};
if opts.invert || opts.duplicates {
if !opts.invert.is_empty() || opts.duplicates {
graph.invert();
}

View file

@ -84,6 +84,20 @@ class MonoPostprocessor < Extensions::Postprocessor
end
end
# Man pages are ASCII only. Unfortunately asciidoc doesn't process these
# characters for us. The `cargo tree` manpage needs a little assistance.
class SpecialCharPostprocessor < Extensions::Postprocessor
def process document, output
if document.basebackend? 'manpage'
output = output.gsub(//, '|')
.gsub(//, '|')
.gsub(//, '`')
.gsub(//, '\-')
end
output
end
end
# General utility for converting text. Example:
#
# convert:lowercase[{somevar}]
@ -107,4 +121,5 @@ Extensions.register :uri_schemes do
inline_macro LinkCargoInlineMacro
inline_macro ConvertInlineMacro
postprocessor MonoPostprocessor
postprocessor SpecialCharPostprocessor
end

View file

@ -52,17 +52,24 @@ myproject v0.1.0 (/myproject)
In this tree, `myproject` depends on `log` with the `serde` feature. `log` in
turn depends on `cfg-if` with "default" features. When using `-e features` it
can be helpful to use `-i` and `-p` flags to show how the features flow into a
package. See the examples below for more detail.
can be helpful to use `-i` flag to show how the features flow into a package.
See the examples below for more detail.
== OPTIONS
=== Tree Options
*-i*::
*--invert*::
Invert the tree. Typically this flag is used with the `-p` flag to show
the dependencies for a specific package.
*-i* _SPEC_::
*--invert* _SPEC_::
Show the reverse dependencies for the given package. This flag will invert
the tree and display the packages that depend on the given package.
+
Note that in a workspace, by default it will only display the package's
reverse dependencies inside the tree of the workspace member in the current
directory. The `--workspace` flag can be used to extend it so that it will
show the package's reverse dependencies across the entire workspace. The `-p`
flag can be used to display the package's reverse dependencies only with the
subtree of the package given to `-p`.
*--no-dedupe*::
Do not de-duplicate repeated dependencies. Usually, when a package has
@ -161,9 +168,9 @@ include::section-exit-status.adoc[]
cargo tree
. Display all the packages that depend on the specified package:
. Display all the packages that depend on the `syn` package:
cargo tree -i -p syn
cargo tree -i syn
. Show the features enabled on each package:
@ -174,13 +181,13 @@ include::section-exit-status.adoc[]
cargo tree -d
. Explain why features are enabled for the given package:
. Explain why features are enabled for the `syn` package:
cargo tree -e features -i -p syn
cargo tree -e features -i syn
+
The `-e features` flag is used to show features. The `-i` flag is used to
invert the graph so that it displays the packages that depend on `syn` (not
what `syn` depends on). An example of what this would display:
invert the graph so that it displays the packages that depend on `syn`. An
example of what this would display:
+
----
syn v1.0.17

View file

@ -57,8 +57,8 @@ each dependency. For example, <code>cargo tree -e features</code>:</p>
<div class="paragraph">
<p>In this tree, <code>myproject</code> depends on <code>log</code> with the <code>serde</code> feature. <code>log</code> in
turn depends on <code>cfg-if</code> with "default" features. When using <code>-e features</code> it
can be helpful to use <code>-i</code> and <code>-p</code> flags to show how the features flow into a
package. See the examples below for more detail.</p>
can be helpful to use <code>-i</code> flag to show how the features flow into a package.
See the examples below for more detail.</p>
</div>
</div>
</div>
@ -69,11 +69,19 @@ package. See the examples below for more detail.</p>
<h3 id="cargo_tree_tree_options">Tree Options</h3>
<div class="dlist">
<dl>
<dt class="hdlist1"><strong>-i</strong></dt>
<dt class="hdlist1"><strong>--invert</strong></dt>
<dt class="hdlist1"><strong>-i</strong> <em>SPEC</em></dt>
<dt class="hdlist1"><strong>--invert</strong> <em>SPEC</em></dt>
<dd>
<p>Invert the tree. Typically this flag is used with the <code>-p</code> flag to show
the dependencies for a specific package.</p>
<p>Show the reverse dependencies for the given package. This flag will invert
the tree and display the packages that depend on the given package.</p>
<div class="paragraph">
<p>Note that in a workspace, by default it will only display the package&#8217;s
reverse dependencies inside the tree of the workspace member in the current
directory. The <code>--workspace</code> flag can be used to extend it so that it will
show the package&#8217;s reverse dependencies across the entire workspace. The <code>-p</code>
flag can be used to display the package&#8217;s reverse dependencies only with the
subtree of the package given to <code>-p</code>.</p>
</div>
</dd>
<dt class="hdlist1"><strong>--no-dedupe</strong></dt>
<dd>
@ -412,10 +420,10 @@ details on environment variables that Cargo reads.</p>
</div>
</li>
<li>
<p>Display all the packages that depend on the specified package:</p>
<p>Display all the packages that depend on the <code>syn</code> package:</p>
<div class="literalblock">
<div class="content">
<pre>cargo tree -i -p syn</pre>
<pre>cargo tree -i syn</pre>
</div>
</div>
</li>
@ -437,16 +445,16 @@ semver-incompatible versions appear in the tree (like 1.0.0 and 2.0.0).</p>
</div>
</li>
<li>
<p>Explain why features are enabled for the given package:</p>
<p>Explain why features are enabled for the <code>syn</code> package:</p>
<div class="literalblock">
<div class="content">
<pre>cargo tree -e features -i -p syn</pre>
<pre>cargo tree -e features -i syn</pre>
</div>
</div>
<div class="paragraph">
<p>The <code>-e features</code> flag is used to show features. The <code>-i</code> flag is used to
invert the graph so that it displays the packages that depend on <code>syn</code> (not
what <code>syn</code> depends on). An example of what this would display:</p>
invert the graph so that it displays the packages that depend on <code>syn</code>. An
example of what this would display:</p>
</div>
<div class="listingblock">
<div class="content">

View file

@ -40,18 +40,18 @@ of a simple project that depends on the "rand" package:
.if n .RS 4
.nf
myproject v0.1.0 (/myproject)
└── rand v0.7.3
├── getrandom v0.1.14
│ ├── cfg\-if v0.1.10
│ └── libc v0.2.68
├── libc v0.2.68 (*)
├── rand_chacha v0.2.2
│ ├── ppv\-lite86 v0.2.6
│ └── rand_core v0.5.1
│ └── getrandom v0.1.14 (*)
└── rand_core v0.5.1 (*)
`\-\- rand v0.7.3
|\-\- getrandom v0.1.14
| |\-\- cfg\-if v0.1.10
| `\-\- libc v0.2.68
|\-\- libc v0.2.68 (*)
|\-\- rand_chacha v0.2.2
| |\-\- ppv\-lite86 v0.2.6
| `\-\- rand_core v0.5.1
| `\-\- getrandom v0.1.14 (*)
`\-\- rand_core v0.5.1 (*)
[build\-dependencies]
└── cc v1.0.50
`\-\- cc v1.0.50
.fi
.if n .RE
.sp
@ -66,25 +66,32 @@ each dependency. For example, \fBcargo tree \-e features\fP:
.if n .RS 4
.nf
myproject v0.1.0 (/myproject)
└── log feature "serde"
└── log v0.4.8
├── serde v1.0.106
└── cfg\-if feature "default"
└── cfg\-if v0.1.10
`\-\- log feature "serde"
`\-\- log v0.4.8
|\-\- serde v1.0.106
`\-\- cfg\-if feature "default"
`\-\- cfg\-if v0.1.10
.fi
.if n .RE
.sp
In this tree, \fBmyproject\fP depends on \fBlog\fP with the \fBserde\fP feature. \fBlog\fP in
turn depends on \fBcfg\-if\fP with "default" features. When using \fB\-e features\fP it
can be helpful to use \fB\-i\fP and \fB\-p\fP flags to show how the features flow into a
package. See the examples below for more detail.
can be helpful to use \fB\-i\fP flag to show how the features flow into a package.
See the examples below for more detail.
.SH "OPTIONS"
.SS "Tree Options"
.sp
\fB\-i\fP, \fB\-\-invert\fP
\fB\-i\fP \fISPEC\fP, \fB\-\-invert\fP \fISPEC\fP
.RS 4
Invert the tree. Typically this flag is used with the \fB\-p\fP flag to show
the dependencies for a specific package.
Show the reverse dependencies for the given package. This flag will invert
the tree and display the packages that depend on the given package.
.sp
Note that in a workspace, by default it will only display the package\(cqs
reverse dependencies inside the tree of the workspace member in the current
directory. The \fB\-\-workspace\fP flag can be used to extend it so that it will
show the package\(cqs reverse dependencies across the entire workspace. The \fB\-p\fP
flag can be used to display the package\(cqs reverse dependencies only with the
subtree of the package given to \fB\-p\fP.
.RE
.sp
\fB\-\-no\-dedupe\fP
@ -516,11 +523,11 @@ cargo tree
. sp -1
. IP " 2." 4.2
.\}
Display all the packages that depend on the specified package:
Display all the packages that depend on the \fBsyn\fP package:
.sp
.if n .RS 4
.nf
cargo tree \-i \-p syn
cargo tree \-i syn
.fi
.if n .RE
.RE
@ -568,41 +575,41 @@ cargo tree \-d
. sp -1
. IP " 5." 4.2
.\}
Explain why features are enabled for the given package:
Explain why features are enabled for the \fBsyn\fP package:
.sp
.if n .RS 4
.nf
cargo tree \-e features \-i \-p syn
cargo tree \-e features \-i syn
.fi
.if n .RE
.sp
The \fB\-e features\fP flag is used to show features. The \fB\-i\fP flag is used to
invert the graph so that it displays the packages that depend on \fBsyn\fP (not
what \fBsyn\fP depends on). An example of what this would display:
invert the graph so that it displays the packages that depend on \fBsyn\fP. An
example of what this would display:
.sp
.if n .RS 4
.nf
syn v1.0.17
├── syn feature "clone\-impls"
│ └── syn feature "default"
│ └── rustversion v1.0.2
│ └── rustversion feature "default"
│ └── myproject v0.1.0 (/myproject)
│ └── myproject feature "default" (command\-line)
├── syn feature "default" (*)
├── syn feature "derive"
│ └── syn feature "default" (*)
├── syn feature "full"
│ └── rustversion v1.0.2 (*)
├── syn feature "parsing"
│ └── syn feature "default" (*)
├── syn feature "printing"
│ └── syn feature "default" (*)
├── syn feature "proc\-macro"
│ └── syn feature "default" (*)
└── syn feature "quote"
├── syn feature "printing" (*)
└── syn feature "proc\-macro" (*)
|\-\- syn feature "clone\-impls"
| `\-\- syn feature "default"
| `\-\- rustversion v1.0.2
| `\-\- rustversion feature "default"
| `\-\- myproject v0.1.0 (/myproject)
| `\-\- myproject feature "default" (command\-line)
|\-\- syn feature "default" (*)
|\-\- syn feature "derive"
| `\-\- syn feature "default" (*)
|\-\- syn feature "full"
| `\-\- rustversion v1.0.2 (*)
|\-\- syn feature "parsing"
| `\-\- syn feature "default" (*)
|\-\- syn feature "printing"
| `\-\- syn feature "default" (*)
|\-\- syn feature "proc\-macro"
| `\-\- syn feature "default" (*)
`\-\- syn feature "quote"
|\-\- syn feature "printing" (*)
`\-\- syn feature "proc\-macro" (*)
.fi
.if n .RE
.sp

View file

@ -582,7 +582,7 @@ foo v0.1.0 ([..]/foo)
)
.run();
p.cargo("tree --invert")
p.cargo("tree --invert foo")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
@ -630,7 +630,7 @@ foo v0.1.0 ([..]/foo)
)
.run();
p.cargo("tree --invert -p c")
p.cargo("tree --invert c")
.with_stdout(
"\
c v1.0.0
@ -644,7 +644,7 @@ c v1.0.0
#[cargo_test]
fn invert_with_build_dep() {
// -i with -p for a common dependency between normal and build deps.
// -i for a common dependency between normal and build deps.
Package::new("common", "1.0.0").publish();
Package::new("bdep", "1.0.0").dep("common", "1.0").publish();
let p = project()
@ -677,7 +677,7 @@ foo v0.1.0 ([..]/foo)
)
.run();
p.cargo("tree -i -p common")
p.cargo("tree -i common")
.with_stdout(
"\
common v1.0.0
@ -1136,8 +1136,8 @@ bar v1.0.0
)
.run();
// invert -p
p.cargo("tree -i -p optdep")
// invert
p.cargo("tree -i optdep")
.with_stdout(
"\
optdep v1.0.0
@ -1149,7 +1149,7 @@ optdep v1.0.0
)
.run();
p.cargo("tree -i -p optdep -Zfeatures=host_dep")
p.cargo("tree -i optdep -Zfeatures=host_dep")
.masquerade_as_nightly_cargo()
.with_stdout(
"\
@ -1252,8 +1252,8 @@ somedep v1.0.0
)
.run();
// invert -p
p.cargo("tree -i -p somedep")
// invert
p.cargo("tree -i somedep")
.with_stdout(
"\
somedep v1.0.0
@ -1264,7 +1264,7 @@ somedep v1.0.0
)
.run();
p.cargo("tree -i -p somedep -Zfeatures=host_dep")
p.cargo("tree -i somedep -Zfeatures=host_dep")
.masquerade_as_nightly_cargo()
.with_stdout(
"\

View file

@ -148,7 +148,7 @@ b v0.1.0 ([..]/foo/b)
)
.run();
p.cargo("tree -e features -i")
p.cargo("tree -e features -i a -i b")
.with_stdout(
"\
a v0.1.0 ([..]/foo/a)
@ -211,7 +211,7 @@ foo v0.1.0 ([..]/foo)
)
.run();
p.cargo("tree -e features --features f1 -i")
p.cargo("tree -e features --features f1 -i foo")
.with_stdout(
"\
foo v0.1.0 ([..]/foo)
@ -223,7 +223,7 @@ foo v0.1.0 ([..]/foo)
)
.run();
p.cargo("tree -e features --features f1 -p notopt -i")
p.cargo("tree -e features --features f1 -i notopt")
.with_stdout(
"\
notopt v1.0.0
@ -241,7 +241,7 @@ notopt v1.0.0
)
.run();
p.cargo("tree -e features --features notopt/animal -p notopt -i")
p.cargo("tree -e features --features notopt/animal -i notopt")
.with_stdout(
"\
notopt v1.0.0
@ -269,7 +269,7 @@ foo v0.1.0 ([..]/foo)
)
.run();
p.cargo("tree -e features --all-features -p opt2 -i")
p.cargo("tree -e features --all-features -i opt2")
.with_stdout(
"\
opt2 v1.0.0