]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | //! Checks the licenses of third-party dependencies. |
476ff2be | 2 | |
ba9703b0 XL |
3 | use cargo_metadata::{Metadata, Package, PackageId, Resolve}; |
4 | use std::collections::{BTreeSet, HashSet}; | |
476ff2be SL |
5 | use std::path::Path; |
6 | ||
ba9703b0 XL |
7 | /// These are licenses that are allowed for all crates, including the runtime, |
8 | /// rustc, tools, etc. | |
b7449926 | 9 | const LICENSES: &[&str] = &[ |
8bb4bdeb XL |
10 | "MIT/Apache-2.0", |
11 | "MIT / Apache-2.0", | |
12 | "Apache-2.0/MIT", | |
3b2f2976 | 13 | "Apache-2.0 / MIT", |
8bb4bdeb | 14 | "MIT OR Apache-2.0", |
416331ca | 15 | "Apache-2.0 OR MIT", |
e1599b0c | 16 | "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license |
8bb4bdeb XL |
17 | "MIT", |
18 | "Unlicense/MIT", | |
8faf50e0 | 19 | "Unlicense OR MIT", |
3dfed10e XL |
20 | "0BSD OR MIT OR Apache-2.0", // adler license |
21 | "Zlib OR Apache-2.0 OR MIT", // tinyvec | |
8bb4bdeb XL |
22 | ]; |
23 | ||
0531ce1d XL |
24 | /// These are exceptions to Rust's permissive licensing policy, and |
25 | /// should be considered bugs. Exceptions are only allowed in Rust | |
26 | /// tooling. It is _crucial_ that no exception crates be dependencies | |
9fa01778 | 27 | /// of the Rust runtime (std/test). |
ba9703b0 | 28 | const EXCEPTIONS: &[(&str, &str)] = &[ |
3dfed10e XL |
29 | ("mdbook", "MPL-2.0"), // mdbook |
30 | ("openssl", "Apache-2.0"), // cargo, mdbook | |
136023e0 XL |
31 | ("colored", "MPL-2.0"), // rustfmt |
32 | ("ordslice", "Apache-2.0"), // rls | |
33 | ("ryu", "Apache-2.0 OR BSL-1.0"), // rls/cargo/... (because of serde) | |
34 | ("bytesize", "Apache-2.0"), // cargo | |
35 | ("im-rc", "MPL-2.0+"), // cargo | |
36 | ("sized-chunks", "MPL-2.0+"), // cargo via im-rc | |
37 | ("bitmaps", "MPL-2.0+"), // cargo via im-rc | |
3dfed10e | 38 | ("crossbeam-queue", "MIT/Apache-2.0 AND BSD-2-Clause"), // rls via rayon |
136023e0 XL |
39 | ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot |
40 | ("snap", "BSD-3-Clause"), // rustc | |
416331ca | 41 | // FIXME: this dependency violates the documentation comment above: |
ba9703b0 | 42 | ("fortanix-sgx-abi", "MPL-2.0"), // libstd but only for `sgx` target |
0531ce1d XL |
43 | ]; |
44 | ||
17df50a5 XL |
45 | const EXCEPTIONS_CRANELIFT: &[(&str, &str)] = &[ |
46 | ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"), | |
47 | ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"), | |
48 | ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"), | |
49 | ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"), | |
50 | ("cranelift-entity", "Apache-2.0 WITH LLVM-exception"), | |
51 | ("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"), | |
52 | ("cranelift-jit", "Apache-2.0 WITH LLVM-exception"), | |
53 | ("cranelift-module", "Apache-2.0 WITH LLVM-exception"), | |
54 | ("cranelift-native", "Apache-2.0 WITH LLVM-exception"), | |
55 | ("cranelift-object", "Apache-2.0 WITH LLVM-exception"), | |
56 | ("libloading", "ISC"), | |
57 | ("mach", "BSD-2-Clause"), | |
58 | ("regalloc", "Apache-2.0 WITH LLVM-exception"), | |
59 | ("target-lexicon", "Apache-2.0 WITH LLVM-exception"), | |
60 | ]; | |
61 | ||
ba9703b0 XL |
62 | /// These are the root crates that are part of the runtime. The licenses for |
63 | /// these and all their dependencies *must not* be in the exception list. | |
64 | const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"]; | |
65 | ||
f035d41b | 66 | /// Crates whose dependencies must be explicitly permitted. |
17df50a5 | 67 | const RESTRICTED_DEPENDENCY_CRATES: &[&str] = &["rustc_driver", "rustc_codegen_llvm"]; |
476ff2be | 68 | |
f035d41b | 69 | /// Crates rustc is allowed to depend on. Avoid adding to the list if possible. |
ba9703b0 XL |
70 | /// |
71 | /// This list is here to provide a speed-bump to adding a new dependency to | |
72 | /// rustc. Please check with the compiler team before adding an entry. | |
f035d41b | 73 | const PERMITTED_DEPENDENCIES: &[&str] = &[ |
3dfed10e XL |
74 | "addr2line", |
75 | "adler", | |
ba9703b0 XL |
76 | "aho-corasick", |
77 | "annotate-snippets", | |
78 | "ansi_term", | |
79 | "arrayvec", | |
80 | "atty", | |
81 | "autocfg", | |
ba9703b0 XL |
82 | "bitflags", |
83 | "block-buffer", | |
84 | "block-padding", | |
ba9703b0 | 85 | "byteorder", |
3dfed10e | 86 | "byte-tools", |
ba9703b0 XL |
87 | "cc", |
88 | "cfg-if", | |
f9f354fc | 89 | "chalk-derive", |
17df50a5 | 90 | "chalk-engine", |
f9f354fc | 91 | "chalk-ir", |
17df50a5 XL |
92 | "chalk-solve", |
93 | "chrono", | |
ba9703b0 XL |
94 | "cmake", |
95 | "compiler_builtins", | |
29967ef6 | 96 | "cpuid-bool", |
ba9703b0 XL |
97 | "crc32fast", |
98 | "crossbeam-deque", | |
99 | "crossbeam-epoch", | |
100 | "crossbeam-queue", | |
101 | "crossbeam-utils", | |
6a06907d | 102 | "cstr", |
ba9703b0 | 103 | "datafrog", |
3dfed10e | 104 | "difference", |
ba9703b0 XL |
105 | "digest", |
106 | "dlmalloc", | |
107 | "either", | |
108 | "ena", | |
109 | "env_logger", | |
3dfed10e | 110 | "expect-test", |
ba9703b0 XL |
111 | "fake-simd", |
112 | "filetime", | |
17df50a5 | 113 | "fixedbitset", |
ba9703b0 XL |
114 | "flate2", |
115 | "fortanix-sgx-abi", | |
ba9703b0 XL |
116 | "generic-array", |
117 | "getopts", | |
118 | "getrandom", | |
3dfed10e | 119 | "gimli", |
fc512014 | 120 | "gsgdt", |
ba9703b0 XL |
121 | "hashbrown", |
122 | "hermit-abi", | |
123 | "humantime", | |
94222f64 | 124 | "if_chain", |
ba9703b0 | 125 | "indexmap", |
3dfed10e | 126 | "instant", |
ba9703b0 | 127 | "itertools", |
17df50a5 | 128 | "itoa", |
ba9703b0 | 129 | "jobserver", |
ba9703b0 XL |
130 | "lazy_static", |
131 | "libc", | |
132 | "libz-sys", | |
133 | "lock_api", | |
134 | "log", | |
17df50a5 | 135 | "matchers", |
3dfed10e | 136 | "maybe-uninit", |
ba9703b0 XL |
137 | "md-5", |
138 | "measureme", | |
139 | "memchr", | |
6a06907d | 140 | "memmap2", |
ba9703b0 XL |
141 | "memoffset", |
142 | "miniz_oxide", | |
ba9703b0 | 143 | "num_cpus", |
17df50a5 XL |
144 | "num-integer", |
145 | "num-traits", | |
3dfed10e | 146 | "object", |
c295e0f8 | 147 | "odht", |
f9f354fc | 148 | "once_cell", |
ba9703b0 XL |
149 | "opaque-debug", |
150 | "parking_lot", | |
151 | "parking_lot_core", | |
3dfed10e | 152 | "pathdiff", |
6a06907d | 153 | "perf-event-open-sys", |
17df50a5 | 154 | "petgraph", |
6a06907d | 155 | "pin-project-lite", |
ba9703b0 XL |
156 | "pkg-config", |
157 | "polonius-engine", | |
158 | "ppv-lite86", | |
159 | "proc-macro2", | |
f9f354fc | 160 | "psm", |
ba9703b0 XL |
161 | "punycode", |
162 | "quick-error", | |
163 | "quote", | |
164 | "rand", | |
165 | "rand_chacha", | |
166 | "rand_core", | |
167 | "rand_hc", | |
ba9703b0 XL |
168 | "rand_pcg", |
169 | "rand_xorshift", | |
c295e0f8 | 170 | "rand_xoshiro", |
ba9703b0 | 171 | "redox_syscall", |
ba9703b0 | 172 | "regex", |
17df50a5 | 173 | "regex-automata", |
ba9703b0 XL |
174 | "regex-syntax", |
175 | "remove_dir_all", | |
17df50a5 XL |
176 | "rls-data", |
177 | "rls-span", | |
ba9703b0 XL |
178 | "rustc-demangle", |
179 | "rustc-hash", | |
180 | "rustc-rayon", | |
181 | "rustc-rayon-core", | |
182 | "rustc_version", | |
17df50a5 | 183 | "ryu", |
ba9703b0 XL |
184 | "scoped-tls", |
185 | "scopeguard", | |
186 | "semver", | |
187 | "semver-parser", | |
188 | "serde", | |
189 | "serde_derive", | |
17df50a5 | 190 | "serde_json", |
ba9703b0 | 191 | "sha-1", |
29967ef6 | 192 | "sha2", |
ba9703b0 | 193 | "smallvec", |
17df50a5 | 194 | "sharded-slab", |
1b1a35ee | 195 | "snap", |
ba9703b0 | 196 | "stable_deref_trait", |
f9f354fc | 197 | "stacker", |
ba9703b0 XL |
198 | "syn", |
199 | "synstructure", | |
200 | "tempfile", | |
201 | "termcolor", | |
ba9703b0 XL |
202 | "termize", |
203 | "thread_local", | |
17df50a5 XL |
204 | "time", |
205 | "tinyvec", | |
3dfed10e XL |
206 | "tracing", |
207 | "tracing-attributes", | |
208 | "tracing-core", | |
17df50a5 XL |
209 | "tracing-log", |
210 | "tracing-serde", | |
211 | "tracing-subscriber", | |
212 | "tracing-tree", | |
ba9703b0 | 213 | "typenum", |
ba9703b0 XL |
214 | "unicode-normalization", |
215 | "unicode-script", | |
216 | "unicode-security", | |
217 | "unicode-width", | |
218 | "unicode-xid", | |
ba9703b0 XL |
219 | "vcpkg", |
220 | "version_check", | |
221 | "wasi", | |
222 | "winapi", | |
ba9703b0 XL |
223 | "winapi-i686-pc-windows-gnu", |
224 | "winapi-util", | |
225 | "winapi-x86_64-pc-windows-gnu", | |
cdc7bbd5 XL |
226 | // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well. |
227 | "yansi-term", | |
0531ce1d XL |
228 | ]; |
229 | ||
17df50a5 XL |
230 | const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[ |
231 | "anyhow", | |
232 | "ar", | |
233 | "autocfg", | |
234 | "bitflags", | |
235 | "cfg-if", | |
236 | "cranelift-bforest", | |
237 | "cranelift-codegen", | |
238 | "cranelift-codegen-meta", | |
239 | "cranelift-codegen-shared", | |
240 | "cranelift-entity", | |
241 | "cranelift-frontend", | |
242 | "cranelift-jit", | |
243 | "cranelift-module", | |
244 | "cranelift-native", | |
245 | "cranelift-object", | |
246 | "crc32fast", | |
247 | "gimli", | |
248 | "hashbrown", | |
249 | "indexmap", | |
250 | "libc", | |
251 | "libloading", | |
252 | "log", | |
253 | "mach", | |
136023e0 | 254 | "memchr", |
17df50a5 XL |
255 | "object", |
256 | "regalloc", | |
257 | "region", | |
258 | "rustc-hash", | |
259 | "smallvec", | |
260 | "target-lexicon", | |
261 | "winapi", | |
262 | "winapi-i686-pc-windows-gnu", | |
263 | "winapi-x86_64-pc-windows-gnu", | |
264 | ]; | |
265 | ||
266 | const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[ | |
267 | // These two crates take quite a long time to build, so don't allow two versions of them | |
268 | // to accidentally sneak into our dependency graph, in order to ensure we keep our CI times | |
269 | // under control. | |
270 | "cargo", | |
271 | "rustc-ap-rustc_ast", | |
272 | ]; | |
273 | ||
ba9703b0 XL |
274 | /// Dependency checks. |
275 | /// | |
3dfed10e XL |
276 | /// `root` is path to the directory with the root `Cargo.toml` (for the workspace). `cargo` is path |
277 | /// to the cargo executable. | |
278 | pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { | |
ba9703b0 XL |
279 | let mut cmd = cargo_metadata::MetadataCommand::new(); |
280 | cmd.cargo_path(cargo) | |
3dfed10e | 281 | .manifest_path(root.join("Cargo.toml")) |
ba9703b0 XL |
282 | .features(cargo_metadata::CargoOpt::AllFeatures); |
283 | let metadata = t!(cmd.exec()); | |
17df50a5 XL |
284 | let runtime_ids = compute_runtime_crates(&metadata); |
285 | check_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad); | |
286 | check_dependencies(&metadata, PERMITTED_DEPENDENCIES, RESTRICTED_DEPENDENCY_CRATES, bad); | |
287 | check_crate_duplicate(&metadata, FORBIDDEN_TO_HAVE_DUPLICATES, bad); | |
136023e0 | 288 | check_rustfix(&metadata, bad); |
17df50a5 XL |
289 | |
290 | // Check rustc_codegen_cranelift independently as it has it's own workspace. | |
291 | let mut cmd = cargo_metadata::MetadataCommand::new(); | |
292 | cmd.cargo_path(cargo) | |
293 | .manifest_path(root.join("compiler/rustc_codegen_cranelift/Cargo.toml")) | |
294 | .features(cargo_metadata::CargoOpt::AllFeatures); | |
295 | let metadata = t!(cmd.exec()); | |
296 | let runtime_ids = HashSet::new(); | |
297 | check_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad); | |
298 | check_dependencies( | |
299 | &metadata, | |
300 | PERMITTED_CRANELIFT_DEPENDENCIES, | |
301 | &["rustc_codegen_cranelift"], | |
302 | bad, | |
303 | ); | |
304 | check_crate_duplicate(&metadata, &[], bad); | |
0531ce1d XL |
305 | } |
306 | ||
ba9703b0 XL |
307 | /// Check that all licenses are in the valid list in `LICENSES`. |
308 | /// | |
309 | /// Packages listed in `EXCEPTIONS` are allowed for tools. | |
17df50a5 XL |
310 | fn check_exceptions( |
311 | metadata: &Metadata, | |
312 | exceptions: &[(&str, &str)], | |
313 | runtime_ids: HashSet<&PackageId>, | |
314 | bad: &mut bool, | |
315 | ) { | |
ba9703b0 | 316 | // Validate the EXCEPTIONS list hasn't changed. |
17df50a5 | 317 | for (name, license) in exceptions { |
ba9703b0 XL |
318 | // Check that the package actually exists. |
319 | if !metadata.packages.iter().any(|p| p.name == *name) { | |
fc512014 XL |
320 | tidy_error!( |
321 | bad, | |
ba9703b0 XL |
322 | "could not find exception package `{}`\n\ |
323 | Remove from EXCEPTIONS list if it is no longer used.", | |
324 | name | |
325 | ); | |
ba9703b0 XL |
326 | } |
327 | // Check that the license hasn't changed. | |
328 | for pkg in metadata.packages.iter().filter(|p| p.name == *name) { | |
ba9703b0 XL |
329 | match &pkg.license { |
330 | None => { | |
fc512014 XL |
331 | tidy_error!( |
332 | bad, | |
ba9703b0 XL |
333 | "dependency exception `{}` does not declare a license expression", |
334 | pkg.id | |
335 | ); | |
ba9703b0 XL |
336 | } |
337 | Some(pkg_license) => { | |
338 | if pkg_license.as_str() != *license { | |
339 | println!("dependency exception `{}` license has changed", name); | |
340 | println!(" previously `{}` now `{}`", license, pkg_license); | |
341 | println!(" update EXCEPTIONS for the new license"); | |
342 | *bad = true; | |
343 | } | |
344 | } | |
345 | } | |
346 | } | |
0531ce1d | 347 | } |
0531ce1d | 348 | |
17df50a5 | 349 | let exception_names: Vec<_> = exceptions.iter().map(|(name, _license)| *name).collect(); |
8bb4bdeb | 350 | |
ba9703b0 XL |
351 | // Check if any package does not have a valid license. |
352 | for pkg in &metadata.packages { | |
353 | if pkg.source.is_none() { | |
354 | // No need to check local packages. | |
0531ce1d | 355 | continue; |
8bb4bdeb | 356 | } |
ba9703b0 XL |
357 | if !runtime_ids.contains(&pkg.id) && exception_names.contains(&pkg.name.as_str()) { |
358 | continue; | |
359 | } | |
360 | let license = match &pkg.license { | |
361 | Some(license) => license, | |
362 | None => { | |
fc512014 | 363 | tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id); |
ba9703b0 XL |
364 | continue; |
365 | } | |
366 | }; | |
367 | if !LICENSES.contains(&license.as_str()) { | |
368 | if pkg.name == "fortanix-sgx-abi" { | |
369 | // This is a specific exception because SGX is considered | |
370 | // "third party". See | |
371 | // https://github.com/rust-lang/rust/issues/62620 for more. In | |
372 | // general, these should never be added. | |
373 | continue; | |
374 | } | |
fc512014 | 375 | tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id); |
ba9703b0 | 376 | } |
476ff2be | 377 | } |
476ff2be SL |
378 | } |
379 | ||
f035d41b XL |
380 | /// Checks the dependency of `RESTRICTED_DEPENDENCY_CRATES` at the given path. Changes `bad` to |
381 | /// `true` if a check failed. | |
0531ce1d | 382 | /// |
f035d41b | 383 | /// Specifically, this checks that the dependencies are on the `PERMITTED_DEPENDENCIES`. |
17df50a5 XL |
384 | fn check_dependencies( |
385 | metadata: &Metadata, | |
386 | permitted_dependencies: &[&'static str], | |
387 | restricted_dependency_crates: &[&'static str], | |
388 | bad: &mut bool, | |
389 | ) { | |
f035d41b | 390 | // Check that the PERMITTED_DEPENDENCIES does not have unused entries. |
17df50a5 | 391 | for name in permitted_dependencies { |
ba9703b0 | 392 | if !metadata.packages.iter().any(|p| p.name == *name) { |
fc512014 XL |
393 | tidy_error!( |
394 | bad, | |
f035d41b XL |
395 | "could not find allowed package `{}`\n\ |
396 | Remove from PERMITTED_DEPENDENCIES list if it is no longer used.", | |
ba9703b0 XL |
397 | name |
398 | ); | |
ba9703b0 XL |
399 | } |
400 | } | |
f035d41b | 401 | // Get the list in a convenient form. |
17df50a5 | 402 | let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect(); |
0531ce1d | 403 | |
9fa01778 | 404 | // Check dependencies. |
0531ce1d XL |
405 | let mut visited = BTreeSet::new(); |
406 | let mut unapproved = BTreeSet::new(); | |
17df50a5 | 407 | for &krate in restricted_dependency_crates.iter() { |
ba9703b0 | 408 | let pkg = pkg_from_name(metadata, krate); |
f035d41b XL |
409 | let mut bad = |
410 | check_crate_dependencies(&permitted_dependencies, metadata, &mut visited, pkg); | |
0531ce1d XL |
411 | unapproved.append(&mut bad); |
412 | } | |
413 | ||
b7449926 | 414 | if !unapproved.is_empty() { |
fc512014 | 415 | tidy_error!(bad, "Dependencies not explicitly permitted:"); |
0531ce1d | 416 | for dep in unapproved { |
ba9703b0 | 417 | println!("* {}", dep); |
0531ce1d | 418 | } |
0531ce1d | 419 | } |
0531ce1d XL |
420 | } |
421 | ||
422 | /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on | |
f035d41b XL |
423 | /// the list of permitted dependencies. Returns a list of disallowed dependencies. |
424 | fn check_crate_dependencies<'a>( | |
425 | permitted_dependencies: &'a HashSet<&'static str>, | |
ba9703b0 XL |
426 | metadata: &'a Metadata, |
427 | visited: &mut BTreeSet<&'a PackageId>, | |
428 | krate: &'a Package, | |
429 | ) -> BTreeSet<&'a PackageId> { | |
9fa01778 | 430 | // This will contain bad deps. |
0531ce1d XL |
431 | let mut unapproved = BTreeSet::new(); |
432 | ||
9fa01778 | 433 | // Check if we have already visited this crate. |
ba9703b0 | 434 | if visited.contains(&krate.id) { |
0531ce1d XL |
435 | return unapproved; |
436 | } | |
437 | ||
ba9703b0 | 438 | visited.insert(&krate.id); |
0531ce1d | 439 | |
f035d41b | 440 | // If this path is in-tree, we don't require it to be explicitly permitted. |
ba9703b0 | 441 | if krate.source.is_some() { |
f035d41b XL |
442 | // If this dependency is not on `PERMITTED_DEPENDENCIES`, add to bad set. |
443 | if !permitted_dependencies.contains(krate.name.as_str()) { | |
ba9703b0 | 444 | unapproved.insert(&krate.id); |
0531ce1d XL |
445 | } |
446 | } | |
447 | ||
ba9703b0 XL |
448 | // Do a DFS in the crate graph. |
449 | let to_check = deps_of(metadata, &krate.id); | |
0531ce1d | 450 | |
ba9703b0 | 451 | for dep in to_check { |
f035d41b | 452 | let mut bad = check_crate_dependencies(permitted_dependencies, metadata, visited, dep); |
0531ce1d XL |
453 | unapproved.append(&mut bad); |
454 | } | |
455 | ||
456 | unapproved | |
457 | } | |
b7449926 | 458 | |
ba9703b0 | 459 | /// Prevents multiple versions of some expensive crates. |
17df50a5 XL |
460 | fn check_crate_duplicate( |
461 | metadata: &Metadata, | |
462 | forbidden_to_have_duplicates: &[&str], | |
463 | bad: &mut bool, | |
464 | ) { | |
465 | for &name in forbidden_to_have_duplicates { | |
ba9703b0 XL |
466 | let matches: Vec<_> = metadata.packages.iter().filter(|pkg| pkg.name == name).collect(); |
467 | match matches.len() { | |
468 | 0 => { | |
fc512014 XL |
469 | tidy_error!( |
470 | bad, | |
ba9703b0 XL |
471 | "crate `{}` is missing, update `check_crate_duplicate` \ |
472 | if it is no longer used", | |
473 | name | |
474 | ); | |
ba9703b0 XL |
475 | } |
476 | 1 => {} | |
477 | _ => { | |
fc512014 XL |
478 | tidy_error!( |
479 | bad, | |
ba9703b0 XL |
480 | "crate `{}` is duplicated in `Cargo.lock`, \ |
481 | it is too expensive to build multiple times, \ | |
482 | so make sure only one version appears across all dependencies", | |
483 | name | |
484 | ); | |
485 | for pkg in matches { | |
486 | println!(" * {}", pkg.id); | |
487 | } | |
ba9703b0 | 488 | } |
b7449926 | 489 | } |
ba9703b0 XL |
490 | } |
491 | } | |
492 | ||
493 | /// Returns a list of dependencies for the given package. | |
494 | fn deps_of<'a>(metadata: &'a Metadata, pkg_id: &'a PackageId) -> Vec<&'a Package> { | |
495 | let resolve = metadata.resolve.as_ref().unwrap(); | |
496 | let node = resolve | |
497 | .nodes | |
498 | .iter() | |
499 | .find(|n| &n.id == pkg_id) | |
500 | .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id)); | |
501 | node.deps | |
502 | .iter() | |
503 | .map(|dep| { | |
504 | metadata.packages.iter().find(|pkg| pkg.id == dep.pkg).unwrap_or_else(|| { | |
505 | panic!("could not find dep `{}` for pkg `{}` in resolve", dep.pkg, pkg_id) | |
506 | }) | |
507 | }) | |
508 | .collect() | |
509 | } | |
510 | ||
511 | /// Finds a package with the given name. | |
512 | fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package { | |
513 | let mut i = metadata.packages.iter().filter(|p| p.name == name); | |
514 | let result = | |
515 | i.next().unwrap_or_else(|| panic!("could not find package `{}` in package list", name)); | |
516 | assert!(i.next().is_none(), "more than one package found for `{}`", name); | |
517 | result | |
518 | } | |
519 | ||
520 | /// Finds all the packages that are in the rust runtime. | |
521 | fn compute_runtime_crates<'a>(metadata: &'a Metadata) -> HashSet<&'a PackageId> { | |
522 | let resolve = metadata.resolve.as_ref().unwrap(); | |
523 | let mut result = HashSet::new(); | |
524 | for name in RUNTIME_CRATES { | |
525 | let id = &pkg_from_name(metadata, name).id; | |
526 | normal_deps_of_r(resolve, id, &mut result); | |
527 | } | |
528 | result | |
529 | } | |
530 | ||
531 | /// Recursively find all normal dependencies. | |
532 | fn normal_deps_of_r<'a>( | |
533 | resolve: &'a Resolve, | |
534 | pkg_id: &'a PackageId, | |
535 | result: &mut HashSet<&'a PackageId>, | |
536 | ) { | |
537 | if !result.insert(pkg_id) { | |
538 | return; | |
539 | } | |
540 | let node = resolve | |
541 | .nodes | |
542 | .iter() | |
543 | .find(|n| &n.id == pkg_id) | |
544 | .unwrap_or_else(|| panic!("could not find `{}` in resolve", pkg_id)); | |
17df50a5 | 545 | for dep in &node.deps { |
ba9703b0 | 546 | normal_deps_of_r(resolve, &dep.pkg, result); |
b7449926 XL |
547 | } |
548 | } | |
136023e0 XL |
549 | |
550 | fn check_rustfix(metadata: &Metadata, bad: &mut bool) { | |
551 | let cargo = pkg_from_name(metadata, "cargo"); | |
552 | let compiletest = pkg_from_name(metadata, "compiletest"); | |
553 | let cargo_deps = deps_of(metadata, &cargo.id); | |
554 | let compiletest_deps = deps_of(metadata, &compiletest.id); | |
555 | let cargo_rustfix = cargo_deps.iter().find(|p| p.name == "rustfix").unwrap(); | |
556 | let compiletest_rustfix = compiletest_deps.iter().find(|p| p.name == "rustfix").unwrap(); | |
557 | if cargo_rustfix.version != compiletest_rustfix.version { | |
558 | tidy_error!( | |
559 | bad, | |
560 | "cargo's rustfix version {} does not match compiletest's rustfix version {}\n\ | |
561 | rustfix should be kept in sync, update the cargo side first, and then update \ | |
562 | compiletest along with cargo.", | |
563 | cargo_rustfix.version, | |
564 | compiletest_rustfix.version | |
565 | ); | |
566 | } | |
567 | } |