diff --git a/src/cargo/core/dependency.rs b/src/cargo/core/dependency.rs index fe102842a..ddd43e1f5 100644 --- a/src/cargo/core/dependency.rs +++ b/src/cargo/core/dependency.rs @@ -402,6 +402,14 @@ impl Dependency { self.matches_id(sum.package_id()) } + pub fn matches_prerelease(&self, sum: &Summary) -> bool { + let id = sum.package_id(); + self.inner.name == id.name() + && (self.inner.only_match_name + || (self.inner.req.matches_prerelease(id.version()) + && self.inner.source_id == id.source_id())) + } + /// Returns `true` if the package (`id`) can fulfill this dependency request. pub fn matches_ignoring_source(&self, id: PackageId) -> bool { self.package_name() == id.name() && self.version_req().matches(id.version()) diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index f72797dd9..edd22ebe0 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -768,7 +768,6 @@ unstable_cli_options!( next_lockfile_bump: bool, no_index_update: bool = ("Do not update the registry index even if the cache is outdated"), panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"), - precise_pre_release: bool = ("Enable pre-release versions to be selected with `update --precise`"), profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"), public_dependency: bool = ("Respect a dependency's `public` field in Cargo.toml to control public/private dependencies"), publish_timeout: bool = ("Enable the `publish.timeout` key in .cargo/config.toml file"), @@ -1158,7 +1157,6 @@ impl CliUnstable { "panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?, "public-dependency" => self.public_dependency = parse_empty(k, v)?, "profile-rustflags" => self.profile_rustflags = parse_empty(k, v)?, - "precise-pre-release" => self.precise_pre_release = parse_empty(k, v)?, "trim-paths" => self.trim_paths = parse_empty(k, v)?, "publish-timeout" => self.publish_timeout = parse_empty(k, v)?, "rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?, diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index cc0e5a66b..b1ef55d24 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -208,9 +208,9 @@ use crate::sources::source::QueryKind; use crate::sources::source::Source; use crate::sources::PathSource; use crate::util::cache_lock::CacheLockMode; -use crate::util::hex; use crate::util::interning::InternedString; use crate::util::network::PollExt; +use crate::util::{hex, VersionExt}; use crate::util::{restricted_names, CargoResult, Filesystem, GlobalContext, LimitErrorReader}; /// The `.cargo-ok` file is used to track if the source is already unpacked. @@ -752,7 +752,13 @@ impl<'gctx> Source for RegistrySource<'gctx> { if let Some((_, requested)) = self .source_id .precise_registry_version(dep.package_name().as_str()) - .filter(|(c, _)| req.matches(c)) + .filter(|(c, to)| { + if to.is_prerelease() && self.gctx.cli_unstable().unstable_options { + req.matches_prerelease(c) + } else { + req.matches(c) + } + }) { req.precise_to(&requested); } @@ -790,7 +796,13 @@ impl<'gctx> Source for RegistrySource<'gctx> { .index .query_inner(dep.package_name(), &req, &mut *self.ops, &mut |s| { let matched = match kind { - QueryKind::Exact => dep.matches(s.as_summary()), + QueryKind::Exact => { + if req.is_precise() && self.gctx.cli_unstable().unstable_options { + dep.matches_prerelease(s.as_summary()) + } else { + dep.matches(s.as_summary()) + } + } QueryKind::Alternatives => true, QueryKind::Normalized => true, }; diff --git a/src/cargo/util/semver_ext.rs b/src/cargo/util/semver_ext.rs index ae32483f3..46b09e2e2 100644 --- a/src/cargo/util/semver_ext.rs +++ b/src/cargo/util/semver_ext.rs @@ -111,6 +111,19 @@ impl OptVersionReq { } } + /// Since Semver does not support prerelease versions, + /// the simplest implementation is taken here without comparing the prerelease section. + /// The logic here is temporary, we'll have to consider more boundary conditions later, + /// and we're not sure if this part of the functionality should be implemented in semver or cargo. + pub fn matches_prerelease(&self, version: &Version) -> bool { + if version.is_prerelease() { + let mut version = version.clone(); + version.pre = semver::Prerelease::EMPTY; + return self.matches(&version); + } + self.matches(version) + } + pub fn matches(&self, version: &Version) -> bool { match self { OptVersionReq::Any => true, diff --git a/src/doc/man/cargo-update.md b/src/doc/man/cargo-update.md index 9c2503407..0e9ca371a 100644 --- a/src/doc/man/cargo-update.md +++ b/src/doc/man/cargo-update.md @@ -46,6 +46,8 @@ revision (such as a SHA hash or tag). While not recommended, you can specify a yanked version of a package (nightly only). When possible, try other non-yanked SemVer-compatible versions or seek help from the maintainers of the package. + +A compatible `pre-release` version can also be specified even when the version requirement in `Cargo.toml` doesn't contain any pre-release identifer (nightly only). {{/option}} {{#option "`-w`" "`--workspace`" }} diff --git a/src/doc/man/generated_txt/cargo-update.txt b/src/doc/man/generated_txt/cargo-update.txt index a1be485b9..e6765c680 100644 --- a/src/doc/man/generated_txt/cargo-update.txt +++ b/src/doc/man/generated_txt/cargo-update.txt @@ -40,6 +40,10 @@ OPTIONS SemVer-compatible versions or seek help from the maintainers of the package. + A compatible pre-release version can also be specified even when the + version requirement in Cargo.toml doesn’t contain any pre-release + identifer (nightly only). + -w, --workspace Attempt to update only packages defined in the workspace. Other packages are updated only if they don’t already exist in the diff --git a/src/doc/src/commands/cargo-update.md b/src/doc/src/commands/cargo-update.md index 6416c8149..3738c7418 100644 --- a/src/doc/src/commands/cargo-update.md +++ b/src/doc/src/commands/cargo-update.md @@ -42,7 +42,8 @@ the package to. If the package comes from a git repository, this can be a git revision (such as a SHA hash or tag).

