1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
#![allow(clippy::needless_doctest_main)] //! Provide the current Git commit SHA1 during build. //! //! When building crates from a Git repository it is often desirable to extract the //! current version number in form of the Git SHA1 to be displayed. This crate extracts //! the current Git SHA1 during build time and makes it accessible as an environment //! variable. //! //! If the crate is currently built without access to the Git SHA1 (i. e. it was extracted //! from a tar-archive, or Git is not installed), instead of failing, it falls back on a //! default value. This value defaults to "", but can be changed with the //! [`use_default()`](struct.GitSHA1.html#method.use_default) method. //! //! //! # Example //! //! In `build.rs`: //! ``` //! use git_sha1::GitSHA1; //! //! fn main() { //! GitSHA1::read().set("GIT_SHA1"); //! } //! ``` //! //! In `main.rs`: //! ``` //! use git_sha1::GitSHA1; //! //! // either as static &str: //! static SHA1: &str = env!("GIT_SHA1"); //! //! // or during runtime: //! fn main() { //! let sha1 = GitSHA1::from_env("GIT_SHA1"); //! //! let long = sha1.long(); //! assert_eq!(SHA1, long); //! //! let short = sha1.short(10); //! // `short` may be shorter if SHA1 does not exist //! assert_eq!(short.len(), usize::min(10, short.len())); //! } //! ``` //! use std::process::Command; /// *deprecated* /// /// Number of hex-characters in the Git SHA1. /// /// There are half as many __bytes__ in a SHA1. /// /// This value is true for any Git SHA1, but must not necessarily be the number of digits /// available in the extracted value. Either because Git is not even installed, or because /// the crate is not compiled from a Git repository and the implementation falls back on a /// default string to return instead. /// #[allow(dead_code)] pub const GIT_SHA1_LENGTH: usize = 40; pub struct GitSHA1 { /// default value that can be used instead of the real Git SHA1, if the crate is not /// in a Git repository (i. e. when building from a .tar-archive) default: String, /// Contains `None` if the current crate does not contain a Git SHA1. sha1: Option<String>, } impl GitSHA1 { /// Although designed with Git in mind, your crate may be compiled from source without /// being in a Git repository. This lets you define the value which is used instead of /// the real Git SHA1 as a drop-in replacement. The default value is "" (an empty /// string). /// /// # Example /// /// ``` /// # use git_sha1::GitSHA1; /// GitSHA1::read().use_default("<empty>").set("GIT_SHA1"); /// // will use: GIT_SHA1="<empty>" /// ``` /// #[allow(dead_code)] // not used here pub fn use_default(mut self, default: &str) -> Self { self.default = default.into(); self } /// Read current Git SHA1 by running `git rev-parse HEAD`. /// /// This only retrieves the SHA1 from git. Use /// [`set(name)`](struct.GitSHA1.html#method.set) to pass compile-time environment /// variable to cargo-build. Afterwards it can be read from your source files. /// /// If the current crate is not a git repository, the read will silently fail and the /// returned string in the end will be substituded by a default value. /// pub fn read() -> Self { let sha1: Option<String> = Command::new("git") .args(&["rev-parse", "HEAD"]) .output() .map_or(None, |out| { Some(String::from_utf8(out.stdout).unwrap().trim().into()) }); Self { default: String::new(), sha1, } } /// Read the comiple-time environment variable from carto-build. This can be used /// during runtime, i.e. in `fn main() {}`. /// /// # Note: /// /// You can read the Git SHA1 statically using `env!`: /// /// ``` /// // "GIT_SHA1" set in `build.rs` /// const GIT_SHA1: &'static str = env!("GIT_SHA1"); /// ``` #[allow(dead_code)] // because we never use it in `build.rs` pub fn from_env(name: &str) -> Self { Self { default: String::new(), sha1: std::env::var(name).ok(), } } /// Generate cargo environment variable for long Git SHA1. /// /// # Example /// /// ``` /// # use git_sha1::GitSHA1; /// GitSHA1::read().set("GIT_SHA1"); /// ``` pub fn set(&self, name: &str) { println!( "cargo:rustc-env={}={}", name, self.sha1.as_ref().unwrap_or(&self.default) ); } /// Return the complete SHA1 as a String. #[allow(dead_code)] // because we never use it in `build.rs` pub fn long(&self) -> String { self.sha1.as_ref().unwrap_or(&self.default).clone() } /// Return a subset of digits (short sha) as a String. /// /// # Note /// /// The number of digits extracted is silently truncated to the maximum number of /// digits available in the Git SHA1. /// #[allow(dead_code)] // because we never use it in `build.rs` pub fn short(&self, count: usize) -> String { match &self.sha1 { None => self.default.clone(), Some(s) => { let count = usize::min(s.len(), count); s.as_str()[..count].into() } } } }