@@ -6,7 +6,7 @@ use crate::core::dependency::DepKind;
66use crate :: core:: resolver:: { features:: CliFeatures , ForceAllTargets , HasDevUnits } ;
77use crate :: core:: { Package , PackageId , PackageIdSpec , PackageIdSpecQuery , Workspace } ;
88use crate :: ops:: { self , Packages } ;
9- use crate :: util:: { CargoResult , GlobalContext } ;
9+ use crate :: util:: CargoResult ;
1010use crate :: { drop_print, drop_println} ;
1111use anyhow:: Context as _;
1212use graph:: Graph ;
@@ -43,8 +43,10 @@ pub struct TreeOptions {
4343 pub format : String ,
4444 /// Includes features in the tree as separate nodes.
4545 pub graph_features : bool ,
46- /// Maximum display depth of the dependency tree.
47- pub max_display_depth : u32 ,
46+ /// Display depth of the dependency tree.
47+ /// If non-negative integer, display dependencies with that amount of max depth.
48+ /// If `workspace`, display dependencies from current workspace only.
49+ pub display_depth : DisplayDepth ,
4850 /// Excludes proc-macro dependencies.
4951 pub no_proc_macro : bool ,
5052}
@@ -86,6 +88,32 @@ impl FromStr for Prefix {
8688 }
8789}
8890
91+ #[ derive( Clone , Copy ) ]
92+ pub enum DisplayDepth {
93+ MaxDisplayDepth ( u32 ) ,
94+ Workspace ,
95+ }
96+
97+ impl FromStr for DisplayDepth {
98+ type Err = clap:: Error ;
99+
100+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
101+ match s {
102+ "workspace" => Ok ( Self :: Workspace ) ,
103+ s => s. parse ( ) . map ( Self :: MaxDisplayDepth ) . map_err ( |_| {
104+ clap:: Error :: raw (
105+ clap:: error:: ErrorKind :: ValueValidation ,
106+ format ! (
107+ "supported values for --depth are non-negative integers and `workspace`, \
108+ but `{}` is unknown",
109+ s
110+ ) ,
111+ )
112+ } ) ,
113+ }
114+ }
115+ }
116+
89117struct Symbols {
90118 down : & ' static str ,
91119 tee : & ' static str ,
@@ -203,14 +231,14 @@ pub fn build_and_print(ws: &Workspace<'_>, opts: &TreeOptions) -> CargoResult<()
203231 try to use option `--target all` first, and then narrow your search scope accordingly.",
204232 ) ?;
205233 } else {
206- print ( ws. gctx ( ) , opts, root_indexes, & pkgs_to_prune, & graph) ?;
234+ print ( ws, opts, root_indexes, & pkgs_to_prune, & graph) ?;
207235 }
208236 Ok ( ( ) )
209237}
210238
211239/// Prints a tree for each given root.
212240fn print (
213- gctx : & GlobalContext ,
241+ ws : & Workspace < ' _ > ,
214242 opts : & TreeOptions ,
215243 roots : Vec < usize > ,
216244 pkgs_to_prune : & [ PackageIdSpec ] ,
@@ -219,7 +247,7 @@ fn print(
219247 let format = Pattern :: new ( & opts. format )
220248 . with_context ( || format ! ( "tree format `{}` not valid" , opts. format) ) ?;
221249
222- let symbols = if gctx. shell ( ) . out_unicode ( ) {
250+ let symbols = if ws . gctx ( ) . shell ( ) . out_unicode ( ) {
223251 & UTF8_SYMBOLS
224252 } else {
225253 & ASCII_SYMBOLS
@@ -231,7 +259,7 @@ fn print(
231259
232260 for ( i, root_index) in roots. into_iter ( ) . enumerate ( ) {
233261 if i != 0 {
234- drop_println ! ( gctx) ;
262+ drop_println ! ( ws . gctx( ) ) ;
235263 }
236264
237265 // A stack of bools used to determine where | symbols should appear
@@ -242,15 +270,15 @@ fn print(
242270 let mut print_stack = vec ! [ ] ;
243271
244272 print_node (
245- gctx ,
273+ ws ,
246274 graph,
247275 root_index,
248276 & format,
249277 symbols,
250278 pkgs_to_prune,
251279 opts. prefix ,
252280 opts. no_dedupe ,
253- opts. max_display_depth ,
281+ opts. display_depth ,
254282 & mut visited_deps,
255283 & mut levels_continue,
256284 & mut print_stack,
@@ -262,36 +290,36 @@ fn print(
262290
263291/// Prints a package and all of its dependencies.
264292fn print_node < ' a > (
265- gctx : & GlobalContext ,
293+ ws : & Workspace < ' _ > ,
266294 graph : & ' a Graph < ' _ > ,
267295 node_index : usize ,
268296 format : & Pattern ,
269297 symbols : & Symbols ,
270298 pkgs_to_prune : & [ PackageIdSpec ] ,
271299 prefix : Prefix ,
272300 no_dedupe : bool ,
273- max_display_depth : u32 ,
301+ display_depth : DisplayDepth ,
274302 visited_deps : & mut HashSet < usize > ,
275303 levels_continue : & mut Vec < bool > ,
276304 print_stack : & mut Vec < usize > ,
277305) {
278306 let new = no_dedupe || visited_deps. insert ( node_index) ;
279307
280308 match prefix {
281- Prefix :: Depth => drop_print ! ( gctx, "{}" , levels_continue. len( ) ) ,
309+ Prefix :: Depth => drop_print ! ( ws . gctx( ) , "{}" , levels_continue. len( ) ) ,
282310 Prefix :: Indent => {
283311 if let Some ( ( last_continues, rest) ) = levels_continue. split_last ( ) {
284312 for continues in rest {
285313 let c = if * continues { symbols. down } else { " " } ;
286- drop_print ! ( gctx, "{} " , c) ;
314+ drop_print ! ( ws . gctx( ) , "{} " , c) ;
287315 }
288316
289317 let c = if * last_continues {
290318 symbols. tee
291319 } else {
292320 symbols. ell
293321 } ;
294- drop_print ! ( gctx, "{0}{1}{1} " , c, symbols. right) ;
322+ drop_print ! ( ws . gctx( ) , "{0}{1}{1} " , c, symbols. right) ;
295323 }
296324 }
297325 Prefix :: None => { }
@@ -307,7 +335,7 @@ fn print_node<'a>(
307335 } else {
308336 " (*)"
309337 } ;
310- drop_println ! ( gctx, "{}{}" , format. display( graph, node_index) , star) ;
338+ drop_println ! ( ws . gctx( ) , "{}{}" , format. display( graph, node_index) , star) ;
311339
312340 if !new || in_cycle {
313341 return ;
@@ -321,15 +349,15 @@ fn print_node<'a>(
321349 EdgeKind :: Feature ,
322350 ] {
323351 print_dependencies (
324- gctx ,
352+ ws ,
325353 graph,
326354 node_index,
327355 format,
328356 symbols,
329357 pkgs_to_prune,
330358 prefix,
331359 no_dedupe,
332- max_display_depth ,
360+ display_depth ,
333361 visited_deps,
334362 levels_continue,
335363 print_stack,
@@ -341,15 +369,15 @@ fn print_node<'a>(
341369
342370/// Prints all the dependencies of a package for the given dependency kind.
343371fn print_dependencies < ' a > (
344- gctx : & GlobalContext ,
372+ ws : & Workspace < ' _ > ,
345373 graph : & ' a Graph < ' _ > ,
346374 node_index : usize ,
347375 format : & Pattern ,
348376 symbols : & Symbols ,
349377 pkgs_to_prune : & [ PackageIdSpec ] ,
350378 prefix : Prefix ,
351379 no_dedupe : bool ,
352- max_display_depth : u32 ,
380+ display_depth : DisplayDepth ,
353381 visited_deps : & mut HashSet < usize > ,
354382 levels_continue : & mut Vec < bool > ,
355383 print_stack : & mut Vec < usize > ,
@@ -371,13 +399,18 @@ fn print_dependencies<'a>(
371399 if let Some ( name) = name {
372400 for continues in & * * levels_continue {
373401 let c = if * continues { symbols. down } else { " " } ;
374- drop_print ! ( gctx, "{} " , c) ;
402+ drop_print ! ( ws . gctx( ) , "{} " , c) ;
375403 }
376404
377- drop_println ! ( gctx, "{}" , name) ;
405+ drop_println ! ( ws . gctx( ) , "{}" , name) ;
378406 }
379407 }
380408
409+ let ( max_display_depth, filter_non_workspace_member) = match display_depth {
410+ DisplayDepth :: MaxDisplayDepth ( max) => ( max, false ) ,
411+ DisplayDepth :: Workspace => ( u32:: MAX , true ) ,
412+ } ;
413+
381414 // Current level exceeds maximum display depth. Skip.
382415 if levels_continue. len ( ) + 1 > max_display_depth as usize {
383416 return ;
@@ -389,6 +422,9 @@ fn print_dependencies<'a>(
389422 // Filter out packages to prune.
390423 match graph. node ( * * dep) {
391424 Node :: Package { package_id, .. } => {
425+ if filter_non_workspace_member && !ws. is_member_id ( * package_id) {
426+ return false ;
427+ }
392428 !pkgs_to_prune. iter ( ) . any ( |spec| spec. matches ( * package_id) )
393429 }
394430 _ => true ,
@@ -399,15 +435,15 @@ fn print_dependencies<'a>(
399435 while let Some ( dependency) = it. next ( ) {
400436 levels_continue. push ( it. peek ( ) . is_some ( ) ) ;
401437 print_node (
402- gctx ,
438+ ws ,
403439 graph,
404440 * dependency,
405441 format,
406442 symbols,
407443 pkgs_to_prune,
408444 prefix,
409445 no_dedupe,
410- max_display_depth ,
446+ display_depth ,
411447 visited_deps,
412448 levels_continue,
413449 print_stack,
0 commit comments