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