Skip to content

feat(tree): Add --depth public behind -Zunstable-options #15243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/cargo/ops/tree/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ impl Node {
pub struct Edge {
kind: EdgeKind,
node: NodeId,
public: bool,
}

impl Edge {
Expand All @@ -88,6 +89,10 @@ impl Edge {
pub fn node(&self) -> NodeId {
self.node
}

pub fn public(&self) -> bool {
self.public
}
}

/// The kind of edge, for separating dependencies into different sections.
Expand All @@ -105,7 +110,7 @@ pub enum EdgeKind {
///
/// The value is a `Vec` because each edge kind can have multiple outgoing
/// edges. For example, package "foo" can have multiple normal dependencies.
#[derive(Clone)]
#[derive(Clone, Debug)]
struct Edges(HashMap<EdgeKind, Vec<Edge>>);

impl Edges {
Expand Down Expand Up @@ -135,6 +140,7 @@ impl Edges {
}

/// A graph of dependencies.
#[derive(Debug)]
pub struct Graph<'a> {
nodes: Vec<Node>,
/// The indexes of `edges` correspond to the `nodes`. That is, `edges[0]`
Expand Down Expand Up @@ -268,6 +274,7 @@ impl<'a> Graph<'a> {
let new_edge = Edge {
kind: edge.kind(),
node: new_to_index,
public: edge.public(),
};
new_graph.edges_mut(new_from).add_edge(new_edge);
}
Expand All @@ -290,6 +297,7 @@ impl<'a> Graph<'a> {
let new_edge = Edge {
kind: edge.kind(),
node: NodeId::new(from_idx, self.nodes[from_idx].name()),
public: edge.public(),
};
new_edges[edge.node().index].add_edge(new_edge);
}
Expand Down Expand Up @@ -514,6 +522,7 @@ fn add_pkg(
let new_edge = Edge {
kind: EdgeKind::Dep(dep.kind()),
node: dep_index,
public: dep.is_public(),
};
if opts.graph_features {
// Add the dependency node with feature nodes in-between.
Expand Down Expand Up @@ -577,12 +586,14 @@ fn add_feature(
let from_edge = Edge {
kind: to.kind(),
node: node_index,
public: to.public(),
};
graph.edges_mut(from).add_edge(from_edge);
}
let to_edge = Edge {
kind: EdgeKind::Feature,
node: to.node(),
public: true,
};
graph.edges_mut(node_index).add_edge(to_edge);
(missing, node_index)
Expand Down Expand Up @@ -620,6 +631,7 @@ fn add_cli_features(
let feature_edge = Edge {
kind: EdgeKind::Feature,
node: package_index,
public: true,
};
let index = add_feature(graph, feature, None, feature_edge).1;
graph.cli_features.insert(index);
Expand Down Expand Up @@ -654,13 +666,15 @@ fn add_cli_features(
let feature_edge = Edge {
kind: EdgeKind::Feature,
node: package_index,
public: true,
};
let index = add_feature(graph, dep_name, None, feature_edge).1;
graph.cli_features.insert(index);
}
let dep_edge = Edge {
kind: EdgeKind::Feature,
node: dep_index,
public: true,
};
let index = add_feature(graph, dep_feature, None, dep_edge).1;
graph.cli_features.insert(index);
Expand Down Expand Up @@ -721,6 +735,7 @@ fn add_feature_rec(
let feature_edge = Edge {
kind: EdgeKind::Feature,
node: package_index,
public: true,
};
let (missing, feat_index) = add_feature(graph, *dep_name, Some(from), feature_edge);
// Don't recursive if the edge already exists to deal with cycles.
Expand Down Expand Up @@ -771,12 +786,14 @@ fn add_feature_rec(
let feature_edge = Edge {
kind: EdgeKind::Feature,
node: package_index,
public: true,
};
add_feature(graph, *dep_name, Some(from), feature_edge);
}
let dep_edge = Edge {
kind: EdgeKind::Feature,
node: dep_index,
public: true,
};
let (missing, feat_index) =
add_feature(graph, *dep_feature, Some(from), dep_edge);
Expand Down
44 changes: 32 additions & 12 deletions src/cargo/ops/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ impl FromStr for Prefix {
#[derive(Clone, Copy)]
pub enum DisplayDepth {
MaxDisplayDepth(u32),
Public,
Workspace,
}

Expand All @@ -100,6 +101,7 @@ impl FromStr for DisplayDepth {
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"workspace" => Ok(Self::Workspace),
"public" => Ok(Self::Public),
s => s.parse().map(Self::MaxDisplayDepth).map_err(|_| {
clap::Error::raw(
clap::error::ErrorKind::ValueValidation,
Expand Down Expand Up @@ -282,7 +284,7 @@ fn print(
&mut visited_deps,
&mut levels_continue,
&mut print_stack,
);
)?;
}

Ok(())
Expand All @@ -302,7 +304,7 @@ fn print_node<'a>(
visited_deps: &mut HashSet<NodeId>,
levels_continue: &mut Vec<(anstyle::Style, bool)>,
print_stack: &mut Vec<NodeId>,
) {
) -> CargoResult<()> {
let new = no_dedupe || visited_deps.insert(node_index);

match prefix {
Expand Down Expand Up @@ -343,7 +345,7 @@ fn print_node<'a>(
drop_println!(ws.gctx(), "{}{}", format.display(graph, node_index), star);

if !new || in_cycle {
return;
return Ok(());
}
print_stack.push(node_index);

Expand All @@ -367,9 +369,11 @@ fn print_node<'a>(
levels_continue,
print_stack,
kind,
);
)?;
}
print_stack.pop();

Ok(())
}

/// Prints all the dependencies of a package for the given dependency kind.
Expand All @@ -387,10 +391,10 @@ fn print_dependencies<'a>(
levels_continue: &mut Vec<(anstyle::Style, bool)>,
print_stack: &mut Vec<NodeId>,
kind: &EdgeKind,
) {
) -> CargoResult<()> {
let deps = graph.edges_of_kind(node_index, kind);
if deps.is_empty() {
return;
return Ok(());
}

let name = match kind {
Expand All @@ -415,14 +419,20 @@ fn print_dependencies<'a>(
}
}

let (max_display_depth, filter_non_workspace_member) = match display_depth {
DisplayDepth::MaxDisplayDepth(max) => (max, false),
DisplayDepth::Workspace => (u32::MAX, true),
let (max_display_depth, filter_non_workspace_member, filter_private) = match display_depth {
DisplayDepth::MaxDisplayDepth(max) => (max, false, false),
DisplayDepth::Workspace => (u32::MAX, true, false),
DisplayDepth::Public => {
if !ws.gctx().cli_unstable().unstable_options {
anyhow::bail!("`--depth public` requires `-Zunstable-options`")
}
(u32::MAX, false, true)
}
};

// Current level exceeds maximum display depth. Skip.
if levels_continue.len() + 1 > max_display_depth as usize {
return;
return Ok(());
}

let mut it = deps
Expand All @@ -434,9 +444,17 @@ fn print_dependencies<'a>(
if filter_non_workspace_member && !ws.is_member_id(*package_id) {
return false;
}
if filter_private && !dep.public() {
return false;
}
!pkgs_to_prune.iter().any(|spec| spec.matches(*package_id))
}
_ => true,
Node::Feature { .. } => {
if filter_private && !dep.public() {
return false;
}
true
}
}
})
.peekable();
Expand All @@ -457,9 +475,11 @@ fn print_dependencies<'a>(
visited_deps,
levels_continue,
print_stack,
);
)?;
levels_continue.pop();
}

