]> git.proxmox.com Git - rustc.git/blob - src/tools/tidy/src/cargo.rs
New upstream version 1.50.0+dfsg1
[rustc.git] / src / tools / tidy / src / cargo.rs
1 //! Tidy check to ensure that `[dependencies]` and `extern crate` are in sync.
2 //!
3 //! This tidy check ensures that all crates listed in the `[dependencies]`
4 //! section of a `Cargo.toml` are present in the corresponding `lib.rs` as
5 //! `extern crate` declarations. This should help us keep the DAG correctly
6 //! structured through various refactorings to prune out unnecessary edges.
7
8 use std::fs;
9 use std::path::Path;
10
11 pub fn check(path: &Path, bad: &mut bool) {
12 if !super::filter_dirs(path) {
13 return;
14 }
15 for entry in t!(path.read_dir(), path).map(|e| t!(e)) {
16 // Look for `Cargo.toml` with a sibling `src/lib.rs` or `lib.rs`.
17 if entry.file_name().to_str() == Some("Cargo.toml") {
18 if path.join("src/lib.rs").is_file() {
19 verify(&entry.path(), &path.join("src/lib.rs"), bad)
20 }
21 if path.join("lib.rs").is_file() {
22 verify(&entry.path(), &path.join("lib.rs"), bad)
23 }
24 } else if t!(entry.file_type()).is_dir() {
25 check(&entry.path(), bad);
26 }
27 }
28 }
29
30 /// Verifies that the dependencies in Cargo.toml at `tomlfile` are synced with
31 /// the `extern crate` annotations in the lib.rs at `libfile`.
32 fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) {
33 let toml = t!(fs::read_to_string(&tomlfile));
34 let librs = t!(fs::read_to_string(&libfile));
35
36 if toml.contains("name = \"bootstrap\"") {
37 return;
38 }
39
40 // "Poor man's TOML parser" -- just assume we use one syntax for now.
41 //
42 // We just look for:
43 //
44 // ````
45 // [dependencies]
46 // name = ...
47 // name2 = ...
48 // name3 = ...
49 // ```
50 //
51 // If we encounter a line starting with `[` then we assume it's the end of
52 // the dependency section and bail out.
53 let deps = match toml.find("[dependencies]") {
54 Some(i) => &toml[i + 1..],
55 None => return,
56 };
57 for line in deps.lines() {
58 if line.starts_with('[') {
59 break;
60 }
61
62 let krate = match line.split_once('=') {
63 None => continue,
64 Some((krate, _)) => krate.trim(),
65 };
66
67 // Don't worry about depending on core/std while not writing `extern crate
68 // core/std` -- that's intentional.
69 if krate == "core" || krate == "std" {
70 continue;
71 }
72
73 // This is intentional -- this dependency just makes the crate available
74 // for others later on.
75 let allowed = krate.starts_with("panic");
76 if toml.contains("name = \"std\"") && allowed {
77 continue;
78 }
79
80 if !librs.contains(&format!("extern crate {}", krate)) {
81 tidy_error!(
82 bad,
83 "{} doesn't have `extern crate {}`, but Cargo.toml \
84 depends on it",
85 libfile.display(),
86 krate
87 );
88 }
89 }
90 }