Skip to content

Commit 8ee1800

Browse files
committed
Add package version requirement to cargo tree Graph Node
Add a new version_req field to the Package variant of the Graph Node enum. Since Node must implement Ord/Eq/Hash, we extract the Package variant into its own struct and add custom implementations of these traits that ignore the version requirement, which is not easily comparable. Signed-off-by: Alexandre Barone <[email protected]>
1 parent 4406c1b commit 8ee1800

File tree

3 files changed

+75
-21
lines changed

3 files changed

+75
-21
lines changed

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

Lines changed: 5 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

@@ -60,11 +62,11 @@ impl<'a> fmt::Display for Display<'a> {
6062
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
6163
let node = self.graph.node(self.node_index);
6264
match node {
63-
Node::Package {
65+
Node::Package(NodePackage {
6466
package_id,
6567
features,
6668
..
67-
} => {
69+
}) => {
6870
let package = self.graph.package_for_id(*package_id);
6971
for chunk in &self.pattern.0 {
7072
match chunk {
@@ -117,7 +119,7 @@ impl<'a> fmt::Display for Display<'a> {
117119
Node::Feature { name, node_index } => {
118120
let for_node = self.graph.node(*node_index);
119121
match for_node {
120-
Node::Package { package_id, .. } => {
122+
Node::Package(NodePackage { package_id, .. }) => {
121123
write!(fmt, "{} feature \"{}\"", package_id.name(), name)?;
122124
if self.graph.is_cli_feature(self.node_index) {
123125
write!(fmt, " (command-line)")?;

src/cargo/ops/tree/graph.rs

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ 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};
13+
use std::hash::{Hash, Hasher};
1214

1315
#[derive(Debug, Copy, Clone)]
1416
pub struct NodeId {
@@ -49,14 +51,55 @@ impl std::hash::Hash for NodeId {
4951
}
5052
}
5153

54+
#[derive(Debug, Clone)]
55+
pub struct NodePackage {
56+
pub package_id: PackageId,
57+
/// Features that are enabled on this package.
58+
pub features: Vec<InternedString>,
59+
pub kind: CompileKind,
60+
// ignore in equality/hash/ordering as it is only informational
61+
pub version_req: OptVersionReq,
62+
}
63+
64+
impl PartialEq for NodePackage {
65+
fn eq(&self, other: &Self) -> bool {
66+
self.package_id == other.package_id
67+
&& self.features == other.features
68+
&& self.kind == other.kind
69+
// ignore version_req
70+
}
71+
}
72+
73+
impl Eq for NodePackage {}
74+
75+
impl PartialOrd for NodePackage {
76+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77+
Some(self.cmp(other))
78+
}
79+
}
80+
81+
impl Ord for NodePackage {
82+
fn cmp(&self, other: &Self) -> Ordering {
83+
self.package_id
84+
.cmp(&other.package_id)
85+
.then_with(|| self.features.cmp(&other.features))
86+
.then_with(|| self.kind.cmp(&other.kind))
87+
// ignore version_req
88+
}
89+
}
90+
91+
impl Hash for NodePackage {
92+
fn hash<H: Hasher>(&self, state: &mut H) {
93+
self.package_id.hash(state);
94+
self.features.hash(state);
95+
self.kind.hash(state);
96+
// ignore version_req
97+
}
98+
}
99+
52100
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
53101
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-
},
102+
Package(NodePackage),
60103
Feature {
61104
/// Index of the package node this feature is for.
62105
node_index: NodeId,
@@ -68,7 +111,7 @@ pub enum Node {
68111
impl Node {
69112
fn name(&self) -> InternedString {
70113
match self {
71-
Self::Package { package_id, .. } => package_id.name(),
114+
Self::Package(NodePackage { package_id, .. }) => package_id.name(),
72115
Self::Feature { name, .. } => *name,
73116
}
74117
}
@@ -218,7 +261,7 @@ impl<'a> Graph<'a> {
218261
.iter()
219262
.enumerate()
220263
.filter(|(_i, node)| match node {
221-
Node::Package { package_id, .. } => package_ids.contains(package_id),
264+
Node::Package(NodePackage { package_id, .. }) => package_ids.contains(package_id),
222265
_ => false,
223266
})
224267
.map(|(i, node)| (node, NodeId::new(i, node.name())))
@@ -235,7 +278,7 @@ impl<'a> Graph<'a> {
235278

236279
fn package_id_for_index(&self, index: NodeId) -> PackageId {
237280
match self.node(index) {
238-
Node::Package { package_id, .. } => *package_id,
281+
Node::Package(NodePackage { package_id, .. }) => *package_id,
239282
Node::Feature { .. } => panic!("unexpected feature node"),
240283
}
241284
}
@@ -314,7 +357,7 @@ impl<'a> Graph<'a> {
314357
// Collect a map of package name to Vec<(&Node, NodeId)>.
315358
let mut packages = HashMap::new();
316359
for (i, node) in self.nodes.iter().enumerate() {
317-
if let Node::Package { package_id, .. } = node {
360+
if let Node::Package(NodePackage { package_id, .. }) = node {
318361
packages
319362
.entry(package_id.name())
320363
.or_insert_with(Vec::new)
@@ -329,17 +372,19 @@ impl<'a> Graph<'a> {
329372
.into_iter()
330373
.map(|(node, _)| {
331374
match node {
332-
Node::Package {
375+
Node::Package(NodePackage {
333376
package_id,
334377
features,
378+
version_req,
335379
..
336-
} => {
380+
}) => {
337381
// Do not treat duplicates on the host or target as duplicates.
338-
Node::Package {
382+
Node::Package(NodePackage {
339383
package_id: package_id.clone(),
340384
features: features.clone(),
341385
kind: CompileKind::Host,
342-
}
386+
version_req: version_req.clone(),
387+
})
343388
}
344389
_ => unreachable!(),
345390
}
@@ -376,12 +421,14 @@ pub fn build<'a>(
376421
let member_id = member.package_id();
377422
let features_for = FeaturesFor::from_for_host(member.proc_macro());
378423
for kind in requested_kinds {
424+
let version_req = OptVersionReq::Any;
379425
let member_index = add_pkg(
380426
&mut graph,
381427
resolve,
382428
resolved_features,
383429
member_id,
384430
features_for,
431+
version_req,
385432
target_data,
386433
*kind,
387434
opts,
@@ -409,6 +456,7 @@ fn add_pkg(
409456
resolved_features: &ResolvedFeatures,
410457
package_id: PackageId,
411458
features_for: FeaturesFor,
459+
version_req: OptVersionReq,
412460
target_data: &RustcTargetData<'_>,
413461
requested_kind: CompileKind,
414462
opts: &TreeOptions,
@@ -419,11 +467,12 @@ fn add_pkg(
419467
FeaturesFor::ArtifactDep(target) => CompileKind::Target(target),
420468
FeaturesFor::NormalOrDev => requested_kind,
421469
};
422-
let node = Node::Package {
470+
let node = Node::Package(NodePackage {
423471
package_id,
424472
features: node_features,
425473
kind: node_kind,
426-
};
474+
version_req: version_req,
475+
});
427476
if let Some(idx) = graph.index.get(&node) {
428477
return *idx;
429478
}
@@ -513,12 +562,14 @@ fn add_pkg(
513562
}
514563
}
515564
};
565+
let dep_version_req = dep.version_req().clone();
516566
let dep_index = add_pkg(
517567
graph,
518568
resolve,
519569
resolved_features,
520570
dep_id,
521571
dep_features_for,
572+
dep_version_req,
522573
target_data,
523574
requested_kind,
524575
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
}

0 commit comments

Comments
 (0)