tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

build.rs (3378B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 // Writes build information to ${OUT_DIR}/build-info.rs which is included in
      6 // the program during compilation:
      7 //
      8 // ```no_run
      9 // const COMMIT_HASH: Option<&'static str> = Some("c31a366");
     10 // const COMMIT_DATE: Option<&'static str> = Some("1988-05-10");
     11 // ```
     12 //
     13 // The values are `None` if running hg failed, e.g. if it is not installed or
     14 // if we are not in an hg repo.
     15 
     16 use std::env;
     17 use std::ffi::OsStr;
     18 use std::fs::File;
     19 use std::io;
     20 use std::io::Write;
     21 use std::path::{Path, PathBuf};
     22 use std::process::Command;
     23 
     24 fn main() -> io::Result<()> {
     25    let cur_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
     26    let build_info = get_build_info(&cur_dir);
     27 
     28    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
     29    let mut fh = File::create(out_dir.join("build-info.rs"))?;
     30    writeln!(
     31        fh,
     32        "const COMMIT_HASH: Option<&'static str> = {:?};",
     33        build_info.hash()
     34    )?;
     35    writeln!(
     36        fh,
     37        "const COMMIT_DATE: Option<&'static str> = {:?};",
     38        build_info.date()
     39    )?;
     40 
     41    Ok(())
     42 }
     43 
     44 fn get_build_info(dir: &Path) -> Box<dyn BuildInfo> {
     45    if Path::exists(&dir.join(".hg")) {
     46        Box::new(Hg {})
     47    } else if Path::exists(&dir.join(".git")) {
     48        Box::new(Git {})
     49    } else if let Some(parent) = dir.parent() {
     50        get_build_info(parent)
     51    } else {
     52        eprintln!("unable to detect vcs");
     53        Box::new(Noop {})
     54    }
     55 }
     56 
     57 trait BuildInfo {
     58    fn hash(&self) -> Option<String>;
     59    fn date(&self) -> Option<String>;
     60 }
     61 
     62 struct Hg;
     63 
     64 impl Hg {
     65    fn exec<I, S>(&self, args: I) -> Option<String>
     66    where
     67        I: IntoIterator<Item = S>,
     68        S: AsRef<OsStr>,
     69    {
     70        Command::new("hg")
     71            .env("HGPLAIN", "1")
     72            .args(args)
     73            .output()
     74            .ok()
     75            .and_then(|r| String::from_utf8(r.stdout).ok())
     76            .map(|s| s.trim_end().into())
     77    }
     78 }
     79 
     80 impl BuildInfo for Hg {
     81    fn hash(&self) -> Option<String> {
     82        self.exec(["log", "-r.", "-T{node|short}"])
     83    }
     84 
     85    fn date(&self) -> Option<String> {
     86        self.exec(["log", "-r.", "-T{date|isodate}"])
     87    }
     88 }
     89 
     90 struct Git;
     91 
     92 impl Git {
     93    fn exec<I, S>(&self, args: I) -> Option<String>
     94    where
     95        I: IntoIterator<Item = S>,
     96        S: AsRef<OsStr>,
     97    {
     98        Command::new("git")
     99            .env("GIT_CONFIG_NOSYSTEM", "1")
    100            .args(args)
    101            .output()
    102            .ok()
    103            .and_then(|r| String::from_utf8(r.stdout).ok())
    104            .map(|s| s.trim_end().into())
    105    }
    106 
    107    fn to_hg_sha(&self, git_sha: String) -> Option<String> {
    108        self.exec(["cinnabar", "git2hg", &git_sha])
    109    }
    110 }
    111 
    112 impl BuildInfo for Git {
    113    fn hash(&self) -> Option<String> {
    114        self.exec(["rev-parse", "HEAD"])
    115            .and_then(|sha| self.to_hg_sha(sha))
    116            .map(|mut s| {
    117                s.truncate(12);
    118                s
    119            })
    120    }
    121 
    122    fn date(&self) -> Option<String> {
    123        self.exec(["log", "-1", "--date=short", "--pretty=format:%cd"])
    124    }
    125 }
    126 
    127 struct Noop;
    128 
    129 impl BuildInfo for Noop {
    130    fn hash(&self) -> Option<String> {
    131        None
    132    }
    133    fn date(&self) -> Option<String> {
    134        None
    135    }
    136 }