1*d4726bddSHONG Yifan //! Common utilities
2*d4726bddSHONG Yifan
3*d4726bddSHONG Yifan pub(crate) mod starlark;
4*d4726bddSHONG Yifan pub(crate) mod symlink;
5*d4726bddSHONG Yifan pub(crate) mod target_triple;
6*d4726bddSHONG Yifan
7*d4726bddSHONG Yifan pub(crate) const CRATES_IO_INDEX_URL: &str = "https://github.com/rust-lang/crates.io-index";
8*d4726bddSHONG Yifan
9*d4726bddSHONG Yifan use std::collections::BTreeMap;
10*d4726bddSHONG Yifan use std::path::{Path, PathBuf};
11*d4726bddSHONG Yifan
12*d4726bddSHONG Yifan /// Convert a string into a valid crate module name by applying transforms to invalid characters
sanitize_module_name(name: &str) -> String13*d4726bddSHONG Yifan pub(crate) fn sanitize_module_name(name: &str) -> String {
14*d4726bddSHONG Yifan name.replace('-', "_")
15*d4726bddSHONG Yifan }
16*d4726bddSHONG Yifan
17*d4726bddSHONG Yifan /// Some character which may be present in version IDs are not valid
18*d4726bddSHONG Yifan /// in Bazel repository names. This converts invalid characters. See
19*d4726bddSHONG Yifan /// [RepositoryName.java](https://github.com/bazelbuild/bazel/blob/4.0.0/src/main/java/com/google/devtools/build/lib/cmdline/RepositoryName.java#L42)
sanitize_repository_name(name: &str) -> String20*d4726bddSHONG Yifan pub(crate) fn sanitize_repository_name(name: &str) -> String {
21*d4726bddSHONG Yifan name.replace('+', "-")
22*d4726bddSHONG Yifan }
23*d4726bddSHONG Yifan
24*d4726bddSHONG Yifan /// Vendored crates are generated by cargo itself in `src/metadata.rs` in the
25*d4726bddSHONG Yifan /// `VendorGenerator::generate()` method. This means that the semver metadata will
26*d4726bddSHONG Yifan /// always contain a (+) symbol, which is not compatible with bazel's labels.
27*d4726bddSHONG Yifan /// This function will rename the cargo vendor generated file paths to be compatible with bazel
28*d4726bddSHONG Yifan /// labels by simply replacing the (+) with a (-). If this file is called by any other cli mod,
29*d4726bddSHONG Yifan /// it just simply joins the out dir to the path
normalize_cargo_file_paths( outputs: BTreeMap<PathBuf, String>, out_dir: &Path, ) -> BTreeMap<PathBuf, String>30*d4726bddSHONG Yifan pub(crate) fn normalize_cargo_file_paths(
31*d4726bddSHONG Yifan outputs: BTreeMap<PathBuf, String>,
32*d4726bddSHONG Yifan out_dir: &Path,
33*d4726bddSHONG Yifan ) -> BTreeMap<PathBuf, String> {
34*d4726bddSHONG Yifan outputs
35*d4726bddSHONG Yifan .into_iter()
36*d4726bddSHONG Yifan .map(|(path, content)| {
37*d4726bddSHONG Yifan let path = out_dir.join(path);
38*d4726bddSHONG Yifan // Get Path Str and Parent Path Str so we can rename the root file
39*d4726bddSHONG Yifan let original_path_str = path.to_str().expect("All file paths should be strings");
40*d4726bddSHONG Yifan let original_parent_path_str = path
41*d4726bddSHONG Yifan .parent()
42*d4726bddSHONG Yifan .expect("Should have parent")
43*d4726bddSHONG Yifan .to_str()
44*d4726bddSHONG Yifan .expect("All file paths should be strings");
45*d4726bddSHONG Yifan
46*d4726bddSHONG Yifan let new_path = if original_parent_path_str.contains('+') {
47*d4726bddSHONG Yifan let new_parent_file_path = sanitize_repository_name(original_parent_path_str);
48*d4726bddSHONG Yifan std::fs::rename(original_parent_path_str, new_parent_file_path)
49*d4726bddSHONG Yifan .expect("Could not rename paths");
50*d4726bddSHONG Yifan PathBuf::from(&original_path_str.replace('+', "-"))
51*d4726bddSHONG Yifan } else {
52*d4726bddSHONG Yifan path
53*d4726bddSHONG Yifan };
54*d4726bddSHONG Yifan
55*d4726bddSHONG Yifan (new_path, content)
56*d4726bddSHONG Yifan })
57*d4726bddSHONG Yifan .collect()
58*d4726bddSHONG Yifan }
59*d4726bddSHONG Yifan
60*d4726bddSHONG Yifan #[cfg(test)]
61*d4726bddSHONG Yifan mod test {
62*d4726bddSHONG Yifan use super::*;
63*d4726bddSHONG Yifan
64*d4726bddSHONG Yifan #[test]
test_sanitize_repository_name()65*d4726bddSHONG Yifan fn test_sanitize_repository_name() {
66*d4726bddSHONG Yifan let name = "anyhow-1.0.0+semver_meta";
67*d4726bddSHONG Yifan let got = sanitize_repository_name(name);
68*d4726bddSHONG Yifan assert_eq!(got, String::from("anyhow-1.0.0-semver_meta"));
69*d4726bddSHONG Yifan }
70*d4726bddSHONG Yifan
71*d4726bddSHONG Yifan #[test]
test_sanitize_repository_name_no_change()72*d4726bddSHONG Yifan fn test_sanitize_repository_name_no_change() {
73*d4726bddSHONG Yifan let name = "tokio-1.20.0";
74*d4726bddSHONG Yifan let got = sanitize_repository_name(name);
75*d4726bddSHONG Yifan assert_eq!(got, String::from("tokio-1.20.0"));
76*d4726bddSHONG Yifan }
77*d4726bddSHONG Yifan
78*d4726bddSHONG Yifan #[test]
test_normalize_cargo_file_paths()79*d4726bddSHONG Yifan fn test_normalize_cargo_file_paths() {
80*d4726bddSHONG Yifan let mut outputs = BTreeMap::new();
81*d4726bddSHONG Yifan outputs.insert(
82*d4726bddSHONG Yifan PathBuf::from("libbpf-sys-1.3.0+v1.3.0/BUILD.bazel"),
83*d4726bddSHONG Yifan "contents".into(),
84*d4726bddSHONG Yifan );
85*d4726bddSHONG Yifan
86*d4726bddSHONG Yifan let outdir = tempfile::tempdir().unwrap();
87*d4726bddSHONG Yifan // create dir to mimic cargo vendor
88*d4726bddSHONG Yifan std::fs::create_dir_all(outdir.path().join("libbpf-sys-1.3.0+v1.3.0")).unwrap();
89*d4726bddSHONG Yifan
90*d4726bddSHONG Yifan let got = normalize_cargo_file_paths(outputs, outdir.path());
91*d4726bddSHONG Yifan for output in got.into_keys() {
92*d4726bddSHONG Yifan assert!(!output.to_str().unwrap().contains('+'));
93*d4726bddSHONG Yifan }
94*d4726bddSHONG Yifan }
95*d4726bddSHONG Yifan
96*d4726bddSHONG Yifan #[test]
test_normalize_cargo_file_paths_no_rename()97*d4726bddSHONG Yifan fn test_normalize_cargo_file_paths_no_rename() {
98*d4726bddSHONG Yifan let mut outputs = BTreeMap::new();
99*d4726bddSHONG Yifan outputs.insert(PathBuf::from("tokio-1.30.0/BUILD.bazel"), "contents".into());
100*d4726bddSHONG Yifan
101*d4726bddSHONG Yifan let outdir = tempfile::tempdir().unwrap();
102*d4726bddSHONG Yifan
103*d4726bddSHONG Yifan let got = normalize_cargo_file_paths(outputs, outdir.path());
104*d4726bddSHONG Yifan for output in got.into_keys() {
105*d4726bddSHONG Yifan assert!(!output.to_str().unwrap().contains('+'));
106*d4726bddSHONG Yifan }
107*d4726bddSHONG Yifan }
108*d4726bddSHONG Yifan }
109