rust_tools_version/
lib.rs

1use std::fmt;
2use std::process::Command;
3
4pub const CURRENT_STABLE: Version = Version {
5    major: 1,
6    minor: 20,
7    patch: 0,
8};
9
10pub const CURRENT_BETA: Version = Version {
11    major: 1,
12    minor: 21,
13    patch: 0,
14};
15
16pub const CURRENT_NIGHTLY: Version = Version {
17    major: 1,
18    minor: 22,
19    patch: 0,
20};
21
22#[derive(Debug, Copy, Clone, Eq, PartialEq)]
23pub struct Version {
24    pub major: u32,
25    pub minor: u32,
26    pub patch: u32,
27}
28
29impl fmt::Display for Version {
30    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
31        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
32    }
33}
34
35impl Version {
36    pub fn new(major: u32, minor: u32, patch: u32) -> Version {
37        Version {
38            major,
39            minor,
40            patch,
41        }
42    }
43
44    pub fn from_env_var() -> Option<Version> {
45        option_env!("CFG_VERSION").and_then(|s| Self::from_string(&s))
46    }
47
48    fn from_string(version_str: &str) -> Option<Version> {
49        use std::str::FromStr;
50        macro_rules! try_opt {
51            ($x: expr) => {
52                match $x {
53                    Some(Ok(x)) => x,
54                    _ => return None,
55                }
56            }
57        }
58
59        let mut nums = version_str.split('.').map(u32::from_str);
60        Some(Version::new(try_opt!(nums.next()), try_opt!(nums.next()), try_opt!(nums.next())))
61    }
62
63    pub fn to_unstable_tool_string(&self) -> String {
64        format!("0.{}{}.{}", self.major, self.minor, self.patch)
65    }
66
67    pub fn to_stable_tool_string(&self) -> String {
68        format!("{}{}.{}.0", self.major, self.minor, self.patch)
69    }
70}
71
72
73pub fn channel() -> Option<&'static str> {
74    option_env!("CFG_RELEASE_CHANNEL")
75}
76
77pub fn commit_hash() -> Option<String> {
78    Command::new("git")
79        .args(&["rev-parse", "--short", "HEAD"])
80        .output()
81        .ok()
82        .and_then(|r| String::from_utf8(r.stdout).ok())
83}
84
85pub fn commit_date() -> Option<String> {
86    Command::new("git")
87        .args(&["log",
88                "-1",
89                "--date=short",
90                "--pretty=format:%cd"])
91        .output()
92        .ok()
93        .and_then(|r| String::from_utf8(r.stdout).ok())
94}
95
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn test_formatting() {
103        let v = Version::new(1, 2, 3);
104        assert_eq!(&v.to_string(), "1.2.3");
105        assert_eq!(&v.to_unstable_tool_string(), "0.12.3");
106        assert_eq!(&v.to_stable_tool_string(), "12.3.0");
107    }
108
109    #[test]
110    fn test_from_str() {
111        assert_eq!(Version::from_string("0.0"), None);
112        assert_eq!(Version::from_string("0.0.a"), None);
113        assert_eq!(Version::from_string("0.."), None);
114        assert_eq!(Version::from_string("0.0.0"), Some(Version::new(0, 0, 0)));
115        assert_eq!(Version::from_string("3.2.1"), Some(Version::new(3, 2, 1)));
116    }
117}