1
+ use std:: borrow:: Cow ;
1
2
use std:: collections:: { HashMap , HashSet } ;
2
3
use std:: fmt:: { self , Debug , Formatter } ;
3
4
use std:: fs;
4
5
use std:: io;
5
6
use std:: path:: { Path , PathBuf } ;
6
7
use std:: task:: Poll ;
7
8
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
+ } ;
9
12
use crate :: ops;
10
13
use crate :: sources:: source:: MaybePackage ;
11
14
use crate :: sources:: source:: QueryKind ;
@@ -14,15 +17,17 @@ use crate::sources::IndexSummary;
14
17
use crate :: util:: errors:: CargoResult ;
15
18
use crate :: util:: important_paths:: find_project_manifest_exact;
16
19
use crate :: util:: internal;
17
- use crate :: util:: toml:: read_manifest;
20
+ use crate :: util:: toml:: { lookup_path_base , read_manifest} ;
18
21
use crate :: util:: GlobalContext ;
19
- use anyhow:: Context as _;
22
+ use anyhow:: { anyhow , Context as _} ;
20
23
use cargo_util:: paths;
24
+ use cargo_util_schemas:: manifest:: PathBaseName ;
21
25
use filetime:: FileTime ;
22
26
use gix:: bstr:: { BString , ByteVec } ;
23
27
use gix:: dir:: entry:: Status ;
24
28
use gix:: index:: entry:: Stage ;
25
29
use ignore:: gitignore:: GitignoreBuilder ;
30
+ use lazycell:: LazyCell ;
26
31
use tracing:: { debug, info, trace, warn} ;
27
32
use walkdir:: WalkDir ;
28
33
@@ -300,7 +305,7 @@ impl<'gctx> RecursivePathSource<'gctx> {
300
305
/// Discovers packages inside this source if it hasn't yet done.
301
306
pub fn load ( & mut self ) -> CargoResult < ( ) > {
302
307
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 ) ?;
304
309
self . loaded = true ;
305
310
}
306
311
@@ -808,7 +813,6 @@ fn last_modified_file(
808
813
fn read_packages (
809
814
path : & Path ,
810
815
source_id : SourceId ,
811
- gctx : & GlobalContext ,
812
816
) -> CargoResult < HashMap < PackageId , Vec < Package > > > {
813
817
let mut all_packages = HashMap :: new ( ) ;
814
818
let mut visited = HashSet :: < PathBuf > :: new ( ) ;
@@ -844,14 +848,7 @@ fn read_packages(
844
848
}
845
849
846
850
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) ?;
855
852
}
856
853
Ok ( true )
857
854
} ) ?;
@@ -878,7 +875,7 @@ fn read_packages(
878
875
}
879
876
}
880
877
881
- fn nested_paths ( manifest : & Manifest ) -> Vec < PathBuf > {
878
+ fn nested_paths ( manifest : & Manifest ) -> Vec < ( PathBuf , Option < PathBaseName > ) > {
882
879
let mut nested_paths = Vec :: new ( ) ;
883
880
let normalized = manifest. normalized_toml ( ) ;
884
881
let dependencies = normalized
@@ -910,7 +907,7 @@ fn nested_paths(manifest: &Manifest) -> Vec<PathBuf> {
910
907
let Some ( path) = dep. path . as_ref ( ) else {
911
908
continue ;
912
909
} ;
913
- nested_paths. push ( PathBuf :: from ( path. as_str ( ) ) ) ;
910
+ nested_paths. push ( ( PathBuf :: from ( path. as_str ( ) ) , dep . base . clone ( ) ) ) ;
914
911
}
915
912
}
916
913
nested_paths
@@ -952,7 +949,6 @@ fn read_nested_packages(
952
949
path : & Path ,
953
950
all_packages : & mut HashMap < PackageId , Vec < Package > > ,
954
951
source_id : SourceId ,
955
- gctx : & GlobalContext ,
956
952
visited : & mut HashSet < PathBuf > ,
957
953
errors : & mut Vec < anyhow:: Error > ,
958
954
) -> CargoResult < ( ) > {
@@ -961,8 +957,10 @@ fn read_nested_packages(
961
957
}
962
958
963
959
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) ?;
964
962
965
- let manifest = match read_manifest ( & manifest_path, source_id, gctx ) {
963
+ let manifest = match read_manifest ( & manifest_path, source_id, & manifest_gctx ) {
966
964
Err ( err) => {
967
965
// Ignore malformed manifests found on git repositories
968
966
//
@@ -1000,10 +998,32 @@ fn read_nested_packages(
1000
998
//
1001
999
// TODO: filesystem/symlink implications?
1002
1000
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) ;
1007
1027
// Ignore broken manifests found on git repositories.
1008
1028
//
1009
1029
// A well formed manifest might still fail to load due to reasons
0 commit comments