Skip to content

Commit 3bfbf09

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 3bfbf09

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-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: 67 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,54 @@ 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+
pub version_req: OptVersionReq,
61+
}
62+
63+
impl PartialEq for NodePackage {
64+
fn eq(&self, other: &Self) -> bool {
65+
self.package_id == other.package_id
66+
&& self.features == other.features
67+
&& self.kind == other.kind
68+
// version_req is not comparable
69+
}
70+
}
71+
72+
impl Eq for NodePackage {}
73+
74+
impl PartialOrd for NodePackage {
75+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
76+
Some(self.cmp(other))
77+
}
78+
}
79+
80+
impl Ord for NodePackage {
81+
fn cmp(&self, other: &Self) -> Ordering {
82+
self.package_id
83+
.cmp(&other.package_id)
84+
.then_with(|| self.features.cmp(&other.features))
85+
.then_with(|| self.kind.cmp(&other.kind))
86+
// version_req is not orderable
87+
}
88+
}
89+
90+
impl Hash for NodePackage {
91+
fn hash<H: Hasher>(&self, state: &mut H) {
92+
self.package_id.hash(state);
93+
self.features.hash(state);
94+
self.kind.hash(state);
95+
// version_req is not hashable
96+
}
97+
}
98+
5299
#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
53100
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-
},
101+
Package(NodePackage),
60102
Feature {
61103
/// Index of the package node this feature is for.
62104
node_index: NodeId,
@@ -68,7 +110,7 @@ pub enum Node {
68110
impl Node {
69111
fn name(&self) -> InternedString {
70112
match self {
71-
Self::Package { package_id, .. } => package_id.name(),
113+
Self::Package(NodePackage { package_id, .. }) => package_id.name(),
72114
Self::Feature { name, .. } => *name,
73115
}
74116
}
@@ -218,7 +260,7 @@ impl<'a> Graph<'a> {
218260
.iter()
219261
.enumerate()
220262
.filter(|(_i, node)| match node {
221-
Node::Package { package_id, .. } => package_ids.contains(package_id),
263+
Node::Package(NodePackage { package_id, .. }) => package_ids.contains(package_id),
222264
_ => false,
223265
})
224266
.map(|(i, node)| (node, NodeId::new(i, node.name())))
@@ -235,7 +277,7 @@ impl<'a> Graph<'a> {
235277

236278
fn package_id_for_index(&self, index: NodeId) -> PackageId {
237279
match self.node(index) {
238-
Node::Package { package_id, .. } => *package_id,
280+
Node::Package(NodePackage { package_id, .. }) => *package_id,
239281
Node::Feature { .. } => panic!("unexpected feature node"),
240282
}
241283
}
@@ -314,7 +356,7 @@ impl<'a> Graph<'a> {
314356
// Collect a map of package name to Vec<(&Node, NodeId)>.
315357
let mut packages = HashMap::new();
316358
for (i, node) in self.nodes.iter().enumerate() {
317-
if let Node::Package { package_id, .. } = node {
359+
if let Node::Package(NodePackage { package_id, .. }) = node {
318360
packages
319361
.entry(package_id.name())
320362
.or_insert_with(Vec::new)
@@ -329,17 +371,19 @@ impl<'a> Graph<'a> {
329371
.into_iter()
330372
.map(|(node, _)| {
331373
match node {
332-
Node::Package {
374+
Node::Package(NodePackage {
333375
package_id,
334376
features,
377+
version_req,
335378
..
336-
} => {
379+
}) => {
337380
// Do not treat duplicates on the host or target as duplicates.
338-
Node::Package {
381+
Node::Package(NodePackage {
339382
package_id: package_id.clone(),
340383
features: features.clone(),
341384
kind: CompileKind::Host,
342-
}
385+
version_req: version_req.clone(),
386+
})
343387
}
344388
_ => unreachable!(),
345389
}
@@ -376,12 +420,14 @@ pub fn build<'a>(
376420
let member_id = member.package_id();
377421
let features_for = FeaturesFor::from_for_host(member.proc_macro());
378422
for kind in requested_kinds {
423+
let version_req = OptVersionReq::Any;
379424
let member_index = add_pkg(
380425
&mut graph,
381426
resolve,
382427
resolved_features,
383428
member_id,
384429
features_for,
430+
version_req,
385431
target_data,
386432
*kind,
387433
opts,
@@ -409,6 +455,7 @@ fn add_pkg(
409455
resolved_features: &ResolvedFeatures,
410456
package_id: PackageId,
411457
features_for: FeaturesFor,
458+
version_req: OptVersionReq,
412459
target_data: &RustcTargetData<'_>,
413460
requested_kind: CompileKind,
414461
opts: &TreeOptions,
@@ -419,11 +466,12 @@ fn add_pkg(
419466
FeaturesFor::ArtifactDep(target) => CompileKind::Target(target),
420467
FeaturesFor::NormalOrDev => requested_kind,
421468
};
422-
let node = Node::Package {
469+
let node = Node::Package(NodePackage {
423470
package_id,
424471
features: node_features,
425472
kind: node_kind,
426-
};
473+
version_req: version_req,
474+
});
427475
if let Some(idx) = graph.index.get(&node) {
428476
return *idx;
429477
}
@@ -513,12 +561,14 @@ fn add_pkg(
513561
}
514562
}
515563
};
564+
let dep_version_req = dep.version_req().clone();
516565
let dep_index = add_pkg(
517566
graph,
518567
resolve,
519568
resolved_features,
520569
dep_id,
521570
dep_features_for,
571+
dep_version_req,
522572
target_data,
523573
requested_kind,
524574
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)