1use std::process::Command;
2use std::str;
3
4use super::{error, Error};
5
6/// A version structure for making relative comparisons.
7#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
8pub struct Version {
9 major: usize,
10 minor: usize,
11 patch: usize,
12}
13
14impl Version {
15 /// Creates a `Version` instance for a specific `major.minor.patch` version.
16 pub fn new(major: usize, minor: usize, patch: usize) -> Self {
17 Version {
18 major: major,
19 minor: minor,
20 patch: patch,
21 }
22 }
23
24 pub fn from_command(command: &mut Command) -> Result<Self, Error> {
25 // Get rustc's verbose version
26 let output = try!(command
27 .args(&["--version", "--verbose"])
28 .output()
29 .map_err(error::from_io));
30 if !output.status.success() {
31 return Err(error::from_str("could not execute rustc"));
32 }
33 let output = try!(str::from_utf8(&output.stdout).map_err(error::from_utf8));
34
35 // Find the release line in the verbose version output.
36 let release = match output.lines().find(|line| line.starts_with("release: ")) {
37 Some(line) => &line["release: ".len()..],
38 None => return Err(error::from_str("could not find rustc release")),
39 };
40
41 // Strip off any extra channel info, e.g. "-beta.N", "-nightly"
42 let version = match release.find('-') {
43 Some(i) => &release[..i],
44 None => release,
45 };
46
47 // Split the version into semver components.
48 let mut iter = version.splitn(3, '.');
49 let major = try!(iter
50 .next()
51 .ok_or_else(|| error::from_str("missing major version")));
52 let minor = try!(iter
53 .next()
54 .ok_or_else(|| error::from_str("missing minor version")));
55 let patch = try!(iter
56 .next()
57 .ok_or_else(|| error::from_str("missing patch version")));
58
59 Ok(Version::new(
60 try!(major.parse().map_err(error::from_num)),
61 try!(minor.parse().map_err(error::from_num)),
62 try!(patch.parse().map_err(error::from_num)),
63 ))
64 }
65}
66

Provided by KDAB

Privacy Policy
Learn Rust with the experts
Find out more