use crate::crates::{Epoch, NormalizedName};
use itertools::Itertools;
use std::env;
use std::io;
use std::path::{Path, PathBuf};
pub struct ChromiumPaths {
pub root: PathBuf,
pub third_party: &'static Path,
pub rust_src_library_subdir: &'static Path,
pub rust_src_vendor_subdir: &'static Path,
pub rust_src_installed: &'static Path,
pub std_config_file: &'static Path,
pub std_build: &'static Path,
pub std_fake_root: &'static Path,
pub std_fake_root_config_template: &'static Path,
pub std_fake_root_cargo_template: &'static Path,
pub third_party_cargo_root: &'static Path,
pub third_party_config_file: &'static Path,
}
impl ChromiumPaths {
pub fn new() -> io::Result<ChromiumPaths> {
let cur_dir = env::current_dir()?;
Ok(ChromiumPaths {
root: cur_dir.clone(),
third_party: check_path(&cur_dir, RUST_THIRD_PARTY_DIR)?,
rust_src_library_subdir: Path::new(RUST_SRC_LIBRARY_SUBDIR),
rust_src_vendor_subdir: Path::new(RUST_SRC_VENDOR_SUBDIR),
rust_src_installed: Path::new(RUST_SRC_INSTALLED_DIR),
std_config_file: check_path(&cur_dir, STD_CONFIG_FILE)?,
std_build: check_path(&cur_dir, STD_BUILD_DIR)?,
std_fake_root: check_path(&cur_dir, STD_FAKE_ROOT)?,
std_fake_root_config_template: check_path(&cur_dir, STD_FAKE_ROOT_CONFIG_TEMPLATE)?,
std_fake_root_cargo_template: check_path(&cur_dir, STD_FAKE_ROOT_CARGO_TEMPLATE)?,
third_party_cargo_root: check_path(&cur_dir, THIRD_PARTY_CARGO_ROOT)?,
third_party_config_file: check_path(&cur_dir, THIRD_PARTY_CONFIG_FILE)?,
})
}
pub fn to_gn_abs_path(&self, path: &Path) -> Result<String, std::path::StripPrefixError> {
Ok(normalize_unix_path_separator(path.strip_prefix(&self.root)?))
}
pub fn strip_template(&self, path: &Path) -> Option<std::path::PathBuf> {
if path.extension()? != "template" {
None
} else {
let mut buf = path.to_owned();
buf.set_file_name(path.file_stem()?);
Some(buf)
}
}
}
fn check_path<'a>(root: &Path, p_str: &'a str) -> io::Result<&'a Path> {
let p = Path::new(p_str);
if !root.join(p).exists() {
return Err(io::Error::other(format!(
"could not find {} (invoked from Chromium checkout root?)",
p.display()
)));
}
Ok(p)
}
pub fn normalize_unix_path_separator(path: impl AsRef<Path>) -> String {
let path = path.as_ref();
path.iter()
.map(|comp| comp.to_str().unwrap_or_else(|| panic!("non-UTF-8 in path {path:?}")))
.join("/")
}
pub fn get_vendor_dir_for_package(
paths: &ChromiumPaths,
name: &str,
version: &semver::Version,
) -> PathBuf {
let epoch = Epoch::from_version(version);
paths.third_party_cargo_root.join("vendor").join(Path::new(&format!("{name}-{epoch}")))
}
pub fn get_build_dir_for_package(
paths: &ChromiumPaths,
name: &str,
version: &semver::Version,
) -> PathBuf {
paths
.third_party
.join(NormalizedName::from_crate_name(name).to_string())
.join(Epoch::from_version(version).to_string())
}
static RUST_THIRD_PARTY_DIR: &str = "third_party/rust";
static RUST_SRC_LIBRARY_SUBDIR: &str = "library";
static RUST_SRC_VENDOR_SUBDIR: &str = "library/vendor";
static RUST_SRC_INSTALLED_DIR: &str = "third_party/rust-toolchain/lib/rustlib/src/rust";
static STD_CONFIG_FILE: &str = "build/rust/std/gnrt_config.toml";
static STD_BUILD_DIR: &str = "build/rust/std/rules";
static STD_FAKE_ROOT: &str = "build/rust/std/fake_root";
static STD_FAKE_ROOT_CONFIG_TEMPLATE: &str = "build/rust/std/fake_root/.cargo/config.toml.template";
static STD_FAKE_ROOT_CARGO_TEMPLATE: &str = "build/rust/std/fake_root/Cargo.toml.template";
static THIRD_PARTY_CARGO_ROOT: &str = "third_party/rust/chromium_crates_io";
static THIRD_PARTY_CONFIG_FILE: &str = "third_party/rust/chromium_crates_io/gnrt_config.toml";
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_normalize() {
assert_eq!(normalize_unix_path_separator(Path::new("rel")), "rel");
assert_eq!(normalize_unix_path_separator(&Path::new("a").join("b")), "a/b");
}
}