mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
Improved error message for versions prefixed with v
(#15484)
### What does this PR try to resolve? - Added an error message when version in `CRATE[@<VER>]` or `--version <VER>` starts with 'v' for `install`, `add`, `yank` and `update --precise <VER>` - Check if version is valid in `cargo yank` Fixes #12331 ### How should we test and review this PR? Added tests for each subcommand
This commit is contained in:
commit
6cba807e2c
@ -286,6 +286,12 @@ fn parse_semver_flag(v: &str) -> CargoResult<VersionReq> {
|
||||
.next()
|
||||
.ok_or_else(|| format_err!("no version provided for the `--version` flag"))?;
|
||||
|
||||
if let Some(stripped) = v.strip_prefix("v") {
|
||||
bail!(
|
||||
"the version provided, `{v}` is not a valid SemVer requirement\n\n\
|
||||
help: try changing the version to `{stripped}`",
|
||||
)
|
||||
}
|
||||
let is_req = "<>=^~".contains(first) || v.contains('*');
|
||||
if is_req {
|
||||
match v.parse::<VersionReq>() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::command_prelude::*;
|
||||
|
||||
use anyhow::Context;
|
||||
use cargo::ops;
|
||||
use cargo_credential::Secret;
|
||||
|
||||
@ -60,5 +61,19 @@ fn resolve_crate<'k>(
|
||||
krate = Some(k);
|
||||
version = Some(v);
|
||||
}
|
||||
|
||||
if let Some(version) = version {
|
||||
semver::Version::parse(version).with_context(|| {
|
||||
if let Some(stripped) = version.strip_prefix("v") {
|
||||
return format!(
|
||||
"the version provided, `{version}` is not a \
|
||||
valid SemVer version\n\n\
|
||||
help: try changing the version to `{stripped}`",
|
||||
);
|
||||
}
|
||||
format!("invalid version `{version}`")
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok((krate, version))
|
||||
}
|
||||
|
@ -523,8 +523,16 @@ impl SourceId {
|
||||
version: semver::Version,
|
||||
precise: &str,
|
||||
) -> CargoResult<SourceId> {
|
||||
let precise = semver::Version::parse(precise)
|
||||
.with_context(|| format!("invalid version format for precise version `{precise}`"))?;
|
||||
let precise = semver::Version::parse(precise).with_context(|| {
|
||||
if let Some(stripped) = precise.strip_prefix("v") {
|
||||
return format!(
|
||||
"the version provided, `{precise}` is not a \
|
||||
valid SemVer version\n\n\
|
||||
help: try changing the version to `{stripped}`",
|
||||
);
|
||||
}
|
||||
format!("invalid version format for precise version `{precise}`")
|
||||
})?;
|
||||
|
||||
Ok(SourceId::wrap(SourceIdInner {
|
||||
precise: Some(Precise::Updated {
|
||||
|
@ -47,8 +47,16 @@ impl CrateSpec {
|
||||
package_name?;
|
||||
|
||||
if let Some(version) = version {
|
||||
semver::VersionReq::parse(version)
|
||||
.with_context(|| format!("invalid version requirement `{version}`"))?;
|
||||
semver::VersionReq::parse(version).with_context(|| {
|
||||
if let Some(stripped) = version.strip_prefix("v") {
|
||||
return format!(
|
||||
"the version provided, `{version}` is not a \
|
||||
valid SemVer requirement\n\n\
|
||||
help: changing the package to `{name}@{stripped}`",
|
||||
);
|
||||
}
|
||||
format!("invalid version requirement `{version}`")
|
||||
})?;
|
||||
}
|
||||
|
||||
let id = Self {
|
||||
|
@ -126,6 +126,7 @@ mod path_base_unstable;
|
||||
mod path_dev;
|
||||
mod path_inferred_name;
|
||||
mod path_inferred_name_conflicts_full_feature;
|
||||
mod prefixed_v_in_version;
|
||||
mod preserve_dep_std_table;
|
||||
mod preserve_features_sorted;
|
||||
mod preserve_features_table;
|
||||
|
1
tests/testsuite/cargo_add/prefixed_v_in_version/in
Symbolic link
1
tests/testsuite/cargo_add/prefixed_v_in_version/in
Symbolic link
@ -0,0 +1 @@
|
||||
../add-basic.in
|
26
tests/testsuite/cargo_add/prefixed_v_in_version/mod.rs
Normal file
26
tests/testsuite/cargo_add/prefixed_v_in_version/mod.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use cargo_test_support::compare::assert_ui;
|
||||
use cargo_test_support::current_dir;
|
||||
use cargo_test_support::file;
|
||||
use cargo_test_support::prelude::*;
|
||||
use cargo_test_support::str;
|
||||
use cargo_test_support::Project;
|
||||
|
||||
#[cargo_test]
|
||||
fn case() {
|
||||
cargo_test_support::registry::init();
|
||||
|
||||
let project = Project::from_template(current_dir!().join("in"));
|
||||
let project_root = project.root();
|
||||
let cwd = &project_root;
|
||||
|
||||
snapbox::cmd::Command::cargo_ui()
|
||||
.arg("add")
|
||||
.arg_line("foo@v0.0.1")
|
||||
.current_dir(cwd)
|
||||
.assert()
|
||||
.code(101)
|
||||
.stdout_eq(str![""])
|
||||
.stderr_eq(file!["stderr.term.svg"]);
|
||||
|
||||
assert_ui().subset_matches(current_dir!().join("out"), &project_root);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
[workspace]
|
||||
|
||||
[package]
|
||||
name = "cargo-list-test-fixture"
|
||||
version = "0.0.0"
|
||||
edition = "2015"
|
@ -0,0 +1,37 @@
|
||||
<svg width="740px" height="146px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
.fg-red { fill: #AA0000 }
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.bold { font-weight: bold; }
|
||||
tspan {
|
||||
font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
|
||||
white-space: pre;
|
||||
line-height: 18px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
|
||||
|
||||
<text xml:space="preserve" class="container fg">
|
||||
<tspan x="10px" y="28px"><tspan class="fg-red bold">error</tspan><tspan class="bold">:</tspan><tspan> the version provided, `v0.0.1` is not a valid SemVer requirement</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="46px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="64px"><tspan>help: changing the package to `foo@0.0.1`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="82px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="100px"><tspan>Caused by:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="118px"><tspan> unexpected character 'v' while parsing major version number</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="136px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -2899,3 +2899,19 @@ fn dry_run_remove_orphan() {
|
||||
// Ensure server is still installed after the dry run
|
||||
assert_has_installed_exe(paths::cargo_home(), "server");
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn prefixed_v_in_version() {
|
||||
pkg("foo", "0.0.1");
|
||||
cargo_process("install foo@v0.0.1")
|
||||
.with_status(1)
|
||||
.with_stderr_data(str![[r#"
|
||||
[ERROR] invalid value 'foo@v0.0.1' for '[CRATE[@<VER>]]...': the version provided, `v0.0.1` is not a valid SemVer requirement
|
||||
|
||||
[HELP] try changing the version to `0.0.1`
|
||||
|
||||
For more information, try '--help'.
|
||||
|
||||
"#]])
|
||||
.run();
|
||||
}
|
||||
|
@ -2709,3 +2709,41 @@ fn update_breaking_pre_release_upgrade() {
|
||||
"#]])
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn prefixed_v_in_version() {
|
||||
Package::new("bar", "1.0.0").publish();
|
||||
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "0.0.1"
|
||||
edition = "2015"
|
||||
authors = []
|
||||
|
||||
[dependencies]
|
||||
bar = "1.0.0"
|
||||
"#,
|
||||
)
|
||||
.file("src/lib.rs", "")
|
||||
.build();
|
||||
|
||||
p.cargo("generate-lockfile").run();
|
||||
|
||||
Package::new("bar", "1.0.1").publish();
|
||||
p.cargo("update bar --precise v1.0.1")
|
||||
.with_status(101)
|
||||
.with_stderr_data(str![[r#"
|
||||
[ERROR] the version provided, `v1.0.1` is not a valid SemVer version
|
||||
|
||||
[HELP] try changing the version to `1.0.1`
|
||||
|
||||
Caused by:
|
||||
unexpected character 'v' while parsing major version number
|
||||
|
||||
"#]])
|
||||
.run();
|
||||
}
|
||||
|
@ -212,3 +212,71 @@ fn inline_and_explicit_version() {
|
||||
"#]])
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn bad_version() {
|
||||
let registry = registry::init();
|
||||
setup("foo", "0.0.1");
|
||||
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "0.0.1"
|
||||
authors = []
|
||||
license = "MIT"
|
||||
description = "foo"
|
||||
"#,
|
||||
)
|
||||
.file("src/main.rs", "fn main() {}")
|
||||
.build();
|
||||
|
||||
p.cargo("yank foo@bar")
|
||||
.replace_crates_io(registry.index_url())
|
||||
.with_status(101)
|
||||
.with_stderr_data(str![[r#"
|
||||
[ERROR] invalid version `bar`
|
||||
|
||||
Caused by:
|
||||
unexpected character 'b' while parsing major version number
|
||||
|
||||
"#]])
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn prefixed_v_in_version() {
|
||||
let registry = registry::init();
|
||||
setup("foo", "0.0.1");
|
||||
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "0.0.1"
|
||||
authors = []
|
||||
license = "MIT"
|
||||
description = "foo"
|
||||
"#,
|
||||
)
|
||||
.file("src/main.rs", "fn main() {}")
|
||||
.build();
|
||||
|
||||
p.cargo("yank bar@v0.0.1")
|
||||
.replace_crates_io(registry.index_url())
|
||||
.with_status(101)
|
||||
.with_stderr_data(str![[r#"
|
||||
[ERROR] the version provided, `v0.0.1` is not a valid SemVer version
|
||||
|
||||
[HELP] try changing the version to `0.0.1`
|
||||
|
||||
Caused by:
|
||||
unexpected character 'v' while parsing major version number
|
||||
|
||||
"#]])
|
||||
.run();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user