use std::{
env::{ consts::{ ARCH, OS }, var },
fs::metadata,
io::{ Error as IoError, ErrorKind },
path::PathBuf,
process::Command,
str::from_utf8
};
use crate::{
error::Error,
helpers::var_bool,
force::{ get_force_bin, get_force_include },
install::install,
path::{ get_bin_path, get_include_path },
version::{ compare_versions, get_protoc_asset_name }
};
pub fn init(version: &str) -> Result<(PathBuf, PathBuf), Error> {
let protoc_bin: PathBuf = get_force_bin()?.map_or_else(|| -> Result<PathBuf, Error> {
let out_dir = PathBuf::from(var("OUT_DIR").map_err(Error::VarError)?);
let protoc_asset_name = get_protoc_asset_name(version, OS, ARCH)?;
let protoc_out_dir = out_dir.join(&protoc_asset_name);
if !protoc_out_dir.exists() {
install(version, &out_dir, &protoc_asset_name, &protoc_out_dir)?;
}
Ok(get_bin_path(version, &protoc_out_dir))
}, Ok)?;
metadata(&protoc_bin).map_err(Error::Io)?;
let output = Command::new(&protoc_bin).args(["--version"]).output().map_err(Error::Io)?;
if !output.status.success() {
return Err(Error::Io(IoError::new(ErrorKind::Other, "test run protoc fail")))
}
if !var_bool("PROTOC_PREBUILT_NOT_CHECK_VERSION") {
let stdout = match from_utf8(&output.stdout) {
Ok(stdout) => stdout,
Err(_) => return Err(
Error::Io(IoError::new(ErrorKind::Other, "parse test run protoc output fail"))
)
};
let returned = stdout.trim().replace("libprotoc ", "");
if !compare_versions(version, &returned) {
return Err(Error::VersionCheck((version, returned)))
}
}
let protoc_include: PathBuf = get_force_include()?
.map_or_else(|| Ok(get_include_path(version, &protoc_bin)), Ok)?;
Ok((protoc_bin, protoc_include))
}