Skip to content

Commit 92544e2

Browse files
committed
Add format option to cargo tree to print the package version constraint
- Add a new formatting option {c} to `cargo tree` that prints the resolved version constraint of packages as specified in Cargo.toml. - Add a unit test to verify that the version constraint is printed correctly. - Update the `cargo tree` command documentation with the new option.
1 parent 4406c1b commit 92544e2

File tree

10 files changed

+187
-51
lines changed

10 files changed

+187
-51
lines changed

src/cargo/ops/tree/format/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::fmt;
22

33
use anyhow::{Error, bail};
44

5+
use crate::ops::tree::graph::NodePackage;
6+
57
use self::parse::{Parser, RawChunk};
68
use super::{Graph, Node, NodeId};
79

@@ -14,6 +16,7 @@ enum Chunk {
1416
Repository,
1517
Features,
1618
LibName,
19+
Constraint,
1720
}
1821

1922
pub struct Pattern(Vec<Chunk>);
@@ -30,6 +33,7 @@ impl Pattern {
3033
RawChunk::Argument("r") => Chunk::Repository,
3134
RawChunk::Argument("f") => Chunk::Features,
3235
RawChunk::Argument("lib") => Chunk::LibName,
36+
RawChunk::Argument("c") => Chunk::Constraint,
3337
RawChunk::Argument(a) => {
3438
bail!("unsupported pattern `{}`", a);
3539
}
@@ -60,11 +64,12 @@ impl<'a> fmt::Display for Display<'a> {
6064
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
6165
let node = self.graph.node(self.node_index);
6266
match node {
63-
Node::Package {
67+
Node::Package(NodePackage {
6468
package_id,
6569
features,
70+
version_req,
6671
..
67-
} => {
72+
}) => {
6873
let package = self.graph.package_for_id(*package_id);
6974
for chunk in &self.pattern.0 {
7075
match chunk {
@@ -111,13 +116,16 @@ impl<'a> fmt::Display for Display<'a> {
111116
write!(fmt, "{}", target.crate_name())?;
112117
}
113118
}
119+
Chunk::Constraint => {
120+
write!(fmt, "{}", version_req)?;
121+
}
114122
}
115123
}
116124
}
117125
Node::Feature { name, node_index } => {
118126
let for_node = self.graph.node(*node_index);
119127
match for_node {
120-
Node::Package { package_id, .. } => {
128+
Node::Package(NodePackage { package_id, .. }) => {
121129
write!(fmt, "{} feature \"{}\"", package_id.name(), name)?;
122130
if self.graph.is_cli_feature(self.node_index) {
123131
write!(fmt, " (command-line)")?;

src/cargo/ops/tree/graph.rs

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use crate::core::dependency::DepKind;
66
use crate::core::resolver::Resolve;
77
use crate::core::resolver::features::{CliFeatures, FeaturesFor, ResolvedFeatures};
88
use crate::core::{FeatureMap, FeatureValue, Package, PackageId, PackageIdSpec, Workspace};
9-
use crate::util::CargoResult;
109
use crate::util::interning::{INTERNED_DEFAULT, InternedString};
10+
use crate::util::{CargoResult, OptVersionReq};
11+
use std::cmp::Ordering;
1112
use std::collections::{HashMap, HashSet};
1213

1314
#[derive(Debug, Copy, Clone)]
@@ -49,14 +50,34 @@ impl std::hash::Hash for NodeId {
4950
}
5051
}
5152

53+
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
54+
pub struct NodePackage {
55+
pub package_id: PackageId,
56+
/// Features that are enabled on this package.
57+
pub features: Vec<InternedString>,
58+
pub kind: CompileKind,
59+
pub version_req: OptVersionReq,
60+
}
61+
62+
impl PartialOrd for NodePackage {
63+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
64+
Some(self.cmp(other))
65+
}
66+
}
67+
68+
impl Ord for NodePackage {
69+
fn cmp(&self, other: &Self) -> Ordering {
70+
self.package_id
71+
.cmp(&other.package_id)
72+
.then_with(|| self.features.cmp(&other.features))
73+
.then_with(|| self.kind.cmp(&other.kind))
74+
// version_req is not orderable
75+
}
76+
}
77+
5278
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
5379
pub enum Node {
54-
Package {
55-
package_id: PackageId,
56-
/// Features that are enabled on this package.
57-
features: Vec<InternedString>,
58-
kind: CompileKind,
59-
},
80+
Package(NodePackage),
6081
Feature {
6182
/// Index of the package node this feature is for.
6283
node_index: NodeId,
@@ -68,7 +89,7 @@ pub enum Node {
6889
impl Node {
6990
fn name(&self) -> InternedString {
7091
match self {
71-
Self::Package { package_id, .. } => package_id.name(),
92+
Self::Package(NodePackage { package_id, .. }) => package_id.name(),
7293
Self::Feature { name, .. } => *name,
7394
}
7495
}
@@ -218,7 +239,7 @@ impl<'a> Graph<'a> {
218239
.iter()
219240
.enumerate()
220241
.filter(|(_i, node)| match node {
221-
Node::Package { package_id, .. } => package_ids.contains(package_id),
242+
Node::Package(NodePackage { package_id, .. }) => package_ids.contains(package_id),
222243
_ => false,
223244
})
224245
.map(|(i, node)| (node, NodeId::new(i, node.name())))
@@ -235,7 +256,7 @@ impl<'a> Graph<'a> {
235256

236257
fn package_id_for_index(&self, index: NodeId) -> PackageId {
237258
match self.node(index) {
238-
Node::Package { package_id, .. } => *package_id,
259+
Node::Package(NodePackage { package_id, .. }) => *package_id,
239260
Node::Feature { .. } => panic!("unexpected feature node"),
240261
}
241262
}
@@ -314,7 +335,7 @@ impl<'a> Graph<'a> {
314335
// Collect a map of package name to Vec<(&Node, NodeId)>.
315336
let mut packages = HashMap::new();
316337
for (i, node) in self.nodes.iter().enumerate() {
317-
if let Node::Package { package_id, .. } = node {
338+
if let Node::Package(NodePackage { package_id, .. }) = node {
318339
packages
319340
.entry(package_id.name())
320341
.or_insert_with(Vec::new)
@@ -329,17 +350,19 @@ impl<'a> Graph<'a> {
329350
.into_iter()
330351
.map(|(node, _)| {
331352
match node {
332-
Node::Package {
353+
Node::Package(NodePackage {
333354
package_id,
334355
features,
356+
version_req,
335357
..
336-
} => {
358+
}) => {
337359
// Do not treat duplicates on the host or target as duplicates.
338-
Node::Package {
360+
Node::Package(NodePackage {
339361
package_id: package_id.clone(),
340362
features: features.clone(),
341363
kind: CompileKind::Host,
342-
}
364+
version_req: version_req.clone(),
365+
})
343366
}
344367
_ => unreachable!(),
345368
}
@@ -376,12 +399,14 @@ pub fn build<'a>(
376399
let member_id = member.package_id();
377400
let features_for = FeaturesFor::from_for_host(member.proc_macro());
378401
for kind in requested_kinds {
402+
let version_req = OptVersionReq::Any;
379403
let member_index = add_pkg(
380404
&mut graph,
381405
resolve,
382406
resolved_features,
383407
member_id,
384408
features_for,
409+
version_req,
385410
target_data,
386411
*kind,
387412
opts,
@@ -409,6 +434,7 @@ fn add_pkg(
409434
resolved_features: &ResolvedFeatures,
410435
package_id: PackageId,
411436
features_for: FeaturesFor,
437+
version_req: OptVersionReq,
412438
target_data: &RustcTargetData<'_>,
413439
requested_kind: CompileKind,
414440
opts: &TreeOptions,
@@ -419,11 +445,12 @@ fn add_pkg(
419445
FeaturesFor::ArtifactDep(target) => CompileKind::Target(target),
420446
FeaturesFor::NormalOrDev => requested_kind,
421447
};
422-
let node = Node::Package {
448+
let node = Node::Package(NodePackage {
423449
package_id,
424450
features: node_features,
425451
kind: node_kind,
426-
};
452+
version_req: version_req,
453+
});
427454
if let Some(idx) = graph.index.get(&node) {
428455
return *idx;
429456
}
@@ -513,12 +540,14 @@ fn add_pkg(
513540
}
514541
}
515542
};
543+
let dep_version_req = dep.version_req().clone();
516544
let dep_index = add_pkg(
517545
graph,
518546
resolve,
519547
resolved_features,
520548
dep_id,
521549
dep_features_for,
550+
dep_version_req,
522551
target_data,
523552
requested_kind,
524553
opts,

src/cargo/ops/tree/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::core::dependency::DepKind;
66
use crate::core::resolver::{ForceAllTargets, HasDevUnits, features::CliFeatures};
77
use crate::core::{Package, PackageId, PackageIdSpec, PackageIdSpecQuery, Workspace};
88
use crate::ops::resolve::SpecsAndResolvedFeatures;
9+
use crate::ops::tree::graph::NodePackage;
910
use crate::ops::{self, Packages};
1011
use crate::util::CargoResult;
1112
use crate::util::style;
@@ -442,7 +443,7 @@ fn print_dependencies<'a>(
442443
.filter(|dep| {
443444
// Filter out packages to prune.
444445
match graph.node(dep.node()) {
445-
Node::Package { package_id, .. } => {
446+
Node::Package(NodePackage { package_id, .. }) => {
446447
if filter_non_workspace_member && !ws.is_member_id(*package_id) {
447448
return false;
448449
}

src/doc/man/cargo-tree.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ strings will be replaced with the corresponding value:
167167
- `{r}` --- The package repository URL.
168168
- `{f}` --- Comma-separated list of package features that are enabled.
169169
- `{lib}` --- The name, as used in a `use` statement, of the package's library.
170+
- `{c}` --- The version constraint resolved for the package.
170171
{{/option}}
171172

172173
{{#option "`--prefix` _prefix_" }}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ OPTIONS
166166
o {lib} — The name, as used in a use statement, of the
167167
package’s library.
168168

169+
o {c} — The version constraint resolved for the package.
170+
169171
--prefix prefix
170172
Sets how each line is displayed. The prefix value can be one of:
171173

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ strings will be replaced with the corresponding value:</p>
170170
<li><code>{r}</code> — The package repository URL.</li>
171171
<li><code>{f}</code> — Comma-separated list of package features that are enabled.</li>
172172
<li><code>{lib}</code> — The name, as used in a <code>use</code> statement, of the package’s library.</li>
173+
<li><code>{c}</code> — The version constraint resolved for the package.</li>
173174
</ul>
174175
</dd>
175176

src/etc/man/cargo-tree.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ strings will be replaced with the corresponding value:
208208
.RS 4
209209
\h'-04'\(bu\h'+03'\fB{lib}\fR \[em] The name, as used in a \fBuse\fR statement, of the package\[cq]s library.
210210
.RE
211+
.sp
212+
.RS 4
213+
\h'-04'\(bu\h'+03'\fB{c}\fR \[em] The version constraint resolved for the package.
214+
.RE
211215
.RE
212216
.sp
213217
\fB\-\-prefix\fR \fIprefix\fR

0 commit comments

Comments
 (0)