@@ -5,9 +5,8 @@ use pixi_config::{Config, ConfigCli};
55use pixi_global:: StateChanges ;
66use pixi_global:: common:: { EnvironmentUpdate , InstallChange , check_all_exposed} ;
77use pixi_global:: project:: ExposedType ;
8- use pixi_global:: { EnvironmentName , Project } ;
8+ use pixi_global:: { EnvironmentName , Project , StateChange } ;
99use serde:: Serialize ;
10- use std:: collections:: HashMap ;
1110
1211/// Updates environments in the global environment.
1312#[ derive( Parser , Debug , Clone ) ]
@@ -129,10 +128,7 @@ pub async fn execute(args: Args) -> miette::Result<()> {
129128 project : & mut Project ,
130129 dry_run : bool ,
131130 json_output : bool ,
132- ) -> miette:: Result < (
133- StateChanges ,
134- Option < EnvironmentUpdate > ,
135- ) > {
131+ ) -> miette:: Result < ( StateChanges , Option < EnvironmentUpdate > ) > {
136132 let mut state_changes = StateChanges :: default ( ) ;
137133
138134 let should_check_for_updates = true ;
@@ -165,22 +161,22 @@ pub async fn execute(args: Args) -> miette::Result<()> {
165161 if should_check_for_updates {
166162 if dry_run || json_output {
167163 // dry-run mode: performs solving only
168- let environment_update = solve_for_dry_run ( project , env_name) . await ?;
164+ let environment_update = project . solve_for_dry_run ( env_name) . await ?;
169165
170166 // Only add to state changes if there are actual changes
171167 if !environment_update. is_empty ( ) {
172168 dry_run_environment_update = Some ( environment_update. clone ( ) ) ;
173169 state_changes. insert_change (
174170 env_name,
175- global :: StateChange :: UpdatedEnvironment ( environment_update) ,
171+ StateChange :: UpdatedEnvironment ( environment_update) ,
176172 ) ;
177173 }
178174 } else {
179175 // Normal mode: actually install
180176 let environment_update = project. install_environment ( env_name) . await ?;
181177 state_changes. insert_change (
182178 env_name,
183- global :: StateChange :: UpdatedEnvironment ( environment_update) ,
179+ StateChange :: UpdatedEnvironment ( environment_update) ,
184180 ) ;
185181 }
186182 }
@@ -208,171 +204,6 @@ pub async fn execute(args: Args) -> miette::Result<()> {
208204 Ok ( ( state_changes, dry_run_environment_update) )
209205 }
210206
211- /// Performs only the solving step to determine what would change in dry-run mode
212- /// This extracts the solving logic from install_environment without the installation
213- async fn solve_for_dry_run (
214- project : & Project ,
215- env_name : & EnvironmentName ,
216- ) -> miette:: Result < crate :: global:: common:: EnvironmentUpdate > {
217- use crate :: global:: common:: { EnvironmentUpdate , InstallChange } ;
218- use miette:: { IntoDiagnostic , WrapErr } ;
219- use pixi_command_dispatcher:: { BuildEnvironment , PixiEnvironmentSpec } ;
220- use pixi_spec_containers:: DependencyMap ;
221- use rattler_conda_types:: { GenericVirtualPackage , Platform } ;
222- use rattler_virtual_packages:: { VirtualPackage , VirtualPackageOverrides } ;
223-
224- let environment = project
225- . environment ( env_name)
226- . ok_or_else ( || miette:: miette!( "Environment {} not found" , env_name. fancy_display( ) ) ) ?;
227-
228- let channels = environment
229- . channels ( )
230- . into_iter ( )
231- . map ( |channel| {
232- channel
233- . clone ( )
234- . into_channel ( project. global_channel_config ( ) )
235- } )
236- . collect :: < Result < Vec < _ > , _ > > ( )
237- . into_diagnostic ( ) ?;
238-
239- let platform = environment. platform . unwrap_or_else ( Platform :: current) ;
240-
241- // For update operations, use "*" (any version) to find latest available packages
242- let mut pixi_specs = DependencyMap :: default ( ) ;
243- let mut dependencies_names = Vec :: new ( ) ;
244-
245- for ( name, _spec) in & environment. dependencies . specs {
246- let any_version_spec = pixi_spec:: PixiSpec :: default ( ) ;
247- pixi_specs. insert ( name. clone ( ) , any_version_spec) ;
248- dependencies_names. push ( name. clone ( ) ) ;
249- }
250-
251- let command_dispatcher = project. command_dispatcher ( ) . map_err ( |e| {
252- miette:: miette!(
253- "Cannot access command dispatcher for dry-run solving: {}" ,
254- e
255- )
256- } ) ?;
257-
258- let virtual_packages = if platform
259- . only_platform ( )
260- . map ( |p| p == Platform :: current ( ) . only_platform ( ) . unwrap_or ( "" ) )
261- . unwrap_or ( false )
262- {
263- VirtualPackage :: detect ( & VirtualPackageOverrides :: default ( ) )
264- . into_diagnostic ( )
265- . wrap_err ( format ! (
266- "Failed to determine virtual packages for environment {}" ,
267- env_name. fancy_display( )
268- ) ) ?
269- . iter ( )
270- . cloned ( )
271- . map ( GenericVirtualPackage :: from)
272- . collect ( )
273- } else {
274- vec ! [ ]
275- } ;
276-
277- let channels = channels
278- . into_iter ( )
279- . map ( |channel| channel. base_url . clone ( ) )
280- . collect :: < Vec < _ > > ( ) ;
281-
282- let build_environment = BuildEnvironment :: simple ( platform, virtual_packages) ;
283- let solve_spec = PixiEnvironmentSpec {
284- name : Some ( env_name. to_string ( ) ) ,
285- dependencies : pixi_specs,
286- build_environment : build_environment. clone ( ) ,
287- channels : channels. clone ( ) ,
288- channel_config : project. global_channel_config ( ) . clone ( ) ,
289- ..Default :: default ( )
290- } ;
291-
292- // SOLVE ONLY
293- let pixi_records = command_dispatcher
294- . solve_pixi_environment ( solve_spec)
295- . await ?;
296-
297- // Compare with current installed packages to detect changes
298- let prefix = project. environment_prefix ( env_name) . await ?;
299- let current_records = prefix. find_installed_packages ( ) . unwrap_or_default ( ) ;
300-
301- // Calculate what would change
302- let install_changes = if current_records. is_empty ( ) && !pixi_records. is_empty ( ) {
303- // Environment doesn't exist yet
304- pixi_records
305- . into_iter ( )
306- . map ( |record| {
307- (
308- record. package_record ( ) . name . clone ( ) ,
309- InstallChange :: Installed ( record. package_record ( ) . version . clone ( ) . into ( ) ) ,
310- )
311- } )
312- . collect ( )
313- } else {
314- // Compare current vs solved packages
315- let current_packages: HashMap < _ , _ > = current_records
316- . iter ( )
317- . map ( |r| {
318- (
319- r. repodata_record . package_record . name . clone ( ) ,
320- & r. repodata_record . package_record . version ,
321- )
322- } )
323- . collect ( ) ;
324-
325- let mut changes = HashMap :: new ( ) ;
326-
327- // Check for upgrades and new packages
328- for record in & pixi_records {
329- let name = & record. package_record ( ) . name ;
330- let new_version = & record. package_record ( ) . version ;
331-
332- if let Some ( current_version) = current_packages. get ( name) {
333- let current_version_converted: rattler_conda_types:: Version =
334- ( * current_version) . clone ( ) . into ( ) ;
335- let new_version_converted: rattler_conda_types:: Version =
336- new_version. clone ( ) . into ( ) ;
337- if current_version_converted != new_version_converted {
338- changes. insert (
339- name. clone ( ) ,
340- InstallChange :: Upgraded (
341- current_version_converted,
342- new_version_converted,
343- ) ,
344- ) ;
345- }
346- } else {
347- changes. insert (
348- name. clone ( ) ,
349- InstallChange :: Installed ( new_version. clone ( ) . into ( ) ) ,
350- ) ;
351- }
352- }
353-
354- // Check for removed packages
355- for ( name, _version) in current_packages {
356- if !pixi_records. iter ( ) . any ( |r| r. package_record ( ) . name == name) {
357- changes. insert ( name. clone ( ) , InstallChange :: Removed ) ;
358- }
359- }
360-
361- changes
362- } ;
363-
364- // Filter to only include changes to top-level dependencies (packages user explicitly installed)
365- let filtered_changes: HashMap < _ , _ > = install_changes
366- . into_iter ( )
367- . filter ( |( package_name, _change) | {
368- // Only keep changes for packages that are in the user's dependency list
369- dependencies_names. contains ( package_name)
370- } )
371- . collect ( ) ;
372-
373- Ok ( EnvironmentUpdate :: new ( filtered_changes, dependencies_names) )
374- }
375-
376207 // Update all environments if the user did not specify any
377208 let env_names = match args. environments {
378209 Some ( env_names) => env_names,
@@ -383,7 +214,8 @@ pub async fn execute(args: Args) -> miette::Result<()> {
383214 state_changes. report ( ) ;
384215 #[ cfg( unix) ]
385216 {
386- let completions_dir = global:: completions:: CompletionsDir :: from_env ( ) . await ?;
217+ let completions_dir =
218+ pixi_global:: completions:: CompletionsDir :: from_env ( ) . await ?;
387219 completions_dir. prune_old_completions ( ) ?;
388220 }
389221 }
0 commit comments