summaryrefslogtreecommitdiff
path: root/tools/external_crates/crate_health/src/crate_collection.rs
blob: 03dc4fe22c6ff68929db7b51e03aee56001888fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright (C) 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate_health_proc_macros::NameAndVersionMap;

use std::{
    collections::HashSet,
    path::{Path, PathBuf},
};

use anyhow::{anyhow, Result};
use semver::Version;
use walkdir::WalkDir;

use crate::{
    android_bp::generate_android_bps, Crate, CrateError, NameAndVersion, NameAndVersionMap,
    NamedAndVersioned,
};

use std::collections::BTreeMap;

#[derive(NameAndVersionMap)]
pub struct CrateCollection {
    crates: BTreeMap<NameAndVersion, Crate>,
    repo_root: PathBuf,
}

impl CrateCollection {
    pub fn new<P: Into<PathBuf>>(repo_root: P) -> CrateCollection {
        CrateCollection { crates: BTreeMap::new(), repo_root: repo_root.into() }
    }
    pub fn add_from(
        &mut self,
        path: &impl AsRef<Path>,
        pseudo_crate: Option<&impl AsRef<Path>>,
    ) -> Result<()> {
        for entry_or_err in WalkDir::new(self.repo_root.join(path)) {
            let entry = entry_or_err?;
            if entry.file_name() == "Cargo.toml" {
                match Crate::from(
                    &entry.path(),
                    &self.repo_root.as_path(),
                    pseudo_crate.map(|p| p.as_ref()),
                ) {
                    Ok(krate) => self.crates.insert_or_error(
                        NameAndVersion::new(krate.name().to_string(), krate.version().clone()),
                        krate,
                    )?,
                    Err(e) => match e.downcast_ref() {
                        Some(CrateError::VirtualCrate(_)) => (),
                        _ => return Err(e),
                    },
                };
            }
        }
        Ok(())
    }
    pub fn repo_root(&self) -> &Path {
        self.repo_root.as_path()
    }
    pub fn print(&self) -> Result<()> {
        for krate in self.crates.values() {
            krate.print()?
        }
        Ok(())
    }
    pub fn stage_crates(&self) -> Result<()> {
        for krate in self.crates.values() {
            krate.stage_crate()?
        }
        Ok(())
    }
    pub fn generate_android_bps(&mut self) -> Result<()> {
        for (nv, output) in generate_android_bps(self.crates.values())?.into_iter() {
            self.crates
                .get_mut(&nv)
                .ok_or(anyhow!("Failed to get crate {} {}", nv.name(), nv.version()))?
                .set_generate_android_bp_output(output.0, output.1);
        }
        Ok(())
    }
}