Update to semver 1.0.0-rc

This commit is contained in:
David Tolnay 2021-05-25 16:46:11 -07:00
parent e931e4796b
commit 3b62e466ec
No known key found for this signature in database
GPG key ID: F9BA143B95FF6D82
14 changed files with 169 additions and 81 deletions

View file

@ -50,7 +50,7 @@ num_cpus = "1.0"
opener = "0.4"
percent-encoding = "2.0"
rustfix = "0.5.0"
semver = { version = "0.10", features = ["serde"] }
semver = { version = "1.0.0-rc.2", features = ["serde"] }
serde = { version = "1.0.123", features = ["derive"] }
serde_ignored = "0.1.0"
serde_json = { version = "1.0.30", features = ["raw_value"] }

View file

@ -5,7 +5,6 @@ use std::path::PathBuf;
use cargo_platform::CfgExpr;
use cargo_util::{paths, ProcessBuilder};
use semver::Version;
use super::BuildContext;
use crate::core::compiler::{CompileKind, Metadata, Unit};
@ -316,10 +315,7 @@ impl<'cfg> Compilation<'cfg> {
.env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
.env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
.env("CARGO_PKG_VERSION_PATCH", &pkg.version().patch.to_string())
.env(
"CARGO_PKG_VERSION_PRE",
&pre_version_component(pkg.version()),
)
.env("CARGO_PKG_VERSION_PRE", pkg.version().pre.as_str())
.env("CARGO_PKG_VERSION", &pkg.version().to_string())
.env("CARGO_PKG_NAME", &*pkg.name())
.env(
@ -368,23 +364,6 @@ fn fill_rustc_tool_env(mut cmd: ProcessBuilder, unit: &Unit) -> ProcessBuilder {
cmd
}
fn pre_version_component(v: &Version) -> String {
if v.pre.is_empty() {
return String::new();
}
let mut ret = String::new();
for (i, x) in v.pre.iter().enumerate() {
if i != 0 {
ret.push('.')
};
ret.push_str(&x.to_string());
}
ret
}
fn target_runner(
bcx: &BuildContext<'_, '_>,
kind: CompileKind,

View file

@ -595,7 +595,7 @@ fn hash_rustc_version(bcx: &BuildContext<'_, '_>, hasher: &mut StableHasher) {
//
// This assumes that the first segment is the important bit ("nightly",
// "beta", "dev", etc.). Skip other parts like the `.3` in `-beta.3`.
vers.pre[0].hash(hasher);
vers.pre.split('.').next().hash(hasher);
// Keep "host" since some people switch hosts to implicitly change
// targets, (like gnu vs musl or gnu vs msvc). In the future, we may want
// to consider hashing `unit.kind.short_name()` instead.

View file

@ -1,7 +1,5 @@
use anyhow::Context as _;
use cargo_platform::Platform;
use log::trace;
use semver::ReqParseError;
use semver::VersionReq;
use serde::ser;
use serde::Serialize;
@ -11,17 +9,17 @@ use std::rc::Rc;
use crate::core::{PackageId, SourceId, Summary};
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
use crate::util::Config;
use crate::util::{Config, OptVersionReq};
/// Information about a dependency requested by a Cargo manifest.
/// Cheap to copy.
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct Dependency {
inner: Rc<Inner>,
}
/// The data underlying a `Dependency`.
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
struct Inner {
name: InternedString,
source_id: SourceId,
@ -32,7 +30,7 @@ struct Inner {
/// `registry` is specified. Or in the case of a crates.io dependency,
/// `source_id` will be crates.io and this will be None.
registry_id: Option<SourceId>,
req: VersionReq,
req: OptVersionReq,
specified_req: bool,
kind: DepKind,
only_match_name: bool,
@ -104,14 +102,32 @@ fn parse_req_with_deprecated(
req: &str,
extra: Option<(PackageId, &Config)>,
) -> CargoResult<VersionReq> {
match VersionReq::parse(req) {
Err(ReqParseError::DeprecatedVersionRequirement(requirement)) => {
let (inside, config) = match extra {
Some(pair) => pair,
None => return Err(ReqParseError::DeprecatedVersionRequirement(requirement).into()),
};
let msg = format!(
"\
let err = match VersionReq::parse(req) {
Ok(req) => return Ok(req),
Err(err) => err,
};
let (inside, config) = match extra {
Some(pair) => pair,
None => return Err(err.into()),
};
let corrected = match req {
".*" => "*",
"0.1.0." => "0.1.0",
"0.3.1.3" => "0.3.13",
"0.2*" => "0.2.*",
"*.0" => "*",
_ => {
return Err(anyhow::Error::new(err).context(format!(
"failed to parse the version requirement `{}` for dependency `{}`",
req, name,
)));
}
};
let msg = format!(
"\
parsed version requirement `{}` is no longer valid
Previous versions of Cargo accepted this malformed requirement,
@ -122,27 +138,15 @@ This will soon become a hard error, so it's either recommended to
update to a fixed version or contact the upstream maintainer about
this warning.
",
req,
inside.name(),
inside.version(),
requirement
);
config.shell().warn(&msg)?;
req,
inside.name(),
inside.version(),
corrected,
);
Ok(requirement)
}
Err(e) => {
let err: CargoResult<VersionReq> = Err(e.into());
let v: VersionReq = err.with_context(|| {
format!(
"failed to parse the version requirement `{}` for dependency `{}`",
req, name
)
})?;
Ok(v)
}
Ok(v) => Ok(v),
}
config.shell().warn(&msg)?;
Ok(VersionReq::parse(corrected).unwrap())
}
impl ser::Serialize for DepKind {
@ -171,8 +175,8 @@ impl Dependency {
let name = name.into();
let arg = Some((inside, config));
let (specified_req, version_req) = match version {
Some(v) => (true, parse_req_with_deprecated(name, v, arg)?),
None => (false, VersionReq::any()),
Some(v) => (true, parse_req_with_deprecated(name, v, arg)?.into()),
None => (false, OptVersionReq::Any),
};
let mut ret = Dependency::new_override(name, source_id);
@ -193,8 +197,8 @@ impl Dependency {
) -> CargoResult<Dependency> {
let name = name.into();
let (specified_req, version_req) = match version {
Some(v) => (true, parse_req_with_deprecated(name, v, None)?),
None => (false, VersionReq::any()),
Some(v) => (true, parse_req_with_deprecated(name, v, None)?.into()),
None => (false, OptVersionReq::Any),
};
let mut ret = Dependency::new_override(name, source_id);
@ -214,7 +218,7 @@ impl Dependency {
name,
source_id,
registry_id: None,
req: VersionReq::any(),
req: OptVersionReq::Any,
kind: DepKind::Normal,
only_match_name: true,
optional: false,
@ -228,7 +232,7 @@ impl Dependency {
}
}
pub fn version_req(&self) -> &VersionReq {
pub fn version_req(&self) -> &OptVersionReq {
&self.inner.req
}
@ -365,7 +369,7 @@ impl Dependency {
/// Sets the version requirement for this dependency.
pub fn set_version_req(&mut self, req: VersionReq) -> &mut Dependency {
Rc::make_mut(&mut self.inner).req = req;
Rc::make_mut(&mut self.inner).req = OptVersionReq::Req(req);
self
}
@ -394,7 +398,7 @@ impl Dependency {
id
);
let me = Rc::make_mut(&mut self.inner);
me.req = VersionReq::exact(id.version());
me.req = OptVersionReq::exact(id.version());
// Only update the `precise` of this source to preserve other
// information about dependency's source which may not otherwise be

View file

@ -5,7 +5,7 @@ use crate::core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary};
use crate::sources::config::SourceConfigMap;
use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
use crate::util::{profile, CanonicalUrl, Config};
use crate::util::{profile, CanonicalUrl, Config, VersionReqExt};
use anyhow::{bail, Context as _};
use log::{debug, trace};
use semver::VersionReq;

View file

@ -2,7 +2,7 @@ use std::fmt;
use crate::core::{Dependency, PackageId, Registry, Summary};
use crate::util::lev_distance::lev_distance;
use crate::util::Config;
use crate::util::{Config, VersionExt};
use anyhow::Error;
use super::context::Context;

View file

@ -8,7 +8,7 @@ use crate::core::{Dependency, Edition, Package, PackageId, Source, SourceId, Wor
use crate::ops::common_for_install_and_uninstall::*;
use crate::sources::{GitSource, PathSource, SourceConfigMap};
use crate::util::errors::CargoResult;
use crate::util::{Config, Filesystem, Rustc, ToSemver};
use crate::util::{Config, Filesystem, Rustc, ToSemver, VersionReqExt};
use crate::{drop_println, ops};
use anyhow::{bail, format_err, Context as _};

View file

@ -70,11 +70,11 @@ use crate::core::dependency::Dependency;
use crate::core::{PackageId, SourceId, Summary};
use crate::sources::registry::{RegistryData, RegistryPackage, INDEX_V_MAX};
use crate::util::interning::InternedString;
use crate::util::{internal, CargoResult, Config, Filesystem, ToSemver};
use crate::util::{internal, CargoResult, Config, Filesystem, OptVersionReq, ToSemver};
use anyhow::bail;
use cargo_util::paths;
use log::{debug, info};
use semver::{Version, VersionReq};
use semver::Version;
use std::collections::{HashMap, HashSet};
use std::convert::TryInto;
use std::fs;
@ -264,7 +264,7 @@ impl<'cfg> RegistryIndex<'cfg> {
/// Returns the hash listed for a specified `PackageId`.
pub fn hash(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> CargoResult<&str> {
let req = VersionReq::exact(pkg.version());
let req = OptVersionReq::exact(pkg.version());
let summary = self
.summaries(pkg.name(), &req, load)?
.next()
@ -285,7 +285,7 @@ impl<'cfg> RegistryIndex<'cfg> {
pub fn summaries<'a, 'b>(
&'a mut self,
name: InternedString,
req: &'b VersionReq,
req: &'b OptVersionReq,
load: &mut dyn RegistryData,
) -> CargoResult<impl Iterator<Item = &'a IndexSummary> + 'b>
where
@ -489,7 +489,7 @@ impl<'cfg> RegistryIndex<'cfg> {
}
pub fn is_yanked(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> CargoResult<bool> {
let req = VersionReq::exact(pkg.version());
let req = OptVersionReq::exact(pkg.version());
let found = self
.summaries(pkg.name(), &req, load)?
.any(|summary| summary.yanked);

View file

@ -168,7 +168,7 @@ use std::path::{Path, PathBuf};
use anyhow::Context as _;
use flate2::read::GzDecoder;
use log::debug;
use semver::{Version, VersionReq};
use semver::Version;
use serde::Deserialize;
use tar::Archive;
@ -179,7 +179,7 @@ use crate::sources::PathSource;
use crate::util::hex;
use crate::util::interning::InternedString;
use crate::util::into_url::IntoUrl;
use crate::util::{restricted_names, CargoResult, Config, Filesystem};
use crate::util::{restricted_names, CargoResult, Config, Filesystem, OptVersionReq};
const PACKAGE_SOURCE_LOCK: &str = ".cargo-ok";
pub const CRATES_IO_INDEX: &str = "https://github.com/rust-lang/crates.io-index";
@ -671,7 +671,7 @@ impl<'cfg> RegistrySource<'cfg> {
// After we've loaded the package configure its summary's `checksum`
// field with the checksum we know for this `PackageId`.
let req = VersionReq::exact(package.version());
let req = OptVersionReq::exact(package.version());
let summary_with_cksum = self
.index
.summaries(package.name(), &req, &mut *self.ops)?

View file

@ -20,6 +20,7 @@ pub use self::progress::{Progress, ProgressStyle};
pub use self::queue::Queue;
pub use self::restricted_names::validate_package_name;
pub use self::rustc::Rustc;
pub use self::semver_ext::{OptVersionReq, VersionExt, VersionReqExt};
pub use self::to_semver::ToSemver;
pub use self::vcs::{existing_vcs_repo, FossilRepo, GitRepo, HgRepo, PijulRepo};
pub use self::workspace::{
@ -53,6 +54,7 @@ mod progress;
mod queue;
pub mod restricted_names;
pub mod rustc;
mod semver_ext;
pub mod to_semver;
pub mod toml;
mod vcs;

View file

@ -0,0 +1,76 @@
use semver::{Comparator, Op, Version, VersionReq};
use std::fmt::{self, Display};
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum OptVersionReq {
Any,
Req(VersionReq),
}
pub trait VersionExt {
fn is_prerelease(&self) -> bool;
}
pub trait VersionReqExt {
fn exact(version: &Version) -> Self;
}
impl VersionExt for Version {
fn is_prerelease(&self) -> bool {
!self.pre.is_empty()
}
}
impl VersionReqExt for VersionReq {
fn exact(version: &Version) -> Self {
VersionReq {
comparators: vec![Comparator {
op: Op::Exact,
major: version.major,
minor: Some(version.minor),
patch: Some(version.patch),
pre: version.pre.clone(),
}],
}
}
}
impl OptVersionReq {
pub fn exact(version: &Version) -> Self {
OptVersionReq::Req(VersionReq::exact(version))
}
pub fn is_exact(&self) -> bool {
match self {
OptVersionReq::Any => false,
OptVersionReq::Req(req) => {
req.comparators.len() == 1 && {
let cmp = &req.comparators[0];
cmp.op == Op::Exact && cmp.minor.is_some() && cmp.patch.is_some()
}
}
}
}
pub fn matches(&self, version: &Version) -> bool {
match self {
OptVersionReq::Any => true,
OptVersionReq::Req(req) => req.matches(version),
}
}
}
impl Display for OptVersionReq {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
OptVersionReq::Any => formatter.write_str("*"),
OptVersionReq::Req(req) => Display::fmt(req, formatter),
}
}
}
impl From<VersionReq> for OptVersionReq {
fn from(req: VersionReq) -> Self {
OptVersionReq::Req(req)
}
}

View file

@ -13,7 +13,7 @@ impl ToSemver for Version {
impl<'a> ToSemver for &'a str {
fn to_semver(self) -> CargoResult<Version> {
match Version::parse(self) {
match Version::parse(self.trim()) {
Ok(v) => Ok(v),
Err(..) => Err(anyhow::format_err!("cannot parse '{}' as a semver", self)),
}

View file

@ -25,7 +25,9 @@ use crate::core::{GitReference, PackageIdSpec, SourceId, WorkspaceConfig, Worksp
use crate::sources::{CRATES_IO_INDEX, CRATES_IO_REGISTRY};
use crate::util::errors::{CargoResult, ManifestError};
use crate::util::interning::InternedString;
use crate::util::{self, config::ConfigRelativePath, validate_package_name, Config, IntoUrl};
use crate::util::{
self, config::ConfigRelativePath, validate_package_name, Config, IntoUrl, VersionReqExt,
};
mod targets;
use self::targets::targets;
@ -778,6 +780,30 @@ impl<'de> de::Deserialize<'de> for VecStringOrBool {
}
}
fn version_trim_whitespace<'de, D>(deserializer: D) -> Result<semver::Version, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = semver::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: de::Error,
{
string.trim().parse().map_err(de::Error::custom)
}
}
deserializer.deserialize_str(Visitor)
}
/// Represents the `package`/`project` sections of a `Cargo.toml`.
///
/// Note that the order of the fields matters, since this is the order they
@ -790,6 +816,7 @@ pub struct TomlProject {
edition: Option<String>,
rust_version: Option<String>,
name: InternedString,
#[serde(deserialize_with = "version_trim_whitespace")]
version: semver::Version,
authors: Option<Vec<String>>,
build: Option<StringOrBool>,

View file

@ -269,7 +269,7 @@ fn cargo_compile_with_invalid_version() {
[ERROR] failed to parse manifest at `[..]`
Caused by:
Expected dot for key `package.version`
unexpected end of input while parsing minor version number for key `package.version`
",
)
.run();
@ -544,7 +544,7 @@ Caused by:
failed to parse the version requirement `y` for dependency `crossbeam`
Caused by:
the given version requirement is invalid
unexpected character 'y' while parsing major version number
",
)
.run();