1+ use std:: borrow:: Cow ;
12use std:: collections:: { HashMap , HashSet } ;
23use std:: fmt:: { self , Debug , Formatter } ;
34use std:: fs;
45use std:: io;
56use std:: path:: { Path , PathBuf } ;
67use std:: task:: Poll ;
78
8- use crate :: core:: { Dependency , EitherManifest , Manifest , Package , PackageId , SourceId } ;
9+ use crate :: core:: {
10+ find_workspace_root, Dependency , EitherManifest , Manifest , Package , PackageId , SourceId ,
11+ } ;
912use crate :: ops;
1013use crate :: sources:: source:: MaybePackage ;
1114use crate :: sources:: source:: QueryKind ;
@@ -14,15 +17,17 @@ use crate::sources::IndexSummary;
1417use crate :: util:: errors:: CargoResult ;
1518use crate :: util:: important_paths:: find_project_manifest_exact;
1619use crate :: util:: internal;
17- use crate :: util:: toml:: read_manifest;
20+ use crate :: util:: toml:: { lookup_path_base , read_manifest} ;
1821use crate :: util:: GlobalContext ;
19- use anyhow:: Context as _;
22+ use anyhow:: { anyhow , Context as _} ;
2023use cargo_util:: paths;
24+ use cargo_util_schemas:: manifest:: PathBaseName ;
2125use filetime:: FileTime ;
2226use gix:: bstr:: { BString , ByteVec } ;
2327use gix:: dir:: entry:: Status ;
2428use gix:: index:: entry:: Stage ;
2529use ignore:: gitignore:: GitignoreBuilder ;
30+ use lazycell:: LazyCell ;
2631use tracing:: { debug, info, trace, warn} ;
2732use walkdir:: WalkDir ;
2833
@@ -300,7 +305,7 @@ impl<'gctx> RecursivePathSource<'gctx> {
300305 /// Discovers packages inside this source if it hasn't yet done.
301306 pub fn load ( & mut self ) -> CargoResult < ( ) > {
302307 if !self . loaded {
303- self . packages = read_packages ( & self . path , self . source_id , self . gctx ) ?;
308+ self . packages = read_packages ( & self . path , self . source_id ) ?;
304309 self . loaded = true ;
305310 }
306311
@@ -808,7 +813,6 @@ fn last_modified_file(
808813fn read_packages (
809814 path : & Path ,
810815 source_id : SourceId ,
811- gctx : & GlobalContext ,
812816) -> CargoResult < HashMap < PackageId , Vec < Package > > > {
813817 let mut all_packages = HashMap :: new ( ) ;
814818 let mut visited = HashSet :: < PathBuf > :: new ( ) ;
@@ -844,14 +848,7 @@ fn read_packages(
844848 }
845849
846850 if has_manifest ( dir) {
847- read_nested_packages (
848- dir,
849- & mut all_packages,
850- source_id,
851- gctx,
852- & mut visited,
853- & mut errors,
854- ) ?;
851+ read_nested_packages ( dir, & mut all_packages, source_id, & mut visited, & mut errors) ?;
855852 }
856853 Ok ( true )
857854 } ) ?;
@@ -878,7 +875,7 @@ fn read_packages(
878875 }
879876}
880877
881- fn nested_paths ( manifest : & Manifest ) -> Vec < PathBuf > {
878+ fn nested_paths ( manifest : & Manifest ) -> Vec < ( PathBuf , Option < PathBaseName > ) > {
882879 let mut nested_paths = Vec :: new ( ) ;
883880 let normalized = manifest. normalized_toml ( ) ;
884881 let dependencies = normalized
@@ -910,7 +907,7 @@ fn nested_paths(manifest: &Manifest) -> Vec<PathBuf> {
910907 let Some ( path) = dep. path . as_ref ( ) else {
911908 continue ;
912909 } ;
913- nested_paths. push ( PathBuf :: from ( path. as_str ( ) ) ) ;
910+ nested_paths. push ( ( PathBuf :: from ( path. as_str ( ) ) , dep . base . clone ( ) ) ) ;
914911 }
915912 }
916913 nested_paths
@@ -952,7 +949,6 @@ fn read_nested_packages(
952949 path : & Path ,
953950 all_packages : & mut HashMap < PackageId , Vec < Package > > ,
954951 source_id : SourceId ,
955- gctx : & GlobalContext ,
956952 visited : & mut HashSet < PathBuf > ,
957953 errors : & mut Vec < anyhow:: Error > ,
958954) -> CargoResult < ( ) > {
@@ -961,8 +957,10 @@ fn read_nested_packages(
961957 }
962958
963959 let manifest_path = find_project_manifest_exact ( path, "Cargo.toml" ) ?;
960+ let mut manifest_gctx = GlobalContext :: default ( ) ?;
961+ manifest_gctx. reload_rooted_at ( & manifest_path) ?;
964962
965- let manifest = match read_manifest ( & manifest_path, source_id, gctx ) {
963+ let manifest = match read_manifest ( & manifest_path, source_id, & manifest_gctx ) {
966964 Err ( err) => {
967965 // Ignore malformed manifests found on git repositories
968966 //
@@ -1000,10 +998,32 @@ fn read_nested_packages(
1000998 //
1001999 // TODO: filesystem/symlink implications?
10021000 if !source_id. is_registry ( ) {
1003- for p in nested. iter ( ) {
1004- let path = paths:: normalize_path ( & path. join ( p) ) ;
1005- let result =
1006- read_nested_packages ( & path, all_packages, source_id, gctx, visited, errors) ;
1001+ let workspace_root_cell: LazyCell < PathBuf > = LazyCell :: new ( ) ;
1002+
1003+ for ( p, base) in nested. iter ( ) {
1004+ let p = if let Some ( base) = base {
1005+ let workspace_root = || {
1006+ workspace_root_cell
1007+ . try_borrow_with ( || {
1008+ find_workspace_root ( & manifest_path, & manifest_gctx) ?
1009+ . ok_or_else ( || anyhow ! ( "failed to find a workspace root" ) )
1010+ } )
1011+ . map ( |p| p. as_path ( ) )
1012+ } ;
1013+ // Pass in `None` for the `cargo-features` not to skip verification: when the
1014+ // package is loaded as a dependency, then it will be checked.
1015+ match lookup_path_base ( base, & manifest_gctx, & workspace_root, None ) {
1016+ Ok ( base) => Cow :: Owned ( base. join ( p) ) ,
1017+ Err ( err) => {
1018+ errors. push ( err) ;
1019+ continue ;
1020+ }
1021+ }
1022+ } else {
1023+ Cow :: Borrowed ( p)
1024+ } ;
1025+ let path = paths:: normalize_path ( & path. join ( p. as_path ( ) ) ) ;
1026+ let result = read_nested_packages ( & path, all_packages, source_id, visited, errors) ;
10071027 // Ignore broken manifests found on git repositories.
10081028 //
10091029 // A well formed manifest might still fail to load due to reasons
0 commit comments