use std::fs;
use std::path::Path;
use std::process::Command;
fn maybe_get_git_commit_sha() -> Option<String> {
let output = Command::new("git")
.args(&["rev-parse", "HEAD"])
.output()
.ok()?;
if !output.status.success() {
return None;
}
String::from_utf8(output.stdout)
.ok()
.map(|s| s.trim().to_string())
}
fn is_workspace_dirty() -> bool {
let output = Command::new("git")
.args(&["status", "--porcelain"])
.output()
.ok();
let Some(output) = output else {
return false;
};
!output.stdout.is_empty()
}
fn maybe_parse_vcs_info_sha() -> Option<String> {
let contents = fs::read_to_string(".cargo_vcs_info.json").ok()?;
const SHA1_KEY: &str = "\"sha1\": \"";
let sha_start = contents.find(SHA1_KEY)?;
let sha_start = sha_start + SHA1_KEY.len();
let sha_end = contents[sha_start..].find('"')?;
let sha = contents[sha_start..sha_start + sha_end].trim().to_string();
if sha.is_empty() {
return None;
}
Some(sha)
}
fn get_git_commit_sha_with_fallback() -> String {
if let Some(mut git_commit) = maybe_get_git_commit_sha() {
if is_workspace_dirty() {
git_commit.push_str("-dirty");
}
return git_commit;
}
maybe_parse_vcs_info_sha().unwrap_or_default()
}
fn generate_version_string(git_commit_sha: &str) -> String {
if git_commit_sha.is_empty() {
env!("CARGO_PKG_VERSION").to_string()
} else {
format!("{} ({})", env!("CARGO_PKG_VERSION"), git_commit_sha)
}
}
fn write_ephemeral_version_string_file(version_string: &str) {
let out_dir = std::env::var("OUT_DIR").unwrap();
let version_file = Path::new(&out_dir).join("version_string.rs");
let content = format!("pub const VERSION_STRING: &str = {:?};", version_string);
fs::write(&version_file, content).unwrap();
}
fn main() {
let git_commit_sha = get_git_commit_sha_with_fallback();
let version_string = generate_version_string(&git_commit_sha);
write_ephemeral_version_string_file(&version_string);
}