use std::env;
use std::ffi::OsStr;
use std::fs;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Result;
use std::path::Path;
use std::path::PathBuf;
fn synchronize(src_tree: &Path, dest_tree: &Path, path: &Path) -> Result<()> {
let src = src_tree.join(path);
let dest = dest_tree.join(path);
println!("cargo:rerun-if-changed={}", src.display());
if !src.exists() {
return Err(Error::new(ErrorKind::Other, "source file not found"));
}
if dest.exists() {
if dest.metadata()?.modified()? >= src.metadata()?.modified()? {
return Ok(());
}
} else {
if let Some(parent) = dest.parent() {
if !parent.is_dir() {
fs::create_dir_all(parent)?;
}
}
}
std::fs::copy(&src, &dest)?;
Ok(())
}
fn find_proto_files(proto_path: &Path) -> Vec<PathBuf> {
walkdir::WalkDir::new(proto_path)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| {
e.path().extension() == Some(OsStr::new("proto")) && e.metadata().unwrap().is_file()
})
.map(|e| e.into_path())
.collect()
}
fn main() -> Result<()> {
let manifest_dir =
PathBuf::from(&env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"));
let resource_dir = manifest_dir.join("src/resources");
if manifest_dir.join("in-git-repo").exists() {
let git_dir = manifest_dir.join("../..");
synchronize(
&git_dir,
&resource_dir,
&PathBuf::from("text/simple_extensions_schema.yaml"),
)?;
for proto_file in find_proto_files(&git_dir.join("proto")) {
synchronize(
&git_dir,
&resource_dir,
proto_file
.strip_prefix(&git_dir)
.expect("failed to strip prefix"),
)?;
}
}
let proto_path = PathBuf::from(&resource_dir).join("proto");
let proto_files: Vec<_> = find_proto_files(&proto_path);
let mut config = prost_build::Config::new();
config.type_attribute(".", "#[derive(::substrait_validator_derive::ProtoMeta)]");
config.compile_protos(&proto_files, &[&proto_path.display().to_string()])?;
for path in &proto_files {
println!("cargo:rerun-if-changed={}", path.display());
}
Ok(())
}