mirror of
https://github.com/archlinuxarm/PKGBUILDs.git
synced 2024-11-28 22:57:37 +00:00
8593 lines
290 KiB
Diff
8593 lines
290 KiB
Diff
|
|
# HG changeset patch
|
|
# User Mike Hommey <mh+mozilla@glandium.org>
|
|
# Date 1654596092 0
|
|
# Node ID f52e2ad948e88e2c4ce83599d379aa4a1e57334e
|
|
# Parent 969171da8cc09d4eb7c070b0ecf33bc5cc504537
|
|
Bug 1772048 - Update rustc_version and semver crates. r=emilio,webdriver-reviewers,kinetik,whimboo
|
|
|
|
semver 1.0 doesn't and won't support Clone on semver::Error[1], so we
|
|
convert the mozversion error type to store the string version of the
|
|
error, which is an incompatible change requiring a version bump on the
|
|
crate.
|
|
|
|
1. https://github.com/dtolnay/semver/pull/280
|
|
|
|
Differential Revision: https://phabricator.services.mozilla.com/D147825
|
|
|
|
diff --git a/.cargo/config.in b/.cargo/config.in
|
|
--- a/.cargo/config.in
|
|
+++ b/.cargo/config.in
|
|
@@ -25,17 +25,17 @@ rev = "3bfc47d9a571d0842676043ba60716318
|
|
[source."https://github.com/mozilla/midir.git"]
|
|
git = "https://github.com/mozilla/midir.git"
|
|
replace-with = "vendored-sources"
|
|
rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
|
|
|
|
[source."https://github.com/mozilla/cubeb-pulse-rs"]
|
|
git = "https://github.com/mozilla/cubeb-pulse-rs"
|
|
replace-with = "vendored-sources"
|
|
-rev = "df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
|
|
+rev = "1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
|
|
|
|
[source."https://github.com/mozilla/cubeb-coreaudio-rs"]
|
|
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
|
|
replace-with = "vendored-sources"
|
|
rev = "44eca95823bb57e964cf7b6d9791ed2ccb4b2108"
|
|
|
|
[source."https://github.com/mozilla/audioipc"]
|
|
git = "https://github.com/mozilla/audioipc"
|
|
diff --git a/Cargo.lock b/Cargo.lock
|
|
--- a/Cargo.lock
|
|
+++ b/Cargo.lock
|
|
@@ -1157,17 +1157,17 @@ dependencies = [
|
|
"mach",
|
|
"ringbuf",
|
|
"triple_buffer",
|
|
]
|
|
|
|
[[package]]
|
|
name = "cubeb-pulse"
|
|
version = "0.4.0"
|
|
-source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=df4dc0288b07b865440f4c7e41ca49ca9ccffc63#df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
|
|
+source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=1f1fe1e08e01a9a534ec7f079702a583a0899ce7#1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
|
|
dependencies = [
|
|
"cubeb-backend",
|
|
"pulse",
|
|
"pulse-ffi",
|
|
"ringbuf",
|
|
"semver",
|
|
]
|
|
|
|
@@ -3399,17 +3399,17 @@ dependencies = [
|
|
"nsstring",
|
|
"url",
|
|
"uuid",
|
|
"xpcom",
|
|
]
|
|
|
|
[[package]]
|
|
name = "mozversion"
|
|
-version = "0.4.3"
|
|
+version = "0.5.0-alpha"
|
|
dependencies = [
|
|
"regex",
|
|
"rust-ini",
|
|
"semver",
|
|
]
|
|
|
|
[[package]]
|
|
name = "mozwer_s"
|
|
@@ -4122,26 +4122,26 @@ dependencies = [
|
|
"proc-macro2",
|
|
"quote",
|
|
"syn",
|
|
]
|
|
|
|
[[package]]
|
|
name = "pulse"
|
|
version = "0.3.0"
|
|
-source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=df4dc0288b07b865440f4c7e41ca49ca9ccffc63#df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
|
|
+source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=1f1fe1e08e01a9a534ec7f079702a583a0899ce7#1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
|
|
dependencies = [
|
|
"bitflags",
|
|
"pulse-ffi",
|
|
]
|
|
|
|
[[package]]
|
|
name = "pulse-ffi"
|
|
version = "0.1.0"
|
|
-source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=df4dc0288b07b865440f4c7e41ca49ca9ccffc63#df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
|
|
+source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=1f1fe1e08e01a9a534ec7f079702a583a0899ce7#1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
|
|
dependencies = [
|
|
"libc",
|
|
]
|
|
|
|
[[package]]
|
|
name = "qcms"
|
|
version = "0.2.0"
|
|
dependencies = [
|
|
@@ -4456,19 +4456,19 @@ checksum = "7ef03e0a2b150c7a90d01faf6254
|
|
[[package]]
|
|
name = "rustc-hash"
|
|
version = "1.1.0"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
|
|
|
[[package]]
|
|
name = "rustc_version"
|
|
-version = "0.2.3"
|
|
-source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
|
+version = "0.4.0"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
|
dependencies = [
|
|
"semver",
|
|
]
|
|
|
|
[[package]]
|
|
name = "ryu"
|
|
version = "1.0.10"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
@@ -4544,28 +4544,19 @@ dependencies = [
|
|
[[package]]
|
|
name = "self_cell"
|
|
version = "0.10.2"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
|
|
|
|
[[package]]
|
|
name = "semver"
|
|
-version = "0.9.0"
|
|
-source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
|
-dependencies = [
|
|
- "semver-parser",
|
|
-]
|
|
-
|
|
-[[package]]
|
|
-name = "semver-parser"
|
|
-version = "0.7.0"
|
|
-source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
|
+version = "1.0.9"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
|
|
|
|
[[package]]
|
|
name = "serde"
|
|
version = "1.0.136"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
|
dependencies = [
|
|
"serde_derive",
|
|
diff --git a/gfx/qcms/Cargo.toml b/gfx/qcms/Cargo.toml
|
|
--- a/gfx/qcms/Cargo.toml
|
|
+++ b/gfx/qcms/Cargo.toml
|
|
@@ -17,9 +17,9 @@ c_bindings = ["libc"]
|
|
neon = []
|
|
iccv4-enabled = []
|
|
cmyk = []
|
|
|
|
[dependencies]
|
|
libc = {version = "0.2", optional = true }
|
|
|
|
[build-dependencies]
|
|
-rustc_version = "0.2"
|
|
+rustc_version = "0.4"
|
|
diff --git a/mozglue/static/rust/Cargo.toml b/mozglue/static/rust/Cargo.toml
|
|
--- a/mozglue/static/rust/Cargo.toml
|
|
+++ b/mozglue/static/rust/Cargo.toml
|
|
@@ -8,12 +8,12 @@ license = "MPL"
|
|
path = "lib.rs"
|
|
|
|
[dependencies]
|
|
arrayvec = "0.5"
|
|
|
|
[build-dependencies]
|
|
mozbuild = "0.1"
|
|
cc = "1"
|
|
-rustc_version = "0.2"
|
|
+rustc_version = "0.4"
|
|
|
|
[features]
|
|
moz_memory = []
|
|
diff --git a/testing/geckodriver/Cargo.toml b/testing/geckodriver/Cargo.toml
|
|
--- a/testing/geckodriver/Cargo.toml
|
|
+++ b/testing/geckodriver/Cargo.toml
|
|
@@ -15,17 +15,17 @@ chrono = "0.4.6"
|
|
clap = { version = "3.1", default-features = false, features = ["cargo", "std", "suggestions", "wrap_help"] }
|
|
hyper = "0.14"
|
|
lazy_static = "1.0"
|
|
log = { version = "0.4", features = ["std"] }
|
|
marionette = { path = "./marionette", version="0.2.0" }
|
|
mozdevice = { path = "../mozbase/rust/mozdevice", version="0.5.0" }
|
|
mozprofile = { path = "../mozbase/rust/mozprofile", version="0.8.0" }
|
|
mozrunner = { path = "../mozbase/rust/mozrunner", version="0.14.0" }
|
|
-mozversion = { path = "../mozbase/rust/mozversion", version="0.4.3" }
|
|
+mozversion = { path = "../mozbase/rust/mozversion", version="0.5.0-alpha" }
|
|
regex = { version="1.0", default-features = false, features = ["perf", "std"] }
|
|
serde = "1.0"
|
|
serde_derive = "1.0"
|
|
serde_json = "1.0"
|
|
serde_yaml = "0.8"
|
|
tempfile = "3"
|
|
url = "2.0"
|
|
uuid = { version = "0.8", features = ["v4"] }
|
|
diff --git a/testing/mozbase/rust/mozversion/Cargo.toml b/testing/mozbase/rust/mozversion/Cargo.toml
|
|
--- a/testing/mozbase/rust/mozversion/Cargo.toml
|
|
+++ b/testing/mozbase/rust/mozversion/Cargo.toml
|
|
@@ -1,14 +1,14 @@
|
|
[package]
|
|
name = "mozversion"
|
|
-version = "0.4.3"
|
|
+version = "0.5.0-alpha"
|
|
authors = ["Mozilla"]
|
|
description = "Utility for accessing Firefox version metadata"
|
|
keywords = ["mozilla", "firefox"]
|
|
repository = "https://hg.mozilla.org/mozilla-central/file/tip/testing/mozbase/rust/mozversion"
|
|
license = "MPL-2.0"
|
|
edition = "2018"
|
|
|
|
[dependencies]
|
|
regex = { version = "1", default-features = false, features = ["perf", "std"] }
|
|
rust-ini = "0.10"
|
|
-semver = "0.9"
|
|
+semver = "1.0"
|
|
diff --git a/testing/mozbase/rust/mozversion/src/lib.rs b/testing/mozbase/rust/mozversion/src/lib.rs
|
|
--- a/testing/mozbase/rust/mozversion/src/lib.rs
|
|
+++ b/testing/mozbase/rust/mozversion/src/lib.rs
|
|
@@ -101,18 +101,18 @@ impl Version {
|
|
// The way the semver crate handles prereleases isn't what we want here
|
|
// This should be fixed in the long term by implementing our own comparison
|
|
// operators, but for now just act as if prerelease metadata was missing,
|
|
// otherwise it is almost impossible to use this with nightly
|
|
semver::Version {
|
|
major: self.major,
|
|
minor: self.minor,
|
|
patch: self.patch,
|
|
- pre: vec![],
|
|
- build: vec![],
|
|
+ pre: semver::Prerelease::EMPTY,
|
|
+ build: semver::BuildMetadata::EMPTY,
|
|
}
|
|
}
|
|
|
|
pub fn matches(&self, version_req: &str) -> VersionResult<bool> {
|
|
let req = semver::VersionReq::parse(version_req)?;
|
|
Ok(req.matches(&self.to_semver()))
|
|
}
|
|
}
|
|
@@ -269,17 +269,17 @@ fn parse_binary_version(version_str: &st
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum Error {
|
|
/// Error parsing a version string
|
|
VersionError(String),
|
|
/// Error reading application metadata
|
|
MetadataError(String),
|
|
/// Error processing a string as a semver comparator
|
|
- SemVerError(semver::ReqParseError),
|
|
+ SemVerError(String),
|
|
}
|
|
|
|
impl Display for Error {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match *self {
|
|
Error::VersionError(ref x) => {
|
|
"VersionError: ".fmt(f)?;
|
|
x.fmt(f)
|
|
@@ -291,28 +291,25 @@ impl Display for Error {
|
|
Error::SemVerError(ref e) => {
|
|
"SemVerError: ".fmt(f)?;
|
|
e.fmt(f)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
-impl From<semver::ReqParseError> for Error {
|
|
- fn from(err: semver::ReqParseError) -> Error {
|
|
- Error::SemVerError(err)
|
|
+impl From<semver::Error> for Error {
|
|
+ fn from(err: semver::Error) -> Error {
|
|
+ Error::SemVerError(err.to_string())
|
|
}
|
|
}
|
|
|
|
impl error::Error for Error {
|
|
fn cause(&self) -> Option<&dyn error::Error> {
|
|
- match *self {
|
|
- Error::SemVerError(ref e) => Some(e),
|
|
- Error::VersionError(_) | Error::MetadataError(_) => None,
|
|
- }
|
|
+ None
|
|
}
|
|
}
|
|
|
|
pub type VersionResult<T> = Result<T, Error>;
|
|
|
|
#[cfg(target_os = "macos")]
|
|
mod platform {
|
|
use std::path::{Path, PathBuf};
|
|
diff --git a/third_party/rust/cubeb-pulse/.cargo-checksum.json b/third_party/rust/cubeb-pulse/.cargo-checksum.json
|
|
--- a/third_party/rust/cubeb-pulse/.cargo-checksum.json
|
|
+++ b/third_party/rust/cubeb-pulse/.cargo-checksum.json
|
|
@@ -1,1 +1,1 @@
|
|
-{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"95d0d2542c04f0c932f58591b92c3051db5c95657bf5f24b6a6110f7b667568d","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"d8f84d114794b79a02c8d93724951a0b924f4815e446d666e66877c7a90d0446","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"839fbbd90e501c9e455e6b46729f8c3cc03b368b6b45d02c82399660b7cf8289","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"11ca424e4eb77f8eb9fd5a6717d1e791facf9743156a8534f0016fcf64d57b0f","src/backend/mod.rs":"d5da05348bf1a7f65c85b14372964a49dc4849f0aee96c75e2c18b51fb03fcaf","src/backend/stream.rs":"525e1f6be1990deef3c42d34fc4e25947be642ce242514f8e3428737146cc755","src/capi.rs":"fa0fa020f0d0efe55aa0fc3596405e8407bbe2cbe6c7a558345304e6da87994e","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
|
|
\ No newline at end of file
|
|
+{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"95d0d2542c04f0c932f58591b92c3051db5c95657bf5f24b6a6110f7b667568d","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"13fe95ad27f37b8423958d78093ecff3ade9fffb28c5980604b624c2b617e5a7","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"839fbbd90e501c9e455e6b46729f8c3cc03b368b6b45d02c82399660b7cf8289","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"11ca424e4eb77f8eb9fd5a6717d1e791facf9743156a8534f0016fcf64d57b0f","src/backend/mod.rs":"d5da05348bf1a7f65c85b14372964a49dc4849f0aee96c75e2c18b51fb03fcaf","src/backend/stream.rs":"e88a04ab7094b9df1bcdd07628369ec70ecb2062b91b0bd86f2642962814405c","src/capi.rs":"fa0fa020f0d0efe55aa0fc3596405e8407bbe2cbe6c7a558345304e6da87994e","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
|
|
\ No newline at end of file
|
|
diff --git a/third_party/rust/cubeb-pulse/Cargo.toml b/third_party/rust/cubeb-pulse/Cargo.toml
|
|
--- a/third_party/rust/cubeb-pulse/Cargo.toml
|
|
+++ b/third_party/rust/cubeb-pulse/Cargo.toml
|
|
@@ -10,10 +10,10 @@ pulse-dlopen = ["pulse-ffi/dlopen"]
|
|
|
|
[lib]
|
|
crate-type = ["staticlib", "rlib"]
|
|
|
|
[dependencies]
|
|
cubeb-backend = "0.10"
|
|
pulse-ffi = { path = "pulse-ffi" }
|
|
pulse = { path = "pulse-rs" }
|
|
-semver = "^0.9"
|
|
+semver = "1.0"
|
|
ringbuf = "0.2"
|
|
diff --git a/third_party/rust/cubeb-pulse/src/backend/stream.rs b/third_party/rust/cubeb-pulse/src/backend/stream.rs
|
|
--- a/third_party/rust/cubeb-pulse/src/backend/stream.rs
|
|
+++ b/third_party/rust/cubeb-pulse/src/backend/stream.rs
|
|
@@ -350,16 +350,25 @@ impl<'ctx> PulseStream<'ctx> {
|
|
ptr::null_mut(),
|
|
read_frames as c_long,
|
|
)
|
|
};
|
|
|
|
if got < 0 || got as usize != read_frames {
|
|
let _ = s.cancel_write();
|
|
stm.shutdown = true;
|
|
+ if got < 0 {
|
|
+ unsafe {
|
|
+ stm.state_callback.unwrap()(
|
|
+ stm as *mut _ as *mut _,
|
|
+ stm.user_ptr,
|
|
+ ffi::CUBEB_STATE_ERROR,
|
|
+ );
|
|
+ }
|
|
+ }
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if read_size > 0 {
|
|
let _ = s.drop();
|
|
}
|
|
@@ -1064,16 +1073,23 @@ impl<'ctx> PulseStream<'ctx> {
|
|
read_ptr as *const _ as *mut _,
|
|
buffer,
|
|
(size / frame_size) as c_long,
|
|
) as i64
|
|
};
|
|
if got < 0 {
|
|
let _ = stm.cancel_write();
|
|
self.shutdown = true;
|
|
+ unsafe {
|
|
+ self.state_callback.unwrap()(
|
|
+ self as *const _ as *mut _,
|
|
+ self.user_ptr,
|
|
+ ffi::CUBEB_STATE_ERROR,
|
|
+ );
|
|
+ }
|
|
return;
|
|
}
|
|
|
|
// If more iterations move offset of read buffer
|
|
if !input_data.is_null() {
|
|
let in_frame_size = self.input_sample_spec.frame_size();
|
|
read_offset += (size / frame_size) * in_frame_size;
|
|
}
|
|
diff --git a/third_party/rust/rustc_version/.cargo-checksum.json b/third_party/rust/rustc_version/.cargo-checksum.json
|
|
--- a/third_party/rust/rustc_version/.cargo-checksum.json
|
|
+++ b/third_party/rust/rustc_version/.cargo-checksum.json
|
|
@@ -1,1 +1,1 @@
|
|
-{"files":{"Cargo.toml":"80b9fb136c8c2945b4875b05b0f5a4b11e4722997e751f17d8d3f241d7c684db","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"58bd14a1dfa1d828e6e99f35c3b7c2149d08e2d990d6ca93f92ab8ffb43275b7","src/errors.rs":"b28c2eeb1278fc3e8d68a64b177034faed67f6762335729d3a6d1e61be8fb034","src/lib.rs":"92a32673f77961724bc52b872781f06d22d166f06838c9582c5adae3c5214f51"},"package":"138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"}
|
|
\ No newline at end of file
|
|
+{"files":{"Cargo.toml":"6a2e927f37b4897e75470e62face13eff0fe846c57f8fcfb98bcd5e0fe8ed0a2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"40f1138d4ddcfcfd0534429cea8dcbdcaf4a175aca1c26662f011f6e83d2fd7a","deny.toml":"22979f2da49546b27a5c892d5216bf74215987810a2d011b58870471883b9437","src/lib.rs":"bc18589948e3c04c3ffb491ffc3d4eccd8037c8e377d0bbae8aca2b21978b1de","tests/all.rs":"7b2969022feab85a948fafd331d9bb30d80357d01afaf7e0f723908e75f39e89"},"package":"bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"}
|
|
\ No newline at end of file
|
|
diff --git a/third_party/rust/rustc_version/Cargo.toml b/third_party/rust/rustc_version/Cargo.toml
|
|
--- a/third_party/rust/rustc_version/Cargo.toml
|
|
+++ b/third_party/rust/rustc_version/Cargo.toml
|
|
@@ -1,26 +1,27 @@
|
|
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
#
|
|
# When uploading crates to the registry Cargo will automatically
|
|
# "normalize" Cargo.toml files for maximal compatibility
|
|
# with all versions of Cargo and also rewrite `path` dependencies
|
|
-# to registry (e.g. crates.io) dependencies
|
|
+# to registry (e.g., crates.io) dependencies
|
|
#
|
|
# If you believe there's an error in this file please file an
|
|
# issue against the rust-lang/cargo repository. If you're
|
|
# editing this file be aware that the upstream Cargo.toml
|
|
# will likely look very different (and much more reasonable)
|
|
|
|
[package]
|
|
+edition = "2018"
|
|
name = "rustc_version"
|
|
-version = "0.2.3"
|
|
-authors = ["Marvin Löbel <loebel.marvin@gmail.com>"]
|
|
+version = "0.4.0"
|
|
+authors = ["Dirkjan Ochtman <dirkjan@ochtman.nl>", "Marvin Löbel <loebel.marvin@gmail.com>"]
|
|
description = "A library for querying the version of a installed rustc compiler"
|
|
documentation = "https://docs.rs/rustc_version/"
|
|
readme = "README.md"
|
|
keywords = ["version", "rustc"]
|
|
license = "MIT/Apache-2.0"
|
|
repository = "https://github.com/Kimundi/rustc-version-rs"
|
|
[dependencies.semver]
|
|
-version = "0.9"
|
|
-[badges.travis-ci]
|
|
-repository = "Kimundi/rustc-version-rs"
|
|
+version = "1.0"
|
|
+[dev-dependencies.doc-comment]
|
|
+version = "0.3"
|
|
diff --git a/third_party/rust/rustc_version/README.md b/third_party/rust/rustc_version/README.md
|
|
--- a/third_party/rust/rustc_version/README.md
|
|
+++ b/third_party/rust/rustc_version/README.md
|
|
@@ -1,40 +1,46 @@
|
|
rustc-version-rs
|
|
-==============
|
|
+================
|
|
+
|
|
+[![Documentation](https://docs.rs/rustc_version/badge.svg)](https://docs.rs/rustc_version/)
|
|
+[![Crates.io](https://img.shields.io/crates/v/rustc_version.svg)](https://crates.io/crates/rustc_version)
|
|
+[![Build status](https://github.com/Kimundi/rustc-version-rs/workflows/CI/badge.svg)](https://github.com/Kimundi/rustc-version-rs/actions?query=workflow%3ACI)
|
|
|
|
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.
|
|
+to make decisions based on the version of the compiler. Current MSRV is 1.32.0.
|
|
|
|
-[![Travis-CI Status](https://travis-ci.org/Kimundi/rustc-version-rs.png?branch=master)](https://travis-ci.org/Kimundi/rustc-version-rs)
|
|
+If this is of interest, also consider looking at these other crates:
|
|
+
|
|
+* [autocfg](https://crates.io/crates/autocfg/), which helps with feature detection instead of depending on compiler versions
|
|
+* [rustversion](https://github.com/dtolnay/rustversion) provides a procedural macro with no other dependencies
|
|
|
|
# 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.
|
|
+... and see the [docs](https://docs.rs/rustc_version) 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 {
|
|
diff --git a/third_party/rust/rustc_version/deny.toml b/third_party/rust/rustc_version/deny.toml
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/rustc_version/deny.toml
|
|
@@ -0,0 +1,3 @@
|
|
+[licenses]
|
|
+allow-osi-fsf-free = "either"
|
|
+copyleft = "deny"
|
|
diff --git a/third_party/rust/rustc_version/src/errors.rs b/third_party/rust/rustc_version/src/errors.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/rustc_version/src/lib.rs b/third_party/rust/rustc_version/src/lib.rs
|
|
--- a/third_party/rust/rustc_version/src/lib.rs
|
|
+++ b/third_party/rust/rustc_version/src/lib.rs
|
|
@@ -17,73 +17,138 @@
|
|
//! 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);
|
|
+//! // 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");
|
|
-//! }
|
|
+//! // 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");
|
|
-//! }
|
|
+//! // 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;
|
|
+#[cfg(test)]
|
|
+#[macro_use]
|
|
+extern crate doc_comment;
|
|
+
|
|
+#[cfg(test)]
|
|
+doctest!("../README.md");
|
|
+
|
|
+use std::collections::HashMap;
|
|
use std::process::Command;
|
|
-use std::{env, str};
|
|
-use std::ffi::OsString;
|
|
+use std::{env, error, fmt, io, num, str};
|
|
+use std::{ffi::OsString, str::FromStr};
|
|
|
|
// Convenience re-export to allow version comparison without needing to add
|
|
// semver crate.
|
|
pub use semver::Version;
|
|
|
|
-mod errors;
|
|
-pub use errors::{Error, Result};
|
|
+use Error::*;
|
|
|
|
/// 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.
|
|
+/// LLVM version
|
|
+///
|
|
+/// LLVM's version numbering scheme is not semver compatible until version 4.0
|
|
+///
|
|
+/// rustc [just prints the major and minor versions], so other parts of the version are not included.
|
|
+///
|
|
+/// [just prints the major and minor versions]: https://github.com/rust-lang/rust/blob/b5c9e2448c9ace53ad5c11585803894651b18b0a/compiler/rustc_codegen_llvm/src/llvm_util.rs#L173-L178
|
|
+#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
+pub struct LlvmVersion {
|
|
+ // fields must be ordered major, minor for comparison to be correct
|
|
+ /// Major version
|
|
+ pub major: u64,
|
|
+ /// Minor version
|
|
+ pub minor: u64,
|
|
+ // TODO: expose micro version here
|
|
+}
|
|
+
|
|
+impl fmt::Display for LlvmVersion {
|
|
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
+ write!(f, "{}.{}", self.major, self.minor)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl FromStr for LlvmVersion {
|
|
+ type Err = LlvmVersionParseError;
|
|
+
|
|
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
+ let mut parts = s
|
|
+ .split('.')
|
|
+ .map(|part| -> Result<u64, LlvmVersionParseError> {
|
|
+ if part == "0" {
|
|
+ Ok(0)
|
|
+ } else if part.starts_with('0') {
|
|
+ Err(LlvmVersionParseError::ComponentMustNotHaveLeadingZeros)
|
|
+ } else if part.starts_with('-') || part.starts_with('+') {
|
|
+ Err(LlvmVersionParseError::ComponentMustNotHaveSign)
|
|
+ } else {
|
|
+ Ok(part.parse()?)
|
|
+ }
|
|
+ });
|
|
+
|
|
+ let major = parts.next().unwrap()?;
|
|
+ let mut minor = 0;
|
|
+
|
|
+ if let Some(part) = parts.next() {
|
|
+ minor = part?;
|
|
+ } else if major < 4 {
|
|
+ // LLVM versions earlier than 4.0 have significant minor versions, so require the minor version in this case.
|
|
+ return Err(LlvmVersionParseError::MinorVersionRequiredBefore4);
|
|
+ }
|
|
+
|
|
+ if let Some(Err(e)) = parts.next() {
|
|
+ return Err(e);
|
|
+ }
|
|
+
|
|
+ if parts.next().is_some() {
|
|
+ return Err(LlvmVersionParseError::TooManyComponents);
|
|
+ }
|
|
+
|
|
+ Ok(Self { major, minor })
|
|
+ }
|
|
+}
|
|
+
|
|
+/// Rustc version plus metadata 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>,
|
|
|
|
@@ -96,27 +161,37 @@ pub struct VersionMeta {
|
|
/// 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,
|
|
+
|
|
+ /// Version of LLVM used by the compiler
|
|
+ pub llvm_version: Option<LlvmVersion>,
|
|
}
|
|
|
|
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;
|
|
+ pub fn for_command(mut cmd: Command) -> Result<VersionMeta> {
|
|
+ let out = cmd
|
|
+ .arg("-vV")
|
|
+ .output()
|
|
+ .map_err(Error::CouldNotExecuteCommand)?;
|
|
|
|
- let out = cmd.arg("-vV").output().map_err(Error::CouldNotExecuteCommand)?;
|
|
- let out = str::from_utf8(&out.stdout)?;
|
|
+ if !out.status.success() {
|
|
+ return Err(Error::CommandError {
|
|
+ stdout: String::from_utf8_lossy(&out.stdout).into(),
|
|
+ stderr: String::from_utf8_lossy(&out.stderr).into(),
|
|
+ });
|
|
+ }
|
|
|
|
- version_meta_for(out)
|
|
+ version_meta_for(str::from_utf8(&out.stdout)?)
|
|
}
|
|
}
|
|
|
|
/// Returns the `rustc` SemVer version.
|
|
pub fn version() -> Result<Version> {
|
|
Ok(version_meta()?.semver)
|
|
}
|
|
|
|
@@ -127,221 +202,216 @@ pub fn version_meta() -> Result<VersionM
|
|
|
|
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 mut map = HashMap::new();
|
|
+ for (i, line) in verbose_version_string.lines().enumerate() {
|
|
+ if i == 0 {
|
|
+ map.insert("short", line);
|
|
+ continue;
|
|
+ }
|
|
|
|
- let short_version_string = out[0];
|
|
+ let mut parts = line.splitn(2, ": ");
|
|
+ let key = match parts.next() {
|
|
+ Some(key) => key,
|
|
+ None => continue,
|
|
+ };
|
|
|
|
- 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)
|
|
+ if let Some(value) = parts.next() {
|
|
+ map.insert(key, value);
|
|
}
|
|
}
|
|
|
|
- let commit_hash = match expect_prefix(out[2], "commit-hash: ")? {
|
|
- "unknown" => None,
|
|
- hash => Some(hash.to_owned()),
|
|
- };
|
|
+ let short_version_string = expect_key("short", &map)?;
|
|
+ let host = expect_key("host", &map)?;
|
|
+ let release = expect_key("release", &map)?;
|
|
+ let semver: Version = release.parse()?;
|
|
|
|
- let commit_date = match expect_prefix(out[3], "commit-date: ")? {
|
|
- "unknown" => None,
|
|
- hash => Some(hash.to_owned()),
|
|
+ let channel = match semver.pre.split('.').next().unwrap() {
|
|
+ "" => Channel::Stable,
|
|
+ "dev" => Channel::Dev,
|
|
+ "beta" => Channel::Beta,
|
|
+ "nightly" => Channel::Nightly,
|
|
+ x => return Err(Error::UnknownPreReleaseTag(x.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())),
|
|
- }
|
|
+ let commit_hash = expect_key_or_unknown("commit-hash", &map)?;
|
|
+ let commit_date = expect_key_or_unknown("commit-date", &map)?;
|
|
+ let build_date = map
|
|
+ .get("build-date")
|
|
+ .filter(|&v| *v != "unknown")
|
|
+ .map(|&v| String::from(v));
|
|
+ let llvm_version = match map.get("LLVM version") {
|
|
+ Some(&v) => Some(v.parse()?),
|
|
+ None => None,
|
|
};
|
|
|
|
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(),
|
|
+ semver,
|
|
+ commit_hash,
|
|
+ commit_date,
|
|
+ build_date,
|
|
+ channel,
|
|
+ host,
|
|
+ short_version_string,
|
|
+ llvm_version,
|
|
})
|
|
}
|
|
|
|
-#[test]
|
|
-fn smoketest() {
|
|
- let v = version().unwrap();
|
|
- assert!(v.major >= 1);
|
|
+fn expect_key_or_unknown(key: &str, map: &HashMap<&str, &str>) -> Result<Option<String>, Error> {
|
|
+ match map.get(key) {
|
|
+ Some(&v) if v == "unknown" => Ok(None),
|
|
+ Some(&v) => Ok(Some(String::from(v))),
|
|
+ None => Err(Error::UnexpectedVersionFormat),
|
|
+ }
|
|
+}
|
|
|
|
- let v = version_meta().unwrap();
|
|
- assert!(v.semver.major >= 1);
|
|
-
|
|
- assert!(version().unwrap() >= Version::parse("1.0.0").unwrap());
|
|
+fn expect_key(key: &str, map: &HashMap<&str, &str>) -> Result<String, Error> {
|
|
+ map.get(key)
|
|
+ .map(|&v| String::from(v))
|
|
+ .ok_or(Error::UnexpectedVersionFormat)
|
|
}
|
|
|
|
-#[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");
|
|
+/// LLVM Version Parse Error
|
|
+#[derive(Debug)]
|
|
+pub enum LlvmVersionParseError {
|
|
+ /// An error occurred in parsing a version component as an integer
|
|
+ ParseIntError(num::ParseIntError),
|
|
+ /// A version component must not have leading zeros
|
|
+ ComponentMustNotHaveLeadingZeros,
|
|
+ /// A version component has a sign
|
|
+ ComponentMustNotHaveSign,
|
|
+ /// Minor version component must be zero on LLVM versions later than 4.0
|
|
+ MinorVersionMustBeZeroAfter4,
|
|
+ /// Minor version component is required on LLVM versions earlier than 4.0
|
|
+ MinorVersionRequiredBefore4,
|
|
+ /// Too many components
|
|
+ TooManyComponents,
|
|
+}
|
|
|
|
- assert!(match res {
|
|
- Err(Error::UnexpectedVersionFormat) => true,
|
|
- _ => false,
|
|
- });
|
|
-
|
|
+impl From<num::ParseIntError> for LlvmVersionParseError {
|
|
+ fn from(e: num::ParseIntError) -> Self {
|
|
+ LlvmVersionParseError::ParseIntError(e)
|
|
+ }
|
|
}
|
|
|
|
-#[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)");
|
|
+impl fmt::Display for LlvmVersionParseError {
|
|
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
+ match self {
|
|
+ LlvmVersionParseError::ParseIntError(e) => {
|
|
+ write!(f, "error parsing LLVM version component: {}", e)
|
|
+ }
|
|
+ LlvmVersionParseError::ComponentMustNotHaveLeadingZeros => {
|
|
+ write!(f, "a version component must not have leading zeros")
|
|
+ }
|
|
+ LlvmVersionParseError::ComponentMustNotHaveSign => {
|
|
+ write!(f, "a version component must not have a sign")
|
|
+ }
|
|
+ LlvmVersionParseError::MinorVersionMustBeZeroAfter4 => write!(
|
|
+ f,
|
|
+ "LLVM's minor version component must be 0 for versions greater than 4.0"
|
|
+ ),
|
|
+ LlvmVersionParseError::MinorVersionRequiredBefore4 => write!(
|
|
+ f,
|
|
+ "LLVM's minor version component is required for versions less than 4.0"
|
|
+ ),
|
|
+ LlvmVersionParseError::TooManyComponents => write!(f, "too many version components"),
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
-
|
|
-#[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");
|
|
+impl error::Error for LlvmVersionParseError {
|
|
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
|
+ match self {
|
|
+ LlvmVersionParseError::ParseIntError(e) => Some(e),
|
|
+ LlvmVersionParseError::ComponentMustNotHaveLeadingZeros
|
|
+ | LlvmVersionParseError::ComponentMustNotHaveSign
|
|
+ | LlvmVersionParseError::MinorVersionMustBeZeroAfter4
|
|
+ | LlvmVersionParseError::MinorVersionRequiredBefore4
|
|
+ | LlvmVersionParseError::TooManyComponents => None,
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
-#[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)");
|
|
+/// The error type for this crate.
|
|
+#[derive(Debug)]
|
|
+pub enum Error {
|
|
+ /// An error occurred while trying to find the `rustc` to run.
|
|
+ CouldNotExecuteCommand(io::Error),
|
|
+ /// Error output from the command that was run.
|
|
+ CommandError {
|
|
+ /// stdout output from the command
|
|
+ stdout: String,
|
|
+ /// stderr output from the command
|
|
+ stderr: String,
|
|
+ },
|
|
+ /// 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 occurred in parsing the semver.
|
|
+ SemVerError(semver::Error),
|
|
+ /// The pre-release tag is unknown.
|
|
+ UnknownPreReleaseTag(String),
|
|
+ /// An error occurred in parsing a `LlvmVersion`.
|
|
+ LlvmVersionError(LlvmVersionParseError),
|
|
}
|
|
|
|
-#[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)");
|
|
+impl fmt::Display for Error {
|
|
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
+ match *self {
|
|
+ CouldNotExecuteCommand(ref e) => write!(f, "could not execute command: {}", e),
|
|
+ CommandError {
|
|
+ ref stdout,
|
|
+ ref stderr,
|
|
+ } => write!(
|
|
+ f,
|
|
+ "error from command -- stderr:\n\n{}\n\nstderr:\n\n{}",
|
|
+ stderr, stdout,
|
|
+ ),
|
|
+ Utf8Error(_) => write!(f, "invalid UTF-8 output from `rustc -vV`"),
|
|
+ UnexpectedVersionFormat => write!(f, "unexpected `rustc -vV` format"),
|
|
+ SemVerError(ref e) => write!(f, "error parsing version: {}", e),
|
|
+ UnknownPreReleaseTag(ref i) => write!(f, "unknown pre-release tag: {}", i),
|
|
+ LlvmVersionError(ref e) => write!(f, "error parsing LLVM's version: {}", e),
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
-/*
|
|
-#[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!();
|
|
+impl error::Error for Error {
|
|
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
|
+ match *self {
|
|
+ CouldNotExecuteCommand(ref e) => Some(e),
|
|
+ CommandError { .. } => None,
|
|
+ Utf8Error(ref e) => Some(e),
|
|
+ UnexpectedVersionFormat => None,
|
|
+ SemVerError(ref e) => Some(e),
|
|
+ UnknownPreReleaseTag(_) => None,
|
|
+ LlvmVersionError(ref e) => Some(e),
|
|
+ }
|
|
+ }
|
|
+}
|
|
|
|
- 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");
|
|
+macro_rules! impl_from {
|
|
+ ($($err_ty:ty => $variant:ident),* $(,)*) => {
|
|
+ $(
|
|
+ impl From<$err_ty> for Error {
|
|
+ fn from(e: $err_ty) -> Error {
|
|
+ Error::$variant(e)
|
|
+ }
|
|
+ }
|
|
+ )*
|
|
+ }
|
|
+}
|
|
|
|
- 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");
|
|
+impl_from! {
|
|
+ str::Utf8Error => Utf8Error,
|
|
+ semver::Error => SemVerError,
|
|
+ LlvmVersionParseError => LlvmVersionError,
|
|
+}
|
|
|
|
- panic!();
|
|
-
|
|
-}
|
|
-*/
|
|
+/// The result type for this crate.
|
|
+pub type Result<T, E = Error> = std::result::Result<T, E>;
|
|
diff --git a/third_party/rust/rustc_version/tests/all.rs b/third_party/rust/rustc_version/tests/all.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/rustc_version/tests/all.rs
|
|
@@ -0,0 +1,456 @@
|
|
+#![allow(clippy::match_like_matches_macro)]
|
|
+
|
|
+use std::process::Command;
|
|
+
|
|
+use rustc_version::{
|
|
+ version, version_meta, version_meta_for, Channel, Error, LlvmVersion, LlvmVersionParseError,
|
|
+ Version, VersionMeta,
|
|
+};
|
|
+
|
|
+#[test]
|
|
+fn rustc_error() {
|
|
+ let mut cmd = Command::new("rustc");
|
|
+ cmd.arg("--FOO");
|
|
+ let stderr = match VersionMeta::for_command(cmd) {
|
|
+ Err(Error::CommandError { stdout: _, stderr }) => stderr,
|
|
+ _ => panic!("command error expected"),
|
|
+ };
|
|
+ assert_eq!(stderr, "error: Unrecognized option: \'FOO\'\n\n");
|
|
+}
|
|
+
|
|
+#[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_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)"
|
|
+ );
|
|
+ assert_eq!(version.llvm_version, None);
|
|
+}
|
|
+
|
|
+#[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");
|
|
+ assert_eq!(version.llvm_version, None);
|
|
+}
|
|
+
|
|
+#[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)"
|
|
+ );
|
|
+ assert_eq!(version.llvm_version, None);
|
|
+}
|
|
+
|
|
+#[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)"
|
|
+ );
|
|
+ assert_eq!(version.llvm_version, None);
|
|
+}
|
|
+
|
|
+#[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)"
|
|
+ );
|
|
+ assert_eq!(
|
|
+ version.llvm_version,
|
|
+ Some(LlvmVersion { major: 3, minor: 9 })
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_1_47_0_stable() {
|
|
+ let version = version_meta_for(
|
|
+ "rustc 1.47.0 (18bf6b4f0 2020-10-07)
|
|
+binary: rustc
|
|
+commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
|
|
+commit-date: 2020-10-07
|
|
+host: powerpc64le-unknown-linux-gnu
|
|
+release: 1.47.0
|
|
+LLVM version: 11.0",
|
|
+ )
|
|
+ .unwrap();
|
|
+
|
|
+ assert_eq!(version.semver, Version::parse("1.47.0").unwrap());
|
|
+ assert_eq!(
|
|
+ version.commit_hash,
|
|
+ Some("18bf6b4f01a6feaf7259ba7cdae58031af1b7b39".into())
|
|
+ );
|
|
+ assert_eq!(version.commit_date, Some("2020-10-07".into()));
|
|
+ assert_eq!(version.channel, Channel::Stable);
|
|
+ assert_eq!(version.host, "powerpc64le-unknown-linux-gnu");
|
|
+ assert_eq!(
|
|
+ version.short_version_string,
|
|
+ "rustc 1.47.0 (18bf6b4f0 2020-10-07)"
|
|
+ );
|
|
+ assert_eq!(
|
|
+ version.llvm_version,
|
|
+ Some(LlvmVersion {
|
|
+ major: 11,
|
|
+ minor: 0,
|
|
+ })
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_micro() {
|
|
+ let version = version_meta_for(
|
|
+ "rustc 1.51.0-nightly (4253153db 2021-01-17)
|
|
+binary: rustc
|
|
+commit-hash: 4253153db205251f72ea4493687a31e04a2a8ca0
|
|
+commit-date: 2021-01-17
|
|
+host: x86_64-pc-windows-msvc
|
|
+release: 1.51.0-nightly
|
|
+LLVM version: 11.0.1",
|
|
+ )
|
|
+ .unwrap();
|
|
+
|
|
+ assert_eq!(version.semver, Version::parse("1.51.0-nightly").unwrap());
|
|
+ assert_eq!(
|
|
+ version.commit_hash.unwrap(),
|
|
+ "4253153db205251f72ea4493687a31e04a2a8ca0"
|
|
+ );
|
|
+ assert_eq!(version.commit_date.unwrap(), "2021-01-17");
|
|
+ assert_eq!(version.host, "x86_64-pc-windows-msvc");
|
|
+ assert_eq!(
|
|
+ version.short_version_string,
|
|
+ "rustc 1.51.0-nightly (4253153db 2021-01-17)"
|
|
+ );
|
|
+ assert_eq!(
|
|
+ version.llvm_version,
|
|
+ Some(LlvmVersion {
|
|
+ major: 11,
|
|
+ minor: 0
|
|
+ })
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_debian_buster() {
|
|
+ let version = version_meta_for(
|
|
+ "rustc 1.41.1
|
|
+binary: rustc
|
|
+commit-hash: unknown
|
|
+commit-date: unknown
|
|
+host: powerpc64le-unknown-linux-gnu
|
|
+release: 1.41.1
|
|
+LLVM version: 7.0",
|
|
+ )
|
|
+ .unwrap();
|
|
+
|
|
+ assert_eq!(version.semver, Version::parse("1.41.1").unwrap());
|
|
+ assert_eq!(version.commit_hash, None);
|
|
+ assert_eq!(version.commit_date, None);
|
|
+ assert_eq!(version.channel, Channel::Stable);
|
|
+ assert_eq!(version.host, "powerpc64le-unknown-linux-gnu");
|
|
+ assert_eq!(version.short_version_string, "rustc 1.41.1");
|
|
+ assert_eq!(
|
|
+ version.llvm_version,
|
|
+ Some(LlvmVersion { major: 7, minor: 0 })
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_termux() {
|
|
+ let version = version_meta_for(
|
|
+ "rustc 1.46.0
|
|
+binary: rustc
|
|
+commit-hash: unknown
|
|
+commit-date: unknown
|
|
+host: aarch64-linux-android
|
|
+release: 1.46.0
|
|
+LLVM version: 10.0",
|
|
+ )
|
|
+ .unwrap();
|
|
+
|
|
+ assert_eq!(version.semver, Version::parse("1.46.0").unwrap());
|
|
+ assert_eq!(version.commit_hash, None);
|
|
+ assert_eq!(version.commit_date, None);
|
|
+ assert_eq!(version.channel, Channel::Stable);
|
|
+ assert_eq!(version.host, "aarch64-linux-android");
|
|
+ assert_eq!(version.short_version_string, "rustc 1.46.0");
|
|
+ assert_eq!(
|
|
+ version.llvm_version,
|
|
+ Some(LlvmVersion {
|
|
+ major: 10,
|
|
+ minor: 0,
|
|
+ })
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_empty() {
|
|
+ let res: Result<LlvmVersion, _> = "".parse();
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::ParseIntError(_)) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_invalid_char() {
|
|
+ let res: Result<LlvmVersion, _> = "A".parse();
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::ParseIntError(_)) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_overflow() {
|
|
+ let res: Result<LlvmVersion, _> = "9999999999999999999999999999999".parse();
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::ParseIntError(_)) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_leading_zero_on_zero() {
|
|
+ let res: Result<LlvmVersion, _> = "00".parse();
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::ComponentMustNotHaveLeadingZeros) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_leading_zero_on_nonzero() {
|
|
+ let res: Result<LlvmVersion, _> = "01".parse();
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::ComponentMustNotHaveLeadingZeros) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_4_components() {
|
|
+ let res: Result<LlvmVersion, _> = "4.0.0.0".parse();
|
|
+
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::TooManyComponents) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_component_sign_plus() {
|
|
+ let res: Result<LlvmVersion, _> = "1.+3".parse();
|
|
+
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::ComponentMustNotHaveSign) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_component_sign_minus() {
|
|
+ let res: Result<LlvmVersion, _> = "1.-3".parse();
|
|
+
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::ComponentMustNotHaveSign) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_3() {
|
|
+ let res: Result<LlvmVersion, _> = "3".parse();
|
|
+
|
|
+ assert!(match res {
|
|
+ Err(LlvmVersionParseError::MinorVersionRequiredBefore4) => true,
|
|
+ _ => false,
|
|
+ });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_5() {
|
|
+ let v: LlvmVersion = "5".parse().unwrap();
|
|
+ assert_eq!(v, LlvmVersion { major: 5, minor: 0 });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_5_0() {
|
|
+ let v: LlvmVersion = "5.0".parse().unwrap();
|
|
+ assert_eq!(v, LlvmVersion { major: 5, minor: 0 });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_4_0() {
|
|
+ let v: LlvmVersion = "4.0".parse().unwrap();
|
|
+ assert_eq!(v, LlvmVersion { major: 4, minor: 0 });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_3_0() {
|
|
+ let v: LlvmVersion = "3.0".parse().unwrap();
|
|
+ assert_eq!(v, LlvmVersion { major: 3, minor: 0 });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_3_9() {
|
|
+ let v: LlvmVersion = "3.9".parse().unwrap();
|
|
+ assert_eq!(v, LlvmVersion { major: 3, minor: 9 });
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_11_0() {
|
|
+ let v: LlvmVersion = "11.0".parse().unwrap();
|
|
+ assert_eq!(
|
|
+ v,
|
|
+ LlvmVersion {
|
|
+ major: 11,
|
|
+ minor: 0
|
|
+ }
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn parse_llvm_version_11() {
|
|
+ let v: LlvmVersion = "11".parse().unwrap();
|
|
+ assert_eq!(
|
|
+ v,
|
|
+ LlvmVersion {
|
|
+ major: 11,
|
|
+ minor: 0
|
|
+ }
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_llvm_version_comparison() {
|
|
+ // check that field order is correct
|
|
+ assert!(LlvmVersion { major: 3, minor: 9 } < LlvmVersion { major: 4, minor: 0 });
|
|
+}
|
|
+
|
|
+/*
|
|
+#[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/third_party/rust/semver-parser/.cargo-checksum.json b/third_party/rust/semver-parser/.cargo-checksum.json
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/semver-parser/.cargo-checksum.json
|
|
+++ /dev/null
|
|
@@ -1,1 +0,0 @@
|
|
-{"files":{"Cargo.toml":"67597114802114d2a7fdb457c1cf5f7e0c951b21e287c6a47b9a86b9028cf64d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d38feaa4f9468cd1e0ece22e0ad2eadfe6195a9a0a3843b7c722d5c7d81804fb","src/common.rs":"dc42336abd34e19ca9f732f33657e106f98dcc8c10d4c2564bc4f160cb31926e","src/lib.rs":"3ac8ef5a280344a25cb18ac386034c0fee8d64060fa14af5e25ed49f0cb2fd9e","src/range.rs":"3596f048d466d43887aff1e8c8c834476672a4627631ed35379c35466b5f02ec","src/recognize.rs":"9f16eda9fcd7d8af7eee4c3b89c611bd648040273fde6b35778f8a50b004c8b1","src/version.rs":"dbd91a4e4fd92a0aa9eb4f858ecbc1ecd680aa60572cc2ad2085e5c5c30e5b77"},"package":"388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"}
|
|
\ No newline at end of file
|
|
diff --git a/third_party/rust/semver-parser/Cargo.toml b/third_party/rust/semver-parser/Cargo.toml
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver-parser/LICENSE-APACHE b/third_party/rust/semver-parser/LICENSE-APACHE
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver-parser/LICENSE-MIT b/third_party/rust/semver-parser/LICENSE-MIT
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver-parser/src/common.rs b/third_party/rust/semver-parser/src/common.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver-parser/src/lib.rs b/third_party/rust/semver-parser/src/lib.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver-parser/src/range.rs b/third_party/rust/semver-parser/src/range.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver-parser/src/recognize.rs b/third_party/rust/semver-parser/src/recognize.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver-parser/src/version.rs b/third_party/rust/semver-parser/src/version.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver/.cargo-checksum.json b/third_party/rust/semver/.cargo-checksum.json
|
|
--- a/third_party/rust/semver/.cargo-checksum.json
|
|
+++ b/third_party/rust/semver/.cargo-checksum.json
|
|
@@ -1,1 +1,1 @@
|
|
-{"files":{"Cargo.toml":"a5b995796b5559de8975a6fee7166c9fda6c21b449ec90bef5f9baaeddd479a5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c780d8c3c802c5fe2c316127900385010c3e57f71c851eea9e8ed8495e2030dd","src/lib.rs":"cb1725a8bb90c1043f187c6ba504d0a9d07793e2f39f5205f926c58849311770","src/version.rs":"ffdf9c628597b889f149f3b2b1245b97c774eae1ce7030bd19235eabecaaede0","src/version_req.rs":"40d20720f5fdc0b3d9e398e64eb448a65987229bd322cab0fedf0cf1843f3bd8","tests/deprecation.rs":"b5ec79e19d61968d05b96b876c449e54d43cbd1762c6e63c23c3470f9db56292","tests/regression.rs":"180b699ad029b81e6135d42f0a8e6d782177bc29a41132f875ee6f8607a46b56","tests/serde.rs":"cdbbefc576ffcc814c30dad9598ab87a7fd9d14c5f42f1349e1db6afc72f8fed"},"package":"1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"}
|
|
\ No newline at end of file
|
|
+{"files":{"Cargo.toml":"2a2126f8fe5d20540ae6cfbf6649ed3af365ffb9a0a788a7552a6e7649a7a75f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"57659341319915482c0b83779fb7f3f0f3accb7a8b881965799116afb5e9f7e9","benches/parse.rs":"6531f66f80ce2fc83878f9bf84f94c42e96f1e709466f2b88be8d95a3cec1511","build.rs":"47b42941210d44567c8561107420d7825aa1d01332c2d2f8892d9e20646a1c77","src/backport.rs":"f8866548840434c8974f135528693f25aacc4ad03639c4e3aea3be351e13fdf8","src/display.rs":"9ba42f7a6579aa9c7dd72f2380036f5c9664592f3eacd09ea25cef291a3e64e5","src/error.rs":"3bb489f4a29f38d93370e64ae8d6e4e9b451a055cd7d392b6aeacab7eb3e1953","src/eval.rs":"b7e7ec976051b9f87ddf5cfdbaad64654d98d86ae0763f7d88b14eeaeac6013c","src/identifier.rs":"601231351ac58602b7d193cb0951b5146bd868b62aba938d5cbe52cf2b93414b","src/impls.rs":"79b5a2ac6ca3d4cb46adfb1494756079f53bef780dd81c3a8d3adf86f91395c8","src/lib.rs":"8e116a19e521909f3fa50206c078f1e23bf033dc8057ba6101f80d5bc5900fed","src/parse.rs":"93593f62cdae489feb4f2e8ae1fa93d90dca63db50669b6265346ffaaf687be5","src/serde.rs":"970d343a6bac21ddd965168d3cc2af9998796bf29bf545e8b37c6bcdd97d9710","tests/node/mod.rs":"2710d9b8daace2038b66db0f8f4cc522dee938e7cbc42d7739c31995343c32f4","tests/test_autotrait.rs":"070500c32ceee14a8a0110c04a01f98278b24614a0aec8c382dcea3da0343f58","tests/test_identifier.rs":"6c3da46c73df210527b60f1069131b15e2c65eb7b5d11793940d00cf66812f4d","tests/test_version.rs":"09e37c3df162205acf3683d1c760a6001e34e1c709fd4a1a265d82450e340003","tests/test_version_req.rs":"b6eea0258cc3b6d567a9f6c42693a97316345083495236c47e85374fd45f7cf0","tests/util/mod.rs":"db61c2cd86af864d8be4f2a3d5f25c86d7712201cc6ab47b715facf5f7f275b7"},"package":"8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"}
|
|
\ No newline at end of file
|
|
diff --git a/third_party/rust/semver/Cargo.toml b/third_party/rust/semver/Cargo.toml
|
|
--- a/third_party/rust/semver/Cargo.toml
|
|
+++ b/third_party/rust/semver/Cargo.toml
|
|
@@ -1,45 +1,38 @@
|
|
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
#
|
|
# When uploading crates to the registry Cargo will automatically
|
|
# "normalize" Cargo.toml files for maximal compatibility
|
|
# with all versions of Cargo and also rewrite `path` dependencies
|
|
-# to registry (e.g. crates.io) dependencies
|
|
+# to registry (e.g., crates.io) dependencies.
|
|
#
|
|
-# If you believe there's an error in this file please file an
|
|
-# issue against the rust-lang/cargo repository. If you're
|
|
-# editing this file be aware that the upstream Cargo.toml
|
|
-# will likely look very different (and much more reasonable)
|
|
+# If you are reading this file be aware that the original Cargo.toml
|
|
+# will likely look very different (and much more reasonable).
|
|
+# See Cargo.toml.orig for the original contents.
|
|
|
|
[package]
|
|
+edition = "2018"
|
|
+rust-version = "1.31"
|
|
name = "semver"
|
|
-version = "0.9.0"
|
|
-authors = ["Steve Klabnik <steve@steveklabnik.com>", "The Rust Project Developers"]
|
|
-description = "Semantic version parsing and comparison.\n"
|
|
-homepage = "https://docs.rs/crate/semver/"
|
|
-documentation = "https://docs.rs/crate/semver/"
|
|
+version = "1.0.9"
|
|
+authors = ["David Tolnay <dtolnay@gmail.com>"]
|
|
+description = "Parser and evaluator for Cargo's flavor of Semantic Versioning"
|
|
+documentation = "https://docs.rs/semver"
|
|
readme = "README.md"
|
|
-license = "MIT/Apache-2.0"
|
|
-repository = "https://github.com/steveklabnik/semver"
|
|
-[dependencies.semver-parser]
|
|
-version = "0.7.0"
|
|
+license = "MIT OR Apache-2.0"
|
|
+repository = "https://github.com/dtolnay/semver"
|
|
+
|
|
+[package.metadata.docs.rs]
|
|
+targets = ["x86_64-unknown-linux-gnu"]
|
|
+rustdoc-args = [
|
|
+ "--cfg",
|
|
+ "doc_cfg",
|
|
+]
|
|
|
|
[dependencies.serde]
|
|
version = "1.0"
|
|
optional = true
|
|
-[dev-dependencies.crates-index]
|
|
-version = "0.5.0"
|
|
-
|
|
-[dev-dependencies.serde_json]
|
|
-version = "1.0"
|
|
-
|
|
-[dev-dependencies.serde_derive]
|
|
-version = "1.0"
|
|
-
|
|
-[dev-dependencies.tempdir]
|
|
-version = "0.3.4"
|
|
+default-features = false
|
|
|
|
[features]
|
|
-default = []
|
|
-ci = ["serde"]
|
|
-[badges.travis-ci]
|
|
-repository = "steveklabnik/semver"
|
|
+default = ["std"]
|
|
+std = []
|
|
diff --git a/third_party/rust/semver/LICENSE-MIT b/third_party/rust/semver/LICENSE-MIT
|
|
--- a/third_party/rust/semver/LICENSE-MIT
|
|
+++ b/third_party/rust/semver/LICENSE-MIT
|
|
@@ -1,10 +1,8 @@
|
|
-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
|
|
diff --git a/third_party/rust/semver/README.md b/third_party/rust/semver/README.md
|
|
--- a/third_party/rust/semver/README.md
|
|
+++ b/third_party/rust/semver/README.md
|
|
@@ -1,103 +1,84 @@
|
|
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.
|
|
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/semver-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/semver)
|
|
+[<img alt="crates.io" src="https://img.shields.io/crates/v/semver.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/semver)
|
|
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-semver-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/semver)
|
|
+[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/semver/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/semver/actions?query=branch%3Amaster)
|
|
|
|
-## SemVer and the Rust ecosystem
|
|
-
|
|
-Rust itself follows the SemVer specification, as does its standard libraries. The two are
|
|
-not tied together.
|
|
+A parser and evaluator for Cargo's flavor of Semantic Versioning.
|
|
|
|
-[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:
|
|
+Semantic Versioning (see <https://semver.org>) is a guideline for how version
|
|
+numbers are assigned and incremented. It is widely followed within the
|
|
+Cargo/crates.io ecosystem for Rust.
|
|
|
|
```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!(),
|
|
-}));
|
|
+[dependencies]
|
|
+semver = "1.0"
|
|
```
|
|
|
|
-If you have multiple `Version`s, you can use the usual comparison operators to compare them:
|
|
-
|
|
-```rust
|
|
-use semver::Version;
|
|
+*Compiler support: requires rustc 1.31+*
|
|
|
|
-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
|
|
+<br>
|
|
|
|
-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:
|
|
+## Example
|
|
|
|
```rust
|
|
-use semver::Version;
|
|
-use semver::VersionReq;
|
|
+use semver::{BuildMetadata, Prerelease, Version, VersionReq};
|
|
+
|
|
+fn main() {
|
|
+ let req = VersionReq::parse(">=1.2.3, <1.8.0").unwrap();
|
|
|
|
-let r = VersionReq::parse(">= 1.0.0").unwrap();
|
|
-let v = Version::parse("1.0.0").unwrap();
|
|
+ // Check whether this requirement matches version 1.2.3-alpha.1 (no)
|
|
+ let version = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: Prerelease::new("alpha.1").unwrap(),
|
|
+ build: BuildMetadata::EMPTY,
|
|
+ };
|
|
+ assert!(!req.matches(&version));
|
|
|
|
-assert!(r.to_string() == ">= 1.0.0".to_string());
|
|
-assert!(r.matches(&v))
|
|
+ // Check whether it matches 1.3.0 (yes it does)
|
|
+ let version = Version::parse("1.3.0").unwrap();
|
|
+ assert!(req.matches(&version));
|
|
+}
|
|
```
|
|
|
|
-It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at
|
|
-https://www.npmjs.org/doc/misc/semver.html
|
|
+<br>
|
|
+
|
|
+## Scope of this crate
|
|
|
|
-**Tilde requirements** specify a minimal version with some updates:
|
|
+Besides Cargo, several other package ecosystems and package managers for other
|
|
+languages also use SemVer: RubyGems/Bundler for Ruby, npm for JavaScript,
|
|
+Composer for PHP, CocoaPods for Objective-C...
|
|
|
|
-```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
|
|
-```
|
|
+The `semver` crate is specifically intended to implement Cargo's interpretation
|
|
+of Semantic Versioning.
|
|
+
|
|
+Where the various tools differ in their interpretation or implementation of the
|
|
+spec, this crate follows the implementation choices made by Cargo. If you are
|
|
+operating on version numbers from some other package ecosystem, you will want to
|
|
+use a different semver library which is appropriate to that ecosystem.
|
|
+
|
|
+The extent of Cargo's SemVer support is documented in the *[Specifying
|
|
+Dependencies]* chapter of the Cargo reference.
|
|
|
|
-**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.
|
|
+[Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
|
|
|
|
-`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.
|
|
+<br>
|
|
+
|
|
+#### License
|
|
|
|
-```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
|
|
-```
|
|
+<sup>
|
|
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
|
|
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
|
|
+</sup>
|
|
+
|
|
+<br>
|
|
+
|
|
+<sub>
|
|
+Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
|
|
+be dual licensed as above, without any additional terms or conditions.
|
|
+</sub>
|
|
diff --git a/third_party/rust/semver/benches/parse.rs b/third_party/rust/semver/benches/parse.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/benches/parse.rs
|
|
@@ -0,0 +1,24 @@
|
|
+#![feature(test)]
|
|
+
|
|
+extern crate test;
|
|
+
|
|
+use semver::{Prerelease, Version, VersionReq};
|
|
+use test::{black_box, Bencher};
|
|
+
|
|
+#[bench]
|
|
+fn parse_prerelease(b: &mut Bencher) {
|
|
+ let text = "x.7.z.92";
|
|
+ b.iter(|| black_box(text).parse::<Prerelease>().unwrap());
|
|
+}
|
|
+
|
|
+#[bench]
|
|
+fn parse_version(b: &mut Bencher) {
|
|
+ let text = "1.0.2021-beta+exp.sha.5114f85";
|
|
+ b.iter(|| black_box(text).parse::<Version>().unwrap());
|
|
+}
|
|
+
|
|
+#[bench]
|
|
+fn parse_version_req(b: &mut Bencher) {
|
|
+ let text = ">=1.2.3, <2.0.0";
|
|
+ b.iter(|| black_box(text).parse::<VersionReq>().unwrap());
|
|
+}
|
|
diff --git a/third_party/rust/semver/build.rs b/third_party/rust/semver/build.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/build.rs
|
|
@@ -0,0 +1,73 @@
|
|
+use std::env;
|
|
+use std::process::Command;
|
|
+use std::str;
|
|
+
|
|
+fn main() {
|
|
+ let compiler = match rustc_minor_version() {
|
|
+ Some(compiler) => compiler,
|
|
+ None => return,
|
|
+ };
|
|
+
|
|
+ if compiler < 33 {
|
|
+ // Exhaustive integer patterns. On older compilers, a final `_` arm is
|
|
+ // required even if every possible integer value is otherwise covered.
|
|
+ // https://github.com/rust-lang/rust/issues/50907
|
|
+ println!("cargo:rustc-cfg=no_exhaustive_int_match");
|
|
+ }
|
|
+
|
|
+ if compiler < 36 {
|
|
+ // extern crate alloc.
|
|
+ // https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#the-alloc-crate-is-stable
|
|
+ println!("cargo:rustc-cfg=no_alloc_crate");
|
|
+ }
|
|
+
|
|
+ if compiler < 39 {
|
|
+ // const Vec::new.
|
|
+ // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.new
|
|
+ println!("cargo:rustc-cfg=no_const_vec_new");
|
|
+ }
|
|
+
|
|
+ if compiler < 40 {
|
|
+ // #[non_exhaustive].
|
|
+ // https://blog.rust-lang.org/2019/12/19/Rust-1.40.0.html#non_exhaustive-structs-enums-and-variants
|
|
+ println!("cargo:rustc-cfg=no_non_exhaustive");
|
|
+ }
|
|
+
|
|
+ if compiler < 45 {
|
|
+ // String::strip_prefix.
|
|
+ // https://doc.rust-lang.org/std/primitive.str.html#method.repeat
|
|
+ println!("cargo:rustc-cfg=no_str_strip_prefix");
|
|
+ }
|
|
+
|
|
+ if compiler < 46 {
|
|
+ // #[track_caller].
|
|
+ // https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller
|
|
+ println!("cargo:rustc-cfg=no_track_caller");
|
|
+ }
|
|
+
|
|
+ if compiler < 52 {
|
|
+ // #![deny(unsafe_op_in_unsafe_fn)].
|
|
+ // https://github.com/rust-lang/rust/issues/71668
|
|
+ println!("cargo:rustc-cfg=no_unsafe_op_in_unsafe_fn_lint");
|
|
+ }
|
|
+
|
|
+ if compiler < 53 {
|
|
+ // Efficient intrinsics for count-leading-zeros and count-trailing-zeros
|
|
+ // on NonZero integers stabilized in 1.53.0. On many architectures these
|
|
+ // are more efficient than counting zeros on ordinary zeroable integers.
|
|
+ // https://doc.rust-lang.org/std/num/struct.NonZeroU64.html#method.leading_zeros
|
|
+ // https://doc.rust-lang.org/std/num/struct.NonZeroU64.html#method.trailing_zeros
|
|
+ println!("cargo:rustc-cfg=no_nonzero_bitscan");
|
|
+ }
|
|
+}
|
|
+
|
|
+fn rustc_minor_version() -> Option<u32> {
|
|
+ let rustc = env::var_os("RUSTC")?;
|
|
+ let output = Command::new(rustc).arg("--version").output().ok()?;
|
|
+ let version = str::from_utf8(&output.stdout).ok()?;
|
|
+ let mut pieces = version.split('.');
|
|
+ if pieces.next() != Some("rustc 1") {
|
|
+ return None;
|
|
+ }
|
|
+ pieces.next()?.parse().ok()
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/backport.rs b/third_party/rust/semver/src/backport.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/backport.rs
|
|
@@ -0,0 +1,51 @@
|
|
+#[cfg(no_str_strip_prefix)] // rustc <1.45
|
|
+pub(crate) trait StripPrefixExt {
|
|
+ fn strip_prefix(&self, ch: char) -> Option<&str>;
|
|
+}
|
|
+
|
|
+#[cfg(no_str_strip_prefix)]
|
|
+impl StripPrefixExt for str {
|
|
+ fn strip_prefix(&self, ch: char) -> Option<&str> {
|
|
+ if self.starts_with(ch) {
|
|
+ Some(&self[ch.len_utf8()..])
|
|
+ } else {
|
|
+ None
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+pub(crate) use crate::alloc::vec::Vec;
|
|
+
|
|
+#[cfg(no_alloc_crate)] // rustc <1.36
|
|
+pub(crate) mod alloc {
|
|
+ pub use std::vec;
|
|
+
|
|
+ pub mod alloc {
|
|
+ use std::mem;
|
|
+
|
|
+ pub struct Layout {
|
|
+ size: usize,
|
|
+ }
|
|
+
|
|
+ impl Layout {
|
|
+ pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
|
+ assert_eq!(align, 2);
|
|
+ Layout { size }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
|
|
+ let len_u16 = (layout.size + 1) / 2;
|
|
+ let mut vec = Vec::new();
|
|
+ vec.reserve_exact(len_u16);
|
|
+ let ptr: *mut u16 = vec.as_mut_ptr();
|
|
+ mem::forget(vec);
|
|
+ ptr as *mut u8
|
|
+ }
|
|
+
|
|
+ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
|
|
+ let len_u16 = (layout.size + 1) / 2;
|
|
+ unsafe { Vec::from_raw_parts(ptr as *mut u16, 0, len_u16) };
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/display.rs b/third_party/rust/semver/src/display.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/display.rs
|
|
@@ -0,0 +1,165 @@
|
|
+use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq};
|
|
+use core::fmt::{self, Alignment, Debug, Display, Write};
|
|
+
|
|
+impl Display for Version {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ let do_display = |formatter: &mut fmt::Formatter| -> fmt::Result {
|
|
+ write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)?;
|
|
+ if !self.pre.is_empty() {
|
|
+ write!(formatter, "-{}", self.pre)?;
|
|
+ }
|
|
+ if !self.build.is_empty() {
|
|
+ write!(formatter, "+{}", self.build)?;
|
|
+ }
|
|
+ Ok(())
|
|
+ };
|
|
+
|
|
+ let do_len = || -> usize {
|
|
+ digits(self.major)
|
|
+ + 1
|
|
+ + digits(self.minor)
|
|
+ + 1
|
|
+ + digits(self.patch)
|
|
+ + !self.pre.is_empty() as usize
|
|
+ + self.pre.len()
|
|
+ + !self.build.is_empty() as usize
|
|
+ + self.build.len()
|
|
+ };
|
|
+
|
|
+ pad(formatter, do_display, do_len)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Display for VersionReq {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ if self.comparators.is_empty() {
|
|
+ return formatter.write_str("*");
|
|
+ }
|
|
+ for (i, comparator) in self.comparators.iter().enumerate() {
|
|
+ if i > 0 {
|
|
+ formatter.write_str(", ")?;
|
|
+ }
|
|
+ write!(formatter, "{}", comparator)?;
|
|
+ }
|
|
+ Ok(())
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Display for Comparator {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ let op = match self.op {
|
|
+ Op::Exact => "=",
|
|
+ Op::Greater => ">",
|
|
+ Op::GreaterEq => ">=",
|
|
+ Op::Less => "<",
|
|
+ Op::LessEq => "<=",
|
|
+ Op::Tilde => "~",
|
|
+ Op::Caret => "^",
|
|
+ Op::Wildcard => "",
|
|
+ #[cfg(no_non_exhaustive)]
|
|
+ Op::__NonExhaustive => unreachable!(),
|
|
+ };
|
|
+ formatter.write_str(op)?;
|
|
+ write!(formatter, "{}", self.major)?;
|
|
+ if let Some(minor) = &self.minor {
|
|
+ write!(formatter, ".{}", minor)?;
|
|
+ if let Some(patch) = &self.patch {
|
|
+ write!(formatter, ".{}", patch)?;
|
|
+ if !self.pre.is_empty() {
|
|
+ write!(formatter, "-{}", self.pre)?;
|
|
+ }
|
|
+ } else if self.op == Op::Wildcard {
|
|
+ formatter.write_str(".*")?;
|
|
+ }
|
|
+ } else if self.op == Op::Wildcard {
|
|
+ formatter.write_str(".*")?;
|
|
+ }
|
|
+ Ok(())
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Display for Prerelease {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ formatter.write_str(self.as_str())
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Display for BuildMetadata {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ formatter.write_str(self.as_str())
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Debug for Version {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ let mut debug = formatter.debug_struct("Version");
|
|
+ debug
|
|
+ .field("major", &self.major)
|
|
+ .field("minor", &self.minor)
|
|
+ .field("patch", &self.patch);
|
|
+ if !self.pre.is_empty() {
|
|
+ debug.field("pre", &self.pre);
|
|
+ }
|
|
+ if !self.build.is_empty() {
|
|
+ debug.field("build", &self.build);
|
|
+ }
|
|
+ debug.finish()
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Debug for Prerelease {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ write!(formatter, "Prerelease(\"{}\")", self)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Debug for BuildMetadata {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ write!(formatter, "BuildMetadata(\"{}\")", self)
|
|
+ }
|
|
+}
|
|
+
|
|
+fn pad(
|
|
+ formatter: &mut fmt::Formatter,
|
|
+ do_display: impl FnOnce(&mut fmt::Formatter) -> fmt::Result,
|
|
+ do_len: impl FnOnce() -> usize,
|
|
+) -> fmt::Result {
|
|
+ let min_width = match formatter.width() {
|
|
+ Some(min_width) => min_width,
|
|
+ None => return do_display(formatter),
|
|
+ };
|
|
+
|
|
+ let len = do_len();
|
|
+ if len >= min_width {
|
|
+ return do_display(formatter);
|
|
+ }
|
|
+
|
|
+ let default_align = Alignment::Left;
|
|
+ let align = formatter.align().unwrap_or(default_align);
|
|
+ let padding = min_width - len;
|
|
+ let (pre_pad, post_pad) = match align {
|
|
+ Alignment::Left => (0, padding),
|
|
+ Alignment::Right => (padding, 0),
|
|
+ Alignment::Center => (padding / 2, (padding + 1) / 2),
|
|
+ };
|
|
+
|
|
+ let fill = formatter.fill();
|
|
+ for _ in 0..pre_pad {
|
|
+ formatter.write_char(fill)?;
|
|
+ }
|
|
+
|
|
+ do_display(formatter)?;
|
|
+
|
|
+ for _ in 0..post_pad {
|
|
+ formatter.write_char(fill)?;
|
|
+ }
|
|
+ Ok(())
|
|
+}
|
|
+
|
|
+fn digits(val: u64) -> usize {
|
|
+ if val < 10 {
|
|
+ 1
|
|
+ } else {
|
|
+ 1 + digits(val / 10)
|
|
+ }
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/error.rs b/third_party/rust/semver/src/error.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/error.rs
|
|
@@ -0,0 +1,124 @@
|
|
+use crate::parse::Error;
|
|
+use core::fmt::{self, Debug, Display};
|
|
+
|
|
+pub(crate) enum ErrorKind {
|
|
+ UnexpectedEnd(Position),
|
|
+ UnexpectedChar(Position, char),
|
|
+ UnexpectedCharAfter(Position, char),
|
|
+ ExpectedCommaFound(Position, char),
|
|
+ LeadingZero(Position),
|
|
+ Overflow(Position),
|
|
+ EmptySegment(Position),
|
|
+ IllegalCharacter(Position),
|
|
+ WildcardNotTheOnlyComparator(char),
|
|
+ UnexpectedAfterWildcard,
|
|
+ ExcessiveComparators,
|
|
+}
|
|
+
|
|
+#[derive(Copy, Clone, Eq, PartialEq)]
|
|
+pub(crate) enum Position {
|
|
+ Major,
|
|
+ Minor,
|
|
+ Patch,
|
|
+ Pre,
|
|
+ Build,
|
|
+}
|
|
+
|
|
+#[cfg(feature = "std")]
|
|
+#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
|
|
+impl std::error::Error for Error {}
|
|
+
|
|
+impl Display for Error {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ match &self.kind {
|
|
+ ErrorKind::UnexpectedEnd(pos) => {
|
|
+ write!(formatter, "unexpected end of input while parsing {}", pos)
|
|
+ }
|
|
+ ErrorKind::UnexpectedChar(pos, ch) => {
|
|
+ write!(
|
|
+ formatter,
|
|
+ "unexpected character {} while parsing {}",
|
|
+ QuotedChar(*ch),
|
|
+ pos,
|
|
+ )
|
|
+ }
|
|
+ ErrorKind::UnexpectedCharAfter(pos, ch) => {
|
|
+ write!(
|
|
+ formatter,
|
|
+ "unexpected character {} after {}",
|
|
+ QuotedChar(*ch),
|
|
+ pos,
|
|
+ )
|
|
+ }
|
|
+ ErrorKind::ExpectedCommaFound(pos, ch) => {
|
|
+ write!(
|
|
+ formatter,
|
|
+ "expected comma after {}, found {}",
|
|
+ pos,
|
|
+ QuotedChar(*ch),
|
|
+ )
|
|
+ }
|
|
+ ErrorKind::LeadingZero(pos) => {
|
|
+ write!(formatter, "invalid leading zero in {}", pos)
|
|
+ }
|
|
+ ErrorKind::Overflow(pos) => {
|
|
+ write!(formatter, "value of {} exceeds u64::MAX", pos)
|
|
+ }
|
|
+ ErrorKind::EmptySegment(pos) => {
|
|
+ write!(formatter, "empty identifier segment in {}", pos)
|
|
+ }
|
|
+ ErrorKind::IllegalCharacter(pos) => {
|
|
+ write!(formatter, "unexpected character in {}", pos)
|
|
+ }
|
|
+ ErrorKind::WildcardNotTheOnlyComparator(ch) => {
|
|
+ write!(
|
|
+ formatter,
|
|
+ "wildcard req ({}) must be the only comparator in the version req",
|
|
+ ch,
|
|
+ )
|
|
+ }
|
|
+ ErrorKind::UnexpectedAfterWildcard => {
|
|
+ formatter.write_str("unexpected character after wildcard in version req")
|
|
+ }
|
|
+ ErrorKind::ExcessiveComparators => {
|
|
+ formatter.write_str("excessive number of version comparators")
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Display for Position {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ formatter.write_str(match self {
|
|
+ Position::Major => "major version number",
|
|
+ Position::Minor => "minor version number",
|
|
+ Position::Patch => "patch version number",
|
|
+ Position::Pre => "pre-release identifier",
|
|
+ Position::Build => "build metadata",
|
|
+ })
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Debug for Error {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ formatter.write_str("Error(\"")?;
|
|
+ Display::fmt(self, formatter)?;
|
|
+ formatter.write_str("\")")?;
|
|
+ Ok(())
|
|
+ }
|
|
+}
|
|
+
|
|
+struct QuotedChar(char);
|
|
+
|
|
+impl Display for QuotedChar {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ // Standard library versions prior to https://github.com/rust-lang/rust/pull/95345
|
|
+ // print character 0 as '\u{0}'. We prefer '\0' to keep error messages
|
|
+ // the same across all supported Rust versions.
|
|
+ if self.0 == '\0' {
|
|
+ formatter.write_str("'\\0'")
|
|
+ } else {
|
|
+ write!(formatter, "{:?}", self.0)
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/eval.rs b/third_party/rust/semver/src/eval.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/eval.rs
|
|
@@ -0,0 +1,181 @@
|
|
+use crate::{Comparator, Op, Version, VersionReq};
|
|
+
|
|
+pub(crate) fn matches_req(req: &VersionReq, ver: &Version) -> bool {
|
|
+ for cmp in &req.comparators {
|
|
+ if !matches_impl(cmp, ver) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if ver.pre.is_empty() {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it
|
|
+ // will only be allowed to satisfy req if at least one comparator with the
|
|
+ // same major.minor.patch also has a prerelease tag.
|
|
+ for cmp in &req.comparators {
|
|
+ if pre_is_compatible(cmp, ver) {
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ false
|
|
+}
|
|
+
|
|
+pub(crate) fn matches_comparator(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ matches_impl(cmp, ver) && (ver.pre.is_empty() || pre_is_compatible(cmp, ver))
|
|
+}
|
|
+
|
|
+fn matches_impl(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ match cmp.op {
|
|
+ Op::Exact | Op::Wildcard => matches_exact(cmp, ver),
|
|
+ Op::Greater => matches_greater(cmp, ver),
|
|
+ Op::GreaterEq => matches_exact(cmp, ver) || matches_greater(cmp, ver),
|
|
+ Op::Less => matches_less(cmp, ver),
|
|
+ Op::LessEq => matches_exact(cmp, ver) || matches_less(cmp, ver),
|
|
+ Op::Tilde => matches_tilde(cmp, ver),
|
|
+ Op::Caret => matches_caret(cmp, ver),
|
|
+ #[cfg(no_non_exhaustive)]
|
|
+ Op::__NonExhaustive => unreachable!(),
|
|
+ }
|
|
+}
|
|
+
|
|
+fn matches_exact(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ if ver.major != cmp.major {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if let Some(minor) = cmp.minor {
|
|
+ if ver.minor != minor {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if let Some(patch) = cmp.patch {
|
|
+ if ver.patch != patch {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ver.pre == cmp.pre
|
|
+}
|
|
+
|
|
+fn matches_greater(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ if ver.major != cmp.major {
|
|
+ return ver.major > cmp.major;
|
|
+ }
|
|
+
|
|
+ match cmp.minor {
|
|
+ None => return false,
|
|
+ Some(minor) => {
|
|
+ if ver.minor != minor {
|
|
+ return ver.minor > minor;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ match cmp.patch {
|
|
+ None => return false,
|
|
+ Some(patch) => {
|
|
+ if ver.patch != patch {
|
|
+ return ver.patch > patch;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ver.pre > cmp.pre
|
|
+}
|
|
+
|
|
+fn matches_less(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ if ver.major != cmp.major {
|
|
+ return ver.major < cmp.major;
|
|
+ }
|
|
+
|
|
+ match cmp.minor {
|
|
+ None => return false,
|
|
+ Some(minor) => {
|
|
+ if ver.minor != minor {
|
|
+ return ver.minor < minor;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ match cmp.patch {
|
|
+ None => return false,
|
|
+ Some(patch) => {
|
|
+ if ver.patch != patch {
|
|
+ return ver.patch < patch;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ver.pre < cmp.pre
|
|
+}
|
|
+
|
|
+fn matches_tilde(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ if ver.major != cmp.major {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if let Some(minor) = cmp.minor {
|
|
+ if ver.minor != minor {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if let Some(patch) = cmp.patch {
|
|
+ if ver.patch != patch {
|
|
+ return ver.patch > patch;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ver.pre >= cmp.pre
|
|
+}
|
|
+
|
|
+fn matches_caret(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ if ver.major != cmp.major {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ let minor = match cmp.minor {
|
|
+ None => return true,
|
|
+ Some(minor) => minor,
|
|
+ };
|
|
+
|
|
+ let patch = match cmp.patch {
|
|
+ None => {
|
|
+ if cmp.major > 0 {
|
|
+ return ver.minor >= minor;
|
|
+ } else {
|
|
+ return ver.minor == minor;
|
|
+ }
|
|
+ }
|
|
+ Some(patch) => patch,
|
|
+ };
|
|
+
|
|
+ if cmp.major > 0 {
|
|
+ if ver.minor != minor {
|
|
+ return ver.minor > minor;
|
|
+ } else if ver.patch != patch {
|
|
+ return ver.patch > patch;
|
|
+ }
|
|
+ } else if minor > 0 {
|
|
+ if ver.minor != minor {
|
|
+ return false;
|
|
+ } else if ver.patch != patch {
|
|
+ return ver.patch > patch;
|
|
+ }
|
|
+ } else if ver.minor != minor || ver.patch != patch {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ ver.pre >= cmp.pre
|
|
+}
|
|
+
|
|
+fn pre_is_compatible(cmp: &Comparator, ver: &Version) -> bool {
|
|
+ cmp.major == ver.major
|
|
+ && cmp.minor == Some(ver.minor)
|
|
+ && cmp.patch == Some(ver.patch)
|
|
+ && !cmp.pre.is_empty()
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/identifier.rs b/third_party/rust/semver/src/identifier.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/identifier.rs
|
|
@@ -0,0 +1,400 @@
|
|
+// This module implements Identifier, a short-optimized string allowed to
|
|
+// contain only the ASCII characters hyphen, dot, 0-9, A-Z, a-z.
|
|
+//
|
|
+// As of mid-2021, the distribution of pre-release lengths on crates.io is:
|
|
+//
|
|
+// length count length count length count
|
|
+// 0 355929 11 81 24 2
|
|
+// 1 208 12 48 25 6
|
|
+// 2 236 13 55 26 10
|
|
+// 3 1909 14 25 27 4
|
|
+// 4 1284 15 15 28 1
|
|
+// 5 1742 16 35 30 1
|
|
+// 6 3440 17 9 31 5
|
|
+// 7 5624 18 6 32 1
|
|
+// 8 1321 19 12 36 2
|
|
+// 9 179 20 2 37 379
|
|
+// 10 65 23 11
|
|
+//
|
|
+// and the distribution of build metadata lengths is:
|
|
+//
|
|
+// length count length count length count
|
|
+// 0 364445 8 7725 18 1
|
|
+// 1 72 9 16 19 1
|
|
+// 2 7 10 85 20 1
|
|
+// 3 28 11 17 22 4
|
|
+// 4 9 12 10 26 1
|
|
+// 5 68 13 9 27 1
|
|
+// 6 73 14 10 40 5
|
|
+// 7 53 15 6
|
|
+//
|
|
+// Therefore it really behooves us to be able to use the entire 8 bytes of a
|
|
+// pointer for inline storage. For both pre-release and build metadata there are
|
|
+// vastly more strings with length exactly 8 bytes than the sum over all lengths
|
|
+// longer than 8 bytes.
|
|
+//
|
|
+// To differentiate the inline representation from the heap allocated long
|
|
+// representation, we'll allocate heap pointers with 2-byte alignment so that
|
|
+// they are guaranteed to have an unset least significant bit. Then in the repr
|
|
+// we store for pointers, we rotate a 1 into the most significant bit of the
|
|
+// most significant byte, which is never set for an ASCII byte.
|
|
+//
|
|
+// Inline repr:
|
|
+//
|
|
+// 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx
|
|
+//
|
|
+// Heap allocated repr:
|
|
+//
|
|
+// 1ppppppp pppppppp pppppppp pppppppp pppppppp pppppppp pppppppp pppppppp 0
|
|
+// ^ most significant bit least significant bit of orig ptr, rotated out ^
|
|
+//
|
|
+// Since the most significant bit doubles as a sign bit for the similarly sized
|
|
+// signed integer type, the CPU has an efficient instruction for inspecting it,
|
|
+// meaning we can differentiate between an inline repr and a heap allocated repr
|
|
+// in one instruction. Effectively an inline repr always looks like a positive
|
|
+// i64 while a heap allocated repr always looks like a negative i64.
|
|
+//
|
|
+// For the inline repr, we store \0 padding on the end of the stored characters,
|
|
+// and thus the string length is readily determined efficiently by a cttz (count
|
|
+// trailing zeros) or bsf (bit scan forward) instruction.
|
|
+//
|
|
+// For the heap allocated repr, the length is encoded as a base-128 varint at
|
|
+// the head of the allocation.
|
|
+//
|
|
+// Empty strings are stored as an all-1 bit pattern, corresponding to -1i64.
|
|
+// Consequently the all-0 bit pattern is never a legal representation in any
|
|
+// repr, leaving it available as a niche for downstream code. For example this
|
|
+// allows size_of::<Version>() == size_of::<Option<Version>>().
|
|
+
|
|
+use crate::alloc::alloc::{alloc, dealloc, Layout};
|
|
+use core::mem;
|
|
+use core::num::{NonZeroU64, NonZeroUsize};
|
|
+use core::ptr::{self, NonNull};
|
|
+use core::slice;
|
|
+use core::str;
|
|
+
|
|
+const PTR_BYTES: usize = mem::size_of::<NonNull<u8>>();
|
|
+
|
|
+// If pointers are already 8 bytes or bigger, then 0. If pointers are smaller
|
|
+// than 8 bytes, then Identifier will contain a byte array to raise its size up
|
|
+// to 8 bytes total.
|
|
+const TAIL_BYTES: usize = 8 * (PTR_BYTES < 8) as usize - PTR_BYTES * (PTR_BYTES < 8) as usize;
|
|
+
|
|
+#[repr(C, align(8))]
|
|
+pub(crate) struct Identifier {
|
|
+ head: NonNull<u8>,
|
|
+ tail: [u8; TAIL_BYTES],
|
|
+}
|
|
+
|
|
+impl Identifier {
|
|
+ pub(crate) const fn empty() -> Self {
|
|
+ // This is a separate constant because unsafe function calls are not
|
|
+ // allowed in a const fn body, only in a const, until later rustc than
|
|
+ // what we support.
|
|
+ const HEAD: NonNull<u8> = unsafe { NonNull::new_unchecked(!0 as *mut u8) };
|
|
+
|
|
+ // `mov rax, -1`
|
|
+ Identifier {
|
|
+ head: HEAD,
|
|
+ tail: [!0; TAIL_BYTES],
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // SAFETY: string must be ASCII and not contain \0 bytes.
|
|
+ pub(crate) unsafe fn new_unchecked(string: &str) -> Self {
|
|
+ let len = string.len();
|
|
+ match len as u64 {
|
|
+ 0 => Self::empty(),
|
|
+ 1..=8 => {
|
|
+ let mut bytes = [0u8; mem::size_of::<Identifier>()];
|
|
+ // SAFETY: string is big enough to read len bytes, bytes is big
|
|
+ // enough to write len bytes, and they do not overlap.
|
|
+ unsafe { ptr::copy_nonoverlapping(string.as_ptr(), bytes.as_mut_ptr(), len) };
|
|
+ // SAFETY: the head field is nonzero because the input string
|
|
+ // was at least 1 byte of ASCII and did not contain \0.
|
|
+ unsafe { mem::transmute::<[u8; mem::size_of::<Identifier>()], Identifier>(bytes) }
|
|
+ }
|
|
+ 9..=0xff_ffff_ffff_ffff => {
|
|
+ // SAFETY: len is in a range that does not contain 0.
|
|
+ let size = bytes_for_varint(unsafe { NonZeroUsize::new_unchecked(len) }) + len;
|
|
+ let align = 2;
|
|
+ // SAFETY: align is not zero, align is a power of two, and
|
|
+ // rounding size up to align does not overflow usize::MAX.
|
|
+ let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
|
|
+ // SAFETY: layout's size is nonzero.
|
|
+ let ptr = unsafe { alloc(layout) };
|
|
+ let mut write = ptr;
|
|
+ let mut varint_remaining = len;
|
|
+ while varint_remaining > 0 {
|
|
+ // SAFETY: size is bytes_for_varint(len) bytes + len bytes.
|
|
+ // This is writing the first bytes_for_varint(len) bytes.
|
|
+ unsafe { ptr::write(write, varint_remaining as u8 | 0x80) };
|
|
+ varint_remaining >>= 7;
|
|
+ // SAFETY: still in bounds of the same allocation.
|
|
+ write = unsafe { write.add(1) };
|
|
+ }
|
|
+ // SAFETY: size is bytes_for_varint(len) bytes + len bytes. This
|
|
+ // is writing to the last len bytes.
|
|
+ unsafe { ptr::copy_nonoverlapping(string.as_ptr(), write, len) };
|
|
+ Identifier {
|
|
+ head: ptr_to_repr(ptr),
|
|
+ tail: [0; TAIL_BYTES],
|
|
+ }
|
|
+ }
|
|
+ 0x100_0000_0000_0000..=0xffff_ffff_ffff_ffff => {
|
|
+ unreachable!("please refrain from storing >64 petabytes of text in semver version");
|
|
+ }
|
|
+ #[cfg(no_exhaustive_int_match)] // rustc <1.33
|
|
+ _ => unreachable!(),
|
|
+ }
|
|
+ }
|
|
+
|
|
+ pub(crate) fn is_empty(&self) -> bool {
|
|
+ // `cmp rdi, -1` -- basically: `repr as i64 == -1`
|
|
+ let empty = Self::empty();
|
|
+ let is_empty = self.head == empty.head && self.tail == empty.tail;
|
|
+ // The empty representation does nothing on Drop. We can't let this one
|
|
+ // drop normally because `impl Drop for Identifier` calls is_empty; that
|
|
+ // would be an infinite recursion.
|
|
+ mem::forget(empty);
|
|
+ is_empty
|
|
+ }
|
|
+
|
|
+ fn is_inline(&self) -> bool {
|
|
+ // `test rdi, rdi` -- basically: `repr as i64 >= 0`
|
|
+ self.head.as_ptr() as usize >> (PTR_BYTES * 8 - 1) == 0
|
|
+ }
|
|
+
|
|
+ fn is_empty_or_inline(&self) -> bool {
|
|
+ // `cmp rdi, -2` -- basically: `repr as i64 > -2`
|
|
+ self.is_empty() || self.is_inline()
|
|
+ }
|
|
+
|
|
+ pub(crate) fn as_str(&self) -> &str {
|
|
+ if self.is_empty() {
|
|
+ ""
|
|
+ } else if self.is_inline() {
|
|
+ // SAFETY: repr is in the inline representation.
|
|
+ unsafe { inline_as_str(self) }
|
|
+ } else {
|
|
+ // SAFETY: repr is in the heap allocated representation.
|
|
+ unsafe { ptr_as_str(&self.head) }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Clone for Identifier {
|
|
+ fn clone(&self) -> Self {
|
|
+ if self.is_empty_or_inline() {
|
|
+ Identifier {
|
|
+ head: self.head,
|
|
+ tail: self.tail,
|
|
+ }
|
|
+ } else {
|
|
+ let ptr = repr_to_ptr(self.head);
|
|
+ // SAFETY: ptr is one of our own heap allocations.
|
|
+ let len = unsafe { decode_len(ptr) };
|
|
+ let size = bytes_for_varint(len) + len.get();
|
|
+ let align = 2;
|
|
+ // SAFETY: align is not zero, align is a power of two, and rounding
|
|
+ // size up to align does not overflow usize::MAX. This is just
|
|
+ // duplicating a previous allocation where all of these guarantees
|
|
+ // were already made.
|
|
+ let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
|
|
+ // SAFETY: layout's size is nonzero.
|
|
+ let clone = unsafe { alloc(layout) };
|
|
+ // SAFETY: new allocation cannot overlap the previous one (this was
|
|
+ // not a realloc). The argument ptrs are readable/writeable
|
|
+ // respectively for size bytes.
|
|
+ unsafe { ptr::copy_nonoverlapping(ptr, clone, size) }
|
|
+ Identifier {
|
|
+ head: ptr_to_repr(clone),
|
|
+ tail: [0; TAIL_BYTES],
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Drop for Identifier {
|
|
+ fn drop(&mut self) {
|
|
+ if self.is_empty_or_inline() {
|
|
+ return;
|
|
+ }
|
|
+ let ptr = repr_to_ptr_mut(self.head);
|
|
+ // SAFETY: ptr is one of our own heap allocations.
|
|
+ let len = unsafe { decode_len(ptr) };
|
|
+ let size = bytes_for_varint(len) + len.get();
|
|
+ let align = 2;
|
|
+ // SAFETY: align is not zero, align is a power of two, and rounding
|
|
+ // size up to align does not overflow usize::MAX. These guarantees were
|
|
+ // made when originally allocating this memory.
|
|
+ let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
|
|
+ // SAFETY: ptr was previously allocated by the same allocator with the
|
|
+ // same layout.
|
|
+ unsafe { dealloc(ptr, layout) }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl PartialEq for Identifier {
|
|
+ fn eq(&self, rhs: &Self) -> bool {
|
|
+ if self.is_empty_or_inline() {
|
|
+ // Fast path (most common)
|
|
+ self.head == rhs.head && self.tail == rhs.tail
|
|
+ } else if rhs.is_empty_or_inline() {
|
|
+ false
|
|
+ } else {
|
|
+ // SAFETY: both reprs are in the heap allocated representation.
|
|
+ unsafe { ptr_as_str(&self.head) == ptr_as_str(&rhs.head) }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+unsafe impl Send for Identifier {}
|
|
+unsafe impl Sync for Identifier {}
|
|
+
|
|
+// We use heap pointers that are 2-byte aligned, meaning they have an
|
|
+// insignificant 0 in the least significant bit. We take advantage of that
|
|
+// unneeded bit to rotate a 1 into the most significant bit to make the repr
|
|
+// distinguishable from ASCII bytes.
|
|
+fn ptr_to_repr(original: *mut u8) -> NonNull<u8> {
|
|
+ // `mov eax, 1`
|
|
+ // `shld rax, rdi, 63`
|
|
+ let modified = (original as usize | 1).rotate_right(1);
|
|
+
|
|
+ // `original + (modified - original)`, but being mindful of provenance.
|
|
+ let diff = modified.wrapping_sub(original as usize);
|
|
+ let modified = original.wrapping_add(diff);
|
|
+
|
|
+ // SAFETY: the most significant bit of repr is known to be set, so the value
|
|
+ // is not zero.
|
|
+ unsafe { NonNull::new_unchecked(modified) }
|
|
+}
|
|
+
|
|
+// Shift out the 1 previously placed into the most significant bit of the least
|
|
+// significant byte. Shift in a low 0 bit to reconstruct the original 2-byte
|
|
+// aligned pointer.
|
|
+fn repr_to_ptr(modified: NonNull<u8>) -> *const u8 {
|
|
+ // `lea rax, [rdi + rdi]`
|
|
+ let modified = modified.as_ptr();
|
|
+ let original = (modified as usize) << 1;
|
|
+
|
|
+ // `modified + (original - modified)`, but being mindful of provenance.
|
|
+ let diff = original.wrapping_sub(modified as usize);
|
|
+ modified.wrapping_add(diff)
|
|
+}
|
|
+
|
|
+fn repr_to_ptr_mut(repr: NonNull<u8>) -> *mut u8 {
|
|
+ repr_to_ptr(repr) as *mut u8
|
|
+}
|
|
+
|
|
+// Compute the length of the inline string, assuming the argument is in short
|
|
+// string representation. Short strings are stored as 1 to 8 nonzero ASCII
|
|
+// bytes, followed by \0 padding for the remaining bytes.
|
|
+//
|
|
+// SAFETY: the identifier must indeed be in the inline representation.
|
|
+unsafe fn inline_len(repr: &Identifier) -> NonZeroUsize {
|
|
+ // SAFETY: Identifier's layout is align(8) and at least size 8. We're doing
|
|
+ // an aligned read of the first 8 bytes from it. The bytes are not all zero
|
|
+ // because inline strings are at least 1 byte long and cannot contain \0.
|
|
+ let repr = unsafe { ptr::read(repr as *const Identifier as *const NonZeroU64) };
|
|
+
|
|
+ // Rustc >=1.53 has intrinsics for counting zeros on a non-zeroable integer.
|
|
+ // On many architectures these are more efficient than counting on ordinary
|
|
+ // zeroable integers (bsf vs cttz). On rustc <1.53 without those intrinsics,
|
|
+ // we count zeros in the u64 rather than the NonZeroU64.
|
|
+ #[cfg(no_nonzero_bitscan)]
|
|
+ let repr = repr.get();
|
|
+
|
|
+ #[cfg(target_endian = "little")]
|
|
+ let zero_bits_on_string_end = repr.leading_zeros();
|
|
+ #[cfg(target_endian = "big")]
|
|
+ let zero_bits_on_string_end = repr.trailing_zeros();
|
|
+
|
|
+ let nonzero_bytes = 8 - zero_bits_on_string_end as usize / 8;
|
|
+
|
|
+ // SAFETY: repr is nonzero, so it has at most 63 zero bits on either end,
|
|
+ // thus at least one nonzero byte.
|
|
+ unsafe { NonZeroUsize::new_unchecked(nonzero_bytes) }
|
|
+}
|
|
+
|
|
+// SAFETY: repr must be in the inline representation, i.e. at least 1 and at
|
|
+// most 8 nonzero ASCII bytes padded on the end with \0 bytes.
|
|
+unsafe fn inline_as_str(repr: &Identifier) -> &str {
|
|
+ let ptr = repr as *const Identifier as *const u8;
|
|
+ let len = unsafe { inline_len(repr) }.get();
|
|
+ // SAFETY: we are viewing the nonzero ASCII prefix of the inline repr's
|
|
+ // contents as a slice of bytes. Input/output lifetimes are correctly
|
|
+ // associated.
|
|
+ let slice = unsafe { slice::from_raw_parts(ptr, len) };
|
|
+ // SAFETY: the string contents are known to be only ASCII bytes, which are
|
|
+ // always valid UTF-8.
|
|
+ unsafe { str::from_utf8_unchecked(slice) }
|
|
+}
|
|
+
|
|
+// Decode varint. Varints consist of between one and eight base-128 digits, each
|
|
+// of which is stored in a byte with most significant bit set. Adjacent to the
|
|
+// varint in memory there is guaranteed to be at least 9 ASCII bytes, each of
|
|
+// which has an unset most significant bit.
|
|
+//
|
|
+// SAFETY: ptr must be one of our own heap allocations, with the varint header
|
|
+// already written.
|
|
+unsafe fn decode_len(ptr: *const u8) -> NonZeroUsize {
|
|
+ // SAFETY: There is at least one byte of varint followed by at least 9 bytes
|
|
+ // of string content, which is at least 10 bytes total for the allocation,
|
|
+ // so reading the first two is no problem.
|
|
+ let [first, second] = unsafe { ptr::read(ptr as *const [u8; 2]) };
|
|
+ if second < 0x80 {
|
|
+ // SAFETY: the length of this heap allocated string has been encoded as
|
|
+ // one base-128 digit, so the length is at least 9 and at most 127. It
|
|
+ // cannot be zero.
|
|
+ unsafe { NonZeroUsize::new_unchecked((first & 0x7f) as usize) }
|
|
+ } else {
|
|
+ return unsafe { decode_len_cold(ptr) };
|
|
+
|
|
+ // Identifiers 128 bytes or longer. This is not exercised by any crate
|
|
+ // version currently published to crates.io.
|
|
+ #[cold]
|
|
+ #[inline(never)]
|
|
+ unsafe fn decode_len_cold(mut ptr: *const u8) -> NonZeroUsize {
|
|
+ let mut len = 0;
|
|
+ let mut shift = 0;
|
|
+ loop {
|
|
+ // SAFETY: varint continues while there are bytes having the
|
|
+ // most significant bit set, i.e. until we start hitting the
|
|
+ // ASCII string content with msb unset.
|
|
+ let byte = unsafe { *ptr };
|
|
+ if byte < 0x80 {
|
|
+ // SAFETY: the string length is known to be 128 bytes or
|
|
+ // longer.
|
|
+ return unsafe { NonZeroUsize::new_unchecked(len) };
|
|
+ }
|
|
+ // SAFETY: still in bounds of the same allocation.
|
|
+ ptr = unsafe { ptr.add(1) };
|
|
+ len += ((byte & 0x7f) as usize) << shift;
|
|
+ shift += 7;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+// SAFETY: repr must be in the heap allocated representation, with varint header
|
|
+// and string contents already written.
|
|
+unsafe fn ptr_as_str(repr: &NonNull<u8>) -> &str {
|
|
+ let ptr = repr_to_ptr(*repr);
|
|
+ let len = unsafe { decode_len(ptr) };
|
|
+ let header = bytes_for_varint(len);
|
|
+ let slice = unsafe { slice::from_raw_parts(ptr.add(header), len.get()) };
|
|
+ // SAFETY: all identifier contents are ASCII bytes, which are always valid
|
|
+ // UTF-8.
|
|
+ unsafe { str::from_utf8_unchecked(slice) }
|
|
+}
|
|
+
|
|
+// Number of base-128 digits required for the varint representation of a length.
|
|
+fn bytes_for_varint(len: NonZeroUsize) -> usize {
|
|
+ #[cfg(no_nonzero_bitscan)] // rustc <1.53
|
|
+ let len = len.get();
|
|
+
|
|
+ let usize_bits = mem::size_of::<usize>() * 8;
|
|
+ let len_bits = usize_bits - len.leading_zeros() as usize;
|
|
+ (len_bits + 6) / 7
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/impls.rs b/third_party/rust/semver/src/impls.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/impls.rs
|
|
@@ -0,0 +1,156 @@
|
|
+use crate::backport::*;
|
|
+use crate::identifier::Identifier;
|
|
+use crate::{BuildMetadata, Comparator, Prerelease, VersionReq};
|
|
+use core::cmp::Ordering;
|
|
+use core::hash::{Hash, Hasher};
|
|
+use core::iter::FromIterator;
|
|
+use core::ops::Deref;
|
|
+
|
|
+impl Default for Identifier {
|
|
+ fn default() -> Self {
|
|
+ Identifier::empty()
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Eq for Identifier {}
|
|
+
|
|
+impl Hash for Identifier {
|
|
+ fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
+ self.as_str().hash(hasher);
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Deref for Prerelease {
|
|
+ type Target = str;
|
|
+
|
|
+ fn deref(&self) -> &Self::Target {
|
|
+ self.identifier.as_str()
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Deref for BuildMetadata {
|
|
+ type Target = str;
|
|
+
|
|
+ fn deref(&self) -> &Self::Target {
|
|
+ self.identifier.as_str()
|
|
+ }
|
|
+}
|
|
+
|
|
+impl PartialOrd for Prerelease {
|
|
+ fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
|
|
+ Some(Ord::cmp(self, rhs))
|
|
+ }
|
|
+}
|
|
+
|
|
+impl PartialOrd for BuildMetadata {
|
|
+ fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
|
|
+ Some(Ord::cmp(self, rhs))
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Ord for Prerelease {
|
|
+ fn cmp(&self, rhs: &Self) -> Ordering {
|
|
+ match self.is_empty() {
|
|
+ true if rhs.is_empty() => return Ordering::Equal,
|
|
+ // A real release compares greater than prerelease.
|
|
+ true => return Ordering::Greater,
|
|
+ // Prerelease compares less than the real release.
|
|
+ false if rhs.is_empty() => return Ordering::Less,
|
|
+ false => {}
|
|
+ }
|
|
+
|
|
+ let lhs = self.as_str().split('.');
|
|
+ let mut rhs = rhs.as_str().split('.');
|
|
+
|
|
+ for lhs in lhs {
|
|
+ let rhs = match rhs.next() {
|
|
+ // Spec: "A larger set of pre-release fields has a higher
|
|
+ // precedence than a smaller set, if all of the preceding
|
|
+ // identifiers are equal."
|
|
+ None => return Ordering::Greater,
|
|
+ Some(rhs) => rhs,
|
|
+ };
|
|
+
|
|
+ let string_cmp = || Ord::cmp(lhs, rhs);
|
|
+ let is_ascii_digit = |b: u8| b.is_ascii_digit();
|
|
+ let ordering = match (
|
|
+ lhs.bytes().all(is_ascii_digit),
|
|
+ rhs.bytes().all(is_ascii_digit),
|
|
+ ) {
|
|
+ // Respect numeric ordering, for example 99 < 100. Spec says:
|
|
+ // "Identifiers consisting of only digits are compared
|
|
+ // numerically."
|
|
+ (true, true) => Ord::cmp(&lhs.len(), &rhs.len()).then_with(string_cmp),
|
|
+ // Spec: "Numeric identifiers always have lower precedence than
|
|
+ // non-numeric identifiers."
|
|
+ (true, false) => return Ordering::Less,
|
|
+ (false, true) => return Ordering::Greater,
|
|
+ // Spec: "Identifiers with letters or hyphens are compared
|
|
+ // lexically in ASCII sort order."
|
|
+ (false, false) => string_cmp(),
|
|
+ };
|
|
+
|
|
+ if ordering != Ordering::Equal {
|
|
+ return ordering;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if rhs.next().is_none() {
|
|
+ Ordering::Equal
|
|
+ } else {
|
|
+ Ordering::Less
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Ord for BuildMetadata {
|
|
+ fn cmp(&self, rhs: &Self) -> Ordering {
|
|
+ let lhs = self.as_str().split('.');
|
|
+ let mut rhs = rhs.as_str().split('.');
|
|
+
|
|
+ for lhs in lhs {
|
|
+ let rhs = match rhs.next() {
|
|
+ None => return Ordering::Greater,
|
|
+ Some(rhs) => rhs,
|
|
+ };
|
|
+
|
|
+ let is_ascii_digit = |b: u8| b.is_ascii_digit();
|
|
+ let ordering = match (
|
|
+ lhs.bytes().all(is_ascii_digit),
|
|
+ rhs.bytes().all(is_ascii_digit),
|
|
+ ) {
|
|
+ (true, true) => {
|
|
+ // 0 < 00 < 1 < 01 < 001 < 2 < 02 < 002 < 10
|
|
+ let lhval = lhs.trim_start_matches('0');
|
|
+ let rhval = rhs.trim_start_matches('0');
|
|
+ Ord::cmp(&lhval.len(), &rhval.len())
|
|
+ .then_with(|| Ord::cmp(lhval, rhval))
|
|
+ .then_with(|| Ord::cmp(&lhs.len(), &rhs.len()))
|
|
+ }
|
|
+ (true, false) => return Ordering::Less,
|
|
+ (false, true) => return Ordering::Greater,
|
|
+ (false, false) => Ord::cmp(lhs, rhs),
|
|
+ };
|
|
+
|
|
+ if ordering != Ordering::Equal {
|
|
+ return ordering;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if rhs.next().is_none() {
|
|
+ Ordering::Equal
|
|
+ } else {
|
|
+ Ordering::Less
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl FromIterator<Comparator> for VersionReq {
|
|
+ fn from_iter<I>(iter: I) -> Self
|
|
+ where
|
|
+ I: IntoIterator<Item = Comparator>,
|
|
+ {
|
|
+ let comparators = Vec::from_iter(iter);
|
|
+ VersionReq { comparators }
|
|
+ }
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/lib.rs b/third_party/rust/semver/src/lib.rs
|
|
--- a/third_party/rust/semver/src/lib.rs
|
|
+++ b/third_party/rust/semver/src/lib.rs
|
|
@@ -1,182 +1,533 @@
|
|
-// 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.
|
|
+//! [![github]](https://github.com/dtolnay/semver) [![crates-io]](https://crates.io/crates/semver) [![docs-rs]](https://docs.rs/semver)
|
|
//!
|
|
-//! Semantic versioning (see http://semver.org/) is a set of rules for
|
|
-//! assigning version numbers.
|
|
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
|
|
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
|
|
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
|
|
//!
|
|
-//! ## SemVer overview
|
|
-//!
|
|
-//! Given a version number MAJOR.MINOR.PATCH, increment the:
|
|
+//! <br>
|
|
//!
|
|
-//! 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).
|
|
+//! A parser and evaluator for Cargo's flavor of Semantic Versioning.
|
|
//!
|
|
-//! ## SemVer and the Rust ecosystem
|
|
-//!
|
|
-//! Rust itself follows the SemVer specification, as does its standard
|
|
-//! libraries. The two are not tied together.
|
|
+//! Semantic Versioning (see <https://semver.org>) is a guideline for how
|
|
+//! version numbers are assigned and incremented. It is widely followed within
|
|
+//! the Cargo/crates.io ecosystem for Rust.
|
|
//!
|
|
-//! [Cargo](http://crates.io), Rust's package manager, uses SemVer to determine
|
|
-//! which versions of packages you need installed.
|
|
+//! <br>
|
|
//!
|
|
-//! ## Versions
|
|
-//!
|
|
-//! At its simplest, the `semver` crate allows you to construct `Version`
|
|
-//! objects using the `parse` method:
|
|
+//! # Example
|
|
//!
|
|
-//! ```{rust}
|
|
-//! use semver::Version;
|
|
+//! ```
|
|
+//! use semver::{BuildMetadata, Prerelease, Version, VersionReq};
|
|
//!
|
|
-//! 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"));
|
|
-//! ```
|
|
+//! fn main() {
|
|
+//! let req = VersionReq::parse(">=1.2.3, <1.8.0").unwrap();
|
|
//!
|
|
-//! 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();
|
|
+//! // Check whether this requirement matches version 1.2.3-alpha.1 (no)
|
|
+//! let version = Version {
|
|
+//! major: 1,
|
|
+//! minor: 2,
|
|
+//! patch: 3,
|
|
+//! pre: Prerelease::new("alpha.1").unwrap(),
|
|
+//! build: BuildMetadata::EMPTY,
|
|
+//! };
|
|
+//! assert!(!req.matches(&version));
|
|
//!
|
|
-//! 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"));
|
|
+//! // Check whether it matches 1.3.0 (yes it does)
|
|
+//! let version = Version::parse("1.3.0").unwrap();
|
|
+//! assert!(req.matches(&version));
|
|
+//! }
|
|
//! ```
|
|
//!
|
|
-//! Similarly, when incrementing the major version number, the patch and minor
|
|
-//! numbers reset to zero (in accordance with section 8 of the spec)
|
|
+//! <br><br>
|
|
//!
|
|
-//! ```{rust}
|
|
-//! use semver::Version;
|
|
-//!
|
|
-//! let mut chrome_release = Version::parse("41.5.5377").unwrap();
|
|
-//! chrome_release.increment_major();
|
|
+//! # Scope of this crate
|
|
//!
|
|
-//! 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:
|
|
+//! Besides Cargo, several other package ecosystems and package managers for
|
|
+//! other languages also use SemVer: RubyGems/Bundler for Ruby, npm for
|
|
+//! JavaScript, Composer for PHP, CocoaPods for Objective-C...
|
|
//!
|
|
-//! ```{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();
|
|
+//! The `semver` crate is specifically intended to implement Cargo's
|
|
+//! interpretation of Semantic Versioning.
|
|
//!
|
|
-//! 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
|
|
+//! Where the various tools differ in their interpretation or implementation of
|
|
+//! the spec, this crate follows the implementation choices made by Cargo. If
|
|
+//! you are operating on version numbers from some other package ecosystem, you
|
|
+//! will want to use a different semver library which is appropriate to that
|
|
+//! ecosystem.
|
|
//!
|
|
-//! **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
|
|
-//! ```
|
|
+//! The extent of Cargo's SemVer support is documented in the *[Specifying
|
|
+//! Dependencies]* chapter of the Cargo reference.
|
|
//!
|
|
-//! **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
|
|
-//! ```
|
|
+//! [Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
|
|
+
|
|
+#![doc(html_root_url = "https://docs.rs/semver/1.0.9")]
|
|
+#![cfg_attr(doc_cfg, feature(doc_cfg))]
|
|
+#![cfg_attr(all(not(feature = "std"), not(no_alloc_crate)), no_std)]
|
|
+#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))]
|
|
+#![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))]
|
|
+#![cfg_attr(no_str_strip_prefix, allow(unstable_name_collisions))]
|
|
+#![allow(
|
|
+ clippy::cast_lossless,
|
|
+ clippy::cast_possible_truncation,
|
|
+ clippy::doc_markdown,
|
|
+ clippy::items_after_statements,
|
|
+ clippy::manual_map,
|
|
+ clippy::match_bool,
|
|
+ clippy::missing_errors_doc,
|
|
+ clippy::must_use_candidate,
|
|
+ clippy::needless_doctest_main,
|
|
+ clippy::option_if_let_else,
|
|
+ clippy::ptr_as_ptr,
|
|
+ clippy::redundant_else,
|
|
+ clippy::semicolon_if_nothing_returned, // https://github.com/rust-lang/rust-clippy/issues/7324
|
|
+ clippy::similar_names,
|
|
+ clippy::unnested_or_patterns,
|
|
+ clippy::unseparated_literal_suffix,
|
|
+ clippy::wildcard_imports
|
|
+)]
|
|
+
|
|
+#[cfg(not(no_alloc_crate))]
|
|
+extern crate alloc;
|
|
+
|
|
+mod backport;
|
|
+mod display;
|
|
+mod error;
|
|
+mod eval;
|
|
+mod identifier;
|
|
+mod impls;
|
|
+mod parse;
|
|
+
|
|
+#[cfg(feature = "serde")]
|
|
+mod serde;
|
|
+
|
|
+use crate::alloc::vec::Vec;
|
|
+use crate::identifier::Identifier;
|
|
+use core::str::FromStr;
|
|
+
|
|
+#[allow(unused_imports)]
|
|
+use crate::backport::*;
|
|
+
|
|
+pub use crate::parse::Error;
|
|
+
|
|
+/// **SemVer version** as defined by <https://semver.org>.
|
|
+///
|
|
+/// # Syntax
|
|
+///
|
|
+/// - The major, minor, and patch numbers may be any integer 0 through u64::MAX.
|
|
+/// When representing a SemVer version as a string, each number is written as
|
|
+/// a base 10 integer. For example, `1.0.119`.
|
|
+///
|
|
+/// - Leading zeros are forbidden in those positions. For example `1.01.00` is
|
|
+/// invalid as a SemVer version.
|
|
+///
|
|
+/// - The pre-release identifier, if present, must conform to the syntax
|
|
+/// documented for [`Prerelease`].
|
|
+///
|
|
+/// - The build metadata, if present, must conform to the syntax documented for
|
|
+/// [`BuildMetadata`].
|
|
+///
|
|
+/// - Whitespace is not allowed anywhere in the version.
|
|
+///
|
|
+/// # Total ordering
|
|
+///
|
|
+/// Given any two SemVer versions, one is less than, greater than, or equal to
|
|
+/// the other. Versions may be compared against one another using Rust's usual
|
|
+/// comparison operators.
|
|
+///
|
|
+/// - The major, minor, and patch number are compared numerically from left to
|
|
+/// right, lexicographically ordered as a 3-tuple of integers. So for example
|
|
+/// version `1.5.0` is less than version `1.19.0`, despite the fact that
|
|
+/// "1.19.0" < "1.5.0" as ASCIIbetically compared strings and 1.19 < 1.5
|
|
+/// as real numbers.
|
|
+///
|
|
+/// - When major, minor, and patch are equal, a pre-release version is
|
|
+/// considered less than the ordinary release: version `1.0.0-alpha.1` is
|
|
+/// less than version `1.0.0`.
|
|
+///
|
|
+/// - Two pre-releases of the same major, minor, patch are compared by
|
|
+/// lexicographic ordering of dot-separated components of the pre-release
|
|
+/// string.
|
|
+///
|
|
+/// - Identifiers consisting of only digits are compared
|
|
+/// numerically: `1.0.0-pre.8` is less than `1.0.0-pre.12`.
|
|
+///
|
|
+/// - Identifiers that contain a letter or hyphen are compared in ASCII sort
|
|
+/// order: `1.0.0-pre12` is less than `1.0.0-pre8`.
|
|
+///
|
|
+/// - Any numeric identifier is always less than any non-numeric
|
|
+/// identifier: `1.0.0-pre.1` is less than `1.0.0-pre.x`.
|
|
+///
|
|
+/// Example: `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`
|
|
+#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
+pub struct Version {
|
|
+ pub major: u64,
|
|
+ pub minor: u64,
|
|
+ pub patch: u64,
|
|
+ pub pre: Prerelease,
|
|
+ pub build: BuildMetadata,
|
|
+}
|
|
+
|
|
+/// **SemVer version requirement** describing the intersection of some version
|
|
+/// comparators, such as `>=1.2.3, <1.8`.
|
|
+///
|
|
+/// # Syntax
|
|
+///
|
|
+/// - Either `*` (meaning "any"), or one or more comma-separated comparators.
|
|
+///
|
|
+/// - A [`Comparator`] is an operator ([`Op`]) and a partial version, separated
|
|
+/// by optional whitespace. For example `>=1.0.0` or `>=1.0`.
|
|
+///
|
|
+/// - Build metadata is syntactically permitted on the partial versions, but is
|
|
+/// completely ignored, as it's never relevant to whether any comparator
|
|
+/// matches a particular version.
|
|
+///
|
|
+/// - Whitespace is permitted around commas and around operators. Whitespace is
|
|
+/// not permitted within a partial version, i.e. anywhere between the major
|
|
+/// version number and its minor, patch, pre-release, or build metadata.
|
|
+#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
|
+#[cfg_attr(no_const_vec_new, derive(Default))]
|
|
+pub struct VersionReq {
|
|
+ pub comparators: Vec<Comparator>,
|
|
+}
|
|
+
|
|
+/// A pair of comparison operator and partial version, such as `>=1.2`. Forms
|
|
+/// one piece of a VersionReq.
|
|
+#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
|
+pub struct Comparator {
|
|
+ pub op: Op,
|
|
+ pub major: u64,
|
|
+ pub minor: Option<u64>,
|
|
+ /// Patch is only allowed if minor is Some.
|
|
+ pub patch: Option<u64>,
|
|
+ /// Non-empty pre-release is only allowed if patch is Some.
|
|
+ pub pre: Prerelease,
|
|
+}
|
|
+
|
|
+/// SemVer comparison operator: `=`, `>`, `>=`, `<`, `<=`, `~`, `^`, `*`.
|
|
+///
|
|
+/// # Op::Exact
|
|
+/// -  **`=I.J.K`** — exactly the version I.J.K
|
|
+/// -  **`=I.J`** — equivalent to `>=I.J.0, <I.(J+1).0`
|
|
+/// -  **`=I`** — equivalent to `>=I.0.0, <(I+1).0.0`
|
|
+///
|
|
+/// # Op::Greater
|
|
+/// -  **`>I.J.K`**
|
|
+/// -  **`>I.J`** — equivalent to `>=I.(J+1).0`
|
|
+/// -  **`>I`** — equivalent to `>=(I+1).0.0`
|
|
+///
|
|
+/// # Op::GreaterEq
|
|
+/// -  **`>=I.J.K`**
|
|
+/// -  **`>=I.J`** — equivalent to `>=I.J.0`
|
|
+/// -  **`>=I`** — equivalent to `>=I.0.0`
|
|
+///
|
|
+/// # Op::Less
|
|
+/// -  **`<I.J.K`**
|
|
+/// -  **`<I.J`** — equivalent to `<I.J.0`
|
|
+/// -  **`<I`** — equivalent to `<I.0.0`
|
|
+///
|
|
+/// # Op::LessEq
|
|
+/// -  **`<=I.J.K`**
|
|
+/// -  **`<=I.J`** — equivalent to `<I.(J+1).0`
|
|
+/// -  **`<=I`** — equivalent to `<(I+1).0.0`
|
|
+///
|
|
+/// # Op::Tilde ("patch" updates)
|
|
+/// *Tilde requirements allow the **patch** part of the semver version (the third number) to increase.*
|
|
+/// -  **`~I.J.K`** — equivalent to `>=I.J.K, <I.(J+1).0`
|
|
+/// -  **`~I.J`** — equivalent to `=I.J`
|
|
+/// -  **`~I`** — equivalent to `=I`
|
|
+///
|
|
+/// # Op::Caret ("compatible" updates)
|
|
+/// *Caret requirements allow parts that are **right of the first nonzero** part of the semver version to increase.*
|
|
+/// -  **`^I.J.K`** (for I\>0) — equivalent to `>=I.J.K, <(I+1).0.0`
|
|
+/// -  **`^0.J.K`** (for J\>0) — equivalent to `>=0.J.K, <0.(J+1).0`
|
|
+/// -  **`^0.0.K`** — equivalent to `=0.0.K`
|
|
+/// -  **`^I.J`** (for I\>0 or J\>0) — equivalent to `^I.J.0`
|
|
+/// -  **`^0.0`** — equivalent to `=0.0`
|
|
+/// -  **`^I`** — equivalent to `=I`
|
|
+///
|
|
+/// # Op::Wildcard
|
|
+/// -  **`I.J.*`** — equivalent to `=I.J`
|
|
+/// -  **`I.*`** or **`I.*.*`** — equivalent to `=I`
|
|
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
|
+#[cfg_attr(not(no_non_exhaustive), non_exhaustive)]
|
|
+pub enum Op {
|
|
+ Exact,
|
|
+ Greater,
|
|
+ GreaterEq,
|
|
+ Less,
|
|
+ LessEq,
|
|
+ Tilde,
|
|
+ Caret,
|
|
+ Wildcard,
|
|
+
|
|
+ #[cfg(no_non_exhaustive)] // rustc <1.40
|
|
+ #[doc(hidden)]
|
|
+ __NonExhaustive,
|
|
+}
|
|
|
|
-#![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))]
|
|
+/// Optional pre-release identifier on a version string. This comes after `-` in
|
|
+/// a SemVer version, like `1.0.0-alpha.1`
|
|
+///
|
|
+/// # Examples
|
|
+///
|
|
+/// Some real world pre-release idioms drawn from crates.io:
|
|
+///
|
|
+/// - **[mio]** <code>0.7.0-<b>alpha.1</b></code> — the most common style
|
|
+/// for numbering pre-releases.
|
|
+///
|
|
+/// - **[pest]** <code>1.0.0-<b>beta.8</b></code>, <code>1.0.0-<b>rc.0</b></code>
|
|
+/// — this crate makes a distinction between betas and release
|
|
+/// candidates.
|
|
+///
|
|
+/// - **[sassers]** <code>0.11.0-<b>shitshow</b></code> — ???.
|
|
+///
|
|
+/// - **[atomic-utils]** <code>0.0.0-<b>reserved</b></code> — a squatted
|
|
+/// crate name.
|
|
+///
|
|
+/// [mio]: https://crates.io/crates/mio
|
|
+/// [pest]: https://crates.io/crates/pest
|
|
+/// [atomic-utils]: https://crates.io/crates/atomic-utils
|
|
+/// [sassers]: https://crates.io/crates/sassers
|
|
+///
|
|
+/// *Tip:* Be aware that if you are planning to number your own pre-releases,
|
|
+/// you should prefer to separate the numeric part from any non-numeric
|
|
+/// identifiers by using a dot in between. That is, prefer pre-releases
|
|
+/// `alpha.1`, `alpha.2`, etc rather than `alpha1`, `alpha2` etc. The SemVer
|
|
+/// spec's rule for pre-release precedence has special treatment of numeric
|
|
+/// components in the pre-release string, but only if there are no non-digit
|
|
+/// characters in the same dot-separated component. So you'd have `alpha.2` <
|
|
+/// `alpha.11` as intended, but `alpha11` < `alpha2`.
|
|
+///
|
|
+/// # Syntax
|
|
+///
|
|
+/// Pre-release strings are a series of dot separated identifiers immediately
|
|
+/// following the patch version. Identifiers must comprise only ASCII
|
|
+/// alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must not be
|
|
+/// empty. Numeric identifiers must not include leading zeros.
|
|
+///
|
|
+/// # Total ordering
|
|
+///
|
|
+/// Pre-releases have a total order defined by the SemVer spec. It uses
|
|
+/// lexicographic ordering of dot-separated components. Identifiers consisting
|
|
+/// of only digits are compared numerically. Otherwise, identifiers are compared
|
|
+/// in ASCII sort order. Any numeric identifier is always less than any
|
|
+/// non-numeric identifier.
|
|
+///
|
|
+/// Example: `alpha` < `alpha.85` < `alpha.90` < `alpha.200` < `alpha.0a` < `alpha.1a0` < `alpha.a` < `beta`
|
|
+#[derive(Default, Clone, Eq, PartialEq, Hash)]
|
|
+pub struct Prerelease {
|
|
+ identifier: Identifier,
|
|
+}
|
|
|
|
-extern crate semver_parser;
|
|
-
|
|
-// Serialization and deserialization support for version numbers
|
|
-#[cfg(feature = "serde")]
|
|
-extern crate serde;
|
|
+/// Optional build metadata identifier. This comes after `+` in a SemVer
|
|
+/// version, as in `0.8.1+zstd.1.5.0`.
|
|
+///
|
|
+/// # Examples
|
|
+///
|
|
+/// Some real world build metadata idioms drawn from crates.io:
|
|
+///
|
|
+/// - **[libgit2-sys]** <code>0.12.20+<b>1.1.0</b></code> — for this
|
|
+/// crate, the build metadata indicates the version of the C libgit2 library
|
|
+/// that the Rust crate is built against.
|
|
+///
|
|
+/// - **[mashup]** <code>0.1.13+<b>deprecated</b></code> — just the word
|
|
+/// "deprecated" for a crate that has been superseded by another. Eventually
|
|
+/// people will take notice of this in Cargo's build output where it lists the
|
|
+/// crates being compiled.
|
|
+///
|
|
+/// - **[google-bigquery2]** <code>2.0.4+<b>20210327</b></code> — this
|
|
+/// library is automatically generated from an official API schema, and the
|
|
+/// build metadata indicates the date on which that schema was last captured.
|
|
+///
|
|
+/// - **[fbthrift-git]** <code>0.0.6+<b>c7fcc0e</b></code> — this crate is
|
|
+/// published from snapshots of a big company monorepo. In monorepo
|
|
+/// development, there is no concept of versions, and all downstream code is
|
|
+/// just updated atomically in the same commit that breaking changes to a
|
|
+/// library are landed. Therefore for crates.io purposes, every published
|
|
+/// version must be assumed to be incompatible with the previous. The build
|
|
+/// metadata provides the source control hash of the snapshotted code.
|
|
+///
|
|
+/// [libgit2-sys]: https://crates.io/crates/libgit2-sys
|
|
+/// [mashup]: https://crates.io/crates/mashup
|
|
+/// [google-bigquery2]: https://crates.io/crates/google-bigquery2
|
|
+/// [fbthrift-git]: https://crates.io/crates/fbthrift-git
|
|
+///
|
|
+/// # Syntax
|
|
+///
|
|
+/// Build metadata is a series of dot separated identifiers immediately
|
|
+/// following the patch or pre-release version. Identifiers must comprise only
|
|
+/// ASCII alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must
|
|
+/// not be empty. Leading zeros *are* allowed, unlike any other place in the
|
|
+/// SemVer grammar.
|
|
+///
|
|
+/// # Total ordering
|
|
+///
|
|
+/// Build metadata is ignored in evaluating `VersionReq`; it plays no role in
|
|
+/// whether a `Version` matches any one of the comparison operators.
|
|
+///
|
|
+/// However for comparing build metadatas among one another, they do have a
|
|
+/// total order which is determined by lexicographic ordering of dot-separated
|
|
+/// components. Identifiers consisting of only digits are compared numerically.
|
|
+/// Otherwise, identifiers are compared in ASCII sort order. Any numeric
|
|
+/// identifier is always less than any non-numeric identifier.
|
|
+///
|
|
+/// Example: `demo` < `demo.85` < `demo.90` < `demo.090` < `demo.200` < `demo.1a0` < `demo.a` < `memo`
|
|
+#[derive(Default, Clone, Eq, PartialEq, Hash)]
|
|
+pub struct BuildMetadata {
|
|
+ identifier: Identifier,
|
|
+}
|
|
|
|
-// We take the common approach of keeping our own module system private, and
|
|
-// just re-exporting the interface that we want.
|
|
+impl Version {
|
|
+ /// Create `Version` with an empty pre-release and build metadata.
|
|
+ ///
|
|
+ /// Equivalent to:
|
|
+ ///
|
|
+ /// ```
|
|
+ /// # use semver::{BuildMetadata, Prerelease, Version};
|
|
+ /// #
|
|
+ /// # const fn new(major: u64, minor: u64, patch: u64) -> Version {
|
|
+ /// Version {
|
|
+ /// major,
|
|
+ /// minor,
|
|
+ /// patch,
|
|
+ /// pre: Prerelease::EMPTY,
|
|
+ /// build: BuildMetadata::EMPTY,
|
|
+ /// }
|
|
+ /// # }
|
|
+ /// ```
|
|
+ pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
|
|
+ Version {
|
|
+ major,
|
|
+ minor,
|
|
+ patch,
|
|
+ pre: Prerelease::EMPTY,
|
|
+ build: BuildMetadata::EMPTY,
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /// Create `Version` by parsing from string representation.
|
|
+ ///
|
|
+ /// # Errors
|
|
+ ///
|
|
+ /// Possible reasons for the parse to fail include:
|
|
+ ///
|
|
+ /// - `1.0` — too few numeric components. A SemVer version must have
|
|
+ /// exactly three. If you are looking at something that has fewer than
|
|
+ /// three numbers in it, it's possible it is a `VersionReq` instead (with
|
|
+ /// an implicit default `^` comparison operator).
|
|
+ ///
|
|
+ /// - `1.0.01` — a numeric component has a leading zero.
|
|
+ ///
|
|
+ /// - `1.0.unknown` — unexpected character in one of the components.
|
|
+ ///
|
|
+ /// - `1.0.0-` or `1.0.0+` — the pre-release or build metadata are
|
|
+ /// indicated present but empty.
|
|
+ ///
|
|
+ /// - `1.0.0-alpha_123` — pre-release or build metadata have something
|
|
+ /// outside the allowed characters, which are `0-9`, `A-Z`, `a-z`, `-`,
|
|
+ /// and `.` (dot).
|
|
+ ///
|
|
+ /// - `23456789999999999999.0.0` — overflow of a u64.
|
|
+ pub fn parse(text: &str) -> Result<Self, Error> {
|
|
+ Version::from_str(text)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl VersionReq {
|
|
+ /// A `VersionReq` with no constraint on the version numbers it matches.
|
|
+ /// Equivalent to `VersionReq::parse("*").unwrap()`.
|
|
+ ///
|
|
+ /// In terms of comparators this is equivalent to `>=0.0.0`.
|
|
+ ///
|
|
+ /// Counterintuitively a `*` VersionReq does not match every possible
|
|
+ /// version number. In particular, in order for *any* `VersionReq` to match
|
|
+ /// a pre-release version, the `VersionReq` must contain at least one
|
|
+ /// `Comparator` that has an explicit major, minor, and patch version
|
|
+ /// identical to the pre-release being matched, and that has a nonempty
|
|
+ /// pre-release component. Since `*` is not written with an explicit major,
|
|
+ /// minor, and patch version, and does not contain a nonempty pre-release
|
|
+ /// component, it does not match any pre-release versions.
|
|
+ #[cfg(not(no_const_vec_new))] // rustc <1.39
|
|
+ pub const STAR: Self = VersionReq {
|
|
+ comparators: Vec::new(),
|
|
+ };
|
|
|
|
-pub use version::{Version, Identifier, SemVerError};
|
|
-pub use version::Identifier::{Numeric, AlphaNumeric};
|
|
-pub use version_req::{VersionReq, ReqParseError};
|
|
+ /// Create `VersionReq` by parsing from string representation.
|
|
+ ///
|
|
+ /// # Errors
|
|
+ ///
|
|
+ /// Possible reasons for the parse to fail include:
|
|
+ ///
|
|
+ /// - `>a.b` — unexpected characters in the partial version.
|
|
+ ///
|
|
+ /// - `@1.0.0` — unrecognized comparison operator.
|
|
+ ///
|
|
+ /// - `^1.0.0, ` — unexpected end of input.
|
|
+ ///
|
|
+ /// - `>=1.0 <2.0` — missing comma between comparators.
|
|
+ ///
|
|
+ /// - `*.*` — unsupported wildcard syntax.
|
|
+ pub fn parse(text: &str) -> Result<Self, Error> {
|
|
+ VersionReq::from_str(text)
|
|
+ }
|
|
+
|
|
+ /// Evaluate whether the given `Version` satisfies the version requirement
|
|
+ /// described by `self`.
|
|
+ pub fn matches(&self, version: &Version) -> bool {
|
|
+ eval::matches_req(self, version)
|
|
+ }
|
|
+}
|
|
+
|
|
+/// The default VersionReq is the same as [`VersionReq::STAR`].
|
|
+#[cfg(not(no_const_vec_new))]
|
|
+impl Default for VersionReq {
|
|
+ fn default() -> Self {
|
|
+ VersionReq::STAR
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Comparator {
|
|
+ pub fn parse(text: &str) -> Result<Self, Error> {
|
|
+ Comparator::from_str(text)
|
|
+ }
|
|
|
|
-// SemVer-compliant versions.
|
|
-mod version;
|
|
+ pub fn matches(&self, version: &Version) -> bool {
|
|
+ eval::matches_comparator(self, version)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Prerelease {
|
|
+ pub const EMPTY: Self = Prerelease {
|
|
+ identifier: Identifier::empty(),
|
|
+ };
|
|
+
|
|
+ pub fn new(text: &str) -> Result<Self, Error> {
|
|
+ Prerelease::from_str(text)
|
|
+ }
|
|
+
|
|
+ pub fn as_str(&self) -> &str {
|
|
+ self.identifier.as_str()
|
|
+ }
|
|
|
|
-// advanced version comparisons
|
|
-mod version_req;
|
|
+ pub fn is_empty(&self) -> bool {
|
|
+ self.identifier.is_empty()
|
|
+ }
|
|
+}
|
|
+
|
|
+impl BuildMetadata {
|
|
+ pub const EMPTY: Self = BuildMetadata {
|
|
+ identifier: Identifier::empty(),
|
|
+ };
|
|
+
|
|
+ pub fn new(text: &str) -> Result<Self, Error> {
|
|
+ BuildMetadata::from_str(text)
|
|
+ }
|
|
+
|
|
+ pub fn as_str(&self) -> &str {
|
|
+ self.identifier.as_str()
|
|
+ }
|
|
+
|
|
+ pub fn is_empty(&self) -> bool {
|
|
+ self.identifier.is_empty()
|
|
+ }
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/parse.rs b/third_party/rust/semver/src/parse.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/parse.rs
|
|
@@ -0,0 +1,405 @@
|
|
+use crate::backport::*;
|
|
+use crate::error::{ErrorKind, Position};
|
|
+use crate::identifier::Identifier;
|
|
+use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq};
|
|
+use core::str::FromStr;
|
|
+
|
|
+/// Error parsing a SemVer version or version requirement.
|
|
+///
|
|
+/// # Example
|
|
+///
|
|
+/// ```
|
|
+/// use semver::Version;
|
|
+///
|
|
+/// fn main() {
|
|
+/// let err = Version::parse("1.q.r").unwrap_err();
|
|
+///
|
|
+/// // "unexpected character 'q' while parsing minor version number"
|
|
+/// eprintln!("{}", err);
|
|
+/// }
|
|
+/// ```
|
|
+pub struct Error {
|
|
+ pub(crate) kind: ErrorKind,
|
|
+}
|
|
+
|
|
+impl FromStr for Version {
|
|
+ type Err = Error;
|
|
+
|
|
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
|
|
+ let mut pos = Position::Major;
|
|
+ let (major, text) = numeric_identifier(text, pos)?;
|
|
+ let text = dot(text, pos)?;
|
|
+
|
|
+ pos = Position::Minor;
|
|
+ let (minor, text) = numeric_identifier(text, pos)?;
|
|
+ let text = dot(text, pos)?;
|
|
+
|
|
+ pos = Position::Patch;
|
|
+ let (patch, text) = numeric_identifier(text, pos)?;
|
|
+
|
|
+ if text.is_empty() {
|
|
+ return Ok(Version::new(major, minor, patch));
|
|
+ }
|
|
+
|
|
+ let (pre, text) = if let Some(text) = text.strip_prefix('-') {
|
|
+ pos = Position::Pre;
|
|
+ let (pre, text) = prerelease_identifier(text)?;
|
|
+ if pre.is_empty() {
|
|
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
|
|
+ }
|
|
+ (pre, text)
|
|
+ } else {
|
|
+ (Prerelease::EMPTY, text)
|
|
+ };
|
|
+
|
|
+ let (build, text) = if let Some(text) = text.strip_prefix('+') {
|
|
+ pos = Position::Build;
|
|
+ let (build, text) = build_identifier(text)?;
|
|
+ if build.is_empty() {
|
|
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
|
|
+ }
|
|
+ (build, text)
|
|
+ } else {
|
|
+ (BuildMetadata::EMPTY, text)
|
|
+ };
|
|
+
|
|
+ if let Some(unexpected) = text.chars().next() {
|
|
+ return Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected)));
|
|
+ }
|
|
+
|
|
+ Ok(Version {
|
|
+ major,
|
|
+ minor,
|
|
+ patch,
|
|
+ pre,
|
|
+ build,
|
|
+ })
|
|
+ }
|
|
+}
|
|
+
|
|
+impl FromStr for VersionReq {
|
|
+ type Err = Error;
|
|
+
|
|
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
|
|
+ let text = text.trim_start_matches(' ');
|
|
+ if let Some((ch, text)) = wildcard(text) {
|
|
+ let rest = text.trim_start_matches(' ');
|
|
+ if rest.is_empty() {
|
|
+ #[cfg(not(no_const_vec_new))]
|
|
+ return Ok(VersionReq::STAR);
|
|
+ #[cfg(no_const_vec_new)] // rustc <1.39
|
|
+ return Ok(VersionReq {
|
|
+ comparators: Vec::new(),
|
|
+ });
|
|
+ } else if rest.starts_with(',') {
|
|
+ return Err(Error::new(ErrorKind::WildcardNotTheOnlyComparator(ch)));
|
|
+ } else {
|
|
+ return Err(Error::new(ErrorKind::UnexpectedAfterWildcard));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ let depth = 0;
|
|
+ let mut comparators = Vec::new();
|
|
+ let len = version_req(text, &mut comparators, depth)?;
|
|
+ unsafe { comparators.set_len(len) }
|
|
+ Ok(VersionReq { comparators })
|
|
+ }
|
|
+}
|
|
+
|
|
+impl FromStr for Comparator {
|
|
+ type Err = Error;
|
|
+
|
|
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
|
|
+ let text = text.trim_start_matches(' ');
|
|
+ let (comparator, pos, rest) = comparator(text)?;
|
|
+ if !rest.is_empty() {
|
|
+ let unexpected = rest.chars().next().unwrap();
|
|
+ return Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected)));
|
|
+ }
|
|
+ Ok(comparator)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl FromStr for Prerelease {
|
|
+ type Err = Error;
|
|
+
|
|
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
|
|
+ let (pre, rest) = prerelease_identifier(text)?;
|
|
+ if !rest.is_empty() {
|
|
+ return Err(Error::new(ErrorKind::IllegalCharacter(Position::Pre)));
|
|
+ }
|
|
+ Ok(pre)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl FromStr for BuildMetadata {
|
|
+ type Err = Error;
|
|
+
|
|
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
|
|
+ let (build, rest) = build_identifier(text)?;
|
|
+ if !rest.is_empty() {
|
|
+ return Err(Error::new(ErrorKind::IllegalCharacter(Position::Build)));
|
|
+ }
|
|
+ Ok(build)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Error {
|
|
+ fn new(kind: ErrorKind) -> Self {
|
|
+ Error { kind }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Op {
|
|
+ const DEFAULT: Self = Op::Caret;
|
|
+}
|
|
+
|
|
+fn numeric_identifier(input: &str, pos: Position) -> Result<(u64, &str), Error> {
|
|
+ let mut len = 0;
|
|
+ let mut value = 0u64;
|
|
+
|
|
+ while let Some(&digit) = input.as_bytes().get(len) {
|
|
+ if digit < b'0' || digit > b'9' {
|
|
+ break;
|
|
+ }
|
|
+ if value == 0 && len > 0 {
|
|
+ return Err(Error::new(ErrorKind::LeadingZero(pos)));
|
|
+ }
|
|
+ match value
|
|
+ .checked_mul(10)
|
|
+ .and_then(|value| value.checked_add((digit - b'0') as u64))
|
|
+ {
|
|
+ Some(sum) => value = sum,
|
|
+ None => return Err(Error::new(ErrorKind::Overflow(pos))),
|
|
+ }
|
|
+ len += 1;
|
|
+ }
|
|
+
|
|
+ if len > 0 {
|
|
+ Ok((value, &input[len..]))
|
|
+ } else if let Some(unexpected) = input[len..].chars().next() {
|
|
+ Err(Error::new(ErrorKind::UnexpectedChar(pos, unexpected)))
|
|
+ } else {
|
|
+ Err(Error::new(ErrorKind::UnexpectedEnd(pos)))
|
|
+ }
|
|
+}
|
|
+
|
|
+fn wildcard(input: &str) -> Option<(char, &str)> {
|
|
+ if let Some(rest) = input.strip_prefix('*') {
|
|
+ Some(('*', rest))
|
|
+ } else if let Some(rest) = input.strip_prefix('x') {
|
|
+ Some(('x', rest))
|
|
+ } else if let Some(rest) = input.strip_prefix('X') {
|
|
+ Some(('X', rest))
|
|
+ } else {
|
|
+ None
|
|
+ }
|
|
+}
|
|
+
|
|
+fn dot(input: &str, pos: Position) -> Result<&str, Error> {
|
|
+ if let Some(rest) = input.strip_prefix('.') {
|
|
+ Ok(rest)
|
|
+ } else if let Some(unexpected) = input.chars().next() {
|
|
+ Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected)))
|
|
+ } else {
|
|
+ Err(Error::new(ErrorKind::UnexpectedEnd(pos)))
|
|
+ }
|
|
+}
|
|
+
|
|
+fn prerelease_identifier(input: &str) -> Result<(Prerelease, &str), Error> {
|
|
+ let (string, rest) = identifier(input, Position::Pre)?;
|
|
+ let identifier = unsafe { Identifier::new_unchecked(string) };
|
|
+ Ok((Prerelease { identifier }, rest))
|
|
+}
|
|
+
|
|
+fn build_identifier(input: &str) -> Result<(BuildMetadata, &str), Error> {
|
|
+ let (string, rest) = identifier(input, Position::Build)?;
|
|
+ let identifier = unsafe { Identifier::new_unchecked(string) };
|
|
+ Ok((BuildMetadata { identifier }, rest))
|
|
+}
|
|
+
|
|
+fn identifier(input: &str, pos: Position) -> Result<(&str, &str), Error> {
|
|
+ let mut accumulated_len = 0;
|
|
+ let mut segment_len = 0;
|
|
+ let mut segment_has_nondigit = false;
|
|
+
|
|
+ loop {
|
|
+ match input.as_bytes().get(accumulated_len + segment_len) {
|
|
+ Some(b'A'..=b'Z') | Some(b'a'..=b'z') | Some(b'-') => {
|
|
+ segment_len += 1;
|
|
+ segment_has_nondigit = true;
|
|
+ }
|
|
+ Some(b'0'..=b'9') => {
|
|
+ segment_len += 1;
|
|
+ }
|
|
+ boundary => {
|
|
+ if segment_len == 0 {
|
|
+ if accumulated_len == 0 && boundary != Some(&b'.') {
|
|
+ return Ok(("", input));
|
|
+ } else {
|
|
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
|
|
+ }
|
|
+ }
|
|
+ if pos == Position::Pre
|
|
+ && segment_len > 1
|
|
+ && !segment_has_nondigit
|
|
+ && input[accumulated_len..].starts_with('0')
|
|
+ {
|
|
+ return Err(Error::new(ErrorKind::LeadingZero(pos)));
|
|
+ }
|
|
+ accumulated_len += segment_len;
|
|
+ if boundary == Some(&b'.') {
|
|
+ accumulated_len += 1;
|
|
+ segment_len = 0;
|
|
+ segment_has_nondigit = false;
|
|
+ } else {
|
|
+ return Ok(input.split_at(accumulated_len));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+fn op(input: &str) -> (Op, &str) {
|
|
+ let bytes = input.as_bytes();
|
|
+ if bytes.get(0) == Some(&b'=') {
|
|
+ (Op::Exact, &input[1..])
|
|
+ } else if bytes.get(0) == Some(&b'>') {
|
|
+ if bytes.get(1) == Some(&b'=') {
|
|
+ (Op::GreaterEq, &input[2..])
|
|
+ } else {
|
|
+ (Op::Greater, &input[1..])
|
|
+ }
|
|
+ } else if bytes.get(0) == Some(&b'<') {
|
|
+ if bytes.get(1) == Some(&b'=') {
|
|
+ (Op::LessEq, &input[2..])
|
|
+ } else {
|
|
+ (Op::Less, &input[1..])
|
|
+ }
|
|
+ } else if bytes.get(0) == Some(&b'~') {
|
|
+ (Op::Tilde, &input[1..])
|
|
+ } else if bytes.get(0) == Some(&b'^') {
|
|
+ (Op::Caret, &input[1..])
|
|
+ } else {
|
|
+ (Op::DEFAULT, input)
|
|
+ }
|
|
+}
|
|
+
|
|
+fn comparator(input: &str) -> Result<(Comparator, Position, &str), Error> {
|
|
+ let (mut op, text) = op(input);
|
|
+ let default_op = input.len() == text.len();
|
|
+ let text = text.trim_start_matches(' ');
|
|
+
|
|
+ let mut pos = Position::Major;
|
|
+ let (major, text) = numeric_identifier(text, pos)?;
|
|
+ let mut has_wildcard = false;
|
|
+
|
|
+ let (minor, text) = if let Some(text) = text.strip_prefix('.') {
|
|
+ pos = Position::Minor;
|
|
+ if let Some((_, text)) = wildcard(text) {
|
|
+ has_wildcard = true;
|
|
+ if default_op {
|
|
+ op = Op::Wildcard;
|
|
+ }
|
|
+ (None, text)
|
|
+ } else {
|
|
+ let (minor, text) = numeric_identifier(text, pos)?;
|
|
+ (Some(minor), text)
|
|
+ }
|
|
+ } else {
|
|
+ (None, text)
|
|
+ };
|
|
+
|
|
+ let (patch, text) = if let Some(text) = text.strip_prefix('.') {
|
|
+ pos = Position::Patch;
|
|
+ if let Some((_, text)) = wildcard(text) {
|
|
+ if default_op {
|
|
+ op = Op::Wildcard;
|
|
+ }
|
|
+ (None, text)
|
|
+ } else if has_wildcard {
|
|
+ return Err(Error::new(ErrorKind::UnexpectedAfterWildcard));
|
|
+ } else {
|
|
+ let (patch, text) = numeric_identifier(text, pos)?;
|
|
+ (Some(patch), text)
|
|
+ }
|
|
+ } else {
|
|
+ (None, text)
|
|
+ };
|
|
+
|
|
+ let (pre, text) = if patch.is_some() && text.starts_with('-') {
|
|
+ pos = Position::Pre;
|
|
+ let text = &text[1..];
|
|
+ let (pre, text) = prerelease_identifier(text)?;
|
|
+ if pre.is_empty() {
|
|
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
|
|
+ }
|
|
+ (pre, text)
|
|
+ } else {
|
|
+ (Prerelease::EMPTY, text)
|
|
+ };
|
|
+
|
|
+ let text = if patch.is_some() && text.starts_with('+') {
|
|
+ pos = Position::Build;
|
|
+ let text = &text[1..];
|
|
+ let (build, text) = build_identifier(text)?;
|
|
+ if build.is_empty() {
|
|
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
|
|
+ }
|
|
+ text
|
|
+ } else {
|
|
+ text
|
|
+ };
|
|
+
|
|
+ let text = text.trim_start_matches(' ');
|
|
+
|
|
+ let comparator = Comparator {
|
|
+ op,
|
|
+ major,
|
|
+ minor,
|
|
+ patch,
|
|
+ pre,
|
|
+ };
|
|
+
|
|
+ Ok((comparator, pos, text))
|
|
+}
|
|
+
|
|
+fn version_req(input: &str, out: &mut Vec<Comparator>, depth: usize) -> Result<usize, Error> {
|
|
+ let (comparator, pos, text) = match comparator(input) {
|
|
+ Ok(success) => success,
|
|
+ Err(mut error) => {
|
|
+ if let Some((ch, mut rest)) = wildcard(input) {
|
|
+ rest = rest.trim_start_matches(' ');
|
|
+ if rest.is_empty() || rest.starts_with(',') {
|
|
+ error.kind = ErrorKind::WildcardNotTheOnlyComparator(ch);
|
|
+ }
|
|
+ }
|
|
+ return Err(error);
|
|
+ }
|
|
+ };
|
|
+
|
|
+ if text.is_empty() {
|
|
+ out.reserve_exact(depth + 1);
|
|
+ unsafe { out.as_mut_ptr().add(depth).write(comparator) }
|
|
+ return Ok(depth + 1);
|
|
+ }
|
|
+
|
|
+ let text = if let Some(text) = text.strip_prefix(',') {
|
|
+ text.trim_start_matches(' ')
|
|
+ } else {
|
|
+ let unexpected = text.chars().next().unwrap();
|
|
+ return Err(Error::new(ErrorKind::ExpectedCommaFound(pos, unexpected)));
|
|
+ };
|
|
+
|
|
+ const MAX_COMPARATORS: usize = 32;
|
|
+ if depth + 1 == MAX_COMPARATORS {
|
|
+ return Err(Error::new(ErrorKind::ExcessiveComparators));
|
|
+ }
|
|
+
|
|
+ // Recurse to collect parsed Comparator objects on the stack. We perform a
|
|
+ // single allocation to allocate exactly the right sized Vec only once the
|
|
+ // total number of comparators is known.
|
|
+ let len = version_req(text, out, depth + 1)?;
|
|
+ unsafe { out.as_mut_ptr().add(depth).write(comparator) }
|
|
+ Ok(len)
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/serde.rs b/third_party/rust/semver/src/serde.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/src/serde.rs
|
|
@@ -0,0 +1,74 @@
|
|
+use crate::{Version, VersionReq};
|
|
+use core::fmt;
|
|
+use serde::de::{Deserialize, Deserializer, Error, Visitor};
|
|
+use serde::ser::{Serialize, Serializer};
|
|
+
|
|
+impl Serialize for Version {
|
|
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
+ where
|
|
+ S: Serializer,
|
|
+ {
|
|
+ serializer.collect_str(self)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Serialize for VersionReq {
|
|
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
+ where
|
|
+ S: Serializer,
|
|
+ {
|
|
+ serializer.collect_str(self)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl<'de> Deserialize<'de> for Version {
|
|
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
+ where
|
|
+ D: Deserializer<'de>,
|
|
+ {
|
|
+ struct VersionVisitor;
|
|
+
|
|
+ impl<'de> Visitor<'de> for VersionVisitor {
|
|
+ type Value = Version;
|
|
+
|
|
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ formatter.write_str("semver version")
|
|
+ }
|
|
+
|
|
+ fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
|
|
+ where
|
|
+ E: Error,
|
|
+ {
|
|
+ string.parse().map_err(Error::custom)
|
|
+ }
|
|
+ }
|
|
+
|
|
+ deserializer.deserialize_str(VersionVisitor)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl<'de> Deserialize<'de> for VersionReq {
|
|
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
+ where
|
|
+ D: Deserializer<'de>,
|
|
+ {
|
|
+ struct VersionReqVisitor;
|
|
+
|
|
+ impl<'de> Visitor<'de> for VersionReqVisitor {
|
|
+ type Value = VersionReq;
|
|
+
|
|
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ formatter.write_str("semver version")
|
|
+ }
|
|
+
|
|
+ fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
|
|
+ where
|
|
+ E: Error,
|
|
+ {
|
|
+ string.parse().map_err(Error::custom)
|
|
+ }
|
|
+ }
|
|
+
|
|
+ deserializer.deserialize_str(VersionReqVisitor)
|
|
+ }
|
|
+}
|
|
diff --git a/third_party/rust/semver/src/version.rs b/third_party/rust/semver/src/version.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver/src/version_req.rs b/third_party/rust/semver/src/version_req.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver/tests/deprecation.rs b/third_party/rust/semver/tests/deprecation.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver/tests/node/mod.rs b/third_party/rust/semver/tests/node/mod.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/tests/node/mod.rs
|
|
@@ -0,0 +1,43 @@
|
|
+#![cfg(test_node_semver)]
|
|
+
|
|
+use semver::Version;
|
|
+use std::fmt::{self, Display};
|
|
+use std::process::Command;
|
|
+
|
|
+#[derive(Default, Eq, PartialEq, Hash, Debug)]
|
|
+pub(super) struct VersionReq(semver::VersionReq);
|
|
+
|
|
+impl VersionReq {
|
|
+ pub(super) const STAR: Self = VersionReq(semver::VersionReq::STAR);
|
|
+
|
|
+ pub(super) fn matches(&self, version: &Version) -> bool {
|
|
+ let out = Command::new("node")
|
|
+ .arg("-e")
|
|
+ .arg(format!(
|
|
+ "console.log(require('semver').satisfies('{}', '{}'))",
|
|
+ version,
|
|
+ self.to_string().replace(',', ""),
|
|
+ ))
|
|
+ .output()
|
|
+ .unwrap();
|
|
+ if out.stdout == b"true\n" {
|
|
+ true
|
|
+ } else if out.stdout == b"false\n" {
|
|
+ false
|
|
+ } else {
|
|
+ let s = String::from_utf8_lossy(&out.stdout) + String::from_utf8_lossy(&out.stderr);
|
|
+ panic!("unexpected output: {}", s);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Display for VersionReq {
|
|
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
+ Display::fmt(&self.0, formatter)
|
|
+ }
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn req(text: &str) -> VersionReq {
|
|
+ VersionReq(crate::util::req(text))
|
|
+}
|
|
diff --git a/third_party/rust/semver/tests/regression.rs b/third_party/rust/semver/tests/regression.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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/third_party/rust/semver/tests/serde.rs b/third_party/rust/semver/tests/serde.rs
|
|
deleted file mode 100644
|
|
--- a/third_party/rust/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());
|
|
-}
|
|
diff --git a/third_party/rust/semver/tests/test_autotrait.rs b/third_party/rust/semver/tests/test_autotrait.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/tests/test_autotrait.rs
|
|
@@ -0,0 +1,12 @@
|
|
+fn assert_send_sync<T: Send + Sync>() {}
|
|
+
|
|
+#[test]
|
|
+fn test() {
|
|
+ assert_send_sync::<semver::BuildMetadata>();
|
|
+ assert_send_sync::<semver::Comparator>();
|
|
+ assert_send_sync::<semver::Error>();
|
|
+ assert_send_sync::<semver::Prerelease>();
|
|
+ assert_send_sync::<semver::Version>();
|
|
+ assert_send_sync::<semver::VersionReq>();
|
|
+ assert_send_sync::<semver::Op>();
|
|
+}
|
|
diff --git a/third_party/rust/semver/tests/test_identifier.rs b/third_party/rust/semver/tests/test_identifier.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/tests/test_identifier.rs
|
|
@@ -0,0 +1,45 @@
|
|
+#![allow(
|
|
+ clippy::eq_op,
|
|
+ clippy::needless_pass_by_value,
|
|
+ clippy::toplevel_ref_arg,
|
|
+ clippy::wildcard_imports
|
|
+)]
|
|
+
|
|
+mod util;
|
|
+
|
|
+use crate::util::*;
|
|
+use semver::Prerelease;
|
|
+
|
|
+#[test]
|
|
+fn test_new() {
|
|
+ fn test(identifier: Prerelease, expected: &str) {
|
|
+ assert_eq!(identifier.is_empty(), expected.is_empty());
|
|
+ assert_eq!(identifier.len(), expected.len());
|
|
+ assert_eq!(identifier.as_str(), expected);
|
|
+ assert_eq!(identifier, identifier);
|
|
+ assert_eq!(identifier, identifier.clone());
|
|
+ }
|
|
+
|
|
+ let ref mut string = String::new();
|
|
+ let limit = if cfg!(miri) { 40 } else { 280 }; // miri is slow
|
|
+ for _ in 0..limit {
|
|
+ test(prerelease(string), string);
|
|
+ string.push('1');
|
|
+ }
|
|
+
|
|
+ if !cfg!(miri) {
|
|
+ let ref string = string.repeat(20000);
|
|
+ test(prerelease(string), string);
|
|
+ }
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_eq() {
|
|
+ assert_eq!(prerelease("-"), prerelease("-"));
|
|
+ assert_ne!(prerelease("a"), prerelease("aa"));
|
|
+ assert_ne!(prerelease("aa"), prerelease("a"));
|
|
+ assert_ne!(prerelease("aaaaaaaaa"), prerelease("a"));
|
|
+ assert_ne!(prerelease("a"), prerelease("aaaaaaaaa"));
|
|
+ assert_ne!(prerelease("aaaaaaaaa"), prerelease("bbbbbbbbb"));
|
|
+ assert_ne!(build_metadata("1"), build_metadata("001"));
|
|
+}
|
|
diff --git a/third_party/rust/semver/tests/test_version.rs b/third_party/rust/semver/tests/test_version.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/tests/test_version.rs
|
|
@@ -0,0 +1,241 @@
|
|
+#![allow(
|
|
+ clippy::nonminimal_bool,
|
|
+ clippy::too_many_lines,
|
|
+ clippy::wildcard_imports
|
|
+)]
|
|
+
|
|
+mod util;
|
|
+
|
|
+use crate::util::*;
|
|
+use semver::{BuildMetadata, Prerelease, Version};
|
|
+
|
|
+#[test]
|
|
+fn test_parse() {
|
|
+ let err = version_err("");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected end of input while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = version_err(" ");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected character ' ' while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = version_err("1");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected end of input while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = version_err("1.2");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected end of input while parsing minor version number",
|
|
+ );
|
|
+
|
|
+ let err = version_err("1.2.3-");
|
|
+ assert_to_string(err, "empty identifier segment in pre-release identifier");
|
|
+
|
|
+ let err = version_err("a.b.c");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected character 'a' while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = version_err("1.2.3 abc");
|
|
+ assert_to_string(err, "unexpected character ' ' after patch version number");
|
|
+
|
|
+ let err = version_err("1.2.3-01");
|
|
+ assert_to_string(err, "invalid leading zero in pre-release identifier");
|
|
+
|
|
+ let parsed = version("1.2.3");
|
|
+ let expected = Version::new(1, 2, 3);
|
|
+ assert_eq!(parsed, expected);
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: Prerelease::EMPTY,
|
|
+ build: BuildMetadata::EMPTY,
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ let parsed = version("1.2.3-alpha1");
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: prerelease("alpha1"),
|
|
+ build: BuildMetadata::EMPTY,
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ let parsed = version("1.2.3+build5");
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: Prerelease::EMPTY,
|
|
+ build: build_metadata("build5"),
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ let parsed = version("1.2.3+5build");
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: Prerelease::EMPTY,
|
|
+ build: build_metadata("5build"),
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ let parsed = version("1.2.3-alpha1+build5");
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: prerelease("alpha1"),
|
|
+ build: build_metadata("build5"),
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ let parsed = version("1.2.3-1.alpha1.9+build5.7.3aedf");
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: prerelease("1.alpha1.9"),
|
|
+ build: build_metadata("build5.7.3aedf"),
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ let parsed = version("1.2.3-0a.alpha1.9+05build.7.3aedf");
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 2,
|
|
+ patch: 3,
|
|
+ pre: prerelease("0a.alpha1.9"),
|
|
+ build: build_metadata("05build.7.3aedf"),
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ let parsed = version("0.4.0-beta.1+0851523");
|
|
+ let expected = Version {
|
|
+ major: 0,
|
|
+ minor: 4,
|
|
+ patch: 0,
|
|
+ pre: prerelease("beta.1"),
|
|
+ build: build_metadata("0851523"),
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+
|
|
+ // for https://nodejs.org/dist/index.json, where some older npm versions are "1.1.0-beta-10"
|
|
+ let parsed = version("1.1.0-beta-10");
|
|
+ let expected = Version {
|
|
+ major: 1,
|
|
+ minor: 1,
|
|
+ patch: 0,
|
|
+ pre: prerelease("beta-10"),
|
|
+ build: BuildMetadata::EMPTY,
|
|
+ };
|
|
+ assert_eq!(parsed, expected);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_eq() {
|
|
+ assert_eq!(version("1.2.3"), version("1.2.3"));
|
|
+ assert_eq!(version("1.2.3-alpha1"), version("1.2.3-alpha1"));
|
|
+ assert_eq!(version("1.2.3+build.42"), version("1.2.3+build.42"));
|
|
+ assert_eq!(version("1.2.3-alpha1+42"), version("1.2.3-alpha1+42"));
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_ne() {
|
|
+ assert_ne!(version("0.0.0"), version("0.0.1"));
|
|
+ assert_ne!(version("0.0.0"), version("0.1.0"));
|
|
+ assert_ne!(version("0.0.0"), version("1.0.0"));
|
|
+ assert_ne!(version("1.2.3-alpha"), version("1.2.3-beta"));
|
|
+ assert_ne!(version("1.2.3+23"), version("1.2.3+42"));
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_display() {
|
|
+ assert_to_string(version("1.2.3"), "1.2.3");
|
|
+ assert_to_string(version("1.2.3-alpha1"), "1.2.3-alpha1");
|
|
+ assert_to_string(version("1.2.3+build.42"), "1.2.3+build.42");
|
|
+ assert_to_string(version("1.2.3-alpha1+42"), "1.2.3-alpha1+42");
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_lt() {
|
|
+ assert!(version("0.0.0") < version("1.2.3-alpha2"));
|
|
+ assert!(version("1.0.0") < version("1.2.3-alpha2"));
|
|
+ assert!(version("1.2.0") < version("1.2.3-alpha2"));
|
|
+ assert!(version("1.2.3-alpha1") < version("1.2.3"));
|
|
+ assert!(version("1.2.3-alpha1") < version("1.2.3-alpha2"));
|
|
+ assert!(!(version("1.2.3-alpha2") < version("1.2.3-alpha2")));
|
|
+ assert!(version("1.2.3+23") < version("1.2.3+42"));
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_le() {
|
|
+ assert!(version("0.0.0") <= version("1.2.3-alpha2"));
|
|
+ assert!(version("1.0.0") <= version("1.2.3-alpha2"));
|
|
+ assert!(version("1.2.0") <= version("1.2.3-alpha2"));
|
|
+ assert!(version("1.2.3-alpha1") <= version("1.2.3-alpha2"));
|
|
+ assert!(version("1.2.3-alpha2") <= version("1.2.3-alpha2"));
|
|
+ assert!(version("1.2.3+23") <= version("1.2.3+42"));
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_gt() {
|
|
+ assert!(version("1.2.3-alpha2") > version("0.0.0"));
|
|
+ assert!(version("1.2.3-alpha2") > version("1.0.0"));
|
|
+ assert!(version("1.2.3-alpha2") > version("1.2.0"));
|
|
+ assert!(version("1.2.3-alpha2") > version("1.2.3-alpha1"));
|
|
+ assert!(version("1.2.3") > version("1.2.3-alpha2"));
|
|
+ assert!(!(version("1.2.3-alpha2") > version("1.2.3-alpha2")));
|
|
+ assert!(!(version("1.2.3+23") > version("1.2.3+42")));
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_ge() {
|
|
+ assert!(version("1.2.3-alpha2") >= version("0.0.0"));
|
|
+ assert!(version("1.2.3-alpha2") >= version("1.0.0"));
|
|
+ assert!(version("1.2.3-alpha2") >= version("1.2.0"));
|
|
+ assert!(version("1.2.3-alpha2") >= version("1.2.3-alpha1"));
|
|
+ assert!(version("1.2.3-alpha2") >= version("1.2.3-alpha2"));
|
|
+ assert!(!(version("1.2.3+23") >= version("1.2.3+42")));
|
|
+}
|
|
+
|
|
+#[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(vs[i - 1]);
|
|
+ let b = version(vs[i]);
|
|
+ assert!(a < b, "nope {:?} < {:?}", a, b);
|
|
+ i += 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_align() {
|
|
+ let version = version("1.2.3-rc1");
|
|
+ assert_eq!("1.2.3-rc1 ", format!("{:20}", version));
|
|
+ assert_eq!("*****1.2.3-rc1******", format!("{:*^20}", version));
|
|
+ assert_eq!(" 1.2.3-rc1", format!("{:>20}", version));
|
|
+}
|
|
diff --git a/third_party/rust/semver/tests/test_version_req.rs b/third_party/rust/semver/tests/test_version_req.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/tests/test_version_req.rs
|
|
@@ -0,0 +1,443 @@
|
|
+#![allow(
|
|
+ clippy::missing_panics_doc,
|
|
+ clippy::shadow_unrelated,
|
|
+ clippy::toplevel_ref_arg,
|
|
+ clippy::wildcard_imports
|
|
+)]
|
|
+
|
|
+mod node;
|
|
+mod util;
|
|
+
|
|
+use crate::util::*;
|
|
+use std::collections::hash_map::DefaultHasher;
|
|
+use std::hash::{Hash, Hasher};
|
|
+
|
|
+#[cfg(test_node_semver)]
|
|
+use node::{req, VersionReq};
|
|
+#[cfg(not(test_node_semver))]
|
|
+use semver::VersionReq;
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+fn assert_match_all(req: &VersionReq, versions: &[&str]) {
|
|
+ for string in versions {
|
|
+ let parsed = version(string);
|
|
+ assert!(req.matches(&parsed), "did not match {}", string);
|
|
+ }
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+fn assert_match_none(req: &VersionReq, versions: &[&str]) {
|
|
+ for string in versions {
|
|
+ let parsed = version(string);
|
|
+ assert!(!req.matches(&parsed), "matched {}", string);
|
|
+ }
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_basic() {
|
|
+ let ref r = req("1.0.0");
|
|
+ assert_to_string(r, "^1.0.0");
|
|
+ assert_match_all(r, &["1.0.0", "1.1.0", "1.0.1"]);
|
|
+ assert_match_none(r, &["0.9.9", "0.10.0", "0.1.0", "1.0.0-pre", "1.0.1-pre"]);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+#[cfg(not(no_const_vec_new))]
|
|
+fn test_default() {
|
|
+ let ref r = VersionReq::default();
|
|
+ assert_eq!(r, &VersionReq::STAR);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_exact() {
|
|
+ let ref r = req("=1.0.0");
|
|
+ assert_to_string(r, "=1.0.0");
|
|
+ assert_match_all(r, &["1.0.0"]);
|
|
+ assert_match_none(r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]);
|
|
+
|
|
+ let ref r = req("=0.9.0");
|
|
+ assert_to_string(r, "=0.9.0");
|
|
+ assert_match_all(r, &["0.9.0"]);
|
|
+ assert_match_none(r, &["0.9.1", "1.9.0", "0.0.9", "0.9.0-pre"]);
|
|
+
|
|
+ let ref r = req("=0.0.2");
|
|
+ assert_to_string(r, "=0.0.2");
|
|
+ assert_match_all(r, &["0.0.2"]);
|
|
+ assert_match_none(r, &["0.0.1", "0.0.3", "0.0.2-pre"]);
|
|
+
|
|
+ let ref r = req("=0.1.0-beta2.a");
|
|
+ assert_to_string(r, "=0.1.0-beta2.a");
|
|
+ assert_match_all(r, &["0.1.0-beta2.a"]);
|
|
+ assert_match_none(r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]);
|
|
+
|
|
+ let ref r = req("=0.1.0+meta");
|
|
+ assert_to_string(r, "=0.1.0");
|
|
+ assert_match_all(r, &["0.1.0", "0.1.0+meta", "0.1.0+any"]);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_greater_than() {
|
|
+ let ref r = req(">= 1.0.0");
|
|
+ assert_to_string(r, ">=1.0.0");
|
|
+ assert_match_all(r, &["1.0.0", "2.0.0"]);
|
|
+ assert_match_none(r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]);
|
|
+
|
|
+ let ref r = req(">= 2.1.0-alpha2");
|
|
+ assert_to_string(r, ">=2.1.0-alpha2");
|
|
+ assert_match_all(r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]);
|
|
+ assert_match_none(
|
|
+ r,
|
|
+ &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"],
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_less_than() {
|
|
+ let ref r = req("< 1.0.0");
|
|
+ assert_to_string(r, "<1.0.0");
|
|
+ assert_match_all(r, &["0.1.0", "0.0.1"]);
|
|
+ assert_match_none(r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]);
|
|
+
|
|
+ let ref r = req("<= 2.1.0-alpha2");
|
|
+ assert_match_all(r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]);
|
|
+ assert_match_none(
|
|
+ r,
|
|
+ &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"],
|
|
+ );
|
|
+
|
|
+ let ref r = req(">1.0.0-alpha, <1.0.0");
|
|
+ assert_match_all(r, &["1.0.0-beta"]);
|
|
+
|
|
+ let ref r = req(">1.0.0-alpha, <1.0");
|
|
+ assert_match_none(r, &["1.0.0-beta"]);
|
|
+
|
|
+ let ref r = req(">1.0.0-alpha, <1");
|
|
+ assert_match_none(r, &["1.0.0-beta"]);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_multiple() {
|
|
+ let ref r = req("> 0.0.9, <= 2.5.3");
|
|
+ assert_to_string(r, ">0.0.9, <=2.5.3");
|
|
+ assert_match_all(r, &["0.0.10", "1.0.0", "2.5.3"]);
|
|
+ assert_match_none(r, &["0.0.8", "2.5.4"]);
|
|
+
|
|
+ let ref r = req("0.3.0, 0.4.0");
|
|
+ assert_to_string(r, "^0.3.0, ^0.4.0");
|
|
+ assert_match_none(r, &["0.0.8", "0.3.0", "0.4.0"]);
|
|
+
|
|
+ let ref r = req("<= 0.2.0, >= 0.5.0");
|
|
+ assert_to_string(r, "<=0.2.0, >=0.5.0");
|
|
+ assert_match_none(r, &["0.0.8", "0.3.0", "0.5.1"]);
|
|
+
|
|
+ let ref r = req("0.1.0, 0.1.4, 0.1.6");
|
|
+ assert_to_string(r, "^0.1.0, ^0.1.4, ^0.1.6");
|
|
+ assert_match_all(r, &["0.1.6", "0.1.9"]);
|
|
+ assert_match_none(r, &["0.1.0", "0.1.4", "0.2.0"]);
|
|
+
|
|
+ let err = req_err("> 0.1.0,");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected end of input while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = req_err("> 0.3.0, ,");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected character ',' while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let ref r = req(">=0.5.1-alpha3, <0.6");
|
|
+ assert_to_string(r, ">=0.5.1-alpha3, <0.6");
|
|
+ assert_match_all(
|
|
+ r,
|
|
+ &[
|
|
+ "0.5.1-alpha3",
|
|
+ "0.5.1-alpha4",
|
|
+ "0.5.1-beta",
|
|
+ "0.5.1",
|
|
+ "0.5.5",
|
|
+ ],
|
|
+ );
|
|
+ assert_match_none(
|
|
+ r,
|
|
+ &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"],
|
|
+ );
|
|
+ assert_match_none(r, &["0.6.0", "0.6.0-pre"]);
|
|
+
|
|
+ // https://github.com/steveklabnik/semver/issues/56
|
|
+ let err = req_err("1.2.3 - 2.3.4");
|
|
+ assert_to_string(err, "expected comma after patch version number, found '-'");
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_whitespace_delimited_comparator_sets() {
|
|
+ // https://github.com/steveklabnik/semver/issues/55
|
|
+ let err = req_err("> 0.0.9 <= 2.5.3");
|
|
+ assert_to_string(err, "expected comma after patch version number, found '<'");
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_tilde() {
|
|
+ let ref r = req("~1");
|
|
+ assert_match_all(r, &["1.0.0", "1.0.1", "1.1.1"]);
|
|
+ assert_match_none(r, &["0.9.1", "2.9.0", "0.0.9"]);
|
|
+
|
|
+ let ref r = req("~1.2");
|
|
+ assert_match_all(r, &["1.2.0", "1.2.1"]);
|
|
+ assert_match_none(r, &["1.1.1", "1.3.0", "0.0.9"]);
|
|
+
|
|
+ let ref r = req("~1.2.2");
|
|
+ assert_match_all(r, &["1.2.2", "1.2.4"]);
|
|
+ assert_match_none(r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]);
|
|
+
|
|
+ let ref r = req("~1.2.3-beta.2");
|
|
+ assert_match_all(r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]);
|
|
+ assert_match_none(r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_caret() {
|
|
+ let ref r = req("^1");
|
|
+ assert_match_all(r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]);
|
|
+ assert_match_none(r, &["0.9.1", "2.9.0", "0.1.4"]);
|
|
+ assert_match_none(r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]);
|
|
+
|
|
+ let ref r = req("^1.1");
|
|
+ assert_match_all(r, &["1.1.2", "1.1.0", "1.2.1"]);
|
|
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]);
|
|
+
|
|
+ let ref r = req("^1.1.2");
|
|
+ assert_match_all(r, &["1.1.2", "1.1.4", "1.2.1"]);
|
|
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);
|
|
+ assert_match_none(r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]);
|
|
+
|
|
+ let ref r = req("^0.1.2");
|
|
+ assert_match_all(r, &["0.1.2", "0.1.4"]);
|
|
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);
|
|
+ assert_match_none(r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]);
|
|
+
|
|
+ let ref r = req("^0.5.1-alpha3");
|
|
+ assert_match_all(
|
|
+ r,
|
|
+ &[
|
|
+ "0.5.1-alpha3",
|
|
+ "0.5.1-alpha4",
|
|
+ "0.5.1-beta",
|
|
+ "0.5.1",
|
|
+ "0.5.5",
|
|
+ ],
|
|
+ );
|
|
+ assert_match_none(
|
|
+ r,
|
|
+ &[
|
|
+ "0.5.1-alpha1",
|
|
+ "0.5.2-alpha3",
|
|
+ "0.5.5-pre",
|
|
+ "0.5.0-pre",
|
|
+ "0.6.0",
|
|
+ ],
|
|
+ );
|
|
+
|
|
+ let ref r = req("^0.0.2");
|
|
+ assert_match_all(r, &["0.0.2"]);
|
|
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]);
|
|
+
|
|
+ let ref r = req("^0.0");
|
|
+ assert_match_all(r, &["0.0.2", "0.0.0"]);
|
|
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]);
|
|
+
|
|
+ let ref r = req("^0");
|
|
+ assert_match_all(r, &["0.9.1", "0.0.2", "0.0.0"]);
|
|
+ assert_match_none(r, &["2.9.0", "1.1.1"]);
|
|
+
|
|
+ let ref r = req("^1.4.2-beta.5");
|
|
+ assert_match_all(
|
|
+ r,
|
|
+ &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"],
|
|
+ );
|
|
+ assert_match_none(
|
|
+ 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_wildcard() {
|
|
+ let err = req_err("");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected end of input while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let ref r = req("*");
|
|
+ assert_match_all(r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);
|
|
+ assert_match_none(r, &["1.0.0-pre"]);
|
|
+
|
|
+ for s in &["x", "X"] {
|
|
+ assert_eq!(*r, req(s));
|
|
+ }
|
|
+
|
|
+ let ref r = req("1.*");
|
|
+ assert_match_all(r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);
|
|
+ assert_match_none(r, &["0.0.9", "1.2.0-pre"]);
|
|
+
|
|
+ for s in &["1.x", "1.X", "1.*.*"] {
|
|
+ assert_eq!(*r, req(s));
|
|
+ }
|
|
+
|
|
+ let ref r = req("1.2.*");
|
|
+ assert_match_all(r, &["1.2.0", "1.2.2", "1.2.4"]);
|
|
+ assert_match_none(r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3", "1.2.2-pre"]);
|
|
+
|
|
+ for s in &["1.2.x", "1.2.X"] {
|
|
+ assert_eq!(*r, req(s));
|
|
+ }
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_logical_or() {
|
|
+ // https://github.com/steveklabnik/semver/issues/57
|
|
+ let err = req_err("=1.2.3 || =2.3.4");
|
|
+ assert_to_string(err, "expected comma after patch version number, found '|'");
|
|
+
|
|
+ let err = req_err("1.1 || =1.2.3");
|
|
+ assert_to_string(err, "expected comma after minor version number, found '|'");
|
|
+
|
|
+ let err = req_err("6.* || 8.* || >= 10.*");
|
|
+ assert_to_string(err, "expected comma after minor version number, found '|'");
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_any() {
|
|
+ #[cfg(not(no_const_vec_new))]
|
|
+ let ref r = VersionReq::STAR;
|
|
+ #[cfg(no_const_vec_new)]
|
|
+ let ref r = VersionReq {
|
|
+ comparators: Vec::new(),
|
|
+ };
|
|
+ assert_match_all(r, &["0.0.1", "0.1.0", "1.0.0"]);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_pre() {
|
|
+ let ref r = req("=2.1.1-really.0");
|
|
+ assert_match_all(r, &["2.1.1-really.0"]);
|
|
+}
|
|
+
|
|
+#[test]
|
|
+pub fn test_parse_errors() {
|
|
+ let err = req_err("\0");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected character '\\0' while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = req_err(">= >= 0.0.2");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected character '>' while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = req_err(">== 0.0.2");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected character '=' while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = req_err("a.0.0");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected character 'a' while parsing major version number",
|
|
+ );
|
|
+
|
|
+ let err = req_err("1.0.0-");
|
|
+ assert_to_string(err, "empty identifier segment in pre-release identifier");
|
|
+
|
|
+ let err = req_err(">=");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "unexpected end of input while parsing major version number",
|
|
+ );
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_cargo3202() {
|
|
+ let ref r = req("0.*.*");
|
|
+ assert_to_string(r, "0.*");
|
|
+ assert_match_all(r, &["0.5.0"]);
|
|
+
|
|
+ let ref r = req("0.0.*");
|
|
+ assert_to_string(r, "0.0.*");
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_digit_after_wildcard() {
|
|
+ let err = req_err("*.1");
|
|
+ assert_to_string(err, "unexpected character after wildcard in version req");
|
|
+
|
|
+ let err = req_err("1.*.1");
|
|
+ assert_to_string(err, "unexpected character after wildcard in version req");
|
|
+
|
|
+ let err = req_err(">=1.*.1");
|
|
+ assert_to_string(err, "unexpected character after wildcard in version req");
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_eq_hash() {
|
|
+ fn calculate_hash(value: impl Hash) -> u64 {
|
|
+ let mut hasher = DefaultHasher::new();
|
|
+ value.hash(&mut hasher);
|
|
+ hasher.finish()
|
|
+ }
|
|
+
|
|
+ assert!(req("^1") == req("^1"));
|
|
+ assert!(calculate_hash(req("^1")) == calculate_hash(req("^1")));
|
|
+ assert!(req("^1") != req("^2"));
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_leading_digit_in_pre_and_build() {
|
|
+ for op in &["=", ">", ">=", "<", "<=", "~", "^"] {
|
|
+ // digit then alpha
|
|
+ req(&format!("{} 1.2.3-1a", op));
|
|
+ req(&format!("{} 1.2.3+1a", op));
|
|
+
|
|
+ // digit then alpha (leading zero)
|
|
+ req(&format!("{} 1.2.3-01a", op));
|
|
+ req(&format!("{} 1.2.3+01", op));
|
|
+
|
|
+ // multiple
|
|
+ req(&format!("{} 1.2.3-1+1", op));
|
|
+ req(&format!("{} 1.2.3-1-1+1-1-1", op));
|
|
+ req(&format!("{} 1.2.3-1a+1a", op));
|
|
+ req(&format!("{} 1.2.3-1a-1a+1a-1a-1a", op));
|
|
+ }
|
|
+}
|
|
+
|
|
+#[test]
|
|
+fn test_wildcard_and_another() {
|
|
+ let err = req_err("*, 0.20.0-any");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "wildcard req (*) must be the only comparator in the version req",
|
|
+ );
|
|
+
|
|
+ let err = req_err("0.20.0-any, *");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "wildcard req (*) must be the only comparator in the version req",
|
|
+ );
|
|
+
|
|
+ let err = req_err("0.20.0-any, *, 1.0");
|
|
+ assert_to_string(
|
|
+ err,
|
|
+ "wildcard req (*) must be the only comparator in the version req",
|
|
+ );
|
|
+}
|
|
diff --git a/third_party/rust/semver/tests/util/mod.rs b/third_party/rust/semver/tests/util/mod.rs
|
|
new file mode 100644
|
|
--- /dev/null
|
|
+++ b/third_party/rust/semver/tests/util/mod.rs
|
|
@@ -0,0 +1,39 @@
|
|
+#![allow(dead_code)]
|
|
+
|
|
+use semver::{BuildMetadata, Error, Prerelease, Version, VersionReq};
|
|
+use std::fmt::Display;
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn version(text: &str) -> Version {
|
|
+ Version::parse(text).unwrap()
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn version_err(text: &str) -> Error {
|
|
+ Version::parse(text).unwrap_err()
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn req(text: &str) -> VersionReq {
|
|
+ VersionReq::parse(text).unwrap()
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn req_err(text: &str) -> Error {
|
|
+ VersionReq::parse(text).unwrap_err()
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn prerelease(text: &str) -> Prerelease {
|
|
+ Prerelease::new(text).unwrap()
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn build_metadata(text: &str) -> BuildMetadata {
|
|
+ BuildMetadata::new(text).unwrap()
|
|
+}
|
|
+
|
|
+#[cfg_attr(not(no_track_caller), track_caller)]
|
|
+pub(super) fn assert_to_string(value: impl Display, expected: &str) {
|
|
+ assert_eq!(value.to_string(), expected);
|
|
+}
|
|
diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml
|
|
--- a/toolkit/library/rust/shared/Cargo.toml
|
|
+++ b/toolkit/library/rust/shared/Cargo.toml
|
|
@@ -16,17 +16,17 @@ nsstring = { path = "../../../../xpcom/r
|
|
netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }
|
|
xpcom = { path = "../../../../xpcom/rust/xpcom" }
|
|
prefs_parser = { path = "../../../../modules/libpref/parser" }
|
|
static_prefs = { path = "../../../../modules/libpref/init/static_prefs" }
|
|
profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
|
|
mozurl = { path = "../../../../netwerk/base/mozurl" }
|
|
webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
|
|
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "44eca95823bb57e964cf7b6d9791ed2ccb4b2108", optional = true }
|
|
-cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="df4dc0288b07b865440f4c7e41ca49ca9ccffc63", optional = true, features=["pulse-dlopen"] }
|
|
+cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="1f1fe1e08e01a9a534ec7f079702a583a0899ce7", optional = true, features=["pulse-dlopen"] }
|
|
cubeb-sys = { version = "0.10", optional = true, features=["gecko-in-tree"] }
|
|
audioipc2-client = { git = "https://github.com/kinetiknz/audioipc-2", rev = "85e9839059f4bf8f68130825b8fd02c39a6a51b9", optional = true } # macos (v2) branch
|
|
audioipc2-server = { git = "https://github.com/kinetiknz/audioipc-2", rev = "85e9839059f4bf8f68130825b8fd02c39a6a51b9", optional = true } # macos (v2) branch
|
|
audioipc-client = { git = "https://github.com/mozilla/audioipc-2", rev = "c144368c4e084ec0f076af6262970655c2d99e8d", optional = true }
|
|
audioipc-server = { git = "https://github.com/mozilla/audioipc-2", rev = "c144368c4e084ec0f076af6262970655c2d99e8d", optional = true }
|
|
encoding_glue = { path = "../../../../intl/encoding_glue" }
|
|
authenticator = "0.3.1"
|
|
gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
|
|
diff --git a/xpcom/rust/gkrust_utils/Cargo.toml b/xpcom/rust/gkrust_utils/Cargo.toml
|
|
--- a/xpcom/rust/gkrust_utils/Cargo.toml
|
|
+++ b/xpcom/rust/gkrust_utils/Cargo.toml
|
|
@@ -1,8 +1,8 @@
|
|
[package]
|
|
name = "gkrust_utils"
|
|
version = "0.1.0"
|
|
authors = ["Jonathan Kingston <jkt@mozilla.com>"]
|
|
|
|
[dependencies]
|
|
-semver = "0.9"
|
|
+semver = "1.0"
|
|
nsstring = { path = "../nsstring" }
|
|
|