tidy: Add a check to ensure Cargo.toml is in sync
This verifies that the crates listed in the `[dependencies]` section of `Cargo.toml` are a subset of the crates listed in `lib.rs` for our in-tree crates. This should help ensure that when we refactor crates over time we keep these dependency lists in sync.
This commit is contained in:
parent
9dd3c54a2c
commit
7bfaeaaf9c
|
@ -242,13 +242,13 @@ cleantestlibs:
|
||||||
|
|
||||||
.PHONY: tidy
|
.PHONY: tidy
|
||||||
tidy: $(HBIN0_H_$(CFG_BUILD))/tidy$(X_$(CFG_BUILD))
|
tidy: $(HBIN0_H_$(CFG_BUILD))/tidy$(X_$(CFG_BUILD))
|
||||||
$< $(S)src
|
$(TARGET_RPATH_VAR0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $< $(S)src
|
||||||
|
|
||||||
$(HBIN0_H_$(CFG_BUILD))/tidy$(X_$(CFG_BUILD)): \
|
$(HBIN0_H_$(CFG_BUILD))/tidy$(X_$(CFG_BUILD)): \
|
||||||
$(TSREQ0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
|
$(TSREQ0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
|
||||||
$(TLIB0_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.std \
|
$(TLIB0_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.std \
|
||||||
$(call rwildcard,$(S)src/tools/tidy/src,*.rs)
|
$(call rwildcard,$(S)src/tools/tidy/src,*.rs)
|
||||||
$(STAGE0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) src/tools/tidy/src/main.rs \
|
$(STAGE0_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(S)src/tools/tidy/src/main.rs \
|
||||||
--out-dir $(@D) --crate-name tidy
|
--out-dir $(@D) --crate-name tidy
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
@ -323,8 +323,7 @@ impl<'a> Step<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Source::ToolLinkchecker { stage } |
|
Source::ToolLinkchecker { stage } |
|
||||||
Source::ToolTidy { stage } |
|
Source::ToolTidy { stage } => {
|
||||||
Source::ToolCargoTest { stage } => {
|
|
||||||
vec![self.libstd(self.compiler(stage))]
|
vec![self.libstd(self.compiler(stage))]
|
||||||
}
|
}
|
||||||
Source::ToolErrorIndex { stage } |
|
Source::ToolErrorIndex { stage } |
|
||||||
|
|
|
@ -9,3 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// See comments in Cargo.toml for why this exists
|
// See comments in Cargo.toml for why this exists
|
||||||
|
|
||||||
|
#![feature(test)]
|
||||||
|
|
||||||
|
extern crate test;
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Tidy check to ensure that `[dependencies]` and `extern crate` are in sync.
|
||||||
|
//!
|
||||||
|
//! This tidy check ensures that all crates listed in the `[dependencies]`
|
||||||
|
//! section of a `Cargo.toml` are present in the corresponding `lib.rs` as
|
||||||
|
//! `extern crate` declarations. This should help us keep the DAG correctly
|
||||||
|
//! structured through various refactorings to prune out unnecessary edges.
|
||||||
|
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
pub fn check(path: &Path, bad: &mut bool) {
|
||||||
|
for entry in t!(path.read_dir()).map(|e| t!(e)) {
|
||||||
|
// Look for `Cargo.toml` with a sibling `src/lib.rs` or `lib.rs`
|
||||||
|
if entry.file_name().to_str() == Some("Cargo.toml") {
|
||||||
|
if path.join("src/lib.rs").is_file() {
|
||||||
|
verify(&entry.path(), &path.join("src/lib.rs"), bad)
|
||||||
|
}
|
||||||
|
if path.join("lib.rs").is_file() {
|
||||||
|
verify(&entry.path(), &path.join("lib.rs"), bad)
|
||||||
|
}
|
||||||
|
} else if t!(entry.file_type()).is_dir() {
|
||||||
|
check(&entry.path(), bad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the dependencies in Cargo.toml at `tomlfile` are sync'd with the
|
||||||
|
// `extern crate` annotations in the lib.rs at `libfile`.
|
||||||
|
fn verify(tomlfile: &Path, libfile: &Path, bad: &mut bool) {
|
||||||
|
let mut toml = String::new();
|
||||||
|
let mut librs = String::new();
|
||||||
|
t!(t!(File::open(tomlfile)).read_to_string(&mut toml));
|
||||||
|
t!(t!(File::open(libfile)).read_to_string(&mut librs));
|
||||||
|
|
||||||
|
if toml.contains("name = \"bootstrap\"") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Poor man's TOML parser", just assume we use one syntax for now
|
||||||
|
//
|
||||||
|
// We just look for:
|
||||||
|
//
|
||||||
|
// [dependencies]
|
||||||
|
// name = ...
|
||||||
|
// name2 = ...
|
||||||
|
// name3 = ...
|
||||||
|
//
|
||||||
|
// If we encounter a line starting with `[` then we assume it's the end of
|
||||||
|
// the dependency section and bail out.
|
||||||
|
let deps = match toml.find("[dependencies]") {
|
||||||
|
Some(i) => &toml[i+1..],
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
let mut lines = deps.lines().peekable();
|
||||||
|
while let Some(line) = lines.next() {
|
||||||
|
if line.starts_with("[") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut parts = line.splitn(2, '=');
|
||||||
|
let krate = parts.next().unwrap().trim();
|
||||||
|
if parts.next().is_none() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't worry about depending on core/std but not saying `extern crate
|
||||||
|
// core/std`, that's intentional.
|
||||||
|
if krate == "core" || krate == "std" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is intentional, this dependency just makes the crate available
|
||||||
|
// for others later on.
|
||||||
|
if krate == "alloc_jemalloc" && toml.contains("name = \"std\"") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !librs.contains(&format!("extern crate {}", krate)) {
|
||||||
|
println!("{} doesn't have `extern crate {}`, but Cargo.toml \
|
||||||
|
depends on it", libfile.display(), krate);
|
||||||
|
*bad = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,8 +71,7 @@ pub fn check(path: &Path, bad: &mut bool) {
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut max = 0;
|
let mut max = 0;
|
||||||
println!("* {} error codes", map.len());
|
for (&code, entries) in map.iter() {
|
||||||
for (code, entries) in map {
|
|
||||||
if code > max {
|
if code > max {
|
||||||
max = code;
|
max = code;
|
||||||
}
|
}
|
||||||
|
@ -81,10 +80,14 @@ pub fn check(path: &Path, bad: &mut bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("duplicate error code: {}", code);
|
println!("duplicate error code: {}", code);
|
||||||
for (file, line_num, line) in entries {
|
for &(ref file, line_num, ref line) in entries.iter() {
|
||||||
println!("{}:{}: {}", file.display(), line_num, line);
|
println!("{}:{}: {}", file.display(), line_num, line);
|
||||||
}
|
}
|
||||||
*bad = true;
|
*bad = true;
|
||||||
}
|
}
|
||||||
println!("* highest error code: E{:04}", max);
|
|
||||||
|
if !*bad {
|
||||||
|
println!("* {} error codes", map.len());
|
||||||
|
println!("* highest error code: E{:04}", max);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,10 @@ pub fn check(path: &Path, bad: &mut bool) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if *bad {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
for feature in features {
|
for feature in features {
|
||||||
lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
|
lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
|
||||||
|
|
|
@ -29,6 +29,7 @@ mod bins;
|
||||||
mod style;
|
mod style;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod features;
|
mod features;
|
||||||
|
mod cargo;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let path = env::args_os().skip(1).next().expect("need an argument");
|
let path = env::args_os().skip(1).next().expect("need an argument");
|
||||||
|
@ -38,6 +39,7 @@ fn main() {
|
||||||
bins::check(&path, &mut bad);
|
bins::check(&path, &mut bad);
|
||||||
style::check(&path, &mut bad);
|
style::check(&path, &mut bad);
|
||||||
errors::check(&path, &mut bad);
|
errors::check(&path, &mut bad);
|
||||||
|
cargo::check(&path, &mut bad);
|
||||||
features::check(&path, &mut bad);
|
features::check(&path, &mut bad);
|
||||||
|
|
||||||
if bad {
|
if bad {
|
||||||
|
|
Loading…
Reference in New Issue