Ok(())
}

fn edge_line_color(kind: EdgeKind) -> anstyle::Style {
Expand Down
132 changes: 132 additions & 0 deletions tests/testsuite/cargo_tree/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1901,6 +1901,138 @@ c v0.1.0 ([ROOT]/foo/c) (*)
.run();
}

#[cargo_test(nightly, reason = "exported_private_dependencies lint is unstable")]
fn depth_public() {
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["diamond", "left-pub", "right-priv", "dep"]
"#,
)
.file(
"diamond/Cargo.toml",
r#"
cargo-features = ["public-dependency"]

[package]
name = "diamond"
version = "0.1.0"

[dependencies]
left-pub = { path = "../left-pub", public = true }
right-priv = { path = "../right-priv", public = true }
"#,
)
.file("diamond/src/lib.rs", "")
.file(
"left-pub/Cargo.toml",
r#"
cargo-features = ["public-dependency"]

[package]
name = "left-pub"
version = "0.1.0"

[dependencies]
dep = { path = "../dep", public = true }
"#,
)
.file("left-pub/src/lib.rs", "")
.file(
"right-priv/Cargo.toml",
r#"
[package]
name = "right-priv"
version = "0.1.0"

[dependencies]
dep = { path = "../dep" }
"#,
)
.file("right-priv/src/lib.rs", "")
.file(
"dep/Cargo.toml",
r#"
[package]
name = "dep"
version = "0.1.0"
"#,
)
.file("dep/src/lib.rs", "")
.build();

