@@ -10,6 +10,7 @@ use pixi_manifest::{
1010use thiserror:: Error ;
1111
1212use crate :: workspace:: Workspace ;
13+ use crate :: workspace:: WorkspaceRegistry ;
1314
1415/// Defines where the search for the workspace should start.
1516#[ derive( Debug , Clone , Default ) ]
@@ -30,6 +31,11 @@ pub enum DiscoveryStart {
3031 ///
3132 /// If no manifest is found at the given path the search will abort.
3233 ExplicitManifest ( PathBuf ) ,
34+
35+ /// Search by name in the workspace registry.
36+ ///
37+ /// If the name is not found in the registry, abort.
38+ WorkspaceRegistry ( String ) ,
3339}
3440
3541impl DiscoveryStart {
@@ -39,6 +45,14 @@ impl DiscoveryStart {
3945 DiscoveryStart :: CurrentDir => std:: env:: current_dir ( ) ,
4046 DiscoveryStart :: SearchRoot ( path) => Ok ( path. clone ( ) ) ,
4147 DiscoveryStart :: ExplicitManifest ( path) => Ok ( path. clone ( ) ) ,
48+ DiscoveryStart :: WorkspaceRegistry ( name) => {
49+ let registry = WorkspaceRegistry :: load ( )
50+ . map_err ( |_| WorkspaceLocatorError :: MissingRegistry ( ) ) ?;
51+ let path = registry
52+ . named_workspace ( name)
53+ . map_err ( |_| WorkspaceLocatorError :: MissingWorkspace ( name. clone ( ) ) ) ?;
54+ Ok ( path)
55+ }
4256 }
4357 }
4458}
@@ -97,6 +111,19 @@ pub enum WorkspaceLocatorError {
97111 #[ error( transparent) ]
98112 #[ diagnostic( transparent) ]
99113 ExplicitManifestError ( #[ from] ExplicitManifestError ) ,
114+
115+ #[ error( "unable to load the workspace registry" ) ]
116+ MissingRegistry ( ) ,
117+
118+ #[ error( "could not find workspace '{}'" , . 0 ) ]
119+ MissingWorkspace ( String ) ,
120+ }
121+
122+ impl From < WorkspaceLocatorError > for std:: io:: Error {
123+ fn from ( err : WorkspaceLocatorError ) -> Self {
124+ // Create a new std::io::Error, using Other kind and the source error
125+ std:: io:: Error :: other ( err)
126+ }
100127}
101128
102129impl WorkspaceLocator {
@@ -160,6 +187,14 @@ impl WorkspaceLocator {
160187 std:: env:: current_dir ( ) . map_err ( WorkspaceLocatorError :: CurrentDir ) ?,
161188 ) ,
162189 DiscoveryStart :: SearchRoot ( path) => pixi_manifest:: DiscoveryStart :: SearchRoot ( path) ,
190+ DiscoveryStart :: WorkspaceRegistry ( name) => {
191+ let registry = WorkspaceRegistry :: load ( )
192+ . map_err ( |_| WorkspaceLocatorError :: MissingRegistry ( ) ) ?;
193+ let path = registry
194+ . named_workspace ( & name)
195+ . map_err ( |_| WorkspaceLocatorError :: MissingWorkspace ( name. clone ( ) ) ) ?;
196+ pixi_manifest:: DiscoveryStart :: ExplicitManifest ( path)
197+ }
163198 } ;
164199
165200 let discovery_source = discovery_start. root ( ) . to_path_buf ( ) ;
@@ -290,6 +325,9 @@ impl WorkspaceLocator {
290325mod test {
291326 use std:: path:: Path ;
292327
328+ use temp_env;
329+ use tempfile:: tempdir;
330+
293331 use super :: * ;
294332
295333 #[ test]
@@ -323,6 +361,52 @@ mod test {
323361 assert_eq ! ( workspace. root, project_root) ;
324362 }
325363
364+ #[ tokio:: test]
365+ async fn test_workspace_locator_registered_workspace ( ) {
366+ // Equivalent to `pixi xxx --workspace ws`
367+ let temp_dir = tempdir ( ) . unwrap ( ) ;
368+ let pixi_home_dir = temp_dir. path ( ) . join ( "pixi-home" ) ;
369+ let crate_root = std:: env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) ;
370+ let project_root = Path :: new ( & crate_root) . parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) ;
371+ temp_env:: async_with_vars (
372+ [ ( "PIXI_HOME" , Some ( pixi_home_dir. to_str ( ) . unwrap ( ) ) ) ] ,
373+ async {
374+ WorkspaceRegistry :: default ( )
375+ . add_workspace ( "ws" . to_string ( ) , project_root. to_path_buf ( ) )
376+ . await
377+ . unwrap ( ) ;
378+
379+ let workspace_locator = WorkspaceLocator :: default ( )
380+ . with_search_start ( DiscoveryStart :: WorkspaceRegistry ( "ws" . to_string ( ) ) ) ;
381+ let workspace = workspace_locator. locate ( ) . unwrap ( ) ;
382+ assert_eq ! ( workspace. root, project_root) ;
383+ } ,
384+ )
385+ . await ;
386+ }
387+
388+ #[ test]
389+ fn test_workspace_locator_registered_workspace_does_not_exist ( ) {
390+ // Equivalent to `pixi xxx --workspace idontexist`
391+ let temp_dir = tempdir ( ) . unwrap ( ) ;
392+ let pixi_home_dir = temp_dir. path ( ) . join ( "pixi-home" ) ;
393+ temp_env:: with_var ( "PIXI_HOME" , Some ( pixi_home_dir. to_str ( ) . unwrap ( ) ) , || {
394+ let workspace_locator = WorkspaceLocator :: default ( )
395+ . with_search_start ( DiscoveryStart :: WorkspaceRegistry ( "idontexist" . to_string ( ) ) ) ;
396+
397+ let result = workspace_locator. locate ( ) ;
398+ assert ! ( result. is_err( ) ) ;
399+
400+ let error = result. unwrap_err ( ) ;
401+ assert ! ( matches!( error, WorkspaceLocatorError :: MissingWorkspace ( _) ) ) ;
402+
403+ // Check that the error message contains the suggestion
404+ let error_message = error. to_string ( ) ;
405+ assert ! ( error_message. contains( "could not find workspace " ) ) ;
406+ assert ! ( error_message. contains( "idontexist" ) ) ;
407+ } ) ;
408+ }
409+
326410 #[ test]
327411 fn test_workspace_locator_explicit_simple ( ) {
328412 // Equivalent to `pixi xxx --manifest pixi.toml`
0 commit comments