mirror of
https://github.com/rust-lang/cargo
synced 2024-10-02 14:04:23 +00:00
Auto merge of #9508 - dtolnay-contrib:semver, r=ehuss
Update to semver 1.0.0 I am working on a 1.0.0 of the `semver` crate some time this week. It would be good to confirm Cargo will be able to use it, beforehand! It's a from-scratch rewrite, but https://github.com/dtolnay/semver/issues/237 has code to compare against 0.10.0 (currently used by Cargo) how every possible version requirement currently published to crates.io matches against every possible crate version. The differences are all broken syntax like `^0-.11.0` previously parsing with ".11.0" as a pre-release string (which is invalid, because pre-release are not allowed to contain empty dot-separated identifiers) and `~2.0-2.2` previously parsing with "2.2" as a pre-release string, when the user almost certainly meant `>=2.0, <=2.2`. I'm not sure how much of those you want to add code into Cargo to preserve behavior, but I would be happy to do it.
This commit is contained in:
commit
2f3df16921
|
@ -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", features = ["serde"] }
|
||||
serde = { version = "1.0.123", features = ["derive"] }
|
||||
serde_ignored = "0.1.0"
|
||||
serde_json = { version = "1.0.30", features = ["raw_value"] }
|
||||
|
|
|
@ -506,7 +506,7 @@ pub trait ToDep {
|
|||
|
||||
impl ToDep for &'static str {
|
||||
fn to_dep(self) -> Dependency {
|
||||
Dependency::parse_no_deprecated(self, Some("1.0.0"), registry_loc()).unwrap()
|
||||
Dependency::parse(self, Some("1.0.0"), registry_loc()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +626,7 @@ pub fn dep(name: &str) -> Dependency {
|
|||
dep_req(name, "*")
|
||||
}
|
||||
pub fn dep_req(name: &str, req: &str) -> Dependency {
|
||||
Dependency::parse_no_deprecated(name, Some(req), registry_loc()).unwrap()
|
||||
Dependency::parse(name, Some(req), registry_loc()).unwrap()
|
||||
}
|
||||
pub fn dep_req_kind(name: &str, req: &str, kind: DepKind, public: bool) -> Dependency {
|
||||
let mut dep = dep_req(name, req);
|
||||
|
@ -639,7 +639,7 @@ pub fn dep_loc(name: &str, location: &str) -> Dependency {
|
|||
let url = location.into_url().unwrap();
|
||||
let master = GitReference::Branch("master".to_string());
|
||||
let source_id = SourceId::for_git(&url, master).unwrap();
|
||||
Dependency::parse_no_deprecated(name, Some("1.0.0"), source_id).unwrap()
|
||||
Dependency::parse(name, Some("1.0.0"), source_id).unwrap()
|
||||
}
|
||||
pub fn dep_kind(name: &str, kind: DepKind) -> Dependency {
|
||||
dep(name).set_kind(kind).clone()
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -47,7 +47,7 @@ pub fn resolve_std<'cfg>(
|
|||
.iter()
|
||||
.map(|&name| {
|
||||
let source_path = SourceId::for_path(&src_path.join("library").join(name))?;
|
||||
let dep = Dependency::parse_no_deprecated(name, None, source_path)?;
|
||||
let dep = Dependency::parse(name, None, source_path)?;
|
||||
Ok(dep)
|
||||
})
|
||||
.collect::<CargoResult<Vec<_>>>()?;
|
||||
|
|
|
@ -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::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,
|
||||
|
@ -99,52 +97,6 @@ pub enum DepKind {
|
|||
Build,
|
||||
}
|
||||
|
||||
fn parse_req_with_deprecated(
|
||||
name: InternedString,
|
||||
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!(
|
||||
"\
|
||||
parsed version requirement `{}` is no longer valid
|
||||
|
||||
Previous versions of Cargo accepted this malformed requirement,
|
||||
but it is being deprecated. This was found when parsing the manifest
|
||||
of {} {}, and the correct version requirement is `{}`.
|
||||
|
||||
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)?;
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
impl ser::Serialize for DepKind {
|
||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
|
@ -165,36 +117,19 @@ impl Dependency {
|
|||
name: impl Into<InternedString>,
|
||||
version: Option<&str>,
|
||||
source_id: SourceId,
|
||||
inside: PackageId,
|
||||
config: &Config,
|
||||
) -> CargoResult<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()),
|
||||
};
|
||||
|
||||
let mut ret = Dependency::new_override(name, source_id);
|
||||
{
|
||||
let ptr = Rc::make_mut(&mut ret.inner);
|
||||
ptr.only_match_name = false;
|
||||
ptr.req = version_req;
|
||||
ptr.specified_req = specified_req;
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
/// Attempt to create a `Dependency` from an entry in the manifest.
|
||||
pub fn parse_no_deprecated(
|
||||
name: impl Into<InternedString>,
|
||||
version: Option<&str>,
|
||||
source_id: SourceId,
|
||||
) -> 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) => match VersionReq::parse(v) {
|
||||
Ok(req) => (true, OptVersionReq::Req(req)),
|
||||
Err(err) => {
|
||||
return Err(anyhow::Error::new(err).context(format!(
|
||||
"failed to parse the version requirement `{}` for dependency `{}`",
|
||||
v, name,
|
||||
)))
|
||||
}
|
||||
},
|
||||
None => (false, OptVersionReq::Any),
|
||||
};
|
||||
|
||||
let mut ret = Dependency::new_override(name, source_id);
|
||||
|
@ -214,7 +149,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 +163,7 @@ impl Dependency {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn version_req(&self) -> &VersionReq {
|
||||
pub fn version_req(&self) -> &OptVersionReq {
|
||||
&self.inner.req
|
||||
}
|
||||
|
||||
|
@ -365,7 +300,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 +329,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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -396,7 +396,6 @@ impl<'cfg> Workspace<'cfg> {
|
|||
.map(|(name, dep)| {
|
||||
dep.to_dependency_split(
|
||||
name,
|
||||
/* pkg_id */ None,
|
||||
source,
|
||||
&mut nested_paths,
|
||||
self.config,
|
||||
|
|
|
@ -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 _};
|
||||
|
@ -180,11 +180,7 @@ fn install_one(
|
|||
} else {
|
||||
None
|
||||
};
|
||||
Some(Dependency::parse_no_deprecated(
|
||||
krate,
|
||||
vers.as_deref(),
|
||||
source_id,
|
||||
)?)
|
||||
Some(Dependency::parse(krate, vers.as_deref(), source_id)?)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
@ -373,7 +373,7 @@ impl<'a> RegistryDependency<'a> {
|
|||
default
|
||||
};
|
||||
|
||||
let mut dep = Dependency::parse_no_deprecated(package.unwrap_or(name), Some(&req), id)?;
|
||||
let mut dep = Dependency::parse(package.unwrap_or(name), Some(&req), id)?;
|
||||
if package.is_some() {
|
||||
dep.set_explicit_name_in_toml(name);
|
||||
}
|
||||
|
@ -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)?
|
||||
|
|
|
@ -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;
|
||||
|
|
76
src/cargo/util/semver_ext.rs
Normal file
76
src/cargo/util/semver_ext.rs
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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)),
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
|
@ -847,7 +874,6 @@ impl TomlProject {
|
|||
}
|
||||
|
||||
struct Context<'a, 'b> {
|
||||
pkgid: Option<PackageId>,
|
||||
deps: &'a mut Vec<Dependency>,
|
||||
source_id: SourceId,
|
||||
nested_paths: &'a mut Vec<PathBuf>,
|
||||
|
@ -1162,7 +1188,6 @@ impl TomlManifest {
|
|||
|
||||
{
|
||||
let mut cx = Context {
|
||||
pkgid: Some(pkgid),
|
||||
deps: &mut deps,
|
||||
source_id,
|
||||
nested_paths: &mut nested_paths,
|
||||
|
@ -1430,7 +1455,6 @@ impl TomlManifest {
|
|||
|
||||
let (replace, patch) = {
|
||||
let mut cx = Context {
|
||||
pkgid: None,
|
||||
deps: &mut deps,
|
||||
source_id,
|
||||
nested_paths: &mut nested_paths,
|
||||
|
@ -1626,7 +1650,6 @@ impl<P: ResolveToPath> TomlDependency<P> {
|
|||
pub(crate) fn to_dependency_split(
|
||||
&self,
|
||||
name: &str,
|
||||
pkgid: Option<PackageId>,
|
||||
source_id: SourceId,
|
||||
nested_paths: &mut Vec<PathBuf>,
|
||||
config: &Config,
|
||||
|
@ -1639,7 +1662,6 @@ impl<P: ResolveToPath> TomlDependency<P> {
|
|||
self.to_dependency(
|
||||
name,
|
||||
&mut Context {
|
||||
pkgid,
|
||||
deps: &mut Vec::new(),
|
||||
source_id,
|
||||
nested_paths,
|
||||
|
@ -1848,10 +1870,7 @@ impl<P: ResolveToPath> DetailedTomlDependency<P> {
|
|||
};
|
||||
|
||||
let version = self.version.as_deref();
|
||||
let mut dep = match cx.pkgid {
|
||||
Some(id) => Dependency::parse(pkg_name, version, new_source_id, id, cx.config)?,
|
||||
None => Dependency::parse_no_deprecated(pkg_name, version, new_source_id)?,
|
||||
};
|
||||
let mut dep = Dependency::parse(pkg_name, version, new_source_id)?;
|
||||
dep.set_features(self.features.iter().flatten())
|
||||
.set_default_features(
|
||||
self.default_features
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -1695,119 +1695,6 @@ fn bump_version_dont_update_registry() {
|
|||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn old_version_req() {
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[project]
|
||||
name = "bar"
|
||||
version = "0.5.0"
|
||||
authors = []
|
||||
|
||||
[dependencies]
|
||||
remote = "0.2*"
|
||||
"#,
|
||||
)
|
||||
.file("src/main.rs", "fn main() {}")
|
||||
.build();
|
||||
|
||||
Package::new("remote", "0.2.0").publish();
|
||||
|
||||
p.cargo("build")
|
||||
.with_stderr(
|
||||
"\
|
||||
warning: parsed version requirement `0.2*` is no longer valid
|
||||
|
||||
Previous versions of Cargo accepted this malformed requirement,
|
||||
but it is being deprecated. This was found when parsing the manifest
|
||||
of bar 0.5.0, and the correct version requirement is `0.2.*`.
|
||||
|
||||
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.
|
||||
|
||||
warning: parsed version requirement `0.2*` is no longer valid
|
||||
|
||||
Previous versions of Cargo accepted this malformed requirement,
|
||||
but it is being deprecated. This was found when parsing the manifest
|
||||
of bar 0.5.0, and the correct version requirement is `0.2.*`.
|
||||
|
||||
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.
|
||||
|
||||
[UPDATING] [..]
|
||||
[DOWNLOADING] crates ...
|
||||
[DOWNLOADED] [..]
|
||||
[COMPILING] [..]
|
||||
[COMPILING] [..]
|
||||
[FINISHED] [..]
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn old_version_req_upstream() {
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[project]
|
||||
name = "bar"
|
||||
version = "0.5.0"
|
||||
authors = []
|
||||
|
||||
[dependencies]
|
||||
remote = "0.3"
|
||||
"#,
|
||||
)
|
||||
.file("src/main.rs", "fn main() {}")
|
||||
.build();
|
||||
|
||||
Package::new("remote", "0.3.0")
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[project]
|
||||
name = "remote"
|
||||
version = "0.3.0"
|
||||
authors = []
|
||||
|
||||
[dependencies]
|
||||
bar = "0.2*"
|
||||
"#,
|
||||
)
|
||||
.file("src/lib.rs", "")
|
||||
.publish();
|
||||
Package::new("bar", "0.2.0").publish();
|
||||
|
||||
p.cargo("build")
|
||||
.with_stderr(
|
||||
"\
|
||||
[UPDATING] [..]
|
||||
[DOWNLOADING] crates ...
|
||||
[DOWNLOADED] [..]
|
||||
warning: parsed version requirement `0.2*` is no longer valid
|
||||
|
||||
Previous versions of Cargo accepted this malformed requirement,
|
||||
but it is being deprecated. This was found when parsing the manifest
|
||||
of remote 0.3.0, and the correct version requirement is `0.2.*`.
|
||||
|
||||
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.
|
||||
|
||||
[COMPILING] [..]
|
||||
[COMPILING] [..]
|
||||
[FINISHED] [..]
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn toml_lies_but_index_is_truth() {
|
||||
Package::new("foo", "0.2.0").publish();
|
||||
|
|
Loading…
Reference in a new issue