1 // Copyright (C) 2023 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 use crate_health_proc_macros::NameAndVersionMap; 16 17 use std::{ 18 collections::HashSet, 19 path::{Path, PathBuf}, 20 }; 21 22 use anyhow::{anyhow, Result}; 23 use semver::Version; 24 use walkdir::WalkDir; 25 26 use crate::{ 27 android_bp::generate_android_bps, Crate, CrateError, NameAndVersion, NameAndVersionMap, 28 NamedAndVersioned, 29 }; 30 31 use std::collections::BTreeMap; 32 33 #[derive(NameAndVersionMap)] 34 pub struct CrateCollection { 35 crates: BTreeMap<NameAndVersion, Crate>, 36 repo_root: PathBuf, 37 } 38 39 impl CrateCollection { new<P: Into<PathBuf>>(repo_root: P) -> CrateCollection40 pub fn new<P: Into<PathBuf>>(repo_root: P) -> CrateCollection { 41 CrateCollection { crates: BTreeMap::new(), repo_root: repo_root.into() } 42 } add_from(&mut self, path: &impl AsRef<Path>) -> Result<()>43 pub fn add_from(&mut self, path: &impl AsRef<Path>) -> Result<()> { 44 for entry_or_err in WalkDir::new(self.repo_root.join(path)) { 45 let entry = entry_or_err?; 46 if entry.file_name() == "Cargo.toml" { 47 match Crate::from(&entry.path(), &self.repo_root.as_path()) { 48 Ok(krate) => self.crates.insert_or_error( 49 NameAndVersion::new(krate.name().to_string(), krate.version().clone()), 50 krate, 51 )?, 52 Err(e) => match e.downcast_ref() { 53 Some(CrateError::VirtualCrate(_)) => (), 54 _ => return Err(e), 55 }, 56 }; 57 } 58 } 59 Ok(()) 60 } repo_root(&self) -> &Path61 pub fn repo_root(&self) -> &Path { 62 self.repo_root.as_path() 63 } print(&self) -> Result<()>64 pub fn print(&self) -> Result<()> { 65 for krate in self.crates.values() { 66 krate.print()? 67 } 68 Ok(()) 69 } stage_crates(&self) -> Result<()>70 pub fn stage_crates(&self) -> Result<()> { 71 for krate in self.crates.values() { 72 krate.stage_crate()? 73 } 74 Ok(()) 75 } generate_android_bps(&mut self) -> Result<()>76 pub fn generate_android_bps(&mut self) -> Result<()> { 77 for (nv, output) in generate_android_bps(self.crates.values())?.into_iter() { 78 self.crates 79 .get_mut(&nv) 80 .ok_or(anyhow!("Failed to get crate {} {}", nv.name(), nv.version()))? 81 .set_generate_android_bp_output(output); 82 } 83 Ok(()) 84 } diff_android_bps(&mut self) -> Result<()>85 pub fn diff_android_bps(&mut self) -> Result<()> { 86 for krate in self.crates.values_mut() { 87 krate.diff_android_bp()?; 88 } 89 Ok(()) 90 } 91 } 92