1
- use std:: collections:: { HashMap , HashSet } ;
2
- use std:: fs;
3
- use std:: io;
4
- use std:: path:: { Path , PathBuf } ;
1
+ use std:: path:: Path ;
5
2
6
- use crate :: core:: { EitherManifest , Manifest , Package , PackageId , SourceId } ;
3
+ use crate :: core:: { EitherManifest , Package , SourceId } ;
7
4
use crate :: util:: errors:: CargoResult ;
8
- use crate :: util:: important_paths:: find_project_manifest_exact;
9
5
use crate :: util:: toml:: read_manifest;
10
6
use crate :: util:: GlobalContext ;
11
- use cargo_util:: paths;
12
- use tracing:: { info, trace} ;
7
+ use tracing:: trace;
13
8
14
9
pub fn read_package (
15
10
path : & Path ,
@@ -33,242 +28,3 @@ pub fn read_package(
33
28
34
29
Ok ( Package :: new ( manifest, path) )
35
30
}
36
-
37
- #[ tracing:: instrument( skip( source_id, gctx) ) ]
38
- pub fn read_packages (
39
- path : & Path ,
40
- source_id : SourceId ,
41
- gctx : & GlobalContext ,
42
- ) -> CargoResult < Vec < Package > > {
43
- let mut all_packages = HashMap :: new ( ) ;
44
- let mut visited = HashSet :: < PathBuf > :: new ( ) ;
45
- let mut errors = Vec :: < anyhow:: Error > :: new ( ) ;
46
-
47
- trace ! (
48
- "looking for root package: {}, source_id={}" ,
49
- path. display( ) ,
50
- source_id
51
- ) ;
52
-
53
- walk ( path, & mut |dir| {
54
- trace ! ( "looking for child package: {}" , dir. display( ) ) ;
55
-
56
- // Don't recurse into hidden/dot directories unless we're at the toplevel
57
- if dir != path {
58
- let name = dir. file_name ( ) . and_then ( |s| s. to_str ( ) ) ;
59
- if name. map ( |s| s. starts_with ( '.' ) ) == Some ( true ) {
60
- return Ok ( false ) ;
61
- }
62
-
63
- // Don't automatically discover packages across git submodules
64
- if dir. join ( ".git" ) . exists ( ) {
65
- return Ok ( false ) ;
66
- }
67
- }
68
-
69
- // Don't ever look at target directories
70
- if dir. file_name ( ) . and_then ( |s| s. to_str ( ) ) == Some ( "target" )
71
- && has_manifest ( dir. parent ( ) . unwrap ( ) )
72
- {
73
- return Ok ( false ) ;
74
- }
75
-
76
- if has_manifest ( dir) {
77
- read_nested_packages (
78
- dir,
79
- & mut all_packages,
80
- source_id,
81
- gctx,
82
- & mut visited,
83
- & mut errors,
84
- ) ?;
85
- }
86
- Ok ( true )
87
- } ) ?;
88
-
89
- if all_packages. is_empty ( ) {
90
- match errors. pop ( ) {
91
- Some ( err) => Err ( err) ,
92
- None => {
93
- if find_project_manifest_exact ( path, "cargo.toml" ) . is_ok ( ) {
94
- Err ( anyhow:: format_err!(
95
- "Could not find Cargo.toml in `{}`, but found cargo.toml please try to rename it to Cargo.toml" ,
96
- path. display( )
97
- ) )
98
- } else {
99
- Err ( anyhow:: format_err!(
100
- "Could not find Cargo.toml in `{}`" ,
101
- path. display( )
102
- ) )
103
- }
104
- }
105
- }
106
- } else {
107
- Ok ( all_packages. into_iter ( ) . map ( |( _, v) | v) . collect ( ) )
108
- }
109
- }
110
-
111
- fn nested_paths ( manifest : & Manifest ) -> Vec < PathBuf > {
112
- let mut nested_paths = Vec :: new ( ) ;
113
- let resolved = manifest. resolved_toml ( ) ;
114
- let dependencies = resolved
115
- . dependencies
116
- . iter ( )
117
- . chain ( resolved. build_dependencies ( ) )
118
- . chain ( resolved. dev_dependencies ( ) )
119
- . chain (
120
- resolved
121
- . target
122
- . as_ref ( )
123
- . into_iter ( )
124
- . flat_map ( |t| t. values ( ) )
125
- . flat_map ( |t| {
126
- t. dependencies
127
- . iter ( )
128
- . chain ( t. build_dependencies ( ) )
129
- . chain ( t. dev_dependencies ( ) )
130
- } ) ,
131
- ) ;
132
- for dep_table in dependencies {
133
- for dep in dep_table. values ( ) {
134
- let cargo_util_schemas:: manifest:: InheritableDependency :: Value ( dep) = dep else {
135
- continue ;
136
- } ;
137
- let cargo_util_schemas:: manifest:: TomlDependency :: Detailed ( dep) = dep else {
138
- continue ;
139
- } ;
140
- let Some ( path) = dep. path . as_ref ( ) else {
141
- continue ;
142
- } ;
143
- nested_paths. push ( PathBuf :: from ( path. as_str ( ) ) ) ;
144
- }
145
- }
146
- nested_paths
147
- }
148
-
149
- fn walk ( path : & Path , callback : & mut dyn FnMut ( & Path ) -> CargoResult < bool > ) -> CargoResult < ( ) > {
150
- if !callback ( path) ? {
151
- trace ! ( "not processing {}" , path. display( ) ) ;
152
- return Ok ( ( ) ) ;
153
- }
154
-
155
- // Ignore any permission denied errors because temporary directories
156
- // can often have some weird permissions on them.
157
- let dirs = match fs:: read_dir ( path) {
158
- Ok ( dirs) => dirs,
159
- Err ( ref e) if e. kind ( ) == io:: ErrorKind :: PermissionDenied => return Ok ( ( ) ) ,
160
- Err ( e) => {
161
- let cx = format ! ( "failed to read directory `{}`" , path. display( ) ) ;
162
- let e = anyhow:: Error :: from ( e) ;
163
- return Err ( e. context ( cx) ) ;
164
- }
165
- } ;
166
- for dir in dirs {
167
- let dir = dir?;
168
- if dir. file_type ( ) ?. is_dir ( ) {
169
- walk ( & dir. path ( ) , callback) ?;
170
- }
171
- }
172
- Ok ( ( ) )
173
- }
174
-
175
- fn has_manifest ( path : & Path ) -> bool {
176
- find_project_manifest_exact ( path, "Cargo.toml" ) . is_ok ( )
177
- }
178
-
179
- fn read_nested_packages (
180
- path : & Path ,
181
- all_packages : & mut HashMap < PackageId , Package > ,
182
- source_id : SourceId ,
183
- gctx : & GlobalContext ,
184
- visited : & mut HashSet < PathBuf > ,
185
- errors : & mut Vec < anyhow:: Error > ,
186
- ) -> CargoResult < ( ) > {
187
- if !visited. insert ( path. to_path_buf ( ) ) {
188
- return Ok ( ( ) ) ;
189
- }
190
-
191
- let manifest_path = find_project_manifest_exact ( path, "Cargo.toml" ) ?;
192
-
193
- let manifest = match read_manifest ( & manifest_path, source_id, gctx) {
194
- Err ( err) => {
195
- // Ignore malformed manifests found on git repositories
196
- //
197
- // git source try to find and read all manifests from the repository
198
- // but since it's not possible to exclude folders from this search
199
- // it's safer to ignore malformed manifests to avoid
200
- //
201
- // TODO: Add a way to exclude folders?
202
- info ! (
203
- "skipping malformed package found at `{}`" ,
204
- path. to_string_lossy( )
205
- ) ;
206
- errors. push ( err. into ( ) ) ;
207
- return Ok ( ( ) ) ;
208
- }
209
- Ok ( tuple) => tuple,
210
- } ;
211
-
212
- let manifest = match manifest {
213
- EitherManifest :: Real ( manifest) => manifest,
214
- EitherManifest :: Virtual ( ..) => return Ok ( ( ) ) ,
215
- } ;
216
- let nested = nested_paths ( & manifest) ;
217
- let pkg = Package :: new ( manifest, & manifest_path) ;
218
-
219
- let pkg_id = pkg. package_id ( ) ;
220
- use std:: collections:: hash_map:: Entry ;
221
- match all_packages. entry ( pkg_id) {
222
- Entry :: Vacant ( v) => {
223
- v. insert ( pkg) ;
224
- }
225
- Entry :: Occupied ( _) => {
226
- // We can assume a package with publish = false isn't intended to be seen
227
- // by users so we can hide the warning about those since the user is unlikely
228
- // to care about those cases.
229
- if pkg. publish ( ) . is_none ( ) {
230
- let _ = gctx. shell ( ) . warn ( format ! (
231
- "skipping duplicate package `{}` found at `{}`" ,
232
- pkg. name( ) ,
233
- path. display( )
234
- ) ) ;
235
- }
236
- }
237
- }
238
-
239
- // Registry sources are not allowed to have `path=` dependencies because
240
- // they're all translated to actual registry dependencies.
241
- //
242
- // We normalize the path here ensure that we don't infinitely walk around
243
- // looking for crates. By normalizing we ensure that we visit this crate at
244
- // most once.
245
- //
246
- // TODO: filesystem/symlink implications?
247
- if !source_id. is_registry ( ) {
248
- for p in nested. iter ( ) {
249
- let path = paths:: normalize_path ( & path. join ( p) ) ;
250
- let result =
251
- read_nested_packages ( & path, all_packages, source_id, gctx, visited, errors) ;
252
- // Ignore broken manifests found on git repositories.
253
- //
254
- // A well formed manifest might still fail to load due to reasons
255
- // like referring to a "path" that requires an extra build step.
256
- //
257
- // See https://github.com/rust-lang/cargo/issues/6822.
258
- if let Err ( err) = result {
259
- if source_id. is_git ( ) {
260
- info ! (
261
- "skipping nested package found at `{}`: {:?}" ,
262
- path. display( ) ,
263
- & err,
264
- ) ;
265
- errors. push ( err) ;
266
- } else {
267
- return Err ( err) ;
268
- }
269
- }
270
- }
271
- }
272
-
273
- Ok ( ( ) )
274
- }
0 commit comments