@@ -13,6 +13,7 @@ use pixi_manifest::FeaturesExt;
1313use  rattler_conda_types:: Platform ; 
1414use  rattler_lock:: LockedPackageRef ; 
1515use  regex:: Regex ; 
16+ use  serde:: { Deserialize ,  Serialize } ; 
1617
1718use  crate :: { 
1819    WorkspaceLocator ,  cli:: cli_config:: WorkspaceConfig ,  lock_file:: UpdateLockFileOptions , 
@@ -36,7 +37,7 @@ use super::cli_config::LockFileUpdateConfig;
3637) ) ] 
3738pub  struct  Args  { 
3839    /// List only packages matching a regular expression 
39-      #[ arg( ) ]  
40+      #[ arg( conflicts_with =  "json" ) ]  
4041    pub  regex :  Option < String > , 
4142
4243    /// The platform to list packages for. Defaults to the current platform. 
@@ -55,8 +56,12 @@ pub struct Args {
5556    pub  lock_file_update_config :  LockFileUpdateConfig , 
5657
5758    /// Invert tree and show what depends on given package in the regex argument 
58-      #[ arg( short,  long,  requires = "regex" ) ]  
59+      #[ arg( short,  long,  requires = "regex" ,  conflicts_with =  "json" ) ]  
5960    pub  invert :  bool , 
61+ 
62+     /// Show a JSON representation of the dependency tree 
63+      #[ arg( long) ]  
64+     pub  json :  bool , 
6065} 
6166
6267struct  Symbols  { 
@@ -108,7 +113,9 @@ pub async fn execute(args: Args) -> miette::Result<()> {
108113
109114    let  stdout = std:: io:: stdout ( ) ; 
110115    let  mut  handle = stdout. lock ( ) ; 
111-     if  args. invert  { 
116+     if  args. json  { 
117+         print_json_dependency_tree ( & mut  handle,  & dep_map,  & direct_deps) ?; 
118+     }  else  if  args. invert  { 
112119        print_inverted_dependency_tree ( 
113120            & mut  handle, 
114121            & invert_dep_map ( & dep_map) , 
@@ -123,6 +130,60 @@ pub async fn execute(args: Args) -> miette::Result<()> {
123130    Ok ( ( ) ) 
124131} 
125132
133+ #[ derive( Debug ,  Clone ,  Serialize ,  Deserialize ) ]  
134+ struct  DependencyTreeNode  { 
135+     name :  String , 
136+     version :  String , 
137+     tags :  Vec < String > , 
138+     dependencies :  Vec < DependencyTreeNode > , 
139+ } 
140+ 
141+ fn  package_to_tree_node ( 
142+     package :  & Package , 
143+     dep_map :  & HashMap < String ,  Package > , 
144+ )  -> DependencyTreeNode  { 
145+     let  dependencies = package
146+         . dependencies 
147+         . iter ( ) 
148+         . filter_map ( |dep_name| dep_map. get ( dep_name) ) 
149+         . map ( |dep| package_to_tree_node ( dep,  dep_map) ) 
150+         . collect ( ) ; 
151+ 
152+     DependencyTreeNode  { 
153+         name :  package. name . clone ( ) , 
154+         version :  package. version . clone ( ) , 
155+         tags :  Vec :: new ( ) , 
156+         dependencies, 
157+     } 
158+ } 
159+ 
160+ /// Print a JSON representation of the dependency tree 
161+ fn  print_json_dependency_tree ( 
162+     handle :  & mut  StdoutLock , 
163+     dep_map :  & HashMap < String ,  Package > , 
164+     direct_deps :  & HashSet < String > , 
165+ )  -> miette:: Result < ( ) >  { 
166+     let  dependencies:  Vec < DependencyTreeNode >  = direct_deps
167+         . iter ( ) 
168+         . filter_map ( |pkg_name| dep_map. get ( pkg_name) ) 
169+         . map ( |pkg| package_to_tree_node ( pkg,  dep_map) ) 
170+         . collect ( ) ; 
171+     let  json = serde_json:: to_string_pretty ( & dependencies) 
172+         . into_diagnostic ( ) 
173+         . wrap_err ( "Failed to serialize dependency tree to JSON" ) ?; 
174+     writeln ! ( handle,  "{}" ,  json) 
175+         . map_err ( |e| { 
176+             if  e. kind ( )  == std:: io:: ErrorKind :: BrokenPipe  { 
177+                 // Exit gracefully 
178+                 std:: process:: exit ( 0 ) ; 
179+             }  else  { 
180+                 e
181+             } 
182+         } ) 
183+         . into_diagnostic ( ) 
184+         . wrap_err ( "Failed to serialize dependency tree to JSON" ) 
185+ } 
186+ 
126187/// Filter and print an inverted dependency tree 
127188fn  print_inverted_dependency_tree ( 
128189    handle :  & mut  StdoutLock , 
0 commit comments