use globwalk::glob; use std::collections::HashMap; use std::fs; use std::fs::OpenOptions; use std::io::Write; use std::path::Path; use walkdir::WalkDir; mod prost_build; mod tonic_build; type BoxResult = Result>; fn main() -> BoxResult<()> { let _ = fs::remove_dir_all("src/google"); let _ = fs::remove_dir_all("src/grafeas"); OpenOptions::new() .write(true) .truncate(true) .open("src/mod.rs")?; let paths: Vec<_> = glob("googleapis/google/{cloud,appengine,bigtable,datastore,iam,identity,pubsub,spanner,storage}/**/*.proto")? .filter_map(Result::ok) .map(|x| x.path().display().to_string()) .filter(|x| !x.contains("alpha")) .collect(); tonic_build::configure() .build_server(false) .format(true) .out_dir("src") .compile(&paths, &["googleapis".to_string()])?; create_mod("src/google")?; // create_mod("src/grafeas")?; deduplicate_mod()?; print_caching(&paths); Ok(()) } fn print_caching(paths: &Vec) { for path in paths { println!("cargo:rerun-if-changed={}", path); } } fn create_mod(p: &str) -> BoxResult<()> { for entry in WalkDir::new(p) { let entry = entry?; let path = entry.path(); let parent = path.parent().expect("has parent"); let current_dir: Vec<_> = glob(&format!("{}/*", parent.display().to_string())[..])? .filter_map(Result::ok) .collect(); let mut file = std::fs::File::create(format!("{}/mod.rs", parent.display()))?; let mut m = HashMap::new(); for module in current_dir { if !module.path().is_file() && module.path().read_dir()?.next().is_none() { continue; } let name = module .path() .file_name() .expect("is file") .to_string_lossy() .replace(".rs", ""); if m.get(&name).is_some() { continue; } m.insert(name.clone(), ()); if name == "mod" || name == "lib" || name.starts_with(".") { continue; } file.write_all(format!("pub mod r#{};\n", name).as_bytes())?; } } Ok(()) } fn deduplicate_mod() -> BoxResult<()> { let rs_src: Vec<_> = glob("src/**/*.rs")?.filter_map(Result::ok).collect(); for file in rs_src { if let Some(file_name) = file.path().file_name() { if file_name.to_string_lossy() == "mod.rs" { continue; } } let display = file.path().display().to_string().replace(".rs", "/mod.rs"); if !Path::new(&display).exists() { continue; } let mut mod_file = fs::OpenOptions::new().append(true).open(display)?; let source = fs::read_to_string(&file.path())?; mod_file.write_all(source.as_bytes())?; fs::remove_file(file.path())?; } Ok(()) }