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