1- use super :: {
2- CondaPrefixUpdater , PixiRecordsByName , PypiRecordsByName , UvResolutionContext ,
3- outdated:: OutdatedEnvironments , utils:: IoConcurrencyLimit ,
4- } ;
5- use crate :: {
6- Workspace ,
7- activation:: CurrentEnvVarBehavior ,
8- environment:: {
9- CondaPrefixUpdated , EnvironmentFile , LockFileUsage , LockedEnvironmentHash ,
10- PerEnvironmentAndPlatform , PerGroup , PerGroupAndPlatform , PythonStatus ,
11- read_environment_file, write_environment_file,
12- } ,
13- install_pypi:: { PyPIBuildConfig , PyPIContextConfig , PyPIEnvironmentUpdater , PyPIUpdateConfig } ,
14- lock_file:: {
15- self , PypiRecord , reporter:: SolveProgressBar ,
16- virtual_packages:: validate_system_meets_environment_requirements,
17- } ,
18- workspace:: {
19- Environment , EnvironmentVars , HasWorkspaceRef , get_activated_environment_variables,
20- grouped_environment:: { GroupedEnvironment , GroupedEnvironmentName } ,
21- } ,
1+ use std:: {
2+ cmp:: PartialEq ,
3+ collections:: { HashMap , HashSet , hash_map:: Entry } ,
4+ future:: { Future , ready} ,
5+ iter,
6+ path:: PathBuf ,
7+ str:: FromStr ,
8+ sync:: Arc ,
9+ time:: { Duration , Instant } ,
2210} ;
11+
2312use barrier_cell:: BarrierCell ;
2413use dashmap:: DashMap ;
2514use fancy_display:: FancyDisplay ;
26- use futures:: { FutureExt , StreamExt , stream:: FuturesUnordered } ;
15+ use futures:: { FutureExt , StreamExt , TryFutureExt , stream:: FuturesUnordered } ;
2716use indexmap:: { IndexMap , IndexSet } ;
2817use indicatif:: ProgressBar ;
2918use itertools:: { Either , Itertools } ;
3019use miette:: { Diagnostic , IntoDiagnostic , MietteDiagnostic , Report , WrapErr } ;
31- use pixi_command_dispatcher:: { BuildEnvironment , CommandDispatcher , PixiEnvironmentSpec } ;
20+ use pixi_command_dispatcher:: {
21+ BuildEnvironment , CommandDispatcher , CommandDispatcherError , PixiEnvironmentSpec ,
22+ SolvePixiEnvironmentError ,
23+ } ;
3224use pixi_consts:: consts;
3325use pixi_glob:: GlobHashCache ;
3426use pixi_manifest:: { ChannelPriority , EnvironmentName , FeaturesExt } ;
@@ -42,24 +34,36 @@ use pixi_uv_conversions::{
4234use pypi_mapping:: { self , MappingClient } ;
4335use pypi_modifiers:: pypi_marker_env:: determine_marker_environment;
4436use rattler:: package_cache:: PackageCache ;
45- use rattler_conda_types:: { Arch , GenericVirtualPackage , PackageName , Platform } ;
37+ use rattler_conda_types:: { Arch , GenericVirtualPackage , PackageName , ParseChannelError , Platform } ;
4638use rattler_lock:: { LockFile , LockedPackageRef , ParseCondaLockError } ;
47- use std:: collections:: hash_map:: Entry ;
48- use std:: {
49- cmp:: PartialEq ,
50- collections:: { HashMap , HashSet } ,
51- future:: { Future , ready} ,
52- iter,
53- path:: PathBuf ,
54- str:: FromStr ,
55- sync:: Arc ,
56- time:: { Duration , Instant } ,
57- } ;
5839use thiserror:: Error ;
5940use tokio:: sync:: Semaphore ;
6041use tracing:: Instrument ;
6142use uv_normalize:: ExtraName ;
6243
44+ use super :: {
45+ CondaPrefixUpdater , PixiRecordsByName , PypiRecordsByName , UvResolutionContext ,
46+ outdated:: OutdatedEnvironments , utils:: IoConcurrencyLimit ,
47+ } ;
48+ use crate :: {
49+ Workspace ,
50+ activation:: CurrentEnvVarBehavior ,
51+ environment:: {
52+ CondaPrefixUpdated , EnvironmentFile , LockFileUsage , LockedEnvironmentHash ,
53+ PerEnvironmentAndPlatform , PerGroup , PerGroupAndPlatform , PythonStatus ,
54+ read_environment_file, write_environment_file,
55+ } ,
56+ install_pypi:: { PyPIBuildConfig , PyPIContextConfig , PyPIEnvironmentUpdater , PyPIUpdateConfig } ,
57+ lock_file:: {
58+ self , PypiRecord , reporter:: SolveProgressBar ,
59+ virtual_packages:: validate_system_meets_environment_requirements,
60+ } ,
61+ workspace:: {
62+ Environment , EnvironmentVars , HasWorkspaceRef , get_activated_environment_variables,
63+ grouped_environment:: { GroupedEnvironment , GroupedEnvironmentName } ,
64+ } ,
65+ } ;
66+
6367impl Workspace {
6468 /// Ensures that the lock-file is up-to-date with the project.
6569 ///
@@ -207,6 +211,25 @@ enum UpdateError {
207211 ParseLockFileError ( #[ from] ParseLockFileError ) ,
208212}
209213
214+ #[ derive( Debug , Error , Diagnostic ) ]
215+ pub enum SolveCondaEnvironmentError {
216+ #[ error( "failed to solve requirements of environment '{}' for platform '{}'" , . environment_name. fancy_display( ) , . platform) ]
217+ SolveFailed {
218+ environment_name : GroupedEnvironmentName ,
219+ platform : Platform ,
220+ #[ source]
221+ #[ diagnostic_source]
222+ source : CommandDispatcherError < SolvePixiEnvironmentError > ,
223+ } ,
224+
225+ #[ error( transparent) ]
226+ #[ diagnostic( transparent) ]
227+ PypiMappingFailed ( Box < dyn Diagnostic + Send + Sync + ' static > ) ,
228+
229+ #[ error( transparent) ]
230+ ParseChannels ( #[ from] ParseChannelError ) ,
231+ }
232+
210233/// Options to pass to [`Workspace::update_lock_file`].
211234#[ derive( Default ) ]
212235pub struct UpdateLockFileOptions {
@@ -1326,6 +1349,7 @@ impl<'p> UpdateContext<'p> {
13261349 channel_priority,
13271350 self . command_dispatcher . clone ( ) ,
13281351 )
1352+ . map_err ( Report :: new)
13291353 . boxed_local ( ) ;
13301354
13311355 // Store the task so we can poll it later.
@@ -1828,7 +1852,7 @@ async fn spawn_solve_conda_environment_task(
18281852 platform : Platform ,
18291853 channel_priority : ChannelPriority ,
18301854 command_dispatcher : CommandDispatcher ,
1831- ) -> miette :: Result < TaskResult > {
1855+ ) -> Result < TaskResult , SolveCondaEnvironmentError > {
18321856 // Get the dependencies for this platform
18331857 let dependencies = group. combined_dependencies ( Some ( platform) ) ;
18341858
@@ -1859,7 +1883,11 @@ async fn spawn_solve_conda_environment_task(
18591883 let has_pypi_dependencies = group. has_pypi_dependencies ( ) ;
18601884
18611885 // Whether we should use custom mapping location
1862- let pypi_name_mapping_location = group. workspace ( ) . pypi_name_mapping_source ( ) ?. clone ( ) ;
1886+ let pypi_name_mapping_location = group
1887+ . workspace ( )
1888+ . pypi_name_mapping_source ( )
1889+ . map_err ( |err| SolveCondaEnvironmentError :: PypiMappingFailed ( err. into ( ) ) ) ?
1890+ . clone ( ) ;
18631891
18641892 // Get the channel configuration
18651893 let channel_config = group. workspace ( ) . channel_config ( ) ;
@@ -1868,8 +1896,7 @@ async fn spawn_solve_conda_environment_task(
18681896 let channels = channels
18691897 . iter ( )
18701898 . map ( |c| c. clone ( ) . into_base_url ( & channel_config) )
1871- . collect :: < Result < Vec < _ > , _ > > ( )
1872- . into_diagnostic ( ) ?;
1899+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
18731900
18741901 // Determine the build variants
18751902 let variants = group. workspace ( ) . variants ( platform) ;
@@ -1893,12 +1920,10 @@ async fn spawn_solve_conda_environment_task(
18931920 enabled_protocols : Default :: default ( ) ,
18941921 } )
18951922 . await
1896- . with_context ( || {
1897- format ! (
1898- "failed to solve requirements of environment '{}' for platform '{}'" ,
1899- group. name( ) . fancy_display( ) ,
1900- platform
1901- )
1923+ . map_err ( |source| SolveCondaEnvironmentError :: SolveFailed {
1924+ environment_name : group_name. clone ( ) ,
1925+ platform,
1926+ source,
19021927 } ) ?;
19031928
19041929 // Add purl's for the conda packages that are also available as pypi packages if
@@ -1911,7 +1936,8 @@ async fn spawn_solve_conda_environment_task(
19111936 records. iter_mut ( ) . filter_map ( PixiRecord :: as_binary_mut) ,
19121937 None ,
19131938 )
1914- . await ?;
1939+ . await
1940+ . map_err ( |err| SolveCondaEnvironmentError :: PypiMappingFailed ( err. into ( ) ) ) ?;
19151941 }
19161942
19171943 // Turn the records into a map by name
0 commit comments