Merge "Allow user to specify semver compatibility logic for suggested updates." into main
diff --git a/tools/cargo_embargo/src/main.rs b/tools/cargo_embargo/src/main.rs
index decc42a..7e80775 100644
--- a/tools/cargo_embargo/src/main.rs
+++ b/tools/cargo_embargo/src/main.rs
@@ -806,6 +806,7 @@
// Other cases.
"MIT OR LGPL-3.0-or-later" => vec!["MIT"],
"MIT/BSD-3-Clause" => vec!["MIT"],
+ "MIT AND (MIT OR Apache-2.0)" => vec!["MIT"],
"LGPL-2.1-only OR BSD-2-Clause" => vec!["BSD-2-Clause"],
_ => {
diff --git a/tools/external_crates/crate_tool/src/managed_crate.rs b/tools/external_crates/crate_tool/src/managed_crate.rs
index b4bb827..f823234 100644
--- a/tools/external_crates/crate_tool/src/managed_crate.rs
+++ b/tools/external_crates/crate_tool/src/managed_crate.rs
@@ -232,7 +232,10 @@
pub fn fix_test_mapping(&self) -> Result<()> {
let mut tm = TestMapping::read(self.android_crate_path().clone())?;
println!("{}", self.name());
- if tm.fix_import_paths() || tm.add_new_tests_to_postsubmit()? {
+ let mut changed = tm.fix_import_paths();
+ changed |= tm.add_new_tests_to_postsubmit()?;
+ changed |= tm.remove_unknown_tests()?;
+ if changed {
tm.write()?;
}
Ok(())
@@ -435,6 +438,7 @@
let android_crate_dir = staged.android_crate.path();
remove_dir_all(android_crate_dir)?;
rename(staged.staging_path(), android_crate_dir)?;
+ staged.fix_test_mapping()?;
checksum::generate(android_crate_dir.abs())?;
Ok(staged)
diff --git a/tools/external_crates/crate_tool/src/managed_repo.rs b/tools/external_crates/crate_tool/src/managed_repo.rs
index 6935988..4771537 100644
--- a/tools/external_crates/crate_tool/src/managed_repo.rs
+++ b/tools/external_crates/crate_tool/src/managed_repo.rs
@@ -22,7 +22,7 @@
str::from_utf8,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, bail, Context, Result};
use crates_index::DependencyKind;
use glob::glob;
use google_metadata::GoogleMetadata;
@@ -599,10 +599,21 @@
self.managed_dir(), managed_dirs.difference(&deps).join(", "), deps.difference(&managed_dirs).join(", ")));
}
- let crate_list = pseudo_crate.read_crate_list()?;
- if deps.iter().ne(crate_list.iter()) {
- return Err(anyhow!("Deps in pseudo_crate/Cargo.toml don't match deps in crate-list.txt\nCargo.toml: {}\ncrate-list.txt: {}",
- deps.iter().join(", "), crate_list.iter().join(", ")));
+ let crate_list = pseudo_crate.read_crate_list("crate-list.txt")?;
+ if !deps.is_subset(&crate_list) {
+ bail!("Deps in pseudo_crate/Cargo.toml don't match deps in crate-list.txt\nCargo.toml: {}\ncrate-list.txt: {}",
+ deps.iter().join(", "), crate_list.iter().join(", "));
+ }
+
+ let expected_deleted_crates =
+ crate_list.difference(&deps).cloned().collect::<BTreeSet<_>>();
+ let deleted_crates = pseudo_crate.read_crate_list("deleted-crates.txt")?;
+ if deleted_crates != expected_deleted_crates {
+ bail!(
+ "Deleted crate list is inconsistent. Expected: {}, Found: {}",
+ expected_deleted_crates.iter().join(", "),
+ deleted_crates.iter().join(", ")
+ );
}
// Per https://android.googlesource.com/platform/tools/repohooks/,
diff --git a/tools/external_crates/crate_tool/src/pseudo_crate.rs b/tools/external_crates/crate_tool/src/pseudo_crate.rs
index ee0ce67..204feb0 100644
--- a/tools/external_crates/crate_tool/src/pseudo_crate.rs
+++ b/tools/external_crates/crate_tool/src/pseudo_crate.rs
@@ -14,7 +14,7 @@
use std::{
cell::OnceCell,
- collections::BTreeMap,
+ collections::{BTreeMap, BTreeSet},
env,
fs::{read, write},
io::BufRead,
@@ -22,7 +22,7 @@
str::from_utf8,
};
-use anyhow::{anyhow, Context, Result};
+use anyhow::{anyhow, bail, Context, Result};
use itertools::Itertools;
use name_and_version::{NameAndVersionMap, NamedAndVersioned};
use rooted_path::RootedPath;
@@ -51,10 +51,13 @@
pub fn get_path(&self) -> &RootedPath {
&self.path
}
- pub fn read_crate_list(&self) -> Result<Vec<String>> {
- let mut lines = Vec::new();
- for line in read(self.path.join("crate-list.txt")?)?.lines() {
- lines.push(line?);
+ pub fn read_crate_list(&self, filename: &str) -> Result<BTreeSet<String>> {
+ let mut lines = BTreeSet::new();
+ for line in read(self.path.join(filename)?)?.lines() {
+ let line = line?;
+ if !lines.insert(line.clone()) {
+ bail!("Duplicate entry {line} in crate list {filename}");
+ }
}
Ok(lines)
}
@@ -62,7 +65,16 @@
impl PseudoCrate<CargoVendorClean> {
pub fn regenerate_crate_list(&self) -> Result<()> {
- write(self.path.join("crate-list.txt")?, format!("{}\n", self.deps().keys().join("\n")))?;
+ let old_crate_list = self.read_crate_list("crate-list.txt")?;
+ let current_crates = self.deps().keys().cloned().collect::<BTreeSet<_>>();
+ write(
+ self.path.join("crate-list.txt")?,
+ format!("{}\n", old_crate_list.union(¤t_crates).join("\n")),
+ )?;
+ write(
+ self.path.join("deleted-crates.txt")?,
+ format!("{}\n", old_crate_list.difference(¤t_crates).join("\n")),
+ )?;
Ok(())
}
fn version_of(&self, crate_name: &str) -> Result<Version> {
@@ -179,6 +191,7 @@
"#,
)?;
write(self.path.join("crate-list.txt")?, "")?;
+ write(self.path.join("deleted-crates.txt")?, "")?;
write(self.path.join(".gitignore")?, "target/\nvendor/\n")?;
ensure_exists_and_empty(&self.path.join("src")?)?;
diff --git a/tools/external_crates/license_checker/src/expression_parser.rs b/tools/external_crates/license_checker/src/expression_parser.rs
index 2754710..5337cd5 100644
--- a/tools/external_crates/license_checker/src/expression_parser.rs
+++ b/tools/external_crates/license_checker/src/expression_parser.rs
@@ -138,6 +138,11 @@
"Apache preferred to MIT"
);
assert_eq!(
+ get_chosen_licenses("foo", Some("MIT AND (MIT OR Apache-2.0)"))?,
+ BTreeSet::from([Licensee::parse("MIT").unwrap().into_req()]),
+ "Complex expression from libm 0.2.11"
+ );
+ assert_eq!(
get_chosen_licenses("webpki", None)?,
BTreeSet::from([
Licensee::parse("ISC").unwrap().into_req(),
diff --git a/tools/external_crates/test_mapping/src/json.rs b/tools/external_crates/test_mapping/src/json.rs
index de199ca..d741b3f 100644
--- a/tools/external_crates/test_mapping/src/json.rs
+++ b/tools/external_crates/test_mapping/src/json.rs
@@ -56,6 +56,22 @@
&& self.presubmit_rust.is_empty()
&& self.postsubmit.is_empty()
}
+ pub fn remove_unknown_tests(&mut self, tests: &BTreeSet<String>) -> bool {
+ let mut changed = false;
+ if self.presubmit.iter().any(|t| !tests.contains(&t.name)) {
+ self.presubmit.retain(|t| tests.contains(&t.name));
+ changed = true;
+ }
+ if self.presubmit_rust.iter().any(|t| !tests.contains(&t.name)) {
+ self.presubmit_rust.retain(|t| tests.contains(&t.name));
+ changed = true;
+ }
+ if self.postsubmit.iter().any(|t| !tests.contains(&t.name)) {
+ self.postsubmit.retain(|t| tests.contains(&t.name));
+ changed = true;
+ }
+ changed
+ }
pub fn set_presubmits(&mut self, tests: &BTreeSet<String>) {
self.presubmit = tests.iter().map(|t| TestMappingName { name: t.to_string() }).collect();
self.presubmit_rust = self.presubmit.clone();
diff --git a/tools/external_crates/test_mapping/src/lib.rs b/tools/external_crates/test_mapping/src/lib.rs
index 185af51..b9a16db 100644
--- a/tools/external_crates/test_mapping/src/lib.rs
+++ b/tools/external_crates/test_mapping/src/lib.rs
@@ -93,6 +93,11 @@
}
Ok(())
}
+ /// Remove tests from TEST_MAPPING that are no longer in the
+ /// Android.bp file
+ pub fn remove_unknown_tests(&mut self) -> Result<bool, TestMappingError> {
+ Ok(self.json.remove_unknown_tests(&self.bp.rust_tests()?))
+ }
/// Update the presubmit and presubmit_rust fields to the
/// set of test targets in the Android.bp file.
/// Since adding new tests directly to presubmits is discouraged,