mirror of
https://gitee.com/openharmony/third_party_rust_version_check
synced 2024-11-22 23:40:02 +00:00
New version: 0.9.
This commit is contained in:
parent
96a6d6ccbe
commit
98871bdc8e
6
.travis.yml
Normal file
6
.travis.yml
Normal file
@ -0,0 +1,6 @@
|
||||
language: rust
|
||||
rust:
|
||||
- 1.0.0
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "version_check"
|
||||
version = "0.1.5"
|
||||
version = "0.9.0"
|
||||
authors = ["Sergio Benitez <sb@sergio.bz>"]
|
||||
description = "Tiny crate to check the version of the installed/running rustc."
|
||||
documentation = "https://docs.rs/version_check/"
|
||||
|
61
README.md
61
README.md
@ -1,5 +1,9 @@
|
||||
# version\_check
|
||||
|
||||
[![Build Status](https://travis-ci.com/SergioBenitez/version_check.svg?branch=master)](https://travis-ci.com/SergioBenitez/version_check)
|
||||
[![Current Crates.io Version](https://img.shields.io/crates/v/version_check.svg)](https://crates.io/crates/version_check)
|
||||
[![rustdocs on docs.rs](https://docs.rs/version_check/badge.svg)](https://docs.rs/version_check)
|
||||
|
||||
This tiny crate checks that the running or installed `rustc` meets some version
|
||||
requirements. The version is queried by calling the Rust compiler with
|
||||
`--version`. The path to the compiler is determined first via the `RUSTC`
|
||||
@ -12,54 +16,57 @@ Add to your `Cargo.toml` file, typically as a build dependency:
|
||||
|
||||
```toml
|
||||
[build-dependencies]
|
||||
version_check = "0.1"
|
||||
version_check = "0.9"
|
||||
```
|
||||
|
||||
`version_check` is compatible and compiles with Rust 1.0.0 and beyond.
|
||||
|
||||
## Examples
|
||||
|
||||
Check that the running compiler is a nightly release:
|
||||
Set a `cfg` flag in `build.rs` if the running compiler was determined to be
|
||||
at least version `1.13.0`:
|
||||
|
||||
```rust
|
||||
extern crate version_check;
|
||||
extern crate version_check as rustc;
|
||||
|
||||
match version_check::is_nightly() {
|
||||
Some(true) => "running a nightly",
|
||||
Some(false) => "not nightly",
|
||||
None => "couldn't figure it out"
|
||||
if rustc::is_min_version("1.13.0").unwrap_or(false) {
|
||||
println!("cargo:rustc-cfg=question_mark_operator");
|
||||
}
|
||||
```
|
||||
|
||||
Check that the running compiler was released on or after `2018-12-18`:
|
||||
|
||||
```rust
|
||||
extern crate version_check as rustc;
|
||||
|
||||
match rustc::is_min_date("2018-12-18") {
|
||||
Some(true) => "Yep! It's recent!",
|
||||
Some(false) => "No, it's older.",
|
||||
None => "Couldn't determine the rustc version."
|
||||
};
|
||||
```
|
||||
|
||||
Check that the running compiler is at least version `1.13.0`:
|
||||
Check that the running compiler supports feature flags:
|
||||
|
||||
```rust
|
||||
extern crate version_check;
|
||||
extern crate version_check as rustc;
|
||||
|
||||
match version_check::is_min_version("1.13.0") {
|
||||
Some((true, version)) => format!("Yes! It's: {}", version),
|
||||
Some((false, version)) => format!("No! {} is too old!", version),
|
||||
None => "couldn't figure it out".into()
|
||||
match rustc::is_feature_flaggable() {
|
||||
Some(true) => "Yes! It's a dev or nightly release!",
|
||||
Some(false) => "No, it's stable or beta.",
|
||||
None => "Couldn't determine the rustc version."
|
||||
};
|
||||
```
|
||||
|
||||
Check that the running compiler was released on or after `2016-12-18`:
|
||||
|
||||
```rust
|
||||
extern crate version_check;
|
||||
|
||||
match version_check::is_min_date("2016-12-18") {
|
||||
Some((true, date)) => format!("Yes! It's: {}", date),
|
||||
Some((false, date)) => format!("No! {} is too long ago!", date),
|
||||
None => "couldn't figure it out".into()
|
||||
};
|
||||
```
|
||||
See the [rustdocs](https://docs.rs/version_check) for more examples and complete
|
||||
documentation.
|
||||
|
||||
## Alternatives
|
||||
|
||||
This crate is dead simple with no dependencies. If you need something more and
|
||||
don't care about panicking if the version cannot be obtained or adding
|
||||
dependencies, see [rustc_version](https://crates.io/crates/rustc_version).
|
||||
This crate is dead simple with no dependencies. If you need something more
|
||||
and don't care about panicking if the version cannot be obtained, or if you
|
||||
don't mind adding dependencies, see
|
||||
[rustc_version](https://crates.io/crates/rustc_version).
|
||||
|
||||
## License
|
||||
|
||||
|
192
src/channel.rs
Normal file
192
src/channel.rs
Normal file
@ -0,0 +1,192 @@
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
enum Kind {
|
||||
Dev,
|
||||
Nightly,
|
||||
Beta,
|
||||
Stable,
|
||||
}
|
||||
|
||||
/// Release channel: "dev", "nightly", "beta", or "stable".
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub struct Channel(Kind);
|
||||
|
||||
impl Channel {
|
||||
/// Reads the release channel of the running compiler. If it cannot be
|
||||
/// determined (see the [top-level documentation](crate)), returns `None`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Channel;
|
||||
///
|
||||
/// match Channel::read() {
|
||||
/// Some(c) => format!("The channel is: {}", c),
|
||||
/// None => format!("Failed to read the release channel.")
|
||||
/// };
|
||||
/// ```
|
||||
pub fn read() -> Option<Channel> {
|
||||
::get_version_and_date()
|
||||
.and_then(|(version, _)| version)
|
||||
.and_then(|version| Channel::parse(&version))
|
||||
}
|
||||
|
||||
/// Parse a Rust release channel from a Rust release version string (of the
|
||||
/// form `major[.minor[.patch[-channel]]]`). Returns `None` if `version` is
|
||||
/// not a valid Rust version string.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Channel;
|
||||
///
|
||||
/// let dev = Channel::parse("1.3.0-dev").unwrap();
|
||||
/// assert!(dev.is_dev());
|
||||
///
|
||||
/// let nightly = Channel::parse("1.42.2-nightly").unwrap();
|
||||
/// assert!(nightly.is_nightly());
|
||||
///
|
||||
/// let beta = Channel::parse("1.32.0-beta").unwrap();
|
||||
/// assert!(beta.is_beta());
|
||||
///
|
||||
/// let stable = Channel::parse("1.4.0").unwrap();
|
||||
/// assert!(stable.is_stable());
|
||||
/// ```
|
||||
pub fn parse(version: &str) -> Option<Channel> {
|
||||
if version.contains("-dev") {
|
||||
Some(Channel(Kind::Dev))
|
||||
} else if version.contains("-nightly") {
|
||||
Some(Channel(Kind::Nightly))
|
||||
} else if version.contains("-beta") {
|
||||
Some(Channel(Kind::Beta))
|
||||
} else if !version.contains("-") {
|
||||
Some(Channel(Kind::Stable))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name of the release channel.
|
||||
fn as_str(&self) -> &'static str {
|
||||
match self.0 {
|
||||
Kind::Dev => "dev",
|
||||
Kind::Beta => "beta",
|
||||
Kind::Nightly => "nightly",
|
||||
Kind::Stable => "stable",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this channel supports feature flags. In other words,
|
||||
/// returns `true` if the channel is either `dev` or `nightly`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Channel;
|
||||
///
|
||||
/// let dev = Channel::parse("1.3.0-dev").unwrap();
|
||||
/// assert!(dev.supports_features());
|
||||
///
|
||||
/// let nightly = Channel::parse("1.42.2-nightly").unwrap();
|
||||
/// assert!(nightly.supports_features());
|
||||
///
|
||||
/// let beta = Channel::parse("1.32.0-beta").unwrap();
|
||||
/// assert!(!beta.supports_features());
|
||||
///
|
||||
/// let stable = Channel::parse("1.4.0").unwrap();
|
||||
/// assert!(!stable.supports_features());
|
||||
/// ```
|
||||
pub fn supports_features(&self) -> bool {
|
||||
match self.0 {
|
||||
Kind::Dev | Kind::Nightly => true,
|
||||
Kind::Beta | Kind::Stable => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this channel is `dev` and `false` otherwise.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Channel;
|
||||
///
|
||||
/// let dev = Channel::parse("1.3.0-dev").unwrap();
|
||||
/// assert!(dev.is_dev());
|
||||
///
|
||||
/// let stable = Channel::parse("1.0.0").unwrap();
|
||||
/// assert!(!stable.is_dev());
|
||||
/// ```
|
||||
pub fn is_dev(&self) -> bool {
|
||||
match self.0 {
|
||||
Kind::Dev => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this channel is `nightly` and `false` otherwise.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Channel;
|
||||
///
|
||||
/// let nightly = Channel::parse("1.3.0-nightly").unwrap();
|
||||
/// assert!(nightly.is_nightly());
|
||||
///
|
||||
/// let stable = Channel::parse("1.0.0").unwrap();
|
||||
/// assert!(!stable.is_nightly());
|
||||
/// ```
|
||||
pub fn is_nightly(&self) -> bool {
|
||||
match self.0 {
|
||||
Kind::Nightly => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this channel is `beta` and `false` otherwise.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Channel;
|
||||
///
|
||||
/// let beta = Channel::parse("1.3.0-beta").unwrap();
|
||||
/// assert!(beta.is_beta());
|
||||
///
|
||||
/// let stable = Channel::parse("1.0.0").unwrap();
|
||||
/// assert!(!stable.is_beta());
|
||||
/// ```
|
||||
pub fn is_beta(&self) -> bool {
|
||||
match self.0 {
|
||||
Kind::Beta => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this channel is `stable` and `false` otherwise.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Channel;
|
||||
///
|
||||
/// let stable = Channel::parse("1.0.0").unwrap();
|
||||
/// assert!(stable.is_stable());
|
||||
///
|
||||
/// let beta = Channel::parse("1.3.0-beta").unwrap();
|
||||
/// assert!(!beta.is_stable());
|
||||
/// ```
|
||||
pub fn is_stable(&self) -> bool {
|
||||
match self.0 {
|
||||
Kind::Stable => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Channel {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
146
src/date.rs
Normal file
146
src/date.rs
Normal file
@ -0,0 +1,146 @@
|
||||
use std::fmt;
|
||||
|
||||
/// Release date including year, month, and day.
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
|
||||
pub struct Date(u32);
|
||||
|
||||
impl Date {
|
||||
/// Reads the release date of the running compiler. If it cannot be
|
||||
/// determined (see the [top-level documentation](crate)), returns `None`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Date;
|
||||
///
|
||||
/// match Date::read() {
|
||||
/// Some(d) => format!("The release date is: {}", d),
|
||||
/// None => format!("Failed to read the release date.")
|
||||
/// };
|
||||
/// ```
|
||||
pub fn read() -> Option<Date> {
|
||||
::get_version_and_date()
|
||||
.and_then(|(_, date)| date)
|
||||
.and_then(|date| Date::parse(&date))
|
||||
}
|
||||
|
||||
/// Return the original (YYYY, MM, DD).
|
||||
fn to_ymd(&self) -> (u8, u8, u8) {
|
||||
let y = self.0 >> 9;
|
||||
let m = (self.0 << 23) >> 28;
|
||||
let d = (self.0 << 27) >> 27;
|
||||
(y as u8, m as u8, d as u8)
|
||||
}
|
||||
|
||||
/// Parse a release date of the form `%Y-%m-%d`. Returns `None` if `date` is
|
||||
/// not in `%Y-%m-%d` format.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Date;
|
||||
///
|
||||
/// let date = Date::parse("2016-04-20").unwrap();
|
||||
///
|
||||
/// assert!(date.at_least("2016-01-10"));
|
||||
/// assert!(date.at_most("2016-04-20"));
|
||||
/// assert!(date.exactly("2016-04-20"));
|
||||
///
|
||||
/// assert!(Date::parse("March 13, 2018").is_none());
|
||||
/// assert!(Date::parse("1-2-3-4-5").is_none());
|
||||
/// ```
|
||||
pub fn parse(date: &str) -> Option<Date> {
|
||||
let ymd: Vec<u32> = date.split("-")
|
||||
.filter_map(|s| s.parse::<u32>().ok())
|
||||
.collect();
|
||||
|
||||
if ymd.len() != 3 {
|
||||
return None
|
||||
}
|
||||
|
||||
let (y, m, d) = (ymd[0], ymd[1], ymd[2]);
|
||||
Some(Date((y << 9) | (m << 5) | d))
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` occurs on or after `date`.
|
||||
///
|
||||
/// If `date` occurs before `self`, or if `date` is not in `%Y-%m-%d`
|
||||
/// format, returns `false`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Date;
|
||||
///
|
||||
/// let date = Date::parse("2020-01-01").unwrap();
|
||||
///
|
||||
/// assert!(date.at_least("2019-12-31"));
|
||||
/// assert!(date.at_least("2020-01-01"));
|
||||
/// assert!(date.at_least("2014-04-31"));
|
||||
///
|
||||
/// assert!(!date.at_least("2020-01-02"));
|
||||
/// assert!(!date.at_least("2024-08-18"));
|
||||
/// ```
|
||||
pub fn at_least(&self, date: &str) -> bool {
|
||||
Date::parse(date)
|
||||
.map(|date| self >= &date)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` occurs on or before `date`.
|
||||
///
|
||||
/// If `date` occurs after `self`, or if `date` is not in `%Y-%m-%d`
|
||||
/// format, returns `false`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Date;
|
||||
///
|
||||
/// let date = Date::parse("2020-01-01").unwrap();
|
||||
///
|
||||
/// assert!(date.at_most("2020-01-01"));
|
||||
/// assert!(date.at_most("2020-01-02"));
|
||||
/// assert!(date.at_most("2024-08-18"));
|
||||
///
|
||||
/// assert!(!date.at_most("2019-12-31"));
|
||||
/// assert!(!date.at_most("2014-04-31"));
|
||||
/// ```
|
||||
pub fn at_most(&self, date: &str) -> bool {
|
||||
Date::parse(date)
|
||||
.map(|date| self <= &date)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` occurs exactly on `date`.
|
||||
///
|
||||
/// If `date` is not exactly `self`, or if `date` is not in `%Y-%m-%d`
|
||||
/// format, returns `false`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Date;
|
||||
///
|
||||
/// let date = Date::parse("2020-01-01").unwrap();
|
||||
///
|
||||
/// assert!(date.exactly("2020-01-01"));
|
||||
///
|
||||
/// assert!(!date.exactly("2019-12-31"));
|
||||
/// assert!(!date.exactly("2014-04-31"));
|
||||
/// assert!(!date.exactly("2020-01-02"));
|
||||
/// assert!(!date.exactly("2024-08-18"));
|
||||
/// ```
|
||||
pub fn exactly(&self, date: &str) -> bool {
|
||||
Date::parse(date)
|
||||
.map(|date| self == &date)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Date {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let (y, m, d) = self.to_ymd();
|
||||
write!(f, "{}-{}-{}", y, m, d)
|
||||
}
|
||||
}
|
357
src/lib.rs
357
src/lib.rs
@ -4,96 +4,96 @@
|
||||
//! `RUSTC` environment variable. If it is not set, then `rustc` is used. If
|
||||
//! that fails, no determination is made, and calls return `None`.
|
||||
//!
|
||||
//! # Example
|
||||
//! # Examples
|
||||
//!
|
||||
//! Check that the running compiler is a nightly release:
|
||||
//! Set a `cfg` flag in `build.rs` if the running compiler was determined to be
|
||||
//! at least version `1.13.0`:
|
||||
//!
|
||||
//! ```rust
|
||||
//! extern crate version_check;
|
||||
//! extern crate version_check as rustc;
|
||||
//!
|
||||
//! match version_check::is_nightly() {
|
||||
//! Some(true) => "running a nightly",
|
||||
//! Some(false) => "not nightly",
|
||||
//! None => "couldn't figure it out"
|
||||
//! if rustc::is_min_version("1.13.0").unwrap_or(false) {
|
||||
//! println!("cargo:rustc-cfg=question_mark_operator");
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! See [`is_max_version`] or [`is_exact_version`] to check if the compiler
|
||||
//! is _at most_ or _exactly_ a certain version.
|
||||
//!
|
||||
//! Check that the running compiler was released on or after `2018-12-18`:
|
||||
//!
|
||||
//! ```rust
|
||||
//! extern crate version_check as rustc;
|
||||
//!
|
||||
//! match rustc::is_min_date("2018-12-18") {
|
||||
//! Some(true) => "Yep! It's recent!",
|
||||
//! Some(false) => "No, it's older.",
|
||||
//! None => "Couldn't determine the rustc version."
|
||||
//! };
|
||||
//! ```
|
||||
//!
|
||||
//! Check that the running compiler is at least version `1.13.0`:
|
||||
//! See [`is_max_date`] or [`is_exact_date`] to check if the compiler was
|
||||
//! released _prior to_ or _exactly on_ a certain date.
|
||||
//!
|
||||
//! Check that the running compiler supports feature flags:
|
||||
//!
|
||||
//! ```rust
|
||||
//! extern crate version_check;
|
||||
//! extern crate version_check as rustc;
|
||||
//!
|
||||
//! match version_check::is_min_version("1.13.0") {
|
||||
//! Some((true, version)) => format!("Yes! It's: {}", version),
|
||||
//! Some((false, version)) => format!("No! {} is too old!", version),
|
||||
//! None => "couldn't figure it out".into()
|
||||
//! match rustc::is_feature_flaggable() {
|
||||
//! Some(true) => "Yes! It's a dev or nightly release!",
|
||||
//! Some(false) => "No, it's stable or beta.",
|
||||
//! None => "Couldn't determine the rustc version."
|
||||
//! };
|
||||
//! ```
|
||||
//!
|
||||
//! Check that the running compiler was released on or after `2016-12-18`:
|
||||
//! Check that the running compiler is on the stable channel:
|
||||
//!
|
||||
//! ```rust
|
||||
//! extern crate version_check;
|
||||
//! extern crate version_check as rustc;
|
||||
//!
|
||||
//! match version_check::is_min_date("2016-12-18") {
|
||||
//! Some((true, date)) => format!("Yes! It's: {}", date),
|
||||
//! Some((false, date)) => format!("No! {} is too long ago!", date),
|
||||
//! None => "couldn't figure it out".into()
|
||||
//! match rustc::Channel::read() {
|
||||
//! Some(c) if c.is_stable() => format!("Yes! It's stable."),
|
||||
//! Some(c) => format!("No, the channel {} is not stable.", c),
|
||||
//! None => format!("Couldn't determine the rustc version.")
|
||||
//! };
|
||||
//! ```
|
||||
//!
|
||||
//! To interact with the version, release date, and release channel as structs,
|
||||
//! use [`Version`], [`Date`], and [`Channel`], respectively. The [`triple()`]
|
||||
//! function returns all three values efficiently.
|
||||
//!
|
||||
//! # Alternatives
|
||||
//!
|
||||
//! This crate is dead simple with no dependencies. If you need something more
|
||||
//! and don't care about panicking if the version cannot be obtained or adding
|
||||
//! dependencies, see [rustc_version](https://crates.io/crates/rustc_version).
|
||||
//! and don't care about panicking if the version cannot be obtained, or if you
|
||||
//! don't mind adding dependencies, see
|
||||
//! [rustc_version](https://crates.io/crates/rustc_version).
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
mod version;
|
||||
mod channel;
|
||||
mod date;
|
||||
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
|
||||
// Convert a string of %Y-%m-%d to a single u32 maintaining ordering.
|
||||
fn str_to_ymd(ymd: &str) -> Option<u32> {
|
||||
let ymd: Vec<u32> = ymd.split("-").filter_map(|s| s.parse::<u32>().ok()).collect();
|
||||
if ymd.len() != 3 {
|
||||
return None
|
||||
}
|
||||
#[doc(inline)] pub use version::*;
|
||||
#[doc(inline)] pub use channel::*;
|
||||
#[doc(inline)] pub use date::*;
|
||||
|
||||
let (y, m, d) = (ymd[0], ymd[1], ymd[2]);
|
||||
Some((y << 9) | (m << 5) | d)
|
||||
}
|
||||
|
||||
// Convert a string with prefix major-minor-patch to a single u64 maintaining
|
||||
// ordering. Assumes none of the components are > 1048576.
|
||||
fn str_to_mmp(mmp: &str) -> Option<u64> {
|
||||
let mut mmp: Vec<u16> = mmp.split('-')
|
||||
.nth(0)
|
||||
.unwrap_or("")
|
||||
.split('.')
|
||||
.filter_map(|s| s.parse::<u16>().ok())
|
||||
.collect();
|
||||
|
||||
if mmp.is_empty() {
|
||||
return None
|
||||
}
|
||||
|
||||
while mmp.len() < 3 {
|
||||
mmp.push(0);
|
||||
}
|
||||
|
||||
let (maj, min, patch) = (mmp[0] as u64, mmp[1] as u64, mmp[2] as u64);
|
||||
Some((maj << 32) | (min << 16) | patch)
|
||||
}
|
||||
|
||||
/// Returns (version, date) as available.
|
||||
/// Parses (version, date) as available from rustc version string.
|
||||
fn version_and_date_from_rustc_version(s: &str) -> (Option<String>, Option<String>) {
|
||||
let last_line = s.lines().last().unwrap_or(s);
|
||||
let mut components = last_line.trim().split(" ");
|
||||
let version = components.nth(1);
|
||||
let date = components.nth(1).map(|s| s.trim_right().trim_right_matches(")"));
|
||||
let date = components.filter(|c| c.ends_with(')')).next()
|
||||
.map(|s| s.trim_right().trim_right_matches(")").trim_left().trim_left_matches('('));
|
||||
(version.map(|s| s.to_string()), date.map(|s| s.to_string()))
|
||||
}
|
||||
|
||||
/// Returns (version, date) as available.
|
||||
/// 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())
|
||||
@ -102,154 +102,187 @@ fn get_version_and_date() -> Option<(Option<String>, Option<String>)> {
|
||||
.map(|s| version_and_date_from_rustc_version(&s))
|
||||
}
|
||||
|
||||
/// Checks that the running or installed `rustc` was released no earlier than
|
||||
/// Reads the triple of [`Version`], [`Channel`], and [`Date`] of the installed
|
||||
/// or running `rustc`.
|
||||
///
|
||||
/// If any attribute cannot be determined (see the [top-level
|
||||
/// documentation](crate)), returns `None`.
|
||||
///
|
||||
/// To obtain only one of three attributes, use [`Version::read()`],
|
||||
/// [`Channel::read()`], or [`Date::read()`].
|
||||
pub fn triple() -> Option<(Version, Channel, Date)> {
|
||||
let (version_str, date_str) = match get_version_and_date() {
|
||||
Some((Some(version), Some(date))) => (version, date),
|
||||
_ => return None
|
||||
};
|
||||
|
||||
// Can't use `?` or `try!` for `Option` in 1.0.0.
|
||||
match Version::parse(&version_str) {
|
||||
Some(version) => match Channel::parse(&version_str) {
|
||||
Some(channel) => match Date::parse(&date_str) {
|
||||
Some(date) => Some((version, channel, date)),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that the running or installed `rustc` was released **on or after**
|
||||
/// some date.
|
||||
///
|
||||
/// The format of `min_date` must be YYYY-MM-DD. For instance: `2016-12-20` or
|
||||
/// `2017-01-09`.
|
||||
///
|
||||
/// If the date cannot be retrieved or parsed, or if `min_date` could not be
|
||||
/// parsed, returns `None`. Otherwise returns a tuple where the first value is
|
||||
/// `true` if the installed `rustc` is at least from `min_date` and the second
|
||||
/// value is the date (in YYYY-MM-DD) of the installed `rustc`.
|
||||
pub fn is_min_date(min_date: &str) -> Option<(bool, String)> {
|
||||
if let Some((_, Some(actual_date_str))) = get_version_and_date() {
|
||||
str_to_ymd(&actual_date_str)
|
||||
.and_then(|actual| str_to_ymd(min_date).map(|min| (min, actual)))
|
||||
.map(|(min, actual)| (actual >= min, actual_date_str))
|
||||
} else {
|
||||
None
|
||||
/// parsed, returns `None`. Otherwise returns `true` if the installed `rustc`
|
||||
/// was release on or after `min_date` and `false` otherwise.
|
||||
pub fn is_min_date(min_date: &str) -> Option<bool> {
|
||||
match (Date::read(), Date::parse(min_date)) {
|
||||
(Some(rustc_date), Some(min_date)) => Some(rustc_date >= min_date),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that the running or installed `rustc` is at least some minimum
|
||||
/// Checks that the running or installed `rustc` was released **on or before**
|
||||
/// some date.
|
||||
///
|
||||
/// The format of `max_date` must be YYYY-MM-DD. For instance: `2016-12-20` or
|
||||
/// `2017-01-09`.
|
||||
///
|
||||
/// If the date cannot be retrieved or parsed, or if `max_date` could not be
|
||||
/// parsed, returns `None`. Otherwise returns `true` if the installed `rustc`
|
||||
/// was release on or before `max_date` and `false` otherwise.
|
||||
pub fn is_max_date(max_date: &str) -> Option<bool> {
|
||||
match (Date::read(), Date::parse(max_date)) {
|
||||
(Some(rustc_date), Some(max_date)) => Some(rustc_date <= max_date),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that the running or installed `rustc` was released **exactly** on
|
||||
/// some date.
|
||||
///
|
||||
/// The format of `date` must be YYYY-MM-DD. For instance: `2016-12-20` or
|
||||
/// `2017-01-09`.
|
||||
///
|
||||
/// If the date cannot be retrieved or parsed, or if `date` could not be parsed,
|
||||
/// returns `None`. Otherwise returns `true` if the installed `rustc` was
|
||||
/// release on `date` and `false` otherwise.
|
||||
pub fn is_exact_date(date: &str) -> Option<bool> {
|
||||
match (Date::read(), Date::parse(date)) {
|
||||
(Some(rustc_date), Some(date)) => Some(rustc_date == date),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that the running or installed `rustc` is **at least** some minimum
|
||||
/// version.
|
||||
///
|
||||
/// The format of `min_version` is a semantic version: `1.3.0`, `1.15.0-beta`,
|
||||
/// `1.14.0`, `1.16.0-nightly`, etc.
|
||||
///
|
||||
/// If the version cannot be retrieved or parsed, or if `min_version` could not
|
||||
/// be parsed, returns `None`. Otherwise returns a tuple where the first value
|
||||
/// is `true` if the installed `rustc` is at least `min_version` and the second
|
||||
/// value is the version (semantic) of the installed `rustc`.
|
||||
pub fn is_min_version(min_version: &str) -> Option<(bool, String)> {
|
||||
if let Some((Some(actual_version_str), _)) = get_version_and_date() {
|
||||
str_to_mmp(&actual_version_str)
|
||||
.and_then(|actual| str_to_mmp(min_version).map(|min| (min, actual)))
|
||||
.map(|(min, actual)| (actual >= min, actual_version_str))
|
||||
} else {
|
||||
None
|
||||
/// be parsed, returns `None`. Otherwise returns `true` if the installed `rustc`
|
||||
/// is at least `min_version` and `false` otherwise.
|
||||
pub fn is_min_version(min_version: &str) -> Option<bool> {
|
||||
match (Version::read(), Version::parse(min_version)) {
|
||||
(Some(rustc_ver), Some(min_ver)) => Some(rustc_ver >= min_ver),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn version_channel_is(channel: &str) -> Option<bool> {
|
||||
get_version_and_date()
|
||||
.and_then(|(version_str_opt, _)| version_str_opt)
|
||||
.map(|version_str| version_str.contains(channel))
|
||||
}
|
||||
|
||||
/// Determines whether the running or installed `rustc` is on the nightly
|
||||
/// channel.
|
||||
/// Checks that the running or installed `rustc` is **at most** some maximum
|
||||
/// version.
|
||||
///
|
||||
/// If the version could not be determined, returns `None`. Otherwise returns
|
||||
/// `Some(true)` if the running version is a nightly release, and `Some(false)`
|
||||
/// otherwise.
|
||||
pub fn is_nightly() -> Option<bool> {
|
||||
version_channel_is("nightly")
|
||||
}
|
||||
|
||||
/// Determines whether the running or installed `rustc` is on the beta channel.
|
||||
/// The format of `max_version` is a semantic version: `1.3.0`, `1.15.0-beta`,
|
||||
/// `1.14.0`, `1.16.0-nightly`, etc.
|
||||
///
|
||||
/// If the version could not be determined, returns `None`. Otherwise returns
|
||||
/// `Some(true)` if the running version is a beta release, and `Some(false)`
|
||||
/// otherwise.
|
||||
pub fn is_beta() -> Option<bool> {
|
||||
version_channel_is("beta")
|
||||
/// If the version cannot be retrieved or parsed, or if `max_version` could not
|
||||
/// be parsed, returns `None`. Otherwise returns `true` if the installed `rustc`
|
||||
/// is at most `max_version` and `false` otherwise.
|
||||
pub fn is_max_version(max_version: &str) -> Option<bool> {
|
||||
match (Version::read(), Version::parse(max_version)) {
|
||||
(Some(rustc_ver), Some(max_ver)) => Some(rustc_ver <= max_ver),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines whether the running or installed `rustc` is on the dev channel.
|
||||
/// Checks that the running or installed `rustc` is **exactly** some version.
|
||||
///
|
||||
/// If the version could not be determined, returns `None`. Otherwise returns
|
||||
/// `Some(true)` if the running version is a dev release, and `Some(false)`
|
||||
/// otherwise.
|
||||
pub fn is_dev() -> Option<bool> {
|
||||
version_channel_is("dev")
|
||||
/// The format of `version` is a semantic version: `1.3.0`, `1.15.0-beta`,
|
||||
/// `1.14.0`, `1.16.0-nightly`, etc.
|
||||
///
|
||||
/// If the version cannot be retrieved or parsed, or if `version` could not be
|
||||
/// parsed, returns `None`. Otherwise returns `true` if the installed `rustc` is
|
||||
/// exactly `version` and `false` otherwise.
|
||||
pub fn is_exact_version(version: &str) -> Option<bool> {
|
||||
match (Version::read(), Version::parse(version)) {
|
||||
(Some(rustc_ver), Some(version)) => Some(rustc_ver == version),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines whether the running or installed `rustc` supports feature flags.
|
||||
/// Checks whether the running or installed `rustc` supports feature flags.
|
||||
///
|
||||
/// In other words, if the channel is either "nightly" or "dev".
|
||||
///
|
||||
/// If the version could not be determined, returns `None`. Otherwise returns
|
||||
/// `Some(true)` if the running version supports features, and `Some(false)`
|
||||
/// otherwise.
|
||||
pub fn supports_features() -> Option<bool> {
|
||||
match is_nightly() {
|
||||
b@Some(true) => b,
|
||||
_ => is_dev()
|
||||
}
|
||||
/// `true` if the running version supports feature flags and `false` otherwise.
|
||||
pub fn is_feature_flaggable() -> Option<bool> {
|
||||
Channel::read().map(|c| c.supports_features())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::version_and_date_from_rustc_version;
|
||||
use super::str_to_mmp;
|
||||
|
||||
macro_rules! check_mmp {
|
||||
($string:expr => ($x:expr, $y:expr, $z:expr)) => (
|
||||
if let Some(mmp) = str_to_mmp($string) {
|
||||
let expected = $x << 32 | $y << 16 | $z;
|
||||
if mmp != expected {
|
||||
panic!("{:?} didn't parse as {}.{}.{}.", $string, $x, $y, $z);
|
||||
}
|
||||
} else {
|
||||
panic!("{:?} didn't parse for mmp testing.", $string);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! check_version {
|
||||
($s:expr => ($x:expr, $y:expr, $z:expr)) => (
|
||||
if let (Some(version_str), _) = version_and_date_from_rustc_version($s) {
|
||||
check_mmp!(&version_str => ($x, $y, $z));
|
||||
macro_rules! check_parse {
|
||||
($s:expr => $v:expr, $d:expr) => (
|
||||
if let (Some(v), d) = version_and_date_from_rustc_version($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);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_str_to_mmp() {
|
||||
check_mmp!("1.18.0" => (1, 18, 0));
|
||||
check_mmp!("1.19.0" => (1, 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));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version_parse() {
|
||||
check_version!("rustc 1.18.0" => (1, 18, 0));
|
||||
check_version!("rustc 1.8.0" => (1, 8, 0));
|
||||
check_version!("rustc 1.20.0-nightly" => (1, 20, 0));
|
||||
check_version!("rustc 1.20" => (1, 20, 0));
|
||||
check_version!("rustc 1.3" => (1, 3, 0));
|
||||
check_version!("rustc 1" => (1, 0, 0));
|
||||
check_version!("rustc 1.2.5.6" => (1, 2, 5));
|
||||
check_version!("rustc 1.5.1-beta" => (1, 5, 1));
|
||||
check_version!("rustc 1.20.0-nightly (d84693b93 2017-07-09)" => (1, 20, 0));
|
||||
check_version!("rustc 1.20.0 (d84693b93 2017-07-09)" => (1, 20, 0));
|
||||
check_version!("rustc 1.20.0 (2017-07-09)" => (1, 20, 0));
|
||||
check_version!("rustc 1.20.0-dev (2017-07-09)" => (1, 20, 0));
|
||||
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_version!("warning: invalid logging spec 'warning', ignoring it
|
||||
rustc 1.30.0-nightly (3bc2ca7e4 2018-09-20)" => (1, 30, 0));
|
||||
check_version!("warning: invalid logging spec 'warning', ignoring it\n
|
||||
rustc 1.30.0-nightly (3bc2ca7e4 2018-09-20)" => (1, 30, 0));
|
||||
check_version!("warning: invalid logging spec 'warning', ignoring it
|
||||
warning: something else went wrong
|
||||
rustc 1.30.0-nightly (3bc2ca7e4 2018-09-20)" => (1, 30, 0));
|
||||
// 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"));
|
||||
|
||||
check_parse!("rustc 1.20.0-dev (2017-07-09)"
|
||||
=> "1.20.0-dev", Some("2017-07-09"));
|
||||
|
||||
check_parse!("rustc 1.20.0-nightly (d84693b93 2017-07-09)"
|
||||
=> "1.20.0-nightly", Some("2017-07-09"));
|
||||
|
||||
check_parse!("rustc 1.20.0 (d84693b93 2017-07-09)"
|
||||
=> "1.20.0", Some("2017-07-09"));
|
||||
|
||||
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"));
|
||||
|
||||
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"));
|
||||
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
221
src/version.rs
Normal file
221
src/version.rs
Normal file
@ -0,0 +1,221 @@
|
||||
use std::fmt;
|
||||
|
||||
/// Version number: `major.minor.patch`, ignoring release channel.
|
||||
#[derive(Debug, 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`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Version;
|
||||
///
|
||||
/// match Version::read() {
|
||||
/// Some(d) => format!("Version is: {}", d),
|
||||
/// None => format!("Failed to read the version.")
|
||||
/// };
|
||||
/// ```
|
||||
pub fn read() -> Option<Version> {
|
||||
::get_version_and_date()
|
||||
.and_then(|(version, _)| version)
|
||||
.and_then(|version| Version::parse(&version))
|
||||
}
|
||||
|
||||
|
||||
/// Parse a Rust release version (of the form
|
||||
/// `major[.minor[.patch[-channel]]]`), ignoring the release channel, if
|
||||
/// any. Returns `None` if `version` is not a valid Rust version string.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Version;
|
||||
///
|
||||
/// let version = Version::parse("1.18.0").unwrap();
|
||||
/// assert!(version.exactly("1.18.0"));
|
||||
///
|
||||
/// let version = Version::parse("1.20.0-nightly").unwrap();
|
||||
/// assert!(version.exactly("1.20.0"));
|
||||
/// assert!(version.exactly("1.20.0-beta"));
|
||||
///
|
||||
/// let version = Version::parse("1.3").unwrap();
|
||||
/// assert!(version.exactly("1.3.0"));
|
||||
///
|
||||
/// let version = Version::parse("1").unwrap();
|
||||
/// assert!(version.exactly("1.0.0"));
|
||||
///
|
||||
/// assert!(Version::parse("one.two.three").is_none());
|
||||
/// ```
|
||||
pub fn parse(version: &str) -> Option<Version> {
|
||||
let mut mmp: Vec<u16> = version.split('-')
|
||||
.nth(0)
|
||||
.unwrap_or("")
|
||||
.split('.')
|
||||
.filter_map(|s| s.parse::<u16>().ok())
|
||||
.collect();
|
||||
|
||||
if mmp.is_empty() {
|
||||
return None
|
||||
}
|
||||
|
||||
while mmp.len() < 3 {
|
||||
mmp.push(0);
|
||||
}
|
||||
|
||||
let (maj, min, patch) = (mmp[0] as u64, mmp[1] as u64, mmp[2] as u64);
|
||||
Some(Version((maj << 32) | (min << 16) | patch))
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` is greater than or equal to `version`.
|
||||
///
|
||||
/// If `version` is greater than `self`, or if `version` is not a valid Rust
|
||||
/// version string, returns `false`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Version;
|
||||
///
|
||||
/// let version = Version::parse("1.35.0").unwrap();
|
||||
///
|
||||
/// assert!(version.at_least("1.33.0"));
|
||||
/// assert!(version.at_least("1.35.0"));
|
||||
/// assert!(version.at_least("1.13.2"));
|
||||
///
|
||||
/// assert!(!version.at_least("1.35.1"));
|
||||
/// assert!(!version.at_least("1.55.0"));
|
||||
/// ```
|
||||
pub fn at_least(&self, version: &str) -> bool {
|
||||
Version::parse(version)
|
||||
.map(|version| self >= &version)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` is less than or equal to `version`.
|
||||
///
|
||||
/// If `version` is less than `self`, or if `version` is not a valid Rust
|
||||
/// version string, returns `false`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Version;
|
||||
///
|
||||
/// let version = Version::parse("1.35.0").unwrap();
|
||||
///
|
||||
/// assert!(version.at_most("1.35.1"));
|
||||
/// assert!(version.at_most("1.55.0"));
|
||||
/// assert!(version.at_most("1.35.0"));
|
||||
///
|
||||
/// assert!(!version.at_most("1.33.0"));
|
||||
/// assert!(!version.at_most("1.13.2"));
|
||||
/// ```
|
||||
pub fn at_most(&self, version: &str) -> bool {
|
||||
Version::parse(version)
|
||||
.map(|version| self <= &version)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` is exactly equal to `version`.
|
||||
///
|
||||
/// If `version` is not equal to `self`, or if `version` is not a valid Rust
|
||||
/// version string, returns `false`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// use version_check::Version;
|
||||
///
|
||||
/// let version = Version::parse("1.35.0").unwrap();
|
||||
///
|
||||
/// assert!(version.exactly("1.35.0"));
|
||||
///
|
||||
/// assert!(!version.exactly("1.33.0"));
|
||||
/// assert!(!version.exactly("1.35.1"));
|
||||
/// assert!(!version.exactly("1.13.2"));
|
||||
/// ```
|
||||
pub fn exactly(&self, version: &str) -> bool {
|
||||
Version::parse(version)
|
||||
.map(|version| self == &version)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Version {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let (major, minor, patch) = self.to_mmp();
|
||||
write!(f, "{}.{}.{}", major, minor, patch)
|
||||
}
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
#[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));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_comparisons() {
|
||||
let version = Version::parse("1.18.0").unwrap();
|
||||
assert!(version.exactly("1.18.0"));
|
||||
assert!(version.at_least("1.12.0"));
|
||||
assert!(version.at_most("1.18.1"));
|
||||
assert!(!version.exactly("1.19.0"));
|
||||
assert!(!version.exactly("1.18.1"));
|
||||
|
||||
let version = Version::parse("1.20.0-nightly").unwrap();
|
||||
assert!(version.exactly("1.20.0-beta"));
|
||||
assert!(version.exactly("1.20.0-nightly"));
|
||||
assert!(version.exactly("1.20.0"));
|
||||
assert!(!version.exactly("1.19"));
|
||||
|
||||
let version = Version::parse("1.3").unwrap();
|
||||
assert!(version.exactly("1.3.0"));
|
||||
assert!(version.exactly("1.3.0-stable"));
|
||||
assert!(version.exactly("1.3"));
|
||||
assert!(!version.exactly("1.5.0-stable"));
|
||||
|
||||
let version = Version::parse("1").unwrap();
|
||||
assert!(version.exactly("1.0.0"));
|
||||
assert!(version.exactly("1.0"));
|
||||
assert!(version.exactly("1"));
|
||||
|
||||
assert!(Version::parse("one.two.three").is_none());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user