Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit f351fed

Browse files
jfgoogGerrit Code Review
authored andcommitted
Merge changes Ib2e07564,I53c0f977,Ia1499ded into main
* changes: Add command to analyze crate imports for problems. Add a new command to update TEST_MAPPING files. Crate for managing TEST_MAPPING files.
2 parents 589f18b + 367cf36 commit f351fed

File tree

11 files changed

+762
-10
lines changed

11 files changed

+762
-10
lines changed

tools/external_crates/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ members = [
66
"name_and_version",
77
"name_and_version_proc_macros",
88
"rooted_path",
9+
"test_mapping",
910
]
1011
resolver = "2"

tools/external_crates/cargo_embargo.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"workspace": true,
2020
"workspace_excludes": [
2121
"crate_tool",
22-
"license_checker"
22+
"license_checker",
23+
"test_mapping"
2324
]
2425
}

tools/external_crates/crate_tool/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ crates-index = "3.2.0"
1515
glob = "0.3"
1616
itertools = "0.11"
1717
num_cpus = "1"
18+
owning_ref = "0.4"
1819
protobuf = "3"
1920
reqwest = { version = "0.12.5", features = ["blocking", "gzip"] }
2021
semver = "1"
@@ -31,6 +32,7 @@ license_checker = { path = "../license_checker" }
3132
name_and_version = { path = "../name_and_version" }
3233
name_and_version_proc_macros = { path = "../name_and_version_proc_macros" }
3334
rooted_path = { path = "../rooted_path" }
35+
test_mapping = { path = "../test_mapping" }
3436

3537
[build-dependencies]
3638
protobuf-codegen = "3"

