xtask/tasks/fmt/house_rules/
package_info.rs1use anyhow::Context;
24use std::ffi::OsStr;
25use std::path::Path;
26use toml_edit::Item;
27use toml_edit::Table;
28
29static VERSION_EXCEPTIONS: &[&str] = &["vmgstool"];
31
32pub fn check_package_info(f: &Path, fix: bool) -> anyhow::Result<()> {
33 if f.file_name() != Some(OsStr::new("Cargo.toml")) {
34 return Ok(());
35 }
36
37 let contents = fs_err::read_to_string(f)?;
38 let mut parsed = contents.parse::<toml_edit::DocumentMut>()?;
39
40 let mut excluded_from_workspace = false;
41 if let Some(metadata) = parsed
42 .get("package")
43 .and_then(|x| x.get("metadata"))
44 .and_then(|x| x.get("xtask"))
45 .and_then(|x| x.get("house-rules"))
46 {
47 let props = metadata.as_table().context("invalid metadata format")?;
48 for (k, v) in props.iter() {
49 if k == "excluded-from-workspace" {
50 excluded_from_workspace = v
51 .as_bool()
52 .context("invalid type for excluded-from-workspace (must be bool)")?;
53 }
54 }
55 }
56
57 if !parsed.contains_key("package") {
58 return Ok(());
60 }
61
62 let mut lints_table = Table::new();
63 lints_table.insert("workspace", Item::Value(true.into()));
64 let old_lints_table = parsed.insert("lints", Item::Table(lints_table.clone()));
65
66 let package = parsed
67 .get_mut("package")
68 .with_context(|| format!("missing package section in {}", f.display()))?
69 .as_table_mut()
70 .with_context(|| format!("invalid package section in {}", f.display()))?;
71
72 let mut rust_version_field = Table::new();
73 rust_version_field.set_dotted(true);
74 rust_version_field.insert("workspace", Item::Value(true.into()));
75 let old_rust_version = package.insert("rust-version", Item::Table(rust_version_field.clone()));
76
77 let mut edition_field = Table::new();
78 edition_field.set_dotted(true);
79 edition_field.insert("workspace", Item::Value(true.into()));
80 let old_edition_field = package.insert("edition", Item::Table(edition_field.clone()));
81
82 let package_name = package
83 .get("name")
84 .with_context(|| format!("missing package name in {}", f.display()))?
85 .as_str()
86 .with_context(|| format!("invalid package name in {}", f.display()))?;
87 let check_version = !VERSION_EXCEPTIONS.contains(&package_name);
88
89 let invalid = package.remove("authors").is_some()
91 | check_version
92 .then(|| package.remove("version"))
93 .flatten()
94 .is_some()
95 | (!excluded_from_workspace
96 && (old_lints_table.map(|o| o.to_string()) != Some(lints_table.to_string()))
97 | (old_rust_version.map(|o| o.to_string())
98 != Some(rust_version_field.to_string()))
99 | (old_edition_field.map(|o| o.to_string()) != Some(edition_field.to_string())));
100
101 if invalid {
102 if !fix {
103 anyhow::bail!(
104 "invalid inclusion of package authors or version, or non-workspaced lints, rust-version, or edition, in {}",
105 f.display()
106 );
107 }
108 fs_err::write(f, parsed.to_string())?;
109 log::info!("fixed package section in {}", f.display());
110 }
111
112 Ok(())
113}