@@ -206,13 +206,18 @@ pub async fn componentize(
206206 let mut library_path = Vec :: with_capacity ( python_path. len ( ) ) ;
207207 for path in python_path {
208208 let mut libraries = Vec :: new ( ) ;
209- search_directory ( Path :: new ( path) , & mut libraries, & mut raw_config) ?;
209+ search_directory (
210+ Path :: new ( path) ,
211+ Path :: new ( path) ,
212+ & mut libraries,
213+ & mut raw_config,
214+ ) ?;
210215 library_path. push ( ( * path, libraries) ) ;
211216 }
212217
213- let config = if let Some ( ( config_path, raw) ) = raw_config {
218+ let config = if let Some ( ( config_root , config_path, raw) ) = raw_config {
214219 let config = ComponentizePyConfig :: try_from ( ( config_path. deref ( ) , raw) ) ?;
215- Some ( ( config_path, config) )
220+ Some ( ( config_root , config_path, config) )
216221 } else {
217222 None
218223 } ;
@@ -221,7 +226,7 @@ pub async fn componentize(
221226 path. to_owned ( )
222227 } else if let Some ( ( config_path, wit_path) ) = config
223228 . as_ref ( )
224- . and_then ( |( p, c) | c. wit_directory . as_deref ( ) . map ( |f| ( p, f) ) )
229+ . and_then ( |( _ , p, c) | c. wit_directory . as_deref ( ) . map ( |f| ( p, f) ) )
225230 {
226231 config_path. join ( wit_path)
227232 } else {
@@ -369,22 +374,29 @@ pub async fn componentize(
369374
370375 let world_dir = tempfile:: tempdir ( ) ?;
371376
372- let ( world_dir_mounts, world_module) = if let Some ( ( config_path, binding_path) ) = config
373- . as_ref ( )
374- . and_then ( |( p, c) | c. bindings . as_deref ( ) . map ( |f| ( p, f) ) )
377+ let ( world_dir_mounts, world_module) = if let Some ( ( config_root, config_path, binding_path) ) =
378+ config
379+ . as_ref ( )
380+ . and_then ( |( r, p, c) | c. bindings . as_deref ( ) . map ( |f| ( r, p, f) ) )
375381 {
376382 summary. generate_code ( world_dir. path ( ) , false ) ?;
377383
378384 let paths = python_path
379385 . iter ( )
380386 . enumerate ( )
381387 . map ( |( index, dir) | {
382- Ok ( config_path
383- . canonicalize ( ) ?
384- . join ( binding_path)
385- . strip_prefix ( Path :: new ( dir) . canonicalize ( ) ?)
386- . ok ( )
387- . map ( |p| ( index, p. to_str ( ) . unwrap ( ) . to_owned ( ) ) ) )
388+ let dir = Path :: new ( dir) . canonicalize ( ) ?;
389+ let config_root = config_root. canonicalize ( ) ?;
390+ Ok ( if config_root == dir {
391+ config_path
392+ . canonicalize ( ) ?
393+ . join ( binding_path)
394+ . strip_prefix ( dir)
395+ . ok ( )
396+ . map ( |p| ( index, p. to_str ( ) . unwrap ( ) . to_owned ( ) ) )
397+ } else {
398+ None
399+ } )
388400 } )
389401 . filter_map ( Result :: transpose)
390402 . collect :: < Result < Vec < _ > > > ( ) ?;
@@ -590,22 +602,42 @@ fn add_wasi_and_stubs(
590602}
591603
592604fn search_directory (
605+ root : & Path ,
593606 path : & Path ,
594607 libraries : & mut Vec < PathBuf > ,
595- config : & mut Option < ( PathBuf , RawComponentizePyConfig ) > ,
608+ config : & mut Option < ( PathBuf , PathBuf , RawComponentizePyConfig ) > ,
596609) -> Result < ( ) > {
597610 if path. is_dir ( ) {
598611 for entry in fs:: read_dir ( path) ? {
599- search_directory ( & entry?. path ( ) , libraries, config) ?;
612+ search_directory ( root , & entry?. path ( ) , libraries, config) ?;
600613 }
601614 } else if let Some ( name) = path. file_name ( ) . and_then ( |name| name. to_str ( ) ) {
602615 if name. ends_with ( NATIVE_EXTENSION_SUFFIX ) {
603616 libraries. push ( path. to_owned ( ) ) ;
604617 } else if name == "componentize-py.toml" {
605- if config. is_some ( ) {
606- bail ! ( "multiple componentize-py.toml files found, which is not yet supported" ) ;
618+ let do_update = if let Some ( ( existing_root, existing_path, _) ) = config {
619+ let path = path. canonicalize ( ) ?;
620+ let existing_path = existing_path. join ( "componentize-py.toml" ) . canonicalize ( ) ?;
621+ if path != existing_path {
622+ bail ! (
623+ "multiple componentize-py.toml files found, \
624+ which is not yet supported: {} and {}",
625+ existing_path. display( ) ,
626+ path. display( )
627+ ) ;
628+ }
629+
630+ // When one directory in `PYTHON_PATH` is a subdirectory of the other, we consider the subdirectory
631+ // to be the true owner of the file. This is important later, when we derive a package name by
632+ // stripping the root directory from the file path.
633+ root. canonicalize ( ) ? > existing_root. canonicalize ( ) ?
607634 } else {
635+ true
636+ } ;
637+
638+ if do_update {
608639 * config = Some ( (
640+ root. to_owned ( ) ,
609641 path. parent ( ) . unwrap ( ) . to_owned ( ) ,
610642 toml:: from_str :: < RawComponentizePyConfig > ( & fs:: read_to_string ( path) ?) ?,
611643 ) ) ;
0 commit comments