diff options
30 files changed, 1 insertions, 4651 deletions
diff --git a/nitrocli/CHANGELOG.md b/nitrocli/CHANGELOG.md index 98296eb..0f62943 100644 --- a/nitrocli/CHANGELOG.md +++ b/nitrocli/CHANGELOG.md @@ -5,6 +5,7 @@ Unreleased - Further decreased binary size by using system allocator - Bumped `nitrokey` dependency to `0.3.3` - Bumped `rand` dependency to `0.6.4` + - Removed `rustc_version`, `semver`, and `semver-parser` dependencies - Bumped `nitrokey-sys` dependency to `3.4.3` - Bumped `libc` dependency to `0.2.46` diff --git a/rustc_version/.gitignore b/rustc_version/.gitignore deleted file mode 100644 index a9d37c5..0000000 --- a/rustc_version/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target -Cargo.lock diff --git a/rustc_version/.travis.yml b/rustc_version/.travis.yml deleted file mode 100644 index ccb8411..0000000 --- a/rustc_version/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: rust -rust: -- nightly -- beta -- stable -before_script: -- | - pip install 'travis-cargo<0.2' --user && - export PATH=$HOME/.local/bin:$PATH -script: -- | - travis-cargo build && - travis-cargo test && - travis-cargo bench && - travis-cargo --only stable doc -after_success: -- travis-cargo --only stable doc-upload -env: - global: - - TRAVIS_CARGO_NIGHTLY_FEATURE="" - - secure: mxQyrd6tyvcC10H7crLgKSSRHwquSnLb5mjzaj8iXf4mkooKpoRaffIiwmGf0IACQUN3nKlA6D6irfD2CqaFiUiUav8RqeAd8FjHFTlYu0nKZkqB1iGZBA7/JrW7mlGJIdmNIbzVRoPRQI/lY/730M/eqxIAb+9/xaSktkD2cJYGUikdiyeTm8idezkB+BOOWIN20yopLWzmBIVs7doQJOA0ewqMlEduwn6axvEk17r9qlSgucywDsTvDWkXSAuYldyJU4PdFez4t10sGsXx+TKfbwcaRmwaOj/MImZUVCtQvutEW9Hb/2hJXjCN2uefZ64BfodKn3wyB7ie7PgOixsLkqoR01d/qbfDsWGg/4iLi3DCq5bVtWJoCCT4lS8kfwi8D8HmvcoCQnT+CdU4LhlV9aHTSEMx0SEJW0DHYE/RnoqJjCj+QsK4ji7HAnyYWVwSGYJfnrL0EAwKararAzKY/vABStJKu1IlBzKCsjIQ+0hMpqnFiWldhfRHt/rYhBtK+HYXElamc8xpF/taK8E40NSHDgC+4TciTAZtyAXOWiMhXS0653U3hvJqYY/LtHmobpIqc1XkHe53gQ0QrBd6UsyUN9FjWOLxvPUx4zcyNFJHXcFiwevfK6gYF+OXepVu8TznAQLSP7ToA7KXbhSSVQDM+7UFVcT41VgDbGY= diff --git a/rustc_version/Cargo.toml b/rustc_version/Cargo.toml deleted file mode 100644 index 422a881..0000000 --- a/rustc_version/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "rustc_version" -version = "0.2.3" -authors = ["Marvin Löbel <loebel.marvin@gmail.com>"] -license = "MIT/Apache-2.0" - -description = "A library for querying the version of a installed rustc compiler" -readme = "README.md" -documentation = "https://docs.rs/rustc_version/" - -repository = "https://github.com/Kimundi/rustc-version-rs" -keywords = ["version", "rustc"] - -[badges] -travis-ci = { repository = "Kimundi/rustc-version-rs" } - -[dependencies] -semver = "0.9" diff --git a/rustc_version/LICENSE-APACHE b/rustc_version/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/rustc_version/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/rustc_version/LICENSE-MIT b/rustc_version/LICENSE-MIT deleted file mode 100644 index 40b8817..0000000 --- a/rustc_version/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2016 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/rustc_version/README.md b/rustc_version/README.md deleted file mode 100644 index f491ca9..0000000 --- a/rustc_version/README.md +++ /dev/null @@ -1,75 +0,0 @@ -rustc-version-rs -============== - -A library for querying the version of a `rustc` compiler. - -This can be used by build scripts or other tools dealing with Rust sources -to make decisions based on the version of the compiler. - -[![Travis-CI Status](https://travis-ci.org/Kimundi/rustc-version-rs.png?branch=master)](https://travis-ci.org/Kimundi/rustc-version-rs) - -# Getting Started - -[rustc-version-rs is available on crates.io](https://crates.io/crates/rustc_version). -It is recommended to look there for the newest released version, as well as links to the newest builds of the docs. - -At the point of the last update of this README, the latest published version could be used like this: - -Add the following dependency to your Cargo manifest... - -```toml -[build-dependencies] -rustc_version = "0.2" -``` - -...and see the [docs](http://kimundi.github.io/rustc-version-rs/rustc_version/index.html) for how to use it. - -# Example - -```rust -// This could be a cargo build script - -extern crate rustc_version; -use rustc_version::{version, version_meta, Channel, Version}; - -fn main() { - // Assert we haven't travelled back in time - assert!(version().unwrap().major >= 1); - - // Set cfg flags depending on release channel - match version_meta().unwrap().channel { - Channel::Stable => { - println!("cargo:rustc-cfg=RUSTC_IS_STABLE"); - } - Channel::Beta => { - println!("cargo:rustc-cfg=RUSTC_IS_BETA"); - } - Channel::Nightly => { - println!("cargo:rustc-cfg=RUSTC_IS_NIGHTLY"); - } - Channel::Dev => { - println!("cargo:rustc-cfg=RUSTC_IS_DEV"); - } - } - - // Check for a minimum version - if version().unwrap() >= Version::parse("1.4.0").unwrap() { - println!("cargo:rustc-cfg=compiler_has_important_bugfix"); - } -} -``` - -## License - -Licensed under either of - - * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any -additional terms or conditions. diff --git a/rustc_version/src/errors.rs b/rustc_version/src/errors.rs deleted file mode 100644 index 54557b6..0000000 --- a/rustc_version/src/errors.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::{self, error, fmt, io, str}; -use semver::{self, Identifier}; - -/// The error type for this crate. -#[derive(Debug)] -pub enum Error { - /// An error ocurrend when executing the `rustc` command. - CouldNotExecuteCommand(io::Error), - /// The output of `rustc -vV` was not valid utf-8. - Utf8Error(str::Utf8Error), - /// The output of `rustc -vV` was not in the expected format. - UnexpectedVersionFormat, - /// An error ocurred in parsing a `VersionReq`. - ReqParseError(semver::ReqParseError), - /// An error ocurred in parsing the semver. - SemVerError(semver::SemVerError), - /// The pre-release tag is unknown. - UnknownPreReleaseTag(Identifier), -} -use Error::*; - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use std::error::Error; - match *self { - CouldNotExecuteCommand(ref e) => write!(f, "{}: {}", self.description(), e), - Utf8Error(_) => write!(f, "{}", self.description()), - UnexpectedVersionFormat => write!(f, "{}", self.description()), - ReqParseError(ref e) => write!(f, "{}: {}", self.description(), e), - SemVerError(ref e) => write!(f, "{}: {}", self.description(), e), - UnknownPreReleaseTag(ref i) => write!(f, "{}: {}", self.description(), i), - } - } -} - -impl error::Error for Error { - fn cause(&self) -> Option<&error::Error> { - match *self { - CouldNotExecuteCommand(ref e) => Some(e), - Utf8Error(ref e) => Some(e), - UnexpectedVersionFormat => None, - ReqParseError(ref e) => Some(e), - SemVerError(ref e) => Some(e), - UnknownPreReleaseTag(_) => None, - } - } - - fn description(&self) -> &str { - match *self { - CouldNotExecuteCommand(_) => "could not execute command", - Utf8Error(_) => "invalid UTF-8 output from `rustc -vV`", - UnexpectedVersionFormat => "unexpected `rustc -vV` format", - ReqParseError(_) => "error parsing version requirement", - SemVerError(_) => "error parsing version", - UnknownPreReleaseTag(_) => "unknown pre-release tag", - } - } -} - -macro_rules! impl_from { - ($($err_ty:ty => $variant:ident),* $(,)*) => { - $( - impl From<$err_ty> for Error { - fn from(e: $err_ty) -> Error { - Error::$variant(e) - } - } - )* - } -} - -impl_from! { - str::Utf8Error => Utf8Error, - semver::SemVerError => SemVerError, - semver::ReqParseError => ReqParseError, -} - -/// The result type for this crate. -pub type Result<T> = std::result::Result<T, Error>; diff --git a/rustc_version/src/lib.rs b/rustc_version/src/lib.rs deleted file mode 100644 index c038288..0000000 --- a/rustc_version/src/lib.rs +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright 2016 rustc-version-rs developers -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![warn(missing_docs)] - -//! Simple library for getting the version information of a `rustc` -//! compiler. -//! -//! This can be used by build scripts or other tools dealing with Rust sources -//! to make decisions based on the version of the compiler. -//! -//! It calls `$RUSTC --version -v` and parses the output, falling -//! back to `rustc` if `$RUSTC` is not set. -//! -//! # Example -//! -//! ```rust -//! // This could be a cargo build script -//! -//! extern crate rustc_version; -//! use rustc_version::{version, version_meta, Channel, Version}; -//! -//! fn main() { -//! // Assert we haven't travelled back in time -//! assert!(version().unwrap().major >= 1); -//! -//! // Set cfg flags depending on release channel -//! match version_meta().unwrap().channel { -//! Channel::Stable => { -//! println!("cargo:rustc-cfg=RUSTC_IS_STABLE"); -//! } -//! Channel::Beta => { -//! println!("cargo:rustc-cfg=RUSTC_IS_BETA"); -//! } -//! Channel::Nightly => { -//! println!("cargo:rustc-cfg=RUSTC_IS_NIGHTLY"); -//! } -//! Channel::Dev => { -//! println!("cargo:rustc-cfg=RUSTC_IS_DEV"); -//! } -//! } -//! -//! // Check for a minimum version -//! if version().unwrap() >= Version::parse("1.4.0").unwrap() { -//! println!("cargo:rustc-cfg=compiler_has_important_bugfix"); -//! } -//! } -//! ``` - -extern crate semver; -use semver::Identifier; -use std::process::Command; -use std::{env, str}; -use std::ffi::OsString; - -// Convenience re-export to allow version comparison without needing to add -// semver crate. -pub use semver::Version; - -mod errors; -pub use errors::{Error, Result}; - -/// Release channel of the compiler. -#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] -pub enum Channel { - /// Development release channel - Dev, - /// Nightly release channel - Nightly, - /// Beta release channel - Beta, - /// Stable release channel - Stable, -} - -/// Rustc version plus metada like git short hash and build date. -#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct VersionMeta { - /// Version of the compiler - pub semver: Version, - - /// Git short hash of the build of the compiler - pub commit_hash: Option<String>, - - /// Commit date of the compiler - pub commit_date: Option<String>, - - /// Build date of the compiler; this was removed between Rust 1.0.0 and 1.1.0. - pub build_date: Option<String>, - - /// Release channel of the compiler - pub channel: Channel, - - /// Host target triple of the compiler - pub host: String, - - /// Short version string of the compiler - pub short_version_string: String, -} - -impl VersionMeta { - /// Returns the version metadata for `cmd`, which should be a `rustc` command. - pub fn for_command(cmd: Command) -> Result<VersionMeta> { - let mut cmd = cmd; - - let out = cmd.arg("-vV").output().map_err(Error::CouldNotExecuteCommand)?; - let out = str::from_utf8(&out.stdout)?; - - version_meta_for(out) - } -} - -/// Returns the `rustc` SemVer version. -pub fn version() -> Result<Version> { - Ok(version_meta()?.semver) -} - -/// Returns the `rustc` SemVer version and additional metadata -/// like the git short hash and build date. -pub fn version_meta() -> Result<VersionMeta> { - let cmd = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); - - VersionMeta::for_command(Command::new(cmd)) -} - -/// Parses a "rustc -vV" output string and returns -/// the SemVer version and additional metadata -/// like the git short hash and build date. -pub fn version_meta_for(verbose_version_string: &str) -> Result<VersionMeta> { - let out: Vec<_> = verbose_version_string.lines().collect(); - - if !(out.len() >= 6 && out.len() <= 8) { - return Err(Error::UnexpectedVersionFormat); - } - - let short_version_string = out[0]; - - fn expect_prefix<'a>(line: &'a str, prefix: &str) -> Result<&'a str> { - if line.starts_with(prefix) { - Ok(&line[prefix.len()..]) - } else { - Err(Error::UnexpectedVersionFormat) - } - } - - let commit_hash = match expect_prefix(out[2], "commit-hash: ")? { - "unknown" => None, - hash => Some(hash.to_owned()), - }; - - let commit_date = match expect_prefix(out[3], "commit-date: ")? { - "unknown" => None, - hash => Some(hash.to_owned()), - }; - - // Handle that the build date may or may not be present. - let mut idx = 4; - let mut build_date = None; - if out[idx].starts_with("build-date") { - build_date = match expect_prefix(out[idx], "build-date: ")? { - "unknown" => None, - s => Some(s.to_owned()), - }; - idx += 1; - } - - let host = expect_prefix(out[idx], "host: ")?; - idx += 1; - let release = expect_prefix(out[idx], "release: ")?; - - let semver: Version = release.parse()?; - - let channel = if semver.pre.is_empty() { - Channel::Stable - } else { - match semver.pre[0] { - Identifier::AlphaNumeric(ref s) if s == "dev" => Channel::Dev, - Identifier::AlphaNumeric(ref s) if s == "beta" => Channel::Beta, - Identifier::AlphaNumeric(ref s) if s == "nightly" => Channel::Nightly, - ref x => return Err(Error::UnknownPreReleaseTag(x.clone())), - } - }; - - Ok(VersionMeta { - semver: semver, - commit_hash: commit_hash, - commit_date: commit_date, - build_date: build_date, - channel: channel, - host: host.into(), - short_version_string: short_version_string.into(), - }) -} - -#[test] -fn smoketest() { - let v = version().unwrap(); - assert!(v.major >= 1); - - let v = version_meta().unwrap(); - assert!(v.semver.major >= 1); - - assert!(version().unwrap() >= Version::parse("1.0.0").unwrap()); -} - -#[test] -fn parse_unexpected() { - let res = version_meta_for( -"rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14) -binary: rustc -commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e -commit-date: 2015-05-13 -rust-birthday: 2015-05-14 -host: x86_64-unknown-linux-gnu -release: 1.0.0"); - - assert!(match res { - Err(Error::UnexpectedVersionFormat) => true, - _ => false, - }); - -} - -#[test] -fn parse_1_0_0() { - let version = version_meta_for( -"rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14) -binary: rustc -commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e -commit-date: 2015-05-13 -build-date: 2015-05-14 -host: x86_64-unknown-linux-gnu -release: 1.0.0").unwrap(); - - assert_eq!(version.semver, Version::parse("1.0.0").unwrap()); - assert_eq!(version.commit_hash, Some("a59de37e99060162a2674e3ff45409ac73595c0e".into())); - assert_eq!(version.commit_date, Some("2015-05-13".into())); - assert_eq!(version.build_date, Some("2015-05-14".into())); - assert_eq!(version.channel, Channel::Stable); - assert_eq!(version.host, "x86_64-unknown-linux-gnu"); - assert_eq!(version.short_version_string, "rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)"); -} - - -#[test] -fn parse_unknown() { - let version = version_meta_for( -"rustc 1.3.0 -binary: rustc -commit-hash: unknown -commit-date: unknown -host: x86_64-unknown-linux-gnu -release: 1.3.0").unwrap(); - - assert_eq!(version.semver, Version::parse("1.3.0").unwrap()); - assert_eq!(version.commit_hash, None); - assert_eq!(version.commit_date, None); - assert_eq!(version.channel, Channel::Stable); - assert_eq!(version.host, "x86_64-unknown-linux-gnu"); - assert_eq!(version.short_version_string, "rustc 1.3.0"); -} - -#[test] -fn parse_nightly() { - let version = version_meta_for( -"rustc 1.5.0-nightly (65d5c0833 2015-09-29) -binary: rustc -commit-hash: 65d5c083377645a115c4ac23a620d3581b9562b6 -commit-date: 2015-09-29 -host: x86_64-unknown-linux-gnu -release: 1.5.0-nightly").unwrap(); - - assert_eq!(version.semver, Version::parse("1.5.0-nightly").unwrap()); - assert_eq!(version.commit_hash, Some("65d5c083377645a115c4ac23a620d3581b9562b6".into())); - assert_eq!(version.commit_date, Some("2015-09-29".into())); - assert_eq!(version.channel, Channel::Nightly); - assert_eq!(version.host, "x86_64-unknown-linux-gnu"); - assert_eq!(version.short_version_string, "rustc 1.5.0-nightly (65d5c0833 2015-09-29)"); -} - -#[test] -fn parse_stable() { - let version = version_meta_for( -"rustc 1.3.0 (9a92aaf19 2015-09-15) -binary: rustc -commit-hash: 9a92aaf19a64603b02b4130fe52958cc12488900 -commit-date: 2015-09-15 -host: x86_64-unknown-linux-gnu -release: 1.3.0").unwrap(); - - assert_eq!(version.semver, Version::parse("1.3.0").unwrap()); - assert_eq!(version.commit_hash, Some("9a92aaf19a64603b02b4130fe52958cc12488900".into())); - assert_eq!(version.commit_date, Some("2015-09-15".into())); - assert_eq!(version.channel, Channel::Stable); - assert_eq!(version.host, "x86_64-unknown-linux-gnu"); - assert_eq!(version.short_version_string, "rustc 1.3.0 (9a92aaf19 2015-09-15)"); -} - -#[test] -fn parse_1_16_0_nightly() { - let version = version_meta_for( -"rustc 1.16.0-nightly (5d994d8b7 2017-01-05) -binary: rustc -commit-hash: 5d994d8b7e482e87467d4a521911477bd8284ce3 -commit-date: 2017-01-05 -host: x86_64-unknown-linux-gnu -release: 1.16.0-nightly -LLVM version: 3.9").unwrap(); - - assert_eq!(version.semver, Version::parse("1.16.0-nightly").unwrap()); - assert_eq!(version.commit_hash, Some("5d994d8b7e482e87467d4a521911477bd8284ce3".into())); - assert_eq!(version.commit_date, Some("2017-01-05".into())); - assert_eq!(version.channel, Channel::Nightly); - assert_eq!(version.host, "x86_64-unknown-linux-gnu"); - assert_eq!(version.short_version_string, "rustc 1.16.0-nightly (5d994d8b7 2017-01-05)"); -} - -/* -#[test] -fn version_matches_replacement() { - let f = |s1: &str, s2: &str| { - let a = Version::parse(s1).unwrap(); - let b = Version::parse(s2).unwrap(); - println!("{} <= {} : {}", s1, s2, a <= b); - }; - - println!(); - - f("1.5.0", "1.5.0"); - f("1.5.0-nightly", "1.5.0"); - f("1.5.0", "1.5.0-nightly"); - f("1.5.0-nightly", "1.5.0-nightly"); - - f("1.5.0", "1.6.0"); - f("1.5.0-nightly", "1.6.0"); - f("1.5.0", "1.6.0-nightly"); - f("1.5.0-nightly", "1.6.0-nightly"); - - panic!(); - -} -*/ diff --git a/semver-parser/.gitignore b/semver-parser/.gitignore deleted file mode 100644 index a9d37c5..0000000 --- a/semver-parser/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -target -Cargo.lock diff --git a/semver-parser/Cargo.toml b/semver-parser/Cargo.toml deleted file mode 100644 index c2be878..0000000 --- a/semver-parser/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "semver-parser" -version = "0.7.0" -authors = ["Steve Klabnik <steve@steveklabnik.com>"] -license = "MIT/Apache-2.0" -repository = "https://github.com/steveklabnik/semver-parser" -homepage = "https://github.com/steveklabnik/semver-parser" -documentation = "https://docs.rs/semver-parser" -description = """ -Parsing of the semver spec. -""" diff --git a/semver-parser/LICENSE-APACHE b/semver-parser/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/semver-parser/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/semver-parser/LICENSE-MIT b/semver-parser/LICENSE-MIT deleted file mode 100644 index fb7494a..0000000 --- a/semver-parser/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2016 Steve Klabnik - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/semver-parser/src/common.rs b/semver-parser/src/common.rs deleted file mode 100644 index 267b4d9..0000000 --- a/semver-parser/src/common.rs +++ /dev/null @@ -1,66 +0,0 @@ -use version::Identifier; -use recognize::{Recognize, Alt, OneOrMore, Inclusive, OneByte}; -use std::str::from_utf8; - -// by the time we get here, we know that it's all valid characters, so this doesn't need to return -// a result or anything -fn parse_meta(s: &str) -> Vec<Identifier> { - // Originally, I wanted to implement this method via calling parse, but parse is tolerant of - // leading zeroes, and we want anything with leading zeroes to be considered alphanumeric, not - // numeric. So the strategy is to check with a recognizer first, and then call parse once - // we've determined that it's a number without a leading zero. - s.split(".") - .map(|part| { - // another wrinkle: we made sure that any number starts with a - // non-zero. But there's a problem: an actual zero is a number, yet - // gets left out by this heuristic. So let's also check for the - // single, lone zero. - if is_alpha_numeric(part) { - Identifier::AlphaNumeric(part.to_string()) - } else { - // we can unwrap here because we know it is only digits due to the regex - Identifier::Numeric(part.parse().unwrap()) - } - }).collect() -} - -// parse optional metadata (preceded by the prefix character) -pub fn parse_optional_meta(s: &[u8], prefix_char: u8)-> Result<(Vec<Identifier>, usize), String> { - if let Some(len) = prefix_char.p(s) { - let start = len; - if let Some(len) = letters_numbers_dash_dot(&s[start..]) { - let end = start + len; - Ok((parse_meta(from_utf8(&s[start..end]).unwrap()), end)) - } else { - Err("Error parsing prerelease".to_string()) - } - } else { - Ok((Vec::new(), 0)) - } -} - -pub fn is_alpha_numeric(s: &str) -> bool { - if let Some((_val, len)) = numeric_identifier(s.as_bytes()) { - // Return true for number with leading zero - // Note: doing it this way also handily makes overflow fail over. - len != s.len() - } else { - true - } -} - -// Note: could plumb overflow error up to return value as Result -pub fn numeric_identifier(s: &[u8]) -> Option<(u64, usize)> { - if let Some(len) = Alt(b'0', OneOrMore(Inclusive(b'0'..b'9'))).p(s) { - from_utf8(&s[0..len]).unwrap().parse().ok().map(|val| (val, len)) - } else { - None - } -} - -pub fn letters_numbers_dash_dot(s: &[u8]) -> Option<usize> { - OneOrMore(OneByte(|c| c == b'-' || c == b'.' || - (b'0' <= c && c <= b'9') || - (b'a' <= c && c <= b'z') || - (b'A' <= c && c <= b'Z'))).p(s) -} diff --git a/semver-parser/src/lib.rs b/semver-parser/src/lib.rs deleted file mode 100644 index 3b0d8f0..0000000 --- a/semver-parser/src/lib.rs +++ /dev/null @@ -1,8 +0,0 @@ -pub mod version; -pub mod range; - -// for private stuff the two share -mod common; - -// for recognizer combinators -mod recognize; diff --git a/semver-parser/src/range.rs b/semver-parser/src/range.rs deleted file mode 100644 index 858be9f..0000000 --- a/semver-parser/src/range.rs +++ /dev/null @@ -1,696 +0,0 @@ -use common::{self, numeric_identifier, letters_numbers_dash_dot}; -use version::Identifier; -use std::str::{FromStr, from_utf8}; -use recognize::*; - -#[derive(Debug)] -pub struct VersionReq { - pub predicates: Vec<Predicate>, -} - -#[derive(PartialEq,Debug)] -pub enum WildcardVersion { - Major, - Minor, - Patch, -} - -#[derive(PartialEq,Debug)] -pub enum Op { - Ex, // Exact - Gt, // Greater than - GtEq, // Greater than or equal to - Lt, // Less than - LtEq, // Less than or equal to - Tilde, // e.g. ~1.0.0 - Compatible, // compatible by definition of semver, indicated by ^ - Wildcard(WildcardVersion), // x.y.*, x.*, * -} - -impl FromStr for Op { - type Err = String; - - fn from_str(s: &str) -> Result<Op, String> { - match s { - "=" => Ok(Op::Ex), - ">" => Ok(Op::Gt), - ">=" => Ok(Op::GtEq), - "<" => Ok(Op::Lt), - "<=" => Ok(Op::LtEq), - "~" => Ok(Op::Tilde), - "^" => Ok(Op::Compatible), - _ => Err(String::from("Could not parse Op")), - } - } -} - -#[derive(PartialEq,Debug)] -pub struct Predicate { - pub op: Op, - pub major: u64, - pub minor: Option<u64>, - pub patch: Option<u64>, - pub pre: Vec<Identifier>, -} - -fn numeric_or_wild(s: &[u8]) -> Option<(Option<u64>, usize)> { - if let Some((val, len)) = numeric_identifier(s) { - Some((Some(val), len)) - } else if let Some(len) = OneOf(b"*xX").p(s) { - Some((None, len)) - } else { - None - } -} - -fn dot_numeric_or_wild(s: &[u8]) -> Option<(Option<u64>, usize)> { - b'.'.p(s).and_then(|len| - numeric_or_wild(&s[len..]).map(|(val, len2)| (val, len + len2)) - ) -} - -fn operation(s: &[u8]) -> Option<(Op, usize)> { - if let Some(len) = "=".p(s) { - Some((Op::Ex, len)) - } else if let Some(len) = ">=".p(s) { - Some((Op::GtEq, len)) - } else if let Some(len) = ">".p(s) { - Some((Op::Gt, len)) - } else if let Some(len) = "<=".p(s) { - Some((Op::LtEq, len)) - } else if let Some(len) = "<".p(s) { - Some((Op::Lt, len)) - } else if let Some(len) = "~".p(s) { - Some((Op::Tilde, len)) - } else if let Some(len) = "^".p(s) { - Some((Op::Compatible, len)) - } else { - None - } -} - -fn whitespace(s: &[u8]) -> Option<usize> { - ZeroOrMore(OneOf(b"\t\r\n ")).p(s) -} - -pub fn parse_predicate(range: &str) -> Result<Predicate, String> { - let s = range.trim().as_bytes(); - let mut i = 0; - let mut operation = if let Some((op, len)) = operation(&s[i..]) { - i += len; - op - } else { - // operations default to Compatible - Op::Compatible - }; - if let Some(len) = whitespace.p(&s[i..]) { - i += len; - } - let major = if let Some((major, len)) = numeric_identifier(&s[i..]) { - i += len; - major - } else { - return Err("Error parsing major version number: ".to_string()); - }; - let minor = if let Some((minor, len)) = dot_numeric_or_wild(&s[i..]) { - i += len; - if minor.is_none() { - operation = Op::Wildcard(WildcardVersion::Minor); - } - minor - } else { - None - }; - let patch = if let Some((patch, len)) = dot_numeric_or_wild(&s[i..]) { - i += len; - if patch.is_none() { - operation = Op::Wildcard(WildcardVersion::Patch); - } - patch - } else { - None - }; - let (pre, pre_len) = common::parse_optional_meta(&s[i..], b'-')?; - i += pre_len; - if let Some(len) = (b'+', letters_numbers_dash_dot).p(&s[i..]) { - i += len; - } - if i != s.len() { - return Err("Extra junk after valid predicate: ".to_string() + - from_utf8(&s[i..]).unwrap()); - } - Ok(Predicate { - op: operation, - major: major, - minor: minor, - patch: patch, - pre: pre, - }) -} - -pub fn parse(ranges: &str) -> Result<VersionReq, String> { - // null is an error - if ranges == "\0" { - return Err(String::from("Null is not a valid VersionReq")); - } - - // an empty range is a major version wildcard - // so is a lone * or x of either capitalization - if (ranges == "") - || (ranges == "*") - || (ranges == "x") - || (ranges == "X") { - return Ok(VersionReq { - predicates: vec![Predicate { - op: Op::Wildcard(WildcardVersion::Major), - major: 0, - minor: None, - patch: None, - pre: Vec::new(), - }], - }); - } - - - let ranges = ranges.trim(); - - let predicates: Result<Vec<_>, String> = ranges - .split(",") - .map(|range| { - parse_predicate(range) - }) - .collect(); - - let predicates = try!(predicates); - - if predicates.len() == 0 { - return Err(String::from("VersionReq did not parse properly")); - } - - Ok(VersionReq { - predicates: predicates, - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use range; - use version::Identifier; - - #[test] - fn test_parsing_default() { - let r = range::parse("1.0.0").unwrap(); - - assert_eq!(Predicate { - op: Op::Compatible, - major: 1, - minor: Some(0), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_exact_01() { - let r = range::parse("=1.0.0").unwrap(); - - assert_eq!(Predicate { - op: Op::Ex, - major: 1, - minor: Some(0), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_exact_02() { - let r = range::parse("=0.9.0").unwrap(); - - assert_eq!(Predicate { - op: Op::Ex, - major: 0, - minor: Some(9), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_exact_03() { - let r = range::parse("=0.1.0-beta2.a").unwrap(); - - assert_eq!(Predicate { - op: Op::Ex, - major: 0, - minor: Some(1), - patch: Some(0), - pre: vec![Identifier::AlphaNumeric(String::from("beta2")), - Identifier::AlphaNumeric(String::from("a"))], - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_parsing_greater_than() { - let r = range::parse("> 1.0.0").unwrap(); - - assert_eq!(Predicate { - op: Op::Gt, - major: 1, - minor: Some(0), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_parsing_greater_than_01() { - let r = range::parse(">= 1.0.0").unwrap(); - - assert_eq!(Predicate { - op: Op::GtEq, - major: 1, - minor: Some(0), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_parsing_greater_than_02() { - let r = range::parse(">= 2.1.0-alpha2").unwrap(); - - assert_eq!(Predicate { - op: Op::GtEq, - major: 2, - minor: Some(1), - patch: Some(0), - pre: vec![Identifier::AlphaNumeric(String::from("alpha2"))], - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_parsing_less_than() { - let r = range::parse("< 1.0.0").unwrap(); - - assert_eq!(Predicate { - op: Op::Lt, - major: 1, - minor: Some(0), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_parsing_less_than_eq() { - let r = range::parse("<= 2.1.0-alpha2").unwrap(); - - assert_eq!(Predicate { - op: Op::LtEq, - major: 2, - minor: Some(1), - patch: Some(0), - pre: vec![Identifier::AlphaNumeric(String::from("alpha2"))], - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_parsing_tilde() { - let r = range::parse("~1").unwrap(); - - assert_eq!(Predicate { - op: Op::Tilde, - major: 1, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_parsing_compatible() { - let r = range::parse("^0").unwrap(); - - assert_eq!(Predicate { - op: Op::Compatible, - major: 0, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_blank() { - let r = range::parse("").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Major), - major: 0, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_wildcard() { - let r = range::parse("*").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Major), - major: 0, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_x() { - let r = range::parse("x").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Major), - major: 0, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_capital_x() { - let r = range::parse("X").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Major), - major: 0, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_minor_wildcard_star() { - let r = range::parse("1.*").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Minor), - major: 1, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_minor_wildcard_x() { - let r = range::parse("1.x").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Minor), - major: 1, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_minor_wildcard_capital_x() { - let r = range::parse("1.X").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Minor), - major: 1, - minor: None, - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_patch_wildcard_star() { - let r = range::parse("1.2.*").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Patch), - major: 1, - minor: Some(2), - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_patch_wildcard_x() { - let r = range::parse("1.2.x").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Patch), - major: 1, - minor: Some(2), - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - fn test_parsing_patch_wildcard_capital_x() { - let r = range::parse("1.2.X").unwrap(); - - assert_eq!(Predicate { - op: Op::Wildcard(WildcardVersion::Patch), - major: 1, - minor: Some(2), - patch: None, - pre: Vec::new(), - }, - r.predicates[0] - ); - } - - #[test] - pub fn test_multiple_01() { - let r = range::parse("> 0.0.9, <= 2.5.3").unwrap(); - - assert_eq!(Predicate { - op: Op::Gt, - major: 0, - minor: Some(0), - patch: Some(9), - pre: Vec::new(), - }, - r.predicates[0] - ); - - assert_eq!(Predicate { - op: Op::LtEq, - major: 2, - minor: Some(5), - patch: Some(3), - pre: Vec::new(), - }, - r.predicates[1] - ); - } - - #[test] - pub fn test_multiple_02() { - let r = range::parse("0.3.0, 0.4.0").unwrap(); - - assert_eq!(Predicate { - op: Op::Compatible, - major: 0, - minor: Some(3), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - - assert_eq!(Predicate { - op: Op::Compatible, - major: 0, - minor: Some(4), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[1] - ); - } - - #[test] - pub fn test_multiple_03() { - let r = range::parse("<= 0.2.0, >= 0.5.0").unwrap(); - - assert_eq!(Predicate { - op: Op::LtEq, - major: 0, - minor: Some(2), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - - assert_eq!(Predicate { - op: Op::GtEq, - major: 0, - minor: Some(5), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[1] - ); - } - - #[test] - pub fn test_multiple_04() { - let r = range::parse("0.1.0, 0.1.4, 0.1.6").unwrap(); - - assert_eq!(Predicate { - op: Op::Compatible, - major: 0, - minor: Some(1), - patch: Some(0), - pre: Vec::new(), - }, - r.predicates[0] - ); - - assert_eq!(Predicate { - op: Op::Compatible, - major: 0, - minor: Some(1), - patch: Some(4), - pre: Vec::new(), - }, - r.predicates[1] - ); - - assert_eq!(Predicate { - op: Op::Compatible, - major: 0, - minor: Some(1), - patch: Some(6), - pre: Vec::new(), - }, - r.predicates[2] - ); - } - - #[test] - pub fn test_multiple_05() { - let r = range::parse(">=0.5.1-alpha3, <0.6").unwrap(); - - assert_eq!(Predicate { - op: Op::GtEq, - major: 0, - minor: Some(5), - patch: Some(1), - pre: vec![Identifier::AlphaNumeric(String::from("alpha3"))], - }, - r.predicates[0] - ); - - assert_eq!(Predicate { - op: Op::Lt, - major: 0, - minor: Some(6), - patch: None, - pre: Vec::new(), - }, - r.predicates[1] - ); - } - - #[test] - fn test_parse_build_metadata_with_predicate() { - assert_eq!(range::parse("^1.2.3+meta").unwrap().predicates[0].op, - Op::Compatible); - assert_eq!(range::parse("~1.2.3+meta").unwrap().predicates[0].op, - Op::Tilde); - assert_eq!(range::parse("=1.2.3+meta").unwrap().predicates[0].op, - Op::Ex); - assert_eq!(range::parse("<=1.2.3+meta").unwrap().predicates[0].op, - Op::LtEq); - assert_eq!(range::parse(">=1.2.3+meta").unwrap().predicates[0].op, - Op::GtEq); - assert_eq!(range::parse("<1.2.3+meta").unwrap().predicates[0].op, - Op::Lt); - assert_eq!(range::parse(">1.2.3+meta").unwrap().predicates[0].op, - Op::Gt); - } - - #[test] - pub fn test_parse_errors() { - assert!(range::parse("\0").is_err()); - assert!(range::parse(">= >= 0.0.2").is_err()); - assert!(range::parse(">== 0.0.2").is_err()); - assert!(range::parse("a.0.0").is_err()); - assert!(range::parse("1.0.0-").is_err()); - assert!(range::parse(">=").is_err()); - assert!(range::parse("> 0.1.0,").is_err()); - assert!(range::parse("> 0.3.0, ,").is_err()); - } - - #[test] - pub fn test_large_major_version() { - assert!(range::parse("18446744073709551617.0.0").is_err()); - } - - #[test] - pub fn test_large_minor_version() { - assert!(range::parse("0.18446744073709551617.0").is_err()); - } - - #[test] - pub fn test_large_patch_version() { - assert!(range::parse("0.0.18446744073709551617").is_err()); - } -} diff --git a/semver-parser/src/recognize.rs b/semver-parser/src/recognize.rs deleted file mode 100644 index c0dd771..0000000 --- a/semver-parser/src/recognize.rs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2017 Google Inc. All rights reserved. -// -// Licensed under either of MIT or Apache License, Version 2.0, -// at your option. -// -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file or at -// https://opensource.org/licenses/MIT. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Simple recognizer combinators. - -// This version is similar to a similar one in the "lang" module of -// xi-editor, but is stripped down to only the needed combinators. - -use std::ops; - -pub trait Recognize { - fn p(&self, s: &[u8]) -> Option<usize>; -} - -impl<F: Fn(&[u8]) -> Option<usize>> Recognize for F { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - self(s) - } -} - -pub struct OneByte<F>(pub F); - -impl<F: Fn(u8) -> bool> Recognize for OneByte<F> { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - if s.is_empty() || !self.0(s[0]) { - None - } else { - Some(1) - } - } -} - -impl Recognize for u8 { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - OneByte(|b| b == *self).p(s) - } -} - -/// Use Inclusive(a..b) to indicate an inclusive range. When a...b syntax becomes -/// stable, we can get rid of this and switch to that. -pub struct Inclusive<T>(pub T); - -impl Recognize for Inclusive<ops::Range<u8>> { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - OneByte(|x| x >= self.0.start && x <= self.0.end).p(s) - } -} - -impl<'a> Recognize for &'a [u8] { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - let len = self.len(); - if s.len() >= len && &s[..len] == *self { - Some(len) - } else { - None - } - } -} - -impl<'a> Recognize for &'a str { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - self.as_bytes().p(s) - } -} - -impl<P1: Recognize, P2: Recognize> Recognize for (P1, P2) { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - self.0.p(s).and_then(|len1| - self.1.p(&s[len1..]).map(|len2| - len1 + len2)) - } -} - -/// Choice from two heterogeneous alternatives. -pub struct Alt<P1, P2>(pub P1, pub P2); - -impl<P1: Recognize, P2: Recognize> Recognize for Alt<P1, P2> { - #[inline(always)] - fn p(&self, s: &[u8]) -> Option<usize> { - self.0.p(s).or_else(|| self.1.p(s)) - } -} - -/// Choice from a homogenous slice of parsers. -pub struct OneOf<'a, P: 'a>(pub &'a [P]); - -impl<'a, P: Recognize> Recognize for OneOf<'a, P> { - #[inline] - fn p(&self, s: &[u8]) -> Option<usize> { - for ref p in self.0 { - if let Some(len) = p.p(s) { - return Some(len); - } - } - None - } -} - -pub struct OneOrMore<P>(pub P); - -impl<P: Recognize> Recognize for OneOrMore<P> { - #[inline] - fn p(&self, s: &[u8]) -> Option<usize> { - let mut i = 0; - let mut count = 0; - while let Some(len) = self.0.p(&s[i..]) { - i += len; - count += 1; - } - if count >= 1 { - Some(i) - } else { - None - } - } -} - -pub struct ZeroOrMore<P>(pub P); - -impl<P: Recognize> Recognize for ZeroOrMore<P> { - #[inline] - fn p(&self, s: &[u8]) -> Option<usize> { - let mut i = 0; - while let Some(len) = self.0.p(&s[i..]) { - i += len; - } - Some(i) - } -} diff --git a/semver-parser/src/version.rs b/semver-parser/src/version.rs deleted file mode 100644 index 570f947..0000000 --- a/semver-parser/src/version.rs +++ /dev/null @@ -1,365 +0,0 @@ -use std::fmt; -use std::str::from_utf8; - -use recognize::*; - -use common::{self, numeric_identifier}; - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Version { - pub major: u64, - pub minor: u64, - pub patch: u64, - pub pre: Vec<Identifier>, - pub build: Vec<Identifier>, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Identifier { - /// An identifier that's solely numbers. - Numeric(u64), - /// An identifier with letters and numbers. - AlphaNumeric(String), -} - -pub fn parse(version: &str) -> Result<Version, String> { - let s = version.trim().as_bytes(); - let mut i = 0; - let major = if let Some((major, len)) = numeric_identifier(&s[i..]) { - i += len; - major - } else { - return Err("Error parsing major identifier".to_string()); - }; - if let Some(len) = b'.'.p(&s[i..]) { - i += len; - } else { - return Err("Expected dot".to_string()); - } - let minor = if let Some((minor, len)) = numeric_identifier(&s[i..]) { - i += len; - minor - } else { - return Err("Error parsing minor identifier".to_string()); - }; - if let Some(len) = b'.'.p(&s[i..]) { - i += len; - } else { - return Err("Expected dot".to_string()); - } - let patch = if let Some((patch, len)) = numeric_identifier(&s[i..]) { - i += len; - patch - } else { - return Err("Error parsing patch identifier".to_string()); - }; - let (pre, pre_len) = common::parse_optional_meta(&s[i..], b'-')?; - i += pre_len; - let (build, build_len) = common::parse_optional_meta(&s[i..], b'+')?; - i += build_len; - if i != s.len() { - return Err("Extra junk after valid version: ".to_string() + - from_utf8(&s[i..]).unwrap()); - } - Ok(Version { - major: major, - minor: minor, - patch: patch, - pre: pre, - build: build, - }) -} - -impl fmt::Display for Version { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{}.{}.{}", self.major, self.minor, self.patch)); - if !self.pre.is_empty() { - let strs: Vec<_> = - self.pre.iter().map(ToString::to_string).collect(); - try!(write!(f, "-{}", strs.join("."))); - } - if !self.build.is_empty() { - let strs: Vec<_> = - self.build.iter().map(ToString::to_string).collect(); - try!(write!(f, "+{}", strs.join("."))); - } - Ok(()) - } -} - -impl fmt::Display for Identifier { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Identifier::Numeric(ref id) => id.fmt(f), - Identifier::AlphaNumeric(ref id) => id.fmt(f), - } - } -} - -#[cfg(test)] -mod tests { - use version; - use super::*; - - #[test] - fn parse_empty() { - let version = ""; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "empty string incorrectly considered a valid parse"); - } - - #[test] - fn parse_blank() { - let version = " "; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "blank string incorrectly considered a valid parse"); - } - - #[test] - fn parse_no_minor_patch() { - let version = "1"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version)); - } - - #[test] - fn parse_no_patch() { - let version = "1.2"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version)); - } - - #[test] - fn parse_empty_pre() { - let version = "1.2.3-"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version)); - } - - #[test] - fn parse_letters() { - let version = "a.b.c"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version)); - } - - #[test] - fn parse_with_letters() { - let version = "1.2.3 a.b.c"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version)); - } - - #[test] - fn parse_basic_version() { - let version = "1.2.3"; - - let parsed = version::parse(version).unwrap(); - - assert_eq!(1, parsed.major); - assert_eq!(2, parsed.minor); - assert_eq!(3, parsed.patch); - } - - #[test] - fn parse_trims_input() { - let version = " 1.2.3 "; - - let parsed = version::parse(version).unwrap(); - - assert_eq!(1, parsed.major); - assert_eq!(2, parsed.minor); - assert_eq!(3, parsed.patch); - } - - #[test] - fn parse_no_major_leading_zeroes() { - let version = "01.0.0"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "01 incorrectly considered a valid major version"); - } - - #[test] - fn parse_no_minor_leading_zeroes() { - let version = "0.01.0"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "01 incorrectly considered a valid minor version"); - } - - #[test] - fn parse_no_patch_leading_zeroes() { - let version = "0.0.01"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "01 incorrectly considered a valid patch version"); - } - - #[test] - fn parse_no_major_overflow() { - let version = "98765432109876543210.0.0"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid major version"); - } - - #[test] - fn parse_no_minor_overflow() { - let version = "0.98765432109876543210.0"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid minor version"); - } - - #[test] - fn parse_no_patch_overflow() { - let version = "0.0.98765432109876543210"; - - let parsed = version::parse(version); - - assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid patch version"); - } - - #[test] - fn parse_basic_prerelease() { - let version = "1.2.3-pre"; - - let parsed = version::parse(version).unwrap(); - - let expected_pre = vec![Identifier::AlphaNumeric(String::from("pre"))]; - assert_eq!(expected_pre, parsed.pre); - } - - #[test] - fn parse_prerelease_alphanumeric() { - let version = "1.2.3-alpha1"; - - let parsed = version::parse(version).unwrap(); - - let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))]; - assert_eq!(expected_pre, parsed.pre); - } - - #[test] - fn parse_prerelease_zero() { - let version = "1.2.3-pre.0"; - - let parsed = version::parse(version).unwrap(); - - let expected_pre = vec![Identifier::AlphaNumeric(String::from("pre")), - Identifier::Numeric(0)]; - assert_eq!(expected_pre, parsed.pre); - } - - #[test] - fn parse_basic_build() { - let version = "1.2.3+build"; - - let parsed = version::parse(version).unwrap(); - - let expected_build = vec![Identifier::AlphaNumeric(String::from("build"))]; - assert_eq!(expected_build, parsed.build); - } - - #[test] - fn parse_build_alphanumeric() { - let version = "1.2.3+build5"; - - let parsed = version::parse(version).unwrap(); - - let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))]; - assert_eq!(expected_build, parsed.build); - } - - #[test] - fn parse_pre_and_build() { - let version = "1.2.3-alpha1+build5"; - - let parsed = version::parse(version).unwrap(); - - let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))]; - assert_eq!(expected_pre, parsed.pre); - - let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))]; - assert_eq!(expected_build, parsed.build); - } - - #[test] - fn parse_complex_metadata_01() { - let version = "1.2.3-1.alpha1.9+build5.7.3aedf "; - - let parsed = version::parse(version).unwrap(); - - let expected_pre = vec![Identifier::Numeric(1), - Identifier::AlphaNumeric(String::from("alpha1")), - Identifier::Numeric(9)]; - assert_eq!(expected_pre, parsed.pre); - - let expected_build = vec![Identifier::AlphaNumeric(String::from("build5")), - Identifier::Numeric(7), - Identifier::AlphaNumeric(String::from("3aedf"))]; - assert_eq!(expected_build, parsed.build); - } - - #[test] - fn parse_complex_metadata_02() { - let version = "0.4.0-beta.1+0851523"; - - let parsed = version::parse(version).unwrap(); - - let expected_pre = vec![Identifier::AlphaNumeric(String::from("beta")), - Identifier::Numeric(1)]; - assert_eq!(expected_pre, parsed.pre); - - let expected_build = vec![Identifier::AlphaNumeric(String::from("0851523"))]; - assert_eq!(expected_build, parsed.build); - } - - #[test] - fn parse_metadata_overflow() { - let version = "0.4.0-beta.1+98765432109876543210"; - - let parsed = version::parse(version).unwrap(); - - let expected_pre = vec![Identifier::AlphaNumeric(String::from("beta")), - Identifier::Numeric(1)]; - assert_eq!(expected_pre, parsed.pre); - - let expected_build = vec![Identifier::AlphaNumeric(String::from("98765432109876543210"))]; - assert_eq!(expected_build, parsed.build); - } - - #[test] - fn parse_regression_01() { - let version = "0.0.0-WIP"; - - let parsed = version::parse(version).unwrap(); - - assert_eq!(0, parsed.major); - assert_eq!(0, parsed.minor); - assert_eq!(0, parsed.patch); - - let expected_pre = vec![Identifier::AlphaNumeric(String::from("WIP"))]; - assert_eq!(expected_pre, parsed.pre); - } -} diff --git a/semver/.gitignore b/semver/.gitignore deleted file mode 100644 index cc3b589..0000000 --- a/semver/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -target/ -*.sw? -Cargo.lock diff --git a/semver/.travis.yml b/semver/.travis.yml deleted file mode 100644 index bb4ba27..0000000 --- a/semver/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: rust -rust: - - nightly - - beta - - stable -sudo: false -script: - - cargo build --verbose - - cargo test --verbose --features ci -addons: - apt: - sources: - - kalakris-cmake - packages: - - cmake -notifications: - email: - on_success: never diff --git a/semver/Cargo.toml b/semver/Cargo.toml deleted file mode 100644 index 1a31f59..0000000 --- a/semver/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] - -name = "semver" -version = "0.9.0" -authors = ["Steve Klabnik <steve@steveklabnik.com>", "The Rust Project Developers"] -license = "MIT/Apache-2.0" -repository = "https://github.com/steveklabnik/semver" -homepage = "https://docs.rs/crate/semver/" -documentation = "https://docs.rs/crate/semver/" -description = """ -Semantic version parsing and comparison. -""" -readme = "README.md" - -[badges] -travis-ci = { repository = "steveklabnik/semver" } - -[dependencies] -semver-parser = "0.7.0" -serde = { version = "1.0", optional = true } - -[features] -default = [] - -# are we testing on CI? -ci = ["serde"] - -[dev-dependencies] -crates-index = "0.5.0" -tempdir = "0.3.4" -serde_json = "1.0" -serde_derive = "1.0" diff --git a/semver/LICENSE-APACHE b/semver/LICENSE-APACHE deleted file mode 100644 index 16fe87b..0000000 --- a/semver/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/semver/LICENSE-MIT b/semver/LICENSE-MIT deleted file mode 100644 index 39d4bdb..0000000 --- a/semver/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/semver/README.md b/semver/README.md deleted file mode 100644 index 2a5306d..0000000 --- a/semver/README.md +++ /dev/null @@ -1,103 +0,0 @@ -semver -====== - -Semantic version parsing and comparison. - -[![Build Status](https://api.travis-ci.org/steveklabnik/semver.svg?branch=master)](https://travis-ci.org/steveklabnik/semver) - -[Documentation](https://steveklabnik.github.io/semver) - -Semantic versioning (see http://semver.org/) is a set of rules for -assigning version numbers. - -## SemVer and the Rust ecosystem - -Rust itself follows the SemVer specification, as does its standard libraries. The two are -not tied together. - -[Cargo](https://crates.io), Rust's package manager, uses SemVer to determine which versions of -packages you need installed. - -## Installation - -To use `semver`, add this to your `[dependencies]` section: - -```toml -semver = "0.7.0" -``` - -And this to your crate root: - -```rust -extern crate semver; -``` - -## Versions - -At its simplest, the `semver` crate allows you to construct `Version` objects using the `parse` -method: - -```rust -use semver::Version; - -assert!(Version::parse("1.2.3") == Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec!(), - build: vec!(), -})); -``` - -If you have multiple `Version`s, you can use the usual comparison operators to compare them: - -```rust -use semver::Version; - -assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta")); -assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); -``` - -## Requirements - -The `semver` crate also provides the ability to compare requirements, which are more complex -comparisons. - -For example, creating a requirement that only matches versions greater than or -equal to 1.0.0: - -```rust -use semver::Version; -use semver::VersionReq; - -let r = VersionReq::parse(">= 1.0.0").unwrap(); -let v = Version::parse("1.0.0").unwrap(); - -assert!(r.to_string() == ">= 1.0.0".to_string()); -assert!(r.matches(&v)) -``` - -It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at -https://www.npmjs.org/doc/misc/semver.html - -**Tilde requirements** specify a minimal version with some updates: - -```notrust -~1.2.3 := >=1.2.3 <1.3.0 -~1.2 := >=1.2.0 <1.3.0 -~1 := >=1.0.0 <2.0.0 -``` - -**Caret requirements** allow SemVer compatible updates to a specified version, -`0.x` and `0.x+1` are not considered compatible, but `1.x` and `1.x+1` are. - -`0.0.x` is not considered compatible with any other version. -Missing minor and patch versions are desugared to `0` but allow flexibility for that value. - -```notrust -^1.2.3 := >=1.2.3 <2.0.0 -^0.2.3 := >=0.2.3 <0.3.0 -^0.0.3 := >=0.0.3 <0.0.4 -^0.0 := >=0.0.0 <0.1.0 -^0 := >=0.0.0 <1.0.0 -``` diff --git a/semver/src/lib.rs b/semver/src/lib.rs deleted file mode 100644 index a38aae0..0000000 --- a/semver/src/lib.rs +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Semantic version parsing and comparison. -//! -//! Semantic versioning (see http://semver.org/) is a set of rules for -//! assigning version numbers. -//! -//! ## SemVer overview -//! -//! Given a version number MAJOR.MINOR.PATCH, increment the: -//! -//! 1. MAJOR version when you make incompatible API changes, -//! 2. MINOR version when you add functionality in a backwards-compatible -//! manner, and -//! 3. PATCH version when you make backwards-compatible bug fixes. -//! -//! Additional labels for pre-release and build metadata are available as -//! extensions to the MAJOR.MINOR.PATCH format. -//! -//! Any references to 'the spec' in this documentation refer to [version 2.0 of -//! the SemVer spec](http://semver.org/spec/v2.0.0.html). -//! -//! ## SemVer and the Rust ecosystem -//! -//! Rust itself follows the SemVer specification, as does its standard -//! libraries. The two are not tied together. -//! -//! [Cargo](http://crates.io), Rust's package manager, uses SemVer to determine -//! which versions of packages you need installed. -//! -//! ## Versions -//! -//! At its simplest, the `semver` crate allows you to construct `Version` -//! objects using the `parse` method: -//! -//! ```{rust} -//! use semver::Version; -//! -//! assert!(Version::parse("1.2.3") == Ok(Version { -//! major: 1, -//! minor: 2, -//! patch: 3, -//! pre: vec!(), -//! build: vec!(), -//! })); -//! ``` -//! -//! If you have multiple `Version`s, you can use the usual comparison operators -//! to compare them: -//! -//! ```{rust} -//! use semver::Version; -//! -//! assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta")); -//! assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); -//! ``` -//! -//! If you explicitly need to modify a Version, SemVer also allows you to -//! increment the major, minor, and patch numbers in accordance with the spec. -//! -//! Please note that in order to do this, you must use a mutable Version: -//! -//! ```{rust} -//! use semver::Version; -//! -//! let mut bugfix_release = Version::parse("1.0.0").unwrap(); -//! bugfix_release.increment_patch(); -//! -//! assert_eq!(Ok(bugfix_release), Version::parse("1.0.1")); -//! ``` -//! -//! When incrementing the minor version number, the patch number resets to zero -//! (in accordance with section 7 of the spec) -//! -//! ```{rust} -//! use semver::Version; -//! -//! let mut feature_release = Version::parse("1.4.6").unwrap(); -//! feature_release.increment_minor(); -//! -//! assert_eq!(Ok(feature_release), Version::parse("1.5.0")); -//! ``` -//! -//! Similarly, when incrementing the major version number, the patch and minor -//! numbers reset to zero (in accordance with section 8 of the spec) -//! -//! ```{rust} -//! use semver::Version; -//! -//! let mut chrome_release = Version::parse("41.5.5377").unwrap(); -//! chrome_release.increment_major(); -//! -//! assert_eq!(Ok(chrome_release), Version::parse("42.0.0")); -//! ``` -//! -//! ## Requirements -//! -//! The `semver` crate also provides the ability to compare requirements, which -//! are more complex comparisons. -//! -//! For example, creating a requirement that only matches versions greater than -//! or equal to 1.0.0: -//! -//! ```{rust} -//! # #![allow(unstable)] -//! use semver::Version; -//! use semver::VersionReq; -//! -//! let r = VersionReq::parse(">= 1.0.0").unwrap(); -//! let v = Version::parse("1.0.0").unwrap(); -//! -//! assert!(r.to_string() == ">= 1.0.0".to_string()); -//! assert!(r.matches(&v)) -//! ``` -//! -//! It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at -//! https://www.npmjs.org/doc/misc/semver.html -//! -//! **Tilde requirements** specify a minimal version with some updates: -//! -//! ```notrust -//! ~1.2.3 := >=1.2.3 <1.3.0 -//! ~1.2 := >=1.2.0 <1.3.0 -//! ~1 := >=1.0.0 <2.0.0 -//! ``` -//! -//! **Caret requirements** allow SemVer compatible updates to a specified -//! verion, `0.x` and `0.x+1` are not considered compatible, but `1.x` and -//! `1.x+1` are. -//! -//! `0.0.x` is not considered compatible with any other version. -//! Missing minor and patch versions are desugared to `0` but allow flexibility -//! for that value. -//! -//! ```notrust -//! ^1.2.3 := >=1.2.3 <2.0.0 -//! ^0.2.3 := >=0.2.3 <0.3.0 -//! ^0.0.3 := >=0.0.3 <0.0.4 -//! ^0.0 := >=0.0.0 <0.1.0 -//! ^0 := >=0.0.0 <1.0.0 -//! ``` -//! -//! **Wildcard requirements** allows parsing of version requirements of the -//! formats `*`, `x.*` and `x.y.*`. -//! -//! ```notrust -//! * := >=0.0.0 -//! 1.* := >=1.0.0 <2.0.0 -//! 1.2.* := >=1.2.0 <1.3.0 -//! ``` - -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico")] -#![deny(missing_docs)] -#![cfg_attr(test, deny(warnings))] - -extern crate semver_parser; - -// Serialization and deserialization support for version numbers -#[cfg(feature = "serde")] -extern crate serde; - -// We take the common approach of keeping our own module system private, and -// just re-exporting the interface that we want. - -pub use version::{Version, Identifier, SemVerError}; -pub use version::Identifier::{Numeric, AlphaNumeric}; -pub use version_req::{VersionReq, ReqParseError}; - -// SemVer-compliant versions. -mod version; - -// advanced version comparisons -mod version_req; diff --git a/semver/src/version.rs b/semver/src/version.rs deleted file mode 100644 index 38de133..0000000 --- a/semver/src/version.rs +++ /dev/null @@ -1,759 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The `version` module gives you tools to create and compare SemVer-compliant -//! versions. - -use std::cmp::{self, Ordering}; -use std::fmt; -use std::hash; -use std::error::Error; - -use std::result; -use std::str; - -use semver_parser; - -#[cfg(feature = "serde")] -use serde::ser::{Serialize, Serializer}; -#[cfg(feature = "serde")] -use serde::de::{self, Deserialize, Deserializer, Visitor}; - -/// An identifier in the pre-release or build metadata. -/// -/// See sections 9 and 10 of the spec for more about pre-release identifers and -/// build metadata. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub enum Identifier { - /// An identifier that's solely numbers. - Numeric(u64), - /// An identifier with letters and numbers. - AlphaNumeric(String), -} - -impl From<semver_parser::version::Identifier> for Identifier { - fn from(other: semver_parser::version::Identifier) -> Identifier { - match other { - semver_parser::version::Identifier::Numeric(n) => Identifier::Numeric(n), - semver_parser::version::Identifier::AlphaNumeric(s) => Identifier::AlphaNumeric(s), - } - } -} - -impl fmt::Display for Identifier { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Identifier::Numeric(ref n) => fmt::Display::fmt(n, f), - Identifier::AlphaNumeric(ref s) => fmt::Display::fmt(s, f), - } - } -} - -#[cfg(feature = "serde")] -impl Serialize for Identifier { - fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error> - where S: Serializer - { - // Serialize Identifier as a number or string. - match *self { - Identifier::Numeric(n) => serializer.serialize_u64(n), - Identifier::AlphaNumeric(ref s) => serializer.serialize_str(s), - } - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Identifier { - fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error> - where D: Deserializer<'de> - { - struct IdentifierVisitor; - - // Deserialize Identifier from a number or string. - impl<'de> Visitor<'de> for IdentifierVisitor { - type Value = Identifier; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a SemVer pre-release or build identifier") - } - - fn visit_u64<E>(self, numeric: u64) -> result::Result<Self::Value, E> - where E: de::Error - { - Ok(Identifier::Numeric(numeric)) - } - - fn visit_str<E>(self, alphanumeric: &str) -> result::Result<Self::Value, E> - where E: de::Error - { - Ok(Identifier::AlphaNumeric(alphanumeric.to_owned())) - } - } - - deserializer.deserialize_any(IdentifierVisitor) - } -} - -/// Represents a version number conforming to the semantic versioning scheme. -#[derive(Clone, Eq, Debug)] -pub struct Version { - /// The major version, to be incremented on incompatible changes. - pub major: u64, - /// The minor version, to be incremented when functionality is added in a - /// backwards-compatible manner. - pub minor: u64, - /// The patch version, to be incremented when backwards-compatible bug - /// fixes are made. - pub patch: u64, - /// The pre-release version identifier, if one exists. - pub pre: Vec<Identifier>, - /// The build metadata, ignored when determining version precedence. - pub build: Vec<Identifier>, -} - -impl From<semver_parser::version::Version> for Version { - fn from(other: semver_parser::version::Version) -> Version { - Version { - major: other.major, - minor: other.minor, - patch: other.patch, - pre: other.pre.into_iter().map(From::from).collect(), - build: other.build.into_iter().map(From::from).collect(), - } - } -} - -#[cfg(feature = "serde")] -impl Serialize for Version { - fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error> - where S: Serializer - { - // Serialize Version as a string. - serializer.collect_str(self) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Version { - fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error> - where D: Deserializer<'de> - { - struct VersionVisitor; - - // Deserialize Version from a string. - impl<'de> Visitor<'de> for VersionVisitor { - type Value = Version; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a SemVer version as a string") - } - - fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E> - where E: de::Error - { - Version::parse(v).map_err(de::Error::custom) - } - } - - deserializer.deserialize_str(VersionVisitor) - } -} - -/// An error type for this crate -/// -/// Currently, just a generic error. Will make this nicer later. -#[derive(Clone,PartialEq,Debug,PartialOrd)] -pub enum SemVerError { - /// An error ocurred while parsing. - ParseError(String), -} - -impl fmt::Display for SemVerError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &SemVerError::ParseError(ref m) => write!(f, "{}", m), - } - } -} - -impl Error for SemVerError { - fn description(&self) -> &str { - match self { - &SemVerError::ParseError(ref m) => m, - } - } -} - -/// A Result type for errors -pub type Result<T> = result::Result<T, SemVerError>; - -impl Version { - - /// Contructs the simple case without pre or build. - pub fn new(major: u64, minor: u64, patch: u64) -> Version { - Version { - major: major, - minor: minor, - patch: patch, - pre: Vec::new(), - build: Vec::new() - } - } - - /// Parse a string into a semver object. - pub fn parse(version: &str) -> Result<Version> { - let res = semver_parser::version::parse(version); - - match res { - // Convert plain String error into proper ParseError - Err(e) => Err(SemVerError::ParseError(e)), - Ok(v) => Ok(From::from(v)), - } - } - - /// Clears the build metadata - fn clear_metadata(&mut self) { - self.build = Vec::new(); - self.pre = Vec::new(); - } - - /// Increments the patch number for this Version (Must be mutable) - pub fn increment_patch(&mut self) { - self.patch += 1; - self.clear_metadata(); - } - - /// Increments the minor version number for this Version (Must be mutable) - /// - /// As instructed by section 7 of the spec, the patch number is reset to 0. - pub fn increment_minor(&mut self) { - self.minor += 1; - self.patch = 0; - self.clear_metadata(); - } - - /// Increments the major version number for this Version (Must be mutable) - /// - /// As instructed by section 8 of the spec, the minor and patch numbers are - /// reset to 0 - pub fn increment_major(&mut self) { - self.major += 1; - self.minor = 0; - self.patch = 0; - self.clear_metadata(); - } - - /// Checks to see if the current Version is in pre-release status - pub fn is_prerelease(&self) -> bool { - !self.pre.is_empty() - } -} - -impl str::FromStr for Version { - type Err = SemVerError; - - fn from_str(s: &str) -> Result<Version> { - Version::parse(s) - } -} - -impl fmt::Display for Version { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{}.{}.{}", self.major, self.minor, self.patch)); - if !self.pre.is_empty() { - try!(write!(f, "-")); - for (i, x) in self.pre.iter().enumerate() { - if i != 0 { - try!(write!(f, ".")) - } - try!(write!(f, "{}", x)); - } - } - if !self.build.is_empty() { - try!(write!(f, "+")); - for (i, x) in self.build.iter().enumerate() { - if i != 0 { - try!(write!(f, ".")) - } - try!(write!(f, "{}", x)); - } - } - Ok(()) - } -} - -impl cmp::PartialEq for Version { - #[inline] - fn eq(&self, other: &Version) -> bool { - // We should ignore build metadata here, otherwise versions v1 and v2 - // can exist such that !(v1 < v2) && !(v1 > v2) && v1 != v2, which - // violate strict total ordering rules. - self.major == other.major && self.minor == other.minor && self.patch == other.patch && - self.pre == other.pre - } -} - -impl cmp::PartialOrd for Version { - fn partial_cmp(&self, other: &Version) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl cmp::Ord for Version { - fn cmp(&self, other: &Version) -> Ordering { - match self.major.cmp(&other.major) { - Ordering::Equal => {} - r => return r, - } - - match self.minor.cmp(&other.minor) { - Ordering::Equal => {} - r => return r, - } - - match self.patch.cmp(&other.patch) { - Ordering::Equal => {} - r => return r, - } - - // NB: semver spec says 0.0.0-pre < 0.0.0 - // but the version of ord defined for vec - // says that [] < [pre] so we alter it here - match (self.pre.len(), other.pre.len()) { - (0, 0) => Ordering::Equal, - (0, _) => Ordering::Greater, - (_, 0) => Ordering::Less, - (_, _) => self.pre.cmp(&other.pre), - } - } -} - -impl hash::Hash for Version { - fn hash<H: hash::Hasher>(&self, into: &mut H) { - self.major.hash(into); - self.minor.hash(into); - self.patch.hash(into); - self.pre.hash(into); - } -} - -impl From<(u64,u64,u64)> for Version { - fn from(tuple: (u64,u64,u64)) -> Version { - let (major, minor, patch) = tuple; - Version::new(major, minor, patch) - } -} - -#[cfg(test)] -mod tests { - use std::result; - use super::Version; - use super::Identifier; - use super::SemVerError; - - #[test] - fn test_parse() { - fn parse_error(e: &str) -> result::Result<Version, SemVerError> { - return Err(SemVerError::ParseError(e.to_string())); - } - - assert_eq!(Version::parse(""), - parse_error("Error parsing major identifier")); - assert_eq!(Version::parse(" "), - parse_error("Error parsing major identifier")); - assert_eq!(Version::parse("1"), - parse_error("Expected dot")); - assert_eq!(Version::parse("1.2"), - parse_error("Expected dot")); - assert_eq!(Version::parse("1.2.3-"), - parse_error("Error parsing prerelease")); - assert_eq!(Version::parse("a.b.c"), - parse_error("Error parsing major identifier")); - assert_eq!(Version::parse("1.2.3 abc"), - parse_error("Extra junk after valid version: abc")); - - assert_eq!(Version::parse("1.2.3"), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: Vec::new(), - })); - - assert_eq!(Version::parse("1.2.3"), - Ok(Version::new(1,2,3))); - - assert_eq!(Version::parse(" 1.2.3 "), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: Vec::new(), - })); - assert_eq!(Version::parse("1.2.3-alpha1"), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: Vec::new(), - })); - assert_eq!(Version::parse(" 1.2.3-alpha1 "), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: Vec::new(), - })); - assert_eq!(Version::parse("1.2.3+build5"), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!(Version::parse(" 1.2.3+build5 "), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!(Version::parse("1.2.3-alpha1+build5"), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!(Version::parse(" 1.2.3-alpha1+build5 "), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!(Version::parse("1.2.3-1.alpha1.9+build5.7.3aedf "), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::Numeric(1), - Identifier::AlphaNumeric(String::from("alpha1")), - Identifier::Numeric(9), - ], - build: vec![Identifier::AlphaNumeric(String::from("build5")), - Identifier::Numeric(7), - Identifier::AlphaNumeric(String::from("3aedf")), - ], - })); - assert_eq!(Version::parse("0.4.0-beta.1+0851523"), - Ok(Version { - major: 0, - minor: 4, - patch: 0, - pre: vec![Identifier::AlphaNumeric(String::from("beta")), - Identifier::Numeric(1), - ], - build: vec![Identifier::AlphaNumeric(String::from("0851523"))], - })); - - } - - #[test] - fn test_increment_patch() { - let mut buggy_release = Version::parse("0.1.0").unwrap(); - buggy_release.increment_patch(); - assert_eq!(buggy_release, Version::parse("0.1.1").unwrap()); - } - - #[test] - fn test_increment_minor() { - let mut feature_release = Version::parse("1.4.6").unwrap(); - feature_release.increment_minor(); - assert_eq!(feature_release, Version::parse("1.5.0").unwrap()); - } - - #[test] - fn test_increment_major() { - let mut chrome_release = Version::parse("46.1.246773").unwrap(); - chrome_release.increment_major(); - assert_eq!(chrome_release, Version::parse("47.0.0").unwrap()); - } - - #[test] - fn test_increment_keep_prerelease() { - let mut release = Version::parse("1.0.0-alpha").unwrap(); - release.increment_patch(); - - assert_eq!(release, Version::parse("1.0.1").unwrap()); - - release.increment_minor(); - - assert_eq!(release, Version::parse("1.1.0").unwrap()); - - release.increment_major(); - - assert_eq!(release, Version::parse("2.0.0").unwrap()); - } - - - #[test] - fn test_increment_clear_metadata() { - let mut release = Version::parse("1.0.0+4442").unwrap(); - release.increment_patch(); - - assert_eq!(release, Version::parse("1.0.1").unwrap()); - release = Version::parse("1.0.1+hello").unwrap(); - - release.increment_minor(); - - assert_eq!(release, Version::parse("1.1.0").unwrap()); - release = Version::parse("1.1.3747+hello").unwrap(); - - release.increment_major(); - - assert_eq!(release, Version::parse("2.0.0").unwrap()); - } - - #[test] - fn test_eq() { - assert_eq!(Version::parse("1.2.3"), Version::parse("1.2.3")); - assert_eq!(Version::parse("1.2.3-alpha1"), - Version::parse("1.2.3-alpha1")); - assert_eq!(Version::parse("1.2.3+build.42"), - Version::parse("1.2.3+build.42")); - assert_eq!(Version::parse("1.2.3-alpha1+42"), - Version::parse("1.2.3-alpha1+42")); - assert_eq!(Version::parse("1.2.3+23"), Version::parse("1.2.3+42")); - } - - #[test] - fn test_ne() { - assert!(Version::parse("0.0.0") != Version::parse("0.0.1")); - assert!(Version::parse("0.0.0") != Version::parse("0.1.0")); - assert!(Version::parse("0.0.0") != Version::parse("1.0.0")); - assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta")); - } - - #[test] - fn test_show() { - assert_eq!(format!("{}", Version::parse("1.2.3").unwrap()), - "1.2.3".to_string()); - assert_eq!(format!("{}", Version::parse("1.2.3-alpha1").unwrap()), - "1.2.3-alpha1".to_string()); - assert_eq!(format!("{}", Version::parse("1.2.3+build.42").unwrap()), - "1.2.3+build.42".to_string()); - assert_eq!(format!("{}", Version::parse("1.2.3-alpha1+42").unwrap()), - "1.2.3-alpha1+42".to_string()); - } - - #[test] - fn test_to_string() { - assert_eq!(Version::parse("1.2.3").unwrap().to_string(), - "1.2.3".to_string()); - assert_eq!(Version::parse("1.2.3-alpha1").unwrap().to_string(), - "1.2.3-alpha1".to_string()); - assert_eq!(Version::parse("1.2.3+build.42").unwrap().to_string(), - "1.2.3+build.42".to_string()); - assert_eq!(Version::parse("1.2.3-alpha1+42").unwrap().to_string(), - "1.2.3-alpha1+42".to_string()); - } - - #[test] - fn test_lt() { - assert!(Version::parse("0.0.0") < Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.0.0") < Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.2.0") < Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3")); - assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3-alpha2")); - assert!(!(Version::parse("1.2.3-alpha2") < Version::parse("1.2.3-alpha2"))); - assert!(!(Version::parse("1.2.3+23") < Version::parse("1.2.3+42"))); - } - - #[test] - fn test_le() { - assert!(Version::parse("0.0.0") <= Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.0.0") <= Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.2.0") <= Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.2.3-alpha1") <= Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.2.3-alpha2") <= Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.2.3+23") <= Version::parse("1.2.3+42")); - } - - #[test] - fn test_gt() { - assert!(Version::parse("1.2.3-alpha2") > Version::parse("0.0.0")); - assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.0.0")); - assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); - assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha1")); - assert!(Version::parse("1.2.3") > Version::parse("1.2.3-alpha2")); - assert!(!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha2"))); - assert!(!(Version::parse("1.2.3+23") > Version::parse("1.2.3+42"))); - } - - #[test] - fn test_ge() { - assert!(Version::parse("1.2.3-alpha2") >= Version::parse("0.0.0")); - assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.0.0")); - assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.0")); - assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha1")); - assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha2")); - assert!(Version::parse("1.2.3+23") >= Version::parse("1.2.3+42")); - } - - #[test] - fn test_prerelease_check() { - assert!(Version::parse("1.0.0").unwrap().is_prerelease() == false); - assert!(Version::parse("0.0.1").unwrap().is_prerelease() == false); - assert!(Version::parse("4.1.4-alpha").unwrap().is_prerelease()); - assert!(Version::parse("1.0.0-beta294296").unwrap().is_prerelease()); - } - - #[test] - fn test_spec_order() { - let vs = ["1.0.0-alpha", - "1.0.0-alpha.1", - "1.0.0-alpha.beta", - "1.0.0-beta", - "1.0.0-beta.2", - "1.0.0-beta.11", - "1.0.0-rc.1", - "1.0.0"]; - let mut i = 1; - while i < vs.len() { - let a = Version::parse(vs[i - 1]); - let b = Version::parse(vs[i]); - assert!(a < b, "nope {:?} < {:?}", a, b); - i += 1; - } - } - - #[test] - fn test_from_str() { - assert_eq!("1.2.3".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: Vec::new(), - })); - assert_eq!(" 1.2.3 ".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: Vec::new(), - })); - assert_eq!("1.2.3-alpha1".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: Vec::new(), - })); - assert_eq!(" 1.2.3-alpha1 ".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: Vec::new(), - })); - assert_eq!("1.2.3+build5".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!(" 1.2.3+build5 ".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: Vec::new(), - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!("1.2.3-alpha1+build5".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!(" 1.2.3-alpha1+build5 ".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], - build: vec![Identifier::AlphaNumeric(String::from("build5"))], - })); - assert_eq!("1.2.3-1.alpha1.9+build5.7.3aedf ".parse(), - Ok(Version { - major: 1, - minor: 2, - patch: 3, - pre: vec![Identifier::Numeric(1), - Identifier::AlphaNumeric(String::from("alpha1")), - Identifier::Numeric(9), - ], - build: vec![Identifier::AlphaNumeric(String::from("build5")), - Identifier::Numeric(7), - Identifier::AlphaNumeric(String::from("3aedf")), - ], - })); - assert_eq!("0.4.0-beta.1+0851523".parse(), - Ok(Version { - major: 0, - minor: 4, - patch: 0, - pre: vec![Identifier::AlphaNumeric(String::from("beta")), - Identifier::Numeric(1), - ], - build: vec![Identifier::AlphaNumeric(String::from("0851523"))], - })); - - } - - #[test] - fn test_from_str_errors() { - fn parse_error(e: &str) -> result::Result<Version, SemVerError> { - return Err(SemVerError::ParseError(e.to_string())); - } - - assert_eq!("".parse(), parse_error("Error parsing major identifier")); - assert_eq!(" ".parse(), parse_error("Error parsing major identifier")); - assert_eq!("1".parse(), parse_error("Expected dot")); - assert_eq!("1.2".parse(), - parse_error("Expected dot")); - assert_eq!("1.2.3-".parse(), - parse_error("Error parsing prerelease")); - assert_eq!("a.b.c".parse(), - parse_error("Error parsing major identifier")); - assert_eq!("1.2.3 abc".parse(), - parse_error("Extra junk after valid version: abc")); - } -} diff --git a/semver/src/version_req.rs b/semver/src/version_req.rs deleted file mode 100644 index 6e6a542..0000000 --- a/semver/src/version_req.rs +++ /dev/null @@ -1,895 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::error::Error; -use std::fmt; -use std::result; -use std::str; - -use Version; -use version::Identifier; -use semver_parser; - -#[cfg(feature = "serde")] -use serde::ser::{Serialize, Serializer}; -#[cfg(feature = "serde")] -use serde::de::{self, Deserialize, Deserializer, Visitor}; - -use self::Op::{Ex, Gt, GtEq, Lt, LtEq, Tilde, Compatible, Wildcard}; -use self::WildcardVersion::{Major, Minor, Patch}; -use self::ReqParseError::*; - -/// A `VersionReq` is a struct containing a list of predicates that can apply to ranges of version -/// numbers. Matching operations can then be done with the `VersionReq` against a particular -/// version to see if it satisfies some or all of the constraints. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct VersionReq { - predicates: Vec<Predicate>, -} - -impl From<semver_parser::range::VersionReq> for VersionReq { - fn from(other: semver_parser::range::VersionReq) -> VersionReq { - VersionReq { predicates: other.predicates.into_iter().map(From::from).collect() } - } -} - -#[cfg(feature = "serde")] -impl Serialize for VersionReq { - fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error> - where S: Serializer - { - // Serialize VersionReq as a string. - serializer.collect_str(self) - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for VersionReq { - fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error> - where D: Deserializer<'de> - { - struct VersionReqVisitor; - - /// Deserialize `VersionReq` from a string. - impl<'de> Visitor<'de> for VersionReqVisitor { - type Value = VersionReq; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a SemVer version requirement as a string") - } - - fn visit_str<E>(self, v: &str) -> result::Result<Self::Value, E> - where E: de::Error - { - VersionReq::parse(v).map_err(de::Error::custom) - } - } - - deserializer.deserialize_str(VersionReqVisitor) - } -} - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -enum WildcardVersion { - Major, - Minor, - Patch, -} - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -enum Op { - Ex, // Exact - Gt, // Greater than - GtEq, // Greater than or equal to - Lt, // Less than - LtEq, // Less than or equal to - Tilde, // e.g. ~1.0.0 - Compatible, // compatible by definition of semver, indicated by ^ - Wildcard(WildcardVersion), // x.y.*, x.*, * -} - -impl From<semver_parser::range::Op> for Op { - fn from(other: semver_parser::range::Op) -> Op { - use semver_parser::range; - match other { - range::Op::Ex => Op::Ex, - range::Op::Gt => Op::Gt, - range::Op::GtEq => Op::GtEq, - range::Op::Lt => Op::Lt, - range::Op::LtEq => Op::LtEq, - range::Op::Tilde => Op::Tilde, - range::Op::Compatible => Op::Compatible, - range::Op::Wildcard(version) => { - match version { - range::WildcardVersion::Major => Op::Wildcard(WildcardVersion::Major), - range::WildcardVersion::Minor => Op::Wildcard(WildcardVersion::Minor), - range::WildcardVersion::Patch => Op::Wildcard(WildcardVersion::Patch), - } - } - } - } -} - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -struct Predicate { - op: Op, - major: u64, - minor: Option<u64>, - patch: Option<u64>, - pre: Vec<Identifier>, -} - -impl From<semver_parser::range::Predicate> for Predicate { - fn from(other: semver_parser::range::Predicate) -> Predicate { - Predicate { - op: From::from(other.op), - major: other.major, - minor: other.minor, - patch: other.patch, - pre: other.pre.into_iter().map(From::from).collect(), - } - } -} - -/// A `ReqParseError` is returned from methods which parse a string into a `VersionReq`. Each -/// enumeration is one of the possible errors that can occur. -#[derive(Clone, Debug, PartialEq)] -pub enum ReqParseError { - /// The given version requirement is invalid. - InvalidVersionRequirement, - /// You have already provided an operation, such as `=`, `~`, or `^`. Only use one. - OpAlreadySet, - /// The sigil you have written is not correct. - InvalidSigil, - /// All components of a version must be numeric. - VersionComponentsMustBeNumeric, - /// There was an error parsing an identifier. - InvalidIdentifier, - /// At least a major version is required. - MajorVersionRequired, - /// An unimplemented version requirement. - UnimplementedVersionRequirement, - /// This form of requirement is deprecated. - DeprecatedVersionRequirement(VersionReq), -} - -impl fmt::Display for ReqParseError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.description().fmt(f) - } -} - -impl Error for ReqParseError { - fn description(&self) -> &str { - match self { - &InvalidVersionRequirement => "the given version requirement is invalid", - &OpAlreadySet => { - "you have already provided an operation, such as =, ~, or ^; only use one" - }, - &InvalidSigil => "the sigil you have written is not correct", - &VersionComponentsMustBeNumeric => "version components must be numeric", - &InvalidIdentifier => "invalid identifier", - &MajorVersionRequired => "at least a major version number is required", - &UnimplementedVersionRequirement => { - "the given version requirement is not implemented, yet" - }, - &DeprecatedVersionRequirement(_) => "This requirement is deprecated", - } - } -} - -impl From<String> for ReqParseError { - fn from(other: String) -> ReqParseError { - match &*other { - "Null is not a valid VersionReq" => ReqParseError::InvalidVersionRequirement, - "VersionReq did not parse properly." => ReqParseError::OpAlreadySet, - _ => ReqParseError::InvalidVersionRequirement, - } - } -} - -impl VersionReq { - /// `any()` is a factory method which creates a `VersionReq` with no constraints. In other - /// words, any version will match against it. - /// - /// # Examples - /// - /// ``` - /// use semver::VersionReq; - /// - /// let anything = VersionReq::any(); - /// ``` - pub fn any() -> VersionReq { - VersionReq { predicates: vec![] } - } - - /// `parse()` is the main constructor of a `VersionReq`. It takes a string like `"^1.2.3"` - /// and turns it into a `VersionReq` that matches that particular constraint. - /// - /// A `Result` is returned which contains a `ReqParseError` if there was a problem parsing the - /// `VersionReq`. - /// - /// # Examples - /// - /// ``` - /// use semver::VersionReq; - /// - /// let version = VersionReq::parse("=1.2.3"); - /// let version = VersionReq::parse(">1.2.3"); - /// let version = VersionReq::parse("<1.2.3"); - /// let version = VersionReq::parse("~1.2.3"); - /// let version = VersionReq::parse("^1.2.3"); - /// let version = VersionReq::parse("1.2.3"); // synonym for ^1.2.3 - /// let version = VersionReq::parse("<=1.2.3"); - /// let version = VersionReq::parse(">=1.2.3"); - /// ``` - /// - /// This example demonstrates error handling, and will panic. - /// - /// ```should-panic - /// use semver::VersionReq; - /// - /// let version = match VersionReq::parse("not a version") { - /// Ok(version) => version, - /// Err(e) => panic!("There was a problem parsing: {}", e), - /// } - /// ``` - pub fn parse(input: &str) -> Result<VersionReq, ReqParseError> { - let res = semver_parser::range::parse(input); - - if let Ok(v) = res { - return Ok(From::from(v)); - } - - return match VersionReq::parse_deprecated(input) { - Some(v) => { - Err(ReqParseError::DeprecatedVersionRequirement(v)) - } - None => Err(From::from(res.err().unwrap())), - } - } - - fn parse_deprecated(version: &str) -> Option<VersionReq> { - return match version { - ".*" => Some(VersionReq::any()), - "0.1.0." => Some(VersionReq::parse("0.1.0").unwrap()), - "0.3.1.3" => Some(VersionReq::parse("0.3.13").unwrap()), - "0.2*" => Some(VersionReq::parse("0.2.*").unwrap()), - "*.0" => Some(VersionReq::any()), - _ => None, - } - } - - /// `exact()` is a factory method which creates a `VersionReq` with one exact constraint. - /// - /// # Examples - /// - /// ``` - /// use semver::VersionReq; - /// use semver::Version; - /// - /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] }; - /// let exact = VersionReq::exact(&version); - /// ``` - pub fn exact(version: &Version) -> VersionReq { - VersionReq { predicates: vec![Predicate::exact(version)] } - } - - /// `matches()` matches a given `Version` against this `VersionReq`. - /// - /// # Examples - /// - /// ``` - /// use semver::VersionReq; - /// use semver::Version; - /// - /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] }; - /// let exact = VersionReq::exact(&version); - /// - /// assert!(exact.matches(&version)); - /// ``` - pub fn matches(&self, version: &Version) -> bool { - // no predicates means anything matches - if self.predicates.is_empty() { - return true; - } - - self.predicates.iter().all(|p| p.matches(version)) && - self.predicates.iter().any(|p| p.pre_tag_is_compatible(version)) - } -} - -impl str::FromStr for VersionReq { - type Err = ReqParseError; - - fn from_str(s: &str) -> Result<VersionReq, ReqParseError> { - VersionReq::parse(s) - } -} - -impl Predicate { - fn exact(version: &Version) -> Predicate { - Predicate { - op: Ex, - major: version.major, - minor: Some(version.minor), - patch: Some(version.patch), - pre: version.pre.clone(), - } - } - - /// `matches()` takes a `Version` and determines if it matches this particular `Predicate`. - pub fn matches(&self, ver: &Version) -> bool { - match self.op { - Ex => self.is_exact(ver), - Gt => self.is_greater(ver), - GtEq => self.is_exact(ver) || self.is_greater(ver), - Lt => !self.is_exact(ver) && !self.is_greater(ver), - LtEq => !self.is_greater(ver), - Tilde => self.matches_tilde(ver), - Compatible => self.is_compatible(ver), - Wildcard(_) => self.matches_wildcard(ver), - } - } - - fn is_exact(&self, ver: &Version) -> bool { - if self.major != ver.major { - return false; - } - - match self.minor { - Some(minor) => { - if minor != ver.minor { - return false; - } - } - None => return true, - } - - match self.patch { - Some(patch) => { - if patch != ver.patch { - return false; - } - } - None => return true, - } - - if self.pre != ver.pre { - return false; - } - - true - } - - // https://docs.npmjs.com/misc/semver#prerelease-tags - fn pre_tag_is_compatible(&self, ver: &Version) -> bool { - // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it will - // only be - // allowed to satisfy comparator sets if at least one comparator with the same - // [major, - // minor, patch] tuple also has a prerelease tag. - !ver.is_prerelease() || - (self.major == ver.major && self.minor == Some(ver.minor) && - self.patch == Some(ver.patch) && !self.pre.is_empty()) - } - - fn is_greater(&self, ver: &Version) -> bool { - if self.major != ver.major { - return ver.major > self.major; - } - - match self.minor { - Some(minor) => { - if minor != ver.minor { - return ver.minor > minor; - } - } - None => return false, - } - - match self.patch { - Some(patch) => { - if patch != ver.patch { - return ver.patch > patch; - } - } - None => return false, - } - - if !self.pre.is_empty() { - return ver.pre.is_empty() || ver.pre > self.pre; - } - - false - } - - // see https://www.npmjs.org/doc/misc/semver.html for behavior - fn matches_tilde(&self, ver: &Version) -> bool { - let minor = match self.minor { - Some(n) => n, - None => return self.major == ver.major, - }; - - match self.patch { - Some(patch) => { - self.major == ver.major && minor == ver.minor && - (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver))) - } - None => self.major == ver.major && minor == ver.minor, - } - } - - // see https://www.npmjs.org/doc/misc/semver.html for behavior - fn is_compatible(&self, ver: &Version) -> bool { - if self.major != ver.major { - return false; - } - - let minor = match self.minor { - Some(n) => n, - None => return self.major == ver.major, - }; - - match self.patch { - Some(patch) => { - if self.major == 0 { - if minor == 0 { - ver.minor == minor && ver.patch == patch && self.pre_is_compatible(ver) - } else { - ver.minor == minor && - (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver))) - } - } else { - ver.minor > minor || - (ver.minor == minor && - (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver)))) - } - } - None => { - if self.major == 0 { - ver.minor == minor - } else { - ver.minor >= minor - } - } - } - } - - fn pre_is_compatible(&self, ver: &Version) -> bool { - ver.pre.is_empty() || ver.pre >= self.pre - } - - // see https://www.npmjs.org/doc/misc/semver.html for behavior - fn matches_wildcard(&self, ver: &Version) -> bool { - match self.op { - Wildcard(Major) => true, - Wildcard(Minor) => self.major == ver.major, - Wildcard(Patch) => { - match self.minor { - Some(minor) => self.major == ver.major && minor == ver.minor, - None => { - // minor and patch version astericks mean match on major - self.major == ver.major - } - } - } - _ => false, // unreachable - } - } -} - -impl fmt::Display for VersionReq { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - if self.predicates.is_empty() { - try!(write!(fmt, "*")); - } else { - for (i, ref pred) in self.predicates.iter().enumerate() { - if i == 0 { - try!(write!(fmt, "{}", pred)); - } else { - try!(write!(fmt, ", {}", pred)); - } - } - } - - Ok(()) - } -} - -impl fmt::Display for Predicate { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self.op { - Wildcard(Major) => try!(write!(fmt, "*")), - Wildcard(Minor) => try!(write!(fmt, "{}.*", self.major)), - Wildcard(Patch) => { - if let Some(minor) = self.minor { - try!(write!(fmt, "{}.{}.*", self.major, minor)) - } else { - try!(write!(fmt, "{}.*.*", self.major)) - } - } - _ => { - try!(write!(fmt, "{}{}", self.op, self.major)); - - match self.minor { - Some(v) => try!(write!(fmt, ".{}", v)), - None => (), - } - - match self.patch { - Some(v) => try!(write!(fmt, ".{}", v)), - None => (), - } - - if !self.pre.is_empty() { - try!(write!(fmt, "-")); - for (i, x) in self.pre.iter().enumerate() { - if i != 0 { - try!(write!(fmt, ".")) - } - try!(write!(fmt, "{}", x)); - } - } - } - } - - Ok(()) - } -} - -impl fmt::Display for Op { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match *self { - Ex => try!(write!(fmt, "= ")), - Gt => try!(write!(fmt, "> ")), - GtEq => try!(write!(fmt, ">= ")), - Lt => try!(write!(fmt, "< ")), - LtEq => try!(write!(fmt, "<= ")), - Tilde => try!(write!(fmt, "~")), - Compatible => try!(write!(fmt, "^")), - // gets handled specially in Predicate::fmt - Wildcard(_) => try!(write!(fmt, "")), - } - Ok(()) - } -} - -#[cfg(test)] -mod test { - use super::{VersionReq, Op}; - use super::super::version::Version; - use std::hash::{Hash, Hasher}; - - fn req(s: &str) -> VersionReq { - VersionReq::parse(s).unwrap() - } - - fn version(s: &str) -> Version { - match Version::parse(s) { - Ok(v) => v, - Err(e) => panic!("`{}` is not a valid version. Reason: {:?}", s, e), - } - } - - fn assert_match(req: &VersionReq, vers: &[&str]) { - for ver in vers.iter() { - assert!(req.matches(&version(*ver)), "did not match {}", ver); - } - } - - fn assert_not_match(req: &VersionReq, vers: &[&str]) { - for ver in vers.iter() { - assert!(!req.matches(&version(*ver)), "matched {}", ver); - } - } - - fn calculate_hash<T: Hash>(t: T) -> u64 { - use std::collections::hash_map::DefaultHasher; - - let mut s = DefaultHasher::new(); - t.hash(&mut s); - s.finish() - } - - #[test] - fn test_parsing_default() { - let r = req("1.0.0"); - - assert_eq!(r.to_string(), "^1.0.0".to_string()); - - assert_match(&r, &["1.0.0", "1.0.1"]); - assert_not_match(&r, &["0.9.9", "0.10.0", "0.1.0"]); - } - - #[test] - fn test_parsing_exact() { - let r = req("=1.0.0"); - - assert!(r.to_string() == "= 1.0.0".to_string()); - assert_eq!(r.to_string(), "= 1.0.0".to_string()); - - assert_match(&r, &["1.0.0"]); - assert_not_match(&r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]); - - let r = req("=0.9.0"); - - assert_eq!(r.to_string(), "= 0.9.0".to_string()); - - assert_match(&r, &["0.9.0"]); - assert_not_match(&r, &["0.9.1", "1.9.0", "0.0.9"]); - - let r = req("=0.1.0-beta2.a"); - - assert_eq!(r.to_string(), "= 0.1.0-beta2.a".to_string()); - - assert_match(&r, &["0.1.0-beta2.a"]); - assert_not_match(&r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]); - } - - #[test] - fn test_parse_metadata_see_issue_88_see_issue_88() { - for op in &[Op::Compatible, Op::Ex, Op::Gt, Op::GtEq, Op::Lt, Op::LtEq, Op::Tilde] { - req(&format!("{} 1.2.3+meta", op)); - } - } - - #[test] - pub fn test_parsing_greater_than() { - let r = req(">= 1.0.0"); - - assert_eq!(r.to_string(), ">= 1.0.0".to_string()); - - assert_match(&r, &["1.0.0", "2.0.0"]); - assert_not_match(&r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]); - - let r = req(">= 2.1.0-alpha2"); - - assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]); - assert_not_match(&r, - &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"]); - } - - #[test] - pub fn test_parsing_less_than() { - let r = req("< 1.0.0"); - - assert_eq!(r.to_string(), "< 1.0.0".to_string()); - - assert_match(&r, &["0.1.0", "0.0.1"]); - assert_not_match(&r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]); - - let r = req("<= 2.1.0-alpha2"); - - assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]); - assert_not_match(&r, - &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"]); - } - - #[test] - pub fn test_multiple() { - let r = req("> 0.0.9, <= 2.5.3"); - assert_eq!(r.to_string(), "> 0.0.9, <= 2.5.3".to_string()); - assert_match(&r, &["0.0.10", "1.0.0", "2.5.3"]); - assert_not_match(&r, &["0.0.8", "2.5.4"]); - - let r = req("0.3.0, 0.4.0"); - assert_eq!(r.to_string(), "^0.3.0, ^0.4.0".to_string()); - assert_not_match(&r, &["0.0.8", "0.3.0", "0.4.0"]); - - let r = req("<= 0.2.0, >= 0.5.0"); - assert_eq!(r.to_string(), "<= 0.2.0, >= 0.5.0".to_string()); - assert_not_match(&r, &["0.0.8", "0.3.0", "0.5.1"]); - - let r = req("0.1.0, 0.1.4, 0.1.6"); - assert_eq!(r.to_string(), "^0.1.0, ^0.1.4, ^0.1.6".to_string()); - assert_match(&r, &["0.1.6", "0.1.9"]); - assert_not_match(&r, &["0.1.0", "0.1.4", "0.2.0"]); - - assert!(VersionReq::parse("> 0.1.0,").is_err()); - assert!(VersionReq::parse("> 0.3.0, ,").is_err()); - - let r = req(">=0.5.1-alpha3, <0.6"); - assert_eq!(r.to_string(), ">= 0.5.1-alpha3, < 0.6".to_string()); - assert_match(&r, - &["0.5.1-alpha3", "0.5.1-alpha4", "0.5.1-beta", "0.5.1", "0.5.5"]); - assert_not_match(&r, - &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"]); - assert_not_match(&r, &["0.6.0", "0.6.0-pre"]); - } - - #[test] - pub fn test_parsing_tilde() { - let r = req("~1"); - assert_match(&r, &["1.0.0", "1.0.1", "1.1.1"]); - assert_not_match(&r, &["0.9.1", "2.9.0", "0.0.9"]); - - let r = req("~1.2"); - assert_match(&r, &["1.2.0", "1.2.1"]); - assert_not_match(&r, &["1.1.1", "1.3.0", "0.0.9"]); - - let r = req("~1.2.2"); - assert_match(&r, &["1.2.2", "1.2.4"]); - assert_not_match(&r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]); - - let r = req("~1.2.3-beta.2"); - assert_match(&r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]); - assert_not_match(&r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]); - } - - #[test] - pub fn test_parsing_compatible() { - let r = req("^1"); - assert_match(&r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]); - assert_not_match(&r, &["0.9.1", "2.9.0", "0.1.4"]); - assert_not_match(&r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]); - - let r = req("^1.1"); - assert_match(&r, &["1.1.2", "1.1.0", "1.2.1"]); - assert_not_match(&r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]); - - let r = req("^1.1.2"); - assert_match(&r, &["1.1.2", "1.1.4", "1.2.1"]); - assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]); - assert_not_match(&r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]); - - let r = req("^0.1.2"); - assert_match(&r, &["0.1.2", "0.1.4"]); - assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]); - assert_not_match(&r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]); - - let r = req("^0.5.1-alpha3"); - assert_match(&r, - &["0.5.1-alpha3", "0.5.1-alpha4", "0.5.1-beta", "0.5.1", "0.5.5"]); - assert_not_match(&r, - &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre", "0.6.0"]); - - let r = req("^0.0.2"); - assert_match(&r, &["0.0.2"]); - assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]); - - let r = req("^0.0"); - assert_match(&r, &["0.0.2", "0.0.0"]); - assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]); - - let r = req("^0"); - assert_match(&r, &["0.9.1", "0.0.2", "0.0.0"]); - assert_not_match(&r, &["2.9.0", "1.1.1"]); - - let r = req("^1.4.2-beta.5"); - assert_match(&r, - &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"]); - assert_not_match(&r, - &["0.9.9", "2.0.0", "1.4.2-alpha", "1.4.2-beta.4", "1.4.3-beta.5"]); - } - - #[test] - pub fn test_parsing_wildcard() { - let r = req(""); - assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); - assert_not_match(&r, &[]); - let r = req("*"); - assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); - assert_not_match(&r, &[]); - let r = req("x"); - assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); - assert_not_match(&r, &[]); - let r = req("X"); - assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); - assert_not_match(&r, &[]); - - let r = req("1.*"); - assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]); - assert_not_match(&r, &["0.0.9"]); - let r = req("1.x"); - assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]); - assert_not_match(&r, &["0.0.9"]); - let r = req("1.X"); - assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]); - assert_not_match(&r, &["0.0.9"]); - - let r = req("1.2.*"); - assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]); - assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]); - let r = req("1.2.x"); - assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]); - assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]); - let r = req("1.2.X"); - assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]); - assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]); - } - - #[test] - pub fn test_any() { - let r = VersionReq::any(); - assert_match(&r, &["0.0.1", "0.1.0", "1.0.0"]); - } - - #[test] - pub fn test_pre() { - let r = req("=2.1.1-really.0"); - assert_match(&r, &["2.1.1-really.0"]); - } - - // #[test] - // pub fn test_parse_errors() { - // assert_eq!(Err(InvalidVersionRequirement), VersionReq::parse("\0")); - // assert_eq!(Err(OpAlreadySet), VersionReq::parse(">= >= 0.0.2")); - // assert_eq!(Err(InvalidSigil), VersionReq::parse(">== 0.0.2")); - // assert_eq!(Err(VersionComponentsMustBeNumeric), - // VersionReq::parse("a.0.0")); - // assert_eq!(Err(InvalidIdentifier), VersionReq::parse("1.0.0-")); - // assert_eq!(Err(MajorVersionRequired), VersionReq::parse(">=")); - // } - - #[test] - pub fn test_from_str() { - assert_eq!("1.0.0".parse::<VersionReq>().unwrap().to_string(), - "^1.0.0".to_string()); - assert_eq!("=1.0.0".parse::<VersionReq>().unwrap().to_string(), - "= 1.0.0".to_string()); - assert_eq!("~1".parse::<VersionReq>().unwrap().to_string(), - "~1".to_string()); - assert_eq!("~1.2".parse::<VersionReq>().unwrap().to_string(), - "~1.2".to_string()); - assert_eq!("^1".parse::<VersionReq>().unwrap().to_string(), - "^1".to_string()); - assert_eq!("^1.1".parse::<VersionReq>().unwrap().to_string(), - "^1.1".to_string()); - assert_eq!("*".parse::<VersionReq>().unwrap().to_string(), - "*".to_string()); - assert_eq!("1.*".parse::<VersionReq>().unwrap().to_string(), - "1.*".to_string()); - assert_eq!("< 1.0.0".parse::<VersionReq>().unwrap().to_string(), - "< 1.0.0".to_string()); - } - - // #[test] - // pub fn test_from_str_errors() { - // assert_eq!(Err(InvalidVersionRequirement), "\0".parse::<VersionReq>()); - // assert_eq!(Err(OpAlreadySet), ">= >= 0.0.2".parse::<VersionReq>()); - // assert_eq!(Err(InvalidSigil), ">== 0.0.2".parse::<VersionReq>()); - // assert_eq!(Err(VersionComponentsMustBeNumeric), - // "a.0.0".parse::<VersionReq>()); - // assert_eq!(Err(InvalidIdentifier), "1.0.0-".parse::<VersionReq>()); - // assert_eq!(Err(MajorVersionRequired), ">=".parse::<VersionReq>()); - // } - - #[test] - fn test_cargo3202() { - let v = "0.*.*".parse::<VersionReq>().unwrap(); - assert_eq!("0.*.*", format!("{}", v.predicates[0])); - - let v = "0.0.*".parse::<VersionReq>().unwrap(); - assert_eq!("0.0.*", format!("{}", v.predicates[0])); - - let r = req("0.*.*"); - assert_match(&r, &["0.5.0"]); - } - - #[test] - fn test_eq_hash() { - assert!(req("^1") == req("^1")); - assert!(calculate_hash(req("^1")) == calculate_hash(req("^1"))); - assert!(req("^1") != req("^2")); - } - - #[test] - fn test_ordering() { - assert!(req("=1") < req("*")); - assert!(req(">1") < req("*")); - assert!(req(">=1") < req("*")); - assert!(req("<1") < req("*")); - assert!(req("<=1") < req("*")); - assert!(req("~1") < req("*")); - assert!(req("^1") < req("*")); - assert!(req("*") == req("*")); - } -} diff --git a/semver/tests/deprecation.rs b/semver/tests/deprecation.rs deleted file mode 100644 index a5f533a..0000000 --- a/semver/tests/deprecation.rs +++ /dev/null @@ -1,22 +0,0 @@ -extern crate semver; - -#[test] -fn test_regressions() { - use semver::VersionReq; - use semver::ReqParseError; - - let versions = vec![ - (".*", VersionReq::any()), - ("0.1.0.", VersionReq::parse("0.1.0").unwrap()), - ("0.3.1.3", VersionReq::parse("0.3.13").unwrap()), - ("0.2*", VersionReq::parse("0.2.*").unwrap()), - ("*.0", VersionReq::any()), - ]; - - for (version, requirement) in versions.into_iter() { - let parsed = VersionReq::parse(version); - let error = parsed.err().unwrap(); - - assert_eq!(ReqParseError::DeprecatedVersionRequirement(requirement), error); - } -} diff --git a/semver/tests/regression.rs b/semver/tests/regression.rs deleted file mode 100644 index ef568a7..0000000 --- a/semver/tests/regression.rs +++ /dev/null @@ -1,25 +0,0 @@ -extern crate semver; -extern crate crates_index; -extern crate tempdir; - -// This test checks to see if every existing crate parses successfully. Important to not break the -// Rust universe! - -#[cfg(feature = "ci")] -#[test] -fn test_regressions() { - use tempdir::TempDir; - use crates_index::Index; - use semver::Version; - - let dir = TempDir::new("semver").unwrap(); - let index = Index::new(dir.into_path()); - index.clone().unwrap(); - - for krate in index.crates() { - for version in krate.versions() { - let v = version.version(); - assert!(Version::parse(v).is_ok(), "failed: {} ({})", version.name(), v); - } - } -} diff --git a/semver/tests/serde.rs b/semver/tests/serde.rs deleted file mode 100644 index bcb9264..0000000 --- a/semver/tests/serde.rs +++ /dev/null @@ -1,90 +0,0 @@ -#![cfg(feature = "serde")] - -#[macro_use] -extern crate serde_derive; - -extern crate semver; -extern crate serde_json; - -use semver::{Identifier, Version, VersionReq}; - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct Identified { - name: String, - identifier: Identifier, -} - -#[derive(Serialize, Deserialize, PartialEq, Debug)] -struct Versioned { - name: String, - vers: Version, -} - -#[test] -fn serialize_identifier() { - let id = Identified { - name: "serde".to_owned(), - identifier: Identifier::Numeric(100), - }; - let j = serde_json::to_string(&id).unwrap(); - assert_eq!(j, r#"{"name":"serde","identifier":100}"#); - - let id = Identified { - name: "serde".to_owned(), - identifier: Identifier::AlphaNumeric("b100".to_owned()), - }; - let j = serde_json::to_string(&id).unwrap(); - assert_eq!(j, r#"{"name":"serde","identifier":"b100"}"#); -} - -#[test] -fn deserialize_identifier() { - let j = r#"{"name":"serde","identifier":100}"#; - let id = serde_json::from_str::<Identified>(j).unwrap(); - let expected = Identified { - name: "serde".to_owned(), - identifier: Identifier::Numeric(100), - }; - assert_eq!(id, expected); - - let j = r#"{"name":"serde","identifier":"b100"}"#; - let id = serde_json::from_str::<Identified>(j).unwrap(); - let expected = Identified { - name: "serde".to_owned(), - identifier: Identifier::AlphaNumeric("b100".to_owned()), - }; - assert_eq!(id, expected); -} - -#[test] -fn serialize_version() { - let v = Versioned { - name: "serde".to_owned(), - vers: Version::parse("1.0.0").unwrap(), - }; - let j = serde_json::to_string(&v).unwrap(); - assert_eq!(j, r#"{"name":"serde","vers":"1.0.0"}"#); -} - -#[test] -fn deserialize_version() { - let j = r#"{"name":"serde","vers":"1.0.0"}"#; - let v = serde_json::from_str::<Versioned>(j).unwrap(); - let expected = Versioned { - name: "serde".to_owned(), - vers: Version::parse("1.0.0").unwrap(), - }; - assert_eq!(v, expected); -} - -#[test] -fn serialize_versionreq() { - let v = VersionReq::exact(&Version::parse("1.0.0").unwrap()); - - assert_eq!(serde_json::to_string(&v).unwrap(), r#""= 1.0.0""#); -} - -#[test] -fn deserialize_versionreq() { - assert_eq!("1.0.0".parse::<VersionReq>().unwrap(), serde_json::from_str(r#""1.0.0""#).unwrap()); -} |