p.cargo("tree --depth public")
.masquerade_as_nightly_cargo(&["public-dependency", "depth-public"])
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] `--depth public` requires `-Zunstable-options`

"#]])
.run();

p.cargo("tree --depth public -p left-pub")
.arg("-Zunstable-options")
.masquerade_as_nightly_cargo(&["public-dependency", "depth-public"])
.with_stdout_data(str![[r#"
left-pub v0.1.0 ([ROOT]/foo/left-pub)
└── dep v0.1.0 ([ROOT]/foo/dep)

"#]])
.run();

p.cargo("tree --depth public -p right-priv")
.arg("-Zunstable-options")
.masquerade_as_nightly_cargo(&["public-dependency", "depth-public"])
.with_stdout_data(str![[r#"
right-priv v0.1.0 ([ROOT]/foo/right-priv)

"#]])
.run();

p.cargo("tree --depth public -p diamond")
.arg("-Zunstable-options")
.masquerade_as_nightly_cargo(&["public-dependency", "depth-public"])
.with_stdout_data(str![[r#"
diamond v0.1.0 ([ROOT]/foo/diamond)
├── left-pub v0.1.0 ([ROOT]/foo/left-pub)
│ └── dep v0.1.0 ([ROOT]/foo/dep)
└── right-priv v0.1.0 ([ROOT]/foo/right-priv)

"#]])
.run();

p.cargo("tree --depth public")
.arg("-Zunstable-options")
.masquerade_as_nightly_cargo(&["public-dependency", "depth-public"])
.with_stdout_data(str![[r#"
dep v0.1.0 ([ROOT]/foo/dep)

diamond v0.1.0 ([ROOT]/foo/diamond)
├── left-pub v0.1.0 ([ROOT]/foo/left-pub)
│ └── dep v0.1.0 ([ROOT]/foo/dep)
└── right-priv v0.1.0 ([ROOT]/foo/right-priv)

left-pub v0.1.0 ([ROOT]/foo/left-pub) (*)

right-priv v0.1.0 ([ROOT]/foo/right-priv) (*)

"#]])
.run();

p.cargo("tree --depth public --invert dep")
.arg("-Zunstable-options")
.masquerade_as_nightly_cargo(&["public-dependency", "depth-public"])
.with_stdout_data(str![[r#"
dep v0.1.0 ([ROOT]/foo/dep)
└── left-pub v0.1.0 ([ROOT]/foo/left-pub)
└── diamond v0.1.0 ([ROOT]/foo/diamond)

"#]])
.run();
}

#[cargo_test]
fn prune() {
let p = make_simple_proj();
Expand Down
Loading