Bug 1716518 - Upgrade version_check to v0.9.3.

Differential Revision: https://phabricator.services.mozilla.com/D117877

Depends on D117876
This commit is contained in:
Mike Hommey 2021-06-15 09:26:05 +00:00
parent 2a170b50e8
commit cd01eda2ee
5 changed files with 233 additions and 75 deletions

4
Cargo.lock generated
View File

@ -5502,9 +5502,9 @@ checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa"
[[package]]
name = "version_check"
version = "0.9.1"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "viaduct"

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"8e79e76a669227ea5f61530ad74ea835434efb34b3143dd8afe7fbd327e1f8f9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"b7e650f3fce5c53249d1cdc608b54df156a97edd636cf9d23498d0cfe7aec63e","README.md":"d45a7a97623a56bf9cb7766976c3807312f7d4ac0cfaf4563ff76bc4d6ad1835","src/channel.rs":"f916ece9beeb7f3d512b423ae6da05d45f284bf42ddf7c14f80b77398d52dac7","src/date.rs":"d31e158a2b49f81da512150c5c93194655dac4114825e285fe2f688c09b001a4","src/lib.rs":"a15eb43cec1acfb0db42e8f93bdf70246ebceb1684ac39496bd28184722e4480","src/version.rs":"7022a20252f8beee0833f5d4f67b863e2f10963a24010e1300cb6603bcb7d514"},"package":"078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce"}
{"files":{"Cargo.toml":"cdbd085c15dcc87659d93787caa5faf9017be5fd8538c7813ccd0bb3284485d6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"b7e650f3fce5c53249d1cdc608b54df156a97edd636cf9d23498d0cfe7aec63e","README.md":"d45a7a97623a56bf9cb7766976c3807312f7d4ac0cfaf4563ff76bc4d6ad1835","src/channel.rs":"f916ece9beeb7f3d512b423ae6da05d45f284bf42ddf7c14f80b77398d52dac7","src/date.rs":"d31e158a2b49f81da512150c5c93194655dac4114825e285fe2f688c09b001a4","src/lib.rs":"61e2d430a282d6fb26e709d7c5d94fe16f62d210efce9d2e3e3092b71eacb639","src/version.rs":"81503116d2d65968edeec37a0e9797a569ac5cafec13ca61bd631b11948ab7ac"},"package":"5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"}

View File

@ -12,7 +12,7 @@
[package]
name = "version_check"
version = "0.9.1"
version = "0.9.3"
authors = ["Sergio Benitez <sb@sergio.bz>"]
description = "Tiny crate to check the version of the installed/running rustc."
documentation = "https://docs.rs/version_check/"

View File

@ -93,13 +93,33 @@ fn version_and_date_from_rustc_version(s: &str) -> (Option<String>, Option<Strin
(version.map(|s| s.to_string()), date.map(|s| s.to_string()))
}
/// Parses (version, date) as available from rustc verbose version output.
fn version_and_date_from_rustc_verbose_version(s: &str) -> (Option<String>, Option<String>) {
let (mut version, mut date) = (None, None);
for line in s.lines() {
let split = |s: &str| s.splitn(2, ":").nth(1).map(|s| s.trim().to_string());
match line.trim().split(" ").nth(0) {
Some("rustc") => {
let (v, d) = version_and_date_from_rustc_version(line);
version = version.or(v);
date = date.or(d);
},
Some("release:") => version = split(line),
Some("commit-date:") if line.ends_with("unknown") => date = None,
Some("commit-date:") => date = split(line),
_ => continue
}
}
(version, date)
}
/// Returns (version, date) as available from `rustc --version`.
fn get_version_and_date() -> Option<(Option<String>, Option<String>)> {
env::var("RUSTC").ok()
.and_then(|rustc| Command::new(rustc).arg("--version").output().ok())
.or_else(|| Command::new("rustc").arg("--version").output().ok())
let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string());
Command::new(rustc).arg("--verbose").arg("--version").output().ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.map(|s| version_and_date_from_rustc_version(&s))
.map(|s| version_and_date_from_rustc_verbose_version(&s))
}
/// Reads the triple of [`Version`], [`Channel`], and [`Date`] of the installed
@ -237,52 +257,112 @@ pub fn is_feature_flaggable() -> Option<bool> {
#[cfg(test)]
mod tests {
use super::version_and_date_from_rustc_version;
use super::version_and_date_from_rustc_verbose_version;
macro_rules! check_parse {
($s:expr => $v:expr, $d:expr) => (
if let (Some(v), d) = version_and_date_from_rustc_version($s) {
(@ $f:expr, $s:expr => $v:expr, $d:expr) => ({
if let (Some(v), d) = $f($s) {
let e_d: Option<&str> = $d.into();
assert_eq!((v, d), ($v.into(), e_d.map(|s| s.into())));
} else {
panic!("{:?} didn't parse for version testing.", $s);
}
)
});
($f:expr, $s:expr => $v:expr, $d:expr) => ({
let warn = "warning: invalid logging spec 'warning', ignoring it";
let warn2 = "warning: sorry, something went wrong :(sad)";
check_parse!(@ $f, $s => $v, $d);
check_parse!(@ $f, &format!("{}\n{}", warn, $s) => $v, $d);
check_parse!(@ $f, &format!("{}\n{}", warn2, $s) => $v, $d);
check_parse!(@ $f, &format!("{}\n{}\n{}", warn, warn2, $s) => $v, $d);
check_parse!(@ $f, &format!("{}\n{}\n{}", warn2, warn, $s) => $v, $d);
})
}
macro_rules! check_terse_parse {
($($s:expr => $v:expr, $d:expr,)+) => {$(
check_parse!(version_and_date_from_rustc_version, $s => $v, $d);
)+}
}
macro_rules! check_verbose_parse {
($($s:expr => $v:expr, $d:expr,)+) => {$(
check_parse!(version_and_date_from_rustc_verbose_version, $s => $v, $d);
)+}
}
#[test]
fn test_version_parse() {
check_parse!("rustc 1.18.0" => "1.18.0", None);
check_parse!("rustc 1.8.0" => "1.8.0", None);
check_parse!("rustc 1.20.0-nightly" => "1.20.0-nightly", None);
check_parse!("rustc 1.20" => "1.20", None);
check_parse!("rustc 1.3" => "1.3", None);
check_parse!("rustc 1" => "1", None);
check_parse!("rustc 1.5.1-beta" => "1.5.1-beta", None);
check_terse_parse! {
"rustc 1.18.0" => "1.18.0", None,
"rustc 1.8.0" => "1.8.0", None,
"rustc 1.20.0-nightly" => "1.20.0-nightly", None,
"rustc 1.20" => "1.20", None,
"rustc 1.3" => "1.3", None,
"rustc 1" => "1", None,
"rustc 1.5.1-beta" => "1.5.1-beta", None,
"rustc 1.20.0 (2017-07-09)" => "1.20.0", Some("2017-07-09"),
"rustc 1.20.0-dev (2017-07-09)" => "1.20.0-dev", Some("2017-07-09"),
"rustc 1.20.0-nightly (d84693b93 2017-07-09)" => "1.20.0-nightly", Some("2017-07-09"),
"rustc 1.20.0 (d84693b93 2017-07-09)" => "1.20.0", Some("2017-07-09"),
"rustc 1.30.0-nightly (3bc2ca7e4 2018-09-20)" => "1.30.0-nightly", Some("2018-09-20"),
};
}
// Because of 1.0.0, we can't use Option<T>: From<T>.
check_parse!("rustc 1.20.0 (2017-07-09)"
=> "1.20.0", Some("2017-07-09"));
#[test]
fn test_verbose_version_parse() {
check_verbose_parse! {
"rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)\n\
binary: rustc\n\
commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e\n\
commit-date: 2015-05-13\n\
build-date: 2015-05-14\n\
host: x86_64-unknown-linux-gnu\n\
release: 1.0.0" => "1.0.0", Some("2015-05-13"),
check_parse!("rustc 1.20.0-dev (2017-07-09)"
=> "1.20.0-dev", Some("2017-07-09"));
"rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)\n\
commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e\n\
commit-date: 2015-05-13\n\
build-date: 2015-05-14\n\
host: x86_64-unknown-linux-gnu\n\
release: 1.0.0" => "1.0.0", Some("2015-05-13"),
check_parse!("rustc 1.20.0-nightly (d84693b93 2017-07-09)"
=> "1.20.0-nightly", Some("2017-07-09"));
"rustc 1.50.0 (cb75ad5db 2021-02-10)\n\
binary: rustc\n\
commit-hash: cb75ad5db02783e8b0222fee363c5f63f7e2cf5b\n\
commit-date: 2021-02-10\n\
host: x86_64-unknown-linux-gnu\n\
release: 1.50.0" => "1.50.0", Some("2021-02-10"),
check_parse!("rustc 1.20.0 (d84693b93 2017-07-09)"
=> "1.20.0", Some("2017-07-09"));
"rustc 1.52.0-nightly (234781afe 2021-03-07)\n\
binary: rustc\n\
commit-hash: 234781afe33d3f339b002f85f948046d8476cfc9\n\
commit-date: 2021-03-07\n\
host: x86_64-unknown-linux-gnu\n\
release: 1.52.0-nightly\n\
LLVM version: 12.0.0" => "1.52.0-nightly", Some("2021-03-07"),
check_parse!("warning: invalid logging spec 'warning', ignoring it
rustc 1.30.0-nightly (3bc2ca7e4 2018-09-20)"
=> "1.30.0-nightly", Some("2018-09-20"));
"rustc 1.41.1\n\
binary: rustc\n\
commit-hash: unknown\n\
commit-date: unknown\n\
host: x86_64-unknown-linux-gnu\n\
release: 1.41.1\n\
LLVM version: 7.0" => "1.41.1", None,
check_parse!("warning: invalid logging spec 'warning', ignoring it\n
rustc 1.30.0-nightly (3bc2ca7e4 2018-09-20)"
=> "1.30.0-nightly", Some("2018-09-20"));
"rustc 1.49.0\n\
binary: rustc\n\
commit-hash: unknown\n\
commit-date: unknown\n\
host: x86_64-unknown-linux-gnu\n\
release: 1.49.0" => "1.49.0", None,
check_parse!("warning: invalid logging spec 'warning', ignoring it
warning: something else went wrong
rustc 1.30.0-nightly (3bc2ca7e4 2018-09-20)"
=> "1.30.0-nightly", Some("2018-09-20"));
"rustc 1.50.0 (Fedora 1.50.0-1.fc33)\n\
binary: rustc\n\
commit-hash: unknown\n\
commit-date: unknown\n\
host: x86_64-unknown-linux-gnu\n\
release: 1.50.0" => "1.50.0", None,
};
}
}

View File

@ -1,17 +1,10 @@
use std::fmt;
/// Version number: `major.minor.patch`, ignoring release channel.
#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
#[derive(PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
pub struct Version(u64);
impl Version {
fn to_mmp(&self) -> (u16, u16, u16) {
let major = self.0 >> 32;
let minor = (self.0 << 32) >> 48;
let patch = (self.0 << 48) >> 48;
(major as u16, minor as u16, patch as u16)
}
/// Reads the version of the running compiler. If it cannot be determined
/// (see the [top-level documentation](crate)), returns `None`.
///
@ -55,25 +48,64 @@ impl Version {
/// assert!(version.exactly("1.0.0"));
///
/// assert!(Version::parse("one.two.three").is_none());
/// assert!(Version::parse("1.65536.2").is_none());
/// assert!(Version::parse("1. 2").is_none());
/// assert!(Version::parse("").is_none());
/// assert!(Version::parse("1.").is_none());
/// assert!(Version::parse("1.2.3.4").is_none());
/// ```
pub fn parse(version: &str) -> Option<Version> {
let mut mmp: Vec<u16> = version.split('-')
let splits = version.split('-')
.nth(0)
.unwrap_or("")
.split('.')
.filter_map(|s| s.parse::<u16>().ok())
.collect();
.map(|s| s.parse::<u16>().ok());
if mmp.is_empty() {
return None
let mut mmp = [0u16; 3];
for (i, split) in splits.enumerate() {
mmp[i] = match (i, split) {
(3, _) | (_, None) => return None,
(_, Some(v)) => v,
};
}
while mmp.len() < 3 {
mmp.push(0);
}
let (maj, min, patch) = (mmp[0], mmp[1], mmp[2]);
Some(Version::from_mmp(maj, min, patch))
}
let (maj, min, patch) = (mmp[0] as u64, mmp[1] as u64, mmp[2] as u64);
Some(Version((maj << 32) | (min << 16) | patch))
/// Creates a `Version` from `(major, minor, patch)` version components.
///
/// # Example
///
/// ```rust
/// use version_check::Version;
///
/// assert!(Version::from_mmp(1, 35, 0).exactly("1.35.0"));
/// assert!(Version::from_mmp(1, 33, 0).exactly("1.33.0"));
/// assert!(Version::from_mmp(1, 35, 1).exactly("1.35.1"));
/// assert!(Version::from_mmp(1, 13, 2).exactly("1.13.2"));
/// ```
pub fn from_mmp(major: u16, minor: u16, patch: u16) -> Version {
Version(((major as u64) << 32) | ((minor as u64) << 16) | patch as u64)
}
/// Returns the `(major, minor, patch)` version components of `self`.
///
/// # Example
///
/// ```rust
/// use version_check::Version;
///
/// assert_eq!(Version::parse("1.35.0").unwrap().to_mmp(), (1, 35, 0));
/// assert_eq!(Version::parse("1.33.0").unwrap().to_mmp(), (1, 33, 0));
/// assert_eq!(Version::parse("1.35.1").unwrap().to_mmp(), (1, 35, 1));
/// assert_eq!(Version::parse("1.13.2").unwrap().to_mmp(), (1, 13, 2));
/// ```
pub fn to_mmp(&self) -> (u16, u16, u16) {
let major = self.0 >> 32;
let minor = (self.0 << 32) >> 48;
let patch = (self.0 << 48) >> 48;
(major as u16, minor as u16, patch as u16)
}
/// Returns `true` if `self` is greater than or equal to `version`.
@ -94,6 +126,11 @@ impl Version {
///
/// assert!(!version.at_least("1.35.1"));
/// assert!(!version.at_least("1.55.0"));
///
/// let version = Version::parse("1.12.5").unwrap();
///
/// assert!(version.at_least("1.12.0"));
/// assert!(!version.at_least("1.35.0"));
/// ```
pub fn at_least(&self, version: &str) -> bool {
Version::parse(version)
@ -158,35 +195,76 @@ impl fmt::Display for Version {
}
}
impl fmt::Debug for Version {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// We don't use `debug_*` because it's not available in `1.0.0`.
write!(f, "Version({:?}, {:?})", self.0, self.to_mmp())
}
}
#[cfg(test)]
mod tests {
use super::Version;
macro_rules! check_mmp {
($s:expr => ($x:expr, $y:expr, $z:expr)) => (
if let Some(v) = Version::parse($s) {
if v.to_mmp() != ($x, $y, $z) {
panic!("{:?} ({}) didn't parse as {}.{}.{}.", $s, v, $x, $y, $z);
}
} else {
panic!("{:?} didn't parse for mmp testing.", $s);
}
macro_rules! assert_to_mmp {
// We don't use `.into::<Option<_>>` because it's not available in 1.0.
// We don't use the message part of `assert!` for the same reason.
($s:expr, None) => (
assert_eq!(Version::parse($s), None);
);
($s:expr, $mmp:expr) => (
assert_eq!(Version::parse($s).map(|v| v.to_mmp()), Some($mmp));
)
}
macro_rules! assert_from_mmp {
(($x:expr, $y:expr, $z:expr) => $s:expr) => {
assert_eq!(Some(Version::from_mmp($x, $y, $z)), Version::parse($s));
};
}
#[test]
fn test_str_to_mmp() {
check_mmp!("1.18.0" => (1, 18, 0));
check_mmp!("3.19.0" => (3, 19, 0));
check_mmp!("1.19.0-nightly" => (1, 19, 0));
check_mmp!("1.12.2349" => (1, 12, 2349));
check_mmp!("0.12" => (0, 12, 0));
check_mmp!("1.12.5" => (1, 12, 5));
check_mmp!("1.12" => (1, 12, 0));
check_mmp!("1" => (1, 0, 0));
check_mmp!("1.4.4-nightly (d84693b93 2017-07-09)" => (1, 4, 4));
check_mmp!("1.58879.4478-dev" => (1, 58879, 4478));
check_mmp!("1.58879.4478-dev (d84693b93 2017-07-09)" => (1, 58879, 4478));
assert_to_mmp!("1", (1, 0, 0));
assert_to_mmp!("1.2", (1, 2, 0));
assert_to_mmp!("1.18.0", (1, 18, 0));
assert_to_mmp!("3.19.0", (3, 19, 0));
assert_to_mmp!("1.19.0-nightly", (1, 19, 0));
assert_to_mmp!("1.12.2349", (1, 12, 2349));
assert_to_mmp!("0.12", (0, 12, 0));
assert_to_mmp!("1.12.5", (1, 12, 5));
assert_to_mmp!("1.12", (1, 12, 0));
assert_to_mmp!("1", (1, 0, 0));
assert_to_mmp!("1.4.4-nightly (d84693b93 2017-07-09))", (1, 4, 4));
assert_to_mmp!("1.58879.4478-dev", (1, 58879, 4478));
assert_to_mmp!("1.58879.4478-dev (d84693b93 2017-07-09))", (1, 58879, 4478));
}
#[test]
fn test_malformed() {
assert_to_mmp!("1.65536.2", None);
assert_to_mmp!("-1.2.3", None);
assert_to_mmp!("1. 2", None);
assert_to_mmp!("", None);
assert_to_mmp!(" ", None);
assert_to_mmp!(".", None);
assert_to_mmp!("one", None);
assert_to_mmp!("1.", None);
assert_to_mmp!("1.2.3.4.5.6", None);
}
#[test]
fn test_from_mmp() {
assert_from_mmp!((1, 18, 0) => "1.18.0");
assert_from_mmp!((3, 19, 0) => "3.19.0");
assert_from_mmp!((1, 19, 0) => "1.19.0");
assert_from_mmp!((1, 12, 2349) => "1.12.2349");
assert_from_mmp!((0, 12, 0) => "0.12");
assert_from_mmp!((1, 12, 5) => "1.12.5");
assert_from_mmp!((1, 12, 0) => "1.12");
assert_from_mmp!((1, 0, 0) => "1");
assert_from_mmp!((1, 4, 4) => "1.4.4");
assert_from_mmp!((1, 58879, 4478) => "1.58879.4478");
}
#[test]