2018-09-17 15:07:53 +03:00
|
|
|
// Writes build information to ${OUT_DIR}/build-info.rs which is included in
|
|
|
|
// the program during compilation:
|
|
|
|
//
|
|
|
|
// ```no_run
|
|
|
|
// const COMMIT_HASH: Option<&'static str> = Some("c31a366");
|
|
|
|
// const COMMIT_DATE: Option<&'static str> = Some("1988-05-10");
|
|
|
|
// ```
|
|
|
|
//
|
|
|
|
// The values are `None` if running hg failed, e.g. if it is not installed or
|
|
|
|
// if we are not in an hg repo.
|
2017-06-22 18:28:18 +03:00
|
|
|
|
|
|
|
use std::env;
|
|
|
|
use std::ffi::OsStr;
|
|
|
|
use std::fs::File;
|
2018-09-17 15:07:53 +03:00
|
|
|
use std::io;
|
2017-06-22 18:28:18 +03:00
|
|
|
use std::io::Write;
|
2018-09-17 15:07:53 +03:00
|
|
|
use std::path::{Path, PathBuf};
|
2017-06-22 18:28:18 +03:00
|
|
|
use std::process::Command;
|
|
|
|
|
2018-09-17 15:07:53 +03:00
|
|
|
fn main() -> io::Result<()> {
|
|
|
|
let cur_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
|
|
|
|
let build_info = get_build_info(&cur_dir);
|
|
|
|
|
|
|
|
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
let mut fh = File::create(out_dir.join("build-info.rs"))?;
|
2017-06-22 18:28:18 +03:00
|
|
|
writeln!(
|
|
|
|
fh,
|
|
|
|
"const COMMIT_HASH: Option<&'static str> = {:?};",
|
2018-09-17 15:07:53 +03:00
|
|
|
build_info.hash()
|
|
|
|
)?;
|
2017-06-22 18:28:18 +03:00
|
|
|
writeln!(
|
|
|
|
fh,
|
|
|
|
"const COMMIT_DATE: Option<&'static str> = {:?};",
|
2018-09-17 15:07:53 +03:00
|
|
|
build_info.date()
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(())
|
2017-06-22 18:28:18 +03:00
|
|
|
}
|
|
|
|
|
2019-08-29 13:23:12 +03:00
|
|
|
fn get_build_info(dir: &Path) -> Box<dyn BuildInfo> {
|
2018-09-17 15:07:53 +03:00
|
|
|
if Path::exists(&dir.join(".hg")) {
|
|
|
|
Box::new(Hg {})
|
|
|
|
} else if Path::exists(&dir.join(".git")) {
|
|
|
|
Box::new(Git {})
|
|
|
|
} else {
|
|
|
|
if let Some(parent) = dir.parent() {
|
|
|
|
get_build_info(parent)
|
|
|
|
} else {
|
|
|
|
eprintln!("unable to detect vcs");
|
|
|
|
Box::new(Noop {})
|
|
|
|
}
|
|
|
|
}
|
2017-06-22 18:28:18 +03:00
|
|
|
}
|
|
|
|
|
2018-09-17 15:07:53 +03:00
|
|
|
trait BuildInfo {
|
|
|
|
fn hash(&self) -> Option<String>;
|
|
|
|
fn date(&self) -> Option<String>;
|
2017-06-22 18:28:18 +03:00
|
|
|
}
|
|
|
|
|
2018-09-17 15:07:53 +03:00
|
|
|
struct Hg;
|
|
|
|
|
|
|
|
impl Hg {
|
|
|
|
fn exec<I, S>(&self, args: I) -> Option<String>
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = S>,
|
|
|
|
S: AsRef<OsStr>,
|
|
|
|
{
|
|
|
|
Command::new("hg")
|
|
|
|
.env("HGPLAIN", "1")
|
|
|
|
.args(args)
|
|
|
|
.output()
|
|
|
|
.ok()
|
|
|
|
.and_then(|r| String::from_utf8(r.stdout).ok())
|
2019-04-12 13:32:20 +03:00
|
|
|
.map(|s| s.trim_end().into())
|
2017-06-22 18:28:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 15:07:53 +03:00
|
|
|
impl BuildInfo for Hg {
|
|
|
|
fn hash(&self) -> Option<String> {
|
|
|
|
self.exec(&["log", "-r.", "-T{node|short}"])
|
|
|
|
}
|
|
|
|
|
|
|
|
fn date(&self) -> Option<String> {
|
|
|
|
self.exec(&["log", "-r.", "-T{date|isodate}"])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Git;
|
|
|
|
|
|
|
|
impl Git {
|
|
|
|
fn exec<I, S>(&self, args: I) -> Option<String>
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = S>,
|
|
|
|
S: AsRef<OsStr>,
|
|
|
|
{
|
|
|
|
Command::new("git")
|
|
|
|
.env("GIT_CONFIG_NOSYSTEM", "1")
|
|
|
|
.args(args)
|
|
|
|
.output()
|
|
|
|
.ok()
|
|
|
|
.and_then(|r| String::from_utf8(r.stdout).ok())
|
2019-04-12 13:32:20 +03:00
|
|
|
.map(|s| s.trim_end().into())
|
2018-09-17 15:07:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn to_hg_sha(&self, git_sha: String) -> Option<String> {
|
|
|
|
self.exec(&["cinnabar", "git2hg", &git_sha])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BuildInfo for Git {
|
|
|
|
fn hash(&self) -> Option<String> {
|
|
|
|
self.exec(&["rev-parse", "HEAD"])
|
|
|
|
.and_then(|sha| self.to_hg_sha(sha))
|
2018-09-20 00:14:37 +03:00
|
|
|
.map(|mut s| {
|
2019-07-25 15:41:28 +03:00
|
|
|
s.truncate(12);
|
|
|
|
s
|
2018-09-20 00:14:37 +03:00
|
|
|
})
|
2018-09-17 15:07:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn date(&self) -> Option<String> {
|
|
|
|
self.exec(&["log", "-1", "--date=short", "--pretty=format:%cd"])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Noop;
|
|
|
|
|
|
|
|
impl BuildInfo for Noop {
|
|
|
|
fn hash(&self) -> Option<String> {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
fn date(&self) -> Option<String> {
|
|
|
|
None
|
|
|
|
}
|
2017-06-22 18:28:18 +03:00
|
|
|
}
|