tools/external_crates/crate_tool/src/main.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ enum Cmd {
6161
#[command(flatten)]
6262
crates: MigrationCrateList,
6363
},
64+
/// Analyze a crate to see if it can be imported.
65+
#[command(hide = true)]
66+
AnalyzeImport {
67+
/// The crate name.
68+
crate_name: String,
69+
},
6470
/// Import a crate and its dependencies into the monorepo.
6571
#[command(hide = true)]
6672
Import {
@@ -118,6 +124,12 @@ enum Cmd {
118124
TryUpdates {},
119125
/// Initialize a new managed repo.
120126
Init {},
127+
/// Update TEST_MAPPING files.
128+
#[command(hide = true)]
129+
TestMapping {
130+
#[command(flatten)]
131+
crates: CrateList,
132+
},
121133
}
122134

123135
#[derive(Args)]
@@ -137,11 +149,7 @@ struct CrateList {
137149
impl CrateList {
138150
fn to_list(&self, managed_repo: &ManagedRepo) -> Result<Vec<String>> {
139151
Ok(if self.all {
140-
managed_repo
141-
.all_crate_names()?
142-
.into_iter()
143-
.filter(|crate_name| !self.exclude.contains(crate_name))
144-
.collect::<Vec<_>>()
152+
managed_repo.all_crate_names()?.difference(&self.exclude).cloned().collect::<Vec<_>>()
145153
} else {
146154
self.crates.clone()
147155
})
@@ -209,6 +217,7 @@ fn main() -> Result<()> {
209217
managed_repo.regenerate(crates.to_list(&managed_repo)?.into_iter(), true)
210218
}
211219
Cmd::PreuploadCheck { files } => managed_repo.preupload_check(&files),
220+
Cmd::AnalyzeImport { crate_name } => managed_repo.analyze_import(&crate_name),
212221
Cmd::Import { crate_name } => managed_repo.import(&crate_name),
213222
Cmd::FixLicenses { crates } => {
214223
managed_repo.fix_licenses(crates.to_list(&managed_repo)?.into_iter())
@@ -225,5 +234,8 @@ fn main() -> Result<()> {
225234
Cmd::Update { crate_name, version } => managed_repo.update(crate_name, version),
226235
Cmd::TryUpdates {} => managed_repo.try_updates(),
227236
Cmd::Init {} => managed_repo.init(),
237+
Cmd::TestMapping { crates } => {
238+
managed_repo.fix_test_mapping(crates.to_list(&managed_repo)?.into_iter())
239+
}
228240
}
229241
}

tools/external_crates/crate_tool/src/managed_crate.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use license_checker::find_licenses;
2727
use name_and_version::NamedAndVersioned;
2828
use rooted_path::RootedPath;
2929
use semver::Version;
30+
use test_mapping::TestMapping;
3031

3132
use crate::{
3233
android_bp::run_cargo_embargo,
@@ -217,6 +218,14 @@ impl<State: ManagedCrateState> ManagedCrate<State> {
217218
metadata.write()?;
218219
Ok(())
219220
}
221+
pub fn fix_test_mapping(&self) -> Result<()> {
222+
let mut tm = TestMapping::read(self.android_crate_path().clone())?;
223+
println!("{}", self.name());
224+
if tm.fix_import_paths() || tm.add_new_tests_to_postsubmit()? {
225+
tm.write()?;
226+
}
227+
Ok(())
228+
}
220229
}
221230

222231
impl ManagedCrate<New> {

tools/external_crates/crate_tool/src/managed_repo.rs

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use std::{
2323
};
2424

2525
use anyhow::{anyhow, Context, Result};
26+
use crates_index::DependencyKind;
2627
use glob::glob;
2728
use google_metadata::GoogleMetadata;
2829
use itertools::Itertools;
@@ -105,13 +106,13 @@ impl ManagedRepo {
105106
) -> Result<ManagedCrate<crate::managed_crate::New>> {
106107
Ok(ManagedCrate::new(Crate::from(self.managed_dir_for(crate_name))?))
107108
}
108-
pub fn all_crate_names(&self) -> Result<Vec<String>> {
109-
let mut managed_dirs = Vec::new();
109+
pub fn all_crate_names(&self) -> Result<BTreeSet<String>> {
110+
let mut managed_dirs = BTreeSet::new();
110111
if self.managed_dir().abs().exists() {
111112
for entry in read_dir(self.managed_dir())? {
112113
let entry = entry?;
113114
if entry.path().is_dir() {
114-
managed_dirs.push(entry.file_name().into_string().map_err(|e| {
115+
managed_dirs.insert(entry.file_name().into_string().map_err(|e| {
115116
anyhow!("Failed to convert {} to string", e.to_string_lossy())
116117
})?);
117118
}
@@ -364,6 +365,75 @@ impl ManagedRepo {
364365

365366
Ok(())
366367
}
368+
pub fn analyze_import(&self, crate_name: &str) -> Result<()> {
369+
if self.contains(crate_name) {
370+
println!("Crate already imported at {}", self.managed_dir_for(crate_name));
371+
return Ok(());
372+
}
373+
let legacy_dir = self.legacy_dir_for(crate_name, None)?;
374+
if legacy_dir.abs().exists() {
375+
println!("Legacy crate already imported at {}", legacy_dir);
376+
return Ok(());
377+
}
378+
379+
let mut managed_crates = self.new_cc();
380+
managed_crates.add_from(self.managed_dir().rel())?;
381+
let legacy_crates = self.legacy_crates()?;
382+
383+
let cio_crate = self.crates_io.get_crate(crate_name)?;
384+
385+
for version in cio_crate.versions() {
386+
println!("Version {}", version.version());
387+
let mut found_problems = false;
388+
for (dep, req) in version.android_deps_with_version_reqs() {
389+
let cc = if managed_crates.contains_name(dep.crate_name()) {
390+
&managed_crates
391+
} else {
392+
&legacy_crates
393+
};
394+
if !cc.contains_name(dep.crate_name()) {
395+
found_problems = true;
396+
println!(
397+
" Dep {} {} has not been imported to Android",
398+
dep.crate_name(),
399+
dep.requirement()
400+
);
401+
if matches!(dep.kind(), DependencyKind::Dev) {
402+
println!(" But this is a dev dependency, probably only needed if you want to run the tests");
403+
}
404+
if dep.is_optional() {
405+
println!(" But this is an optional dependency, used by the following features: {}", dep.features().join(", "));
406+
}
407+
continue;
408+
}
409+
let versions = cc.get_versions(dep.crate_name()).collect::<Vec<_>>();
410+
let has_matching_version =
411+
versions.iter().any(|(nv, _)| req.matches_relaxed(nv.version()));
412+
if !has_matching_version {
413+
found_problems = true;
414+
}
415+
if !has_matching_version || versions.len() > 1 {
416+
if has_matching_version {
417+
println!(" Dep {} has multiple versions available. You may need to override the default choice in cargo_embargo.json", dep.crate_name());
418+
}
419+
for (_, dep_crate) in versions {
420+
println!(
421+
" Dep {} {} is {}satisfied by v{} at {}",
422+
dep.crate_name(),
423+
dep.requirement(),
424+
if req.matches_relaxed(dep_crate.version()) { "" } else { "not " },
425+
dep_crate.version(),
426+
dep_crate.path()
427+
);
428+
}
429+
}
430+
}
431+
if !found_problems {
432+
println!(" No problems found with this version.")
433+
}
434+
}
435+
Ok(())
436+
}
367437
pub fn import(&self, crate_name: &str) -> Result<()> {
368438
let (new_deps, pseudo_crate) = self.add_crate_and_dependencies(crate_name)?;
369439

@@ -503,7 +573,7 @@ impl ManagedRepo {
503573
let pseudo_crate = self.pseudo_crate().vendor()?;
504574
let deps = pseudo_crate.deps().keys().cloned().collect::<BTreeSet<_>>();
505575

506-
let managed_dirs = self.all_crate_names()?.into_iter().collect();
576+
let managed_dirs = self.all_crate_names()?;
507577

508578
if deps != managed_dirs {
509579
return Err(anyhow!("Deps in pseudo_crate/Cargo.toml don't match directories in {}\nDirectories not in Cargo.toml: {}\nCargo.toml deps with no directory: {}",
@@ -837,6 +907,13 @@ impl ManagedRepo {
837907
self.pseudo_crate().init()?;
838908
Ok(())
839909
}
910+
pub fn fix_test_mapping<T: AsRef<str>>(&self, crates: impl Iterator<Item = T>) -> Result<()> {
911+
for crate_name in crates {
912+
let mc = self.managed_crate_for(crate_name.as_ref())?;
913+
mc.fix_test_mapping()?;
914+
}
915+
Ok(())
916+
}
840917
}
841918

842919
// Files that are ignored when migrating a crate to the monorepo.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "test_mapping"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
android_bp = "0.3"
8+
json-strip-comments = "1"
9+
owning_ref = "0.4"
10+
serde = { version = "=1.0.210", features = ["derive"] }
11+
serde_json = "1"
12+
thiserror = "1.0"
13+
rooted_path = { path = "../rooted_path" }

0 commit comments

Comments
 (0)