While not recommended, you can specify a yanked version of a package (nightly only). When possible, try other non-yanked SemVer-compatible versions or seek help -from the maintainers of the package. +from the maintainers of the package.

+

A compatible pre-release version can also be specified even when the version requirement in Cargo.toml doesn’t contain any pre-release identifer (nightly only).

-w
diff --git a/src/doc/src/reference/unstable.md b/src/doc/src/reference/unstable.md index f0c5ffed0..e5656b54f 100644 --- a/src/doc/src/reference/unstable.md +++ b/src/doc/src/reference/unstable.md @@ -347,7 +347,7 @@ Take for example this `Cargo.toml`. my-dependency = "0.1.1" ``` -It's possible to update `my-dependancy` to a pre-release with `update -Zprecise-pre-release -p my-dependency --precise 0.1.2-pre.0`. +It's possible to update `my-dependancy` to a pre-release with `update -Zunstable-options my-dependency --precise 0.1.2-pre.0`. This is because `0.1.2-pre.0` is considered compatible with `0.1.1`. It would not be possible to upgrade to `0.2.0-pre.0` from `0.1.1` in the same way. diff --git a/src/etc/man/cargo-update.1 b/src/etc/man/cargo-update.1 index daad6db8a..921575fec 100644 --- a/src/etc/man/cargo-update.1 +++ b/src/etc/man/cargo-update.1 @@ -43,6 +43,8 @@ revision (such as a SHA hash or tag). While not recommended, you can specify a yanked version of a package (nightly only). When possible, try other non\-yanked SemVer\-compatible versions or seek help from the maintainers of the package. +.sp +A compatible \fBpre\-release\fR version can also be specified even when the version requirement in \fBCargo.toml\fR doesn\[cq]t contain any pre\-release identifer (nightly only). .RE .sp \fB\-w\fR, diff --git a/tests/testsuite/cargo/z_help/stdout.term.svg b/tests/testsuite/cargo/z_help/stdout.term.svg index a664709f1..cde7a9595 100644 --- a/tests/testsuite/cargo/z_help/stdout.term.svg +++ b/tests/testsuite/cargo/z_help/stdout.term.svg @@ -1,4 +1,4 @@ - +