Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 46 additions & 44 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
//! Checks the licenses of third-party dependencies.

use std::collections::{HashMap, HashSet};
use std::collections::{BTreeSet, HashMap, HashSet};
use std::fmt::{Display, Formatter};
use std::fs::{File, read_dir};
use std::io::Write;
use std::fs::{self, read_dir};
use std::io;
use std::path::Path;

use cargo_metadata::semver::Version;
use cargo_metadata::{Metadata, Package, PackageId};

use crate::diagnostics::{RunningCheck, TidyCtx};

#[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"]
mod proc_macro_deps;

#[derive(Clone, Copy)]
struct ListLocation {
path: &'static str,
Expand Down Expand Up @@ -722,53 +719,58 @@ fn check_proc_macro_dep_list(root: &Path, cargo: &Path, bless: bool, check: &mut
}
// Remove the proc-macro crates themselves
proc_macro_deps.retain(|pkg| !is_proc_macro_pkg(&metadata[pkg]));
// Sort and deduplicate the crate names.
let proc_macro_deps =
proc_macro_deps.into_iter().map(|dep| metadata[dep].name.as_ref()).collect::<BTreeSet<_>>();

let proc_macro_deps: HashSet<_> =
proc_macro_deps.into_iter().map(|dep| metadata[dep].name.as_ref()).collect();
let expected = proc_macro_deps::CRATES.iter().copied().collect::<HashSet<_>>();

let needs_blessing = proc_macro_deps.difference(&expected).next().is_some()
|| expected.difference(&proc_macro_deps).next().is_some();
let expected = {
use std::fmt::Write;

if needs_blessing && bless {
let mut proc_macro_deps: Vec<_> = proc_macro_deps.into_iter().collect();
proc_macro_deps.sort();
let mut file = File::create(root.join("src/bootstrap/src/utils/proc_macro_deps.rs"))
.expect("`proc_macro_deps` should exist");
writeln!(
&mut file,
"/// Do not update manually - use `./x.py test tidy --bless`
const HEADER: &str = "\
/// Do not update manually - use `./x.py test tidy --bless`
/// Holds all direct and indirect dependencies of proc-macro crates in tree.
/// See <https://github.com/rust-lang/rust/issues/134863>
pub static CRATES: &[&str] = &[
// tidy-alphabetical-start"
)
.unwrap();
// tidy-alphabetical-start
";
const FOOTER: &str = " // tidy-alphabetical-end
];
";

let mut buf = String::with_capacity(4096);
buf.push_str(HEADER);
for dep in proc_macro_deps {
writeln!(&mut file, " {dep:?},").unwrap();
writeln!(buf, " {dep:?},").unwrap();
}
writeln!(
&mut file,
" // tidy-alphabetical-end
];"
)
.unwrap();
} else {
let mut error_found = false;
buf.push_str(FOOTER);
buf
};

for missing in proc_macro_deps.difference(&expected) {
error_found = true;
check.error(format!(
"proc-macro crate dependency `{missing}` is not registered in `src/bootstrap/src/utils/proc_macro_deps.rs`",
));
}
for extra in expected.difference(&proc_macro_deps) {
error_found = true;
check.error(format!(
"`{extra}` is registered in `src/bootstrap/src/utils/proc_macro_deps.rs`, but is not a proc-macro crate dependency",
));
const PROC_MACRO_DEPS_RS: &str = "src/bootstrap/src/utils/proc_macro_deps.rs";
let proc_macro_deps_rs_path = &root.join(PROC_MACRO_DEPS_RS);
let actual = match fs::read_to_string(proc_macro_deps_rs_path) {
Ok(actual) => actual,
Err(e) => {
if e.kind() == io::ErrorKind::NotFound {
check.error(format!(
"`{PROC_MACRO_DEPS_RS}` not found; has it been moved or renamed?"
));
} else {
check.error(format!("`{PROC_MACRO_DEPS_RS}` could not be read: {e:?}"));
}
return;
}
if error_found {
};

if actual != expected {
if bless {
fs::write(proc_macro_deps_rs_path, &expected).unwrap();
} else {
let diff = similar::TextDiff::from_lines(&actual, &expected);
let mut unified = diff.unified_diff();
unified.header(PROC_MACRO_DEPS_RS, "(expected)");

check.error(format!("`{PROC_MACRO_DEPS_RS}` is not up-to-date:\n{unified}"));
check.message("Run `./x.py test tidy --bless` to regenerate the list");
}
}
Expand Down
Loading