hglib/commands/
version.rs

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 file,
3// You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use regex::bytes::Regex;
6
7use crate::client::{Client, HglibError, Runner};
8use crate::{runcommand, MkArg};
9
10pub struct Arg {}
11
12impl Default for Arg {
13    fn default() -> Self {
14        Self {}
15    }
16}
17
18impl Arg {
19    fn run(&self, client: &mut Client) -> Result<(Vec<u8>, i32), HglibError> {
20        runcommand!(client, "version", &[""], "-q", true)
21    }
22}
23
24#[derive(Debug, PartialEq, Eq)]
25pub struct Version {
26    pub major: u32,
27    pub minor: u32,
28    pub micro: Option<u32>,
29    pub build_info: Option<String>,
30}
31
32impl Ord for Version {
33    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
34        for c in &[self.major.cmp(&other.major), self.minor.cmp(&other.minor)] {
35            if c != &std::cmp::Ordering::Equal {
36                return *c;
37            }
38        }
39
40        match (self.micro, other.micro) {
41            (None, None) => std::cmp::Ordering::Equal,
42            (Some(x), None) => x.cmp(&0),
43            (None, Some(y)) => 0.cmp(&y),
44            (Some(x), Some(y)) => x.cmp(&y),
45        }
46    }
47}
48
49impl PartialOrd for Version {
50    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
51        Some(self.cmp(other))
52    }
53}
54
55impl Version {
56    pub fn from_tuple(v: &(u32, u32, Option<u32>)) -> Version {
57        Version {
58            major: v.0,
59            minor: v.1,
60            micro: v.2,
61            build_info: None,
62        }
63    }
64}
65
66impl PartialEq<(u32, u32, Option<u32>)> for Version {
67    fn eq(&self, other: &(u32, u32, Option<u32>)) -> bool {
68        self == &Version::from_tuple(other)
69    }
70}
71
72impl PartialOrd<(u32, u32, Option<u32>)> for Version {
73    fn partial_cmp(&self, other: &(u32, u32, Option<u32>)) -> Option<std::cmp::Ordering> {
74        Some(self.cmp(&Version::from_tuple(other)))
75    }
76}
77
78impl Client {
79    pub fn version(&mut self, x: Arg) -> Result<Version, HglibError> {
80        let (data, _) = x.run(self)?;
81        let pat = Regex::new(r".*?(\d+)\.(\d+)\.?(\d+)?(\+[0-9a-f-]+)?").unwrap();
82        let cap = pat.captures_iter(&data).next().unwrap();
83
84        let micro = if let Some(buf) = cap.get(3) {
85            Some(
86                buf.as_bytes()
87                    .iter()
88                    .fold(0, |r, x| r * 10 + u32::from(*x - b'0')),
89            )
90        } else {
91            None
92        };
93
94        let build_info = if let Some(buf) = cap.get(4) {
95            Some(String::from_utf8(buf.as_bytes().to_vec())?)
96        } else {
97            None
98        };
99
100        Ok(Version {
101            major: cap[1].iter().fold(0, |r, x| r * 10 + u32::from(*x - b'0')),
102            minor: cap[2].iter().fold(0, |r, x| r * 10 + u32::from(*x - b'0')),
103            micro,
104            build_info,
105        })
106    }
107}