1#[macro_use]
20extern crate quick_error;
21
22use std::process::Command;
23
24use std::env;
25use std::fs::{create_dir_all, File};
26use std::io::{BufWriter, Read, Write};
27use std::path::Path;
28
29quick_error! {
30 #[derive(Debug)]
31 pub enum Error {
32 Io(err: std::io::Error) {
33 from()
34 }
35 MissingEnvVar {
36 }
37 }
38}
39
40fn same_content_as(path: &Path, content: &str) -> Result<bool, Error> {
41 let mut f = File::open(path)?;
42 let mut current = String::new();
43 f.read_to_string(&mut current)?;
44
45 Ok(current == content)
46}
47
48fn git_describe() -> Option<String> {
49 Command::new("git")
50 .args(&["describe", "--tags", "--always"])
51 .output()
52 .ok()
53 .and_then(|out| {
54 std::str::from_utf8(&out.stdout[..])
55 .map(str::trim)
56 .map(str::to_owned)
57 .ok()
58 })
59}
60
61pub fn write_version_file() -> Result<(), Error> {
63 let path = env::var_os("OUT_DIR").ok_or(Error::MissingEnvVar)?;
64 let path: &Path = path.as_ref();
65
66 create_dir_all(path)?;
67
68 let path = path.join("version.rs");
69
70 let content = if let Some(describe) = git_describe() {
71 format!("static GIT_BUILD_VERSION: Option<&'static str> = Some(\"{}\");\n", describe)
72 } else {
73 "static GIT_BUILD_VERSION: Option<&'static str> = None;\n".to_owned()
74 };
75
76 let is_fresh = if path.exists() {
77 same_content_as(&path, &content)?
78 } else {
79 false
80 };
81
82 if !is_fresh {
83 let mut file = BufWriter::new(File::create(&path)?);
84
85 write!(file, "{}", content)?;
86 }
87 Ok(())
88}