From 5f07c9cb528f0cd57425c966ef78f0e38260625e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 23 May 2023 17:13:39 -0500 Subject: [PATCH 1/4] test(upgrade): Verify current MSRV behavior --- .../cli_rust_version/in/Cargo.toml | 7 ++++ .../cli_rust_version/in/src/lib.rs | 0 tests/cargo-upgrade/cli_rust_version/mod.rs | 39 +++++++++++++++++++ .../cli_rust_version/out/Cargo.toml | 7 ++++ .../cli_rust_version/out/src/lib.rs | 0 .../cargo-upgrade/cli_rust_version/stderr.log | 3 ++ .../cargo-upgrade/cli_rust_version/stdout.log | 3 ++ .../ignore_rust_version/in/Cargo.toml | 7 ++++ .../ignore_rust_version/in/src/lib.rs | 0 .../cargo-upgrade/ignore_rust_version/mod.rs | 36 +++++++++++++++++ .../ignore_rust_version/out/Cargo.toml | 7 ++++ .../ignore_rust_version/out/src/lib.rs | 0 .../ignore_rust_version/stderr.log | 3 ++ .../ignore_rust_version/stdout.log | 3 ++ tests/cargo-upgrade/main.rs | 3 ++ .../package_rust_version/in/Cargo.toml | 7 ++++ .../package_rust_version/in/src/lib.rs | 0 .../cargo-upgrade/package_rust_version/mod.rs | 36 +++++++++++++++++ .../package_rust_version/out/Cargo.toml | 7 ++++ .../package_rust_version/out/src/lib.rs | 0 .../package_rust_version/stderr.log | 3 ++ .../package_rust_version/stdout.log | 3 ++ 22 files changed, 174 insertions(+) create mode 100644 tests/cargo-upgrade/cli_rust_version/in/Cargo.toml create mode 100644 tests/cargo-upgrade/cli_rust_version/in/src/lib.rs create mode 100644 tests/cargo-upgrade/cli_rust_version/mod.rs create mode 100644 tests/cargo-upgrade/cli_rust_version/out/Cargo.toml create mode 100644 tests/cargo-upgrade/cli_rust_version/out/src/lib.rs create mode 100644 tests/cargo-upgrade/cli_rust_version/stderr.log create mode 100644 tests/cargo-upgrade/cli_rust_version/stdout.log create mode 100644 tests/cargo-upgrade/ignore_rust_version/in/Cargo.toml create mode 100644 tests/cargo-upgrade/ignore_rust_version/in/src/lib.rs create mode 100644 tests/cargo-upgrade/ignore_rust_version/mod.rs create mode 100644 tests/cargo-upgrade/ignore_rust_version/out/Cargo.toml create mode 100644 tests/cargo-upgrade/ignore_rust_version/out/src/lib.rs create mode 100644 tests/cargo-upgrade/ignore_rust_version/stderr.log create mode 100644 tests/cargo-upgrade/ignore_rust_version/stdout.log create mode 100644 tests/cargo-upgrade/package_rust_version/in/Cargo.toml create mode 100644 tests/cargo-upgrade/package_rust_version/in/src/lib.rs create mode 100644 tests/cargo-upgrade/package_rust_version/mod.rs create mode 100644 tests/cargo-upgrade/package_rust_version/out/Cargo.toml create mode 100644 tests/cargo-upgrade/package_rust_version/out/src/lib.rs create mode 100644 tests/cargo-upgrade/package_rust_version/stderr.log create mode 100644 tests/cargo-upgrade/package_rust_version/stdout.log diff --git a/tests/cargo-upgrade/cli_rust_version/in/Cargo.toml b/tests/cargo-upgrade/cli_rust_version/in/Cargo.toml new file mode 100644 index 0000000000..f1ec569f3d --- /dev/null +++ b/tests/cargo-upgrade/cli_rust_version/in/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +rust-version = "1.64.0" + +[dependencies] +my-package = "0.1.1" diff --git a/tests/cargo-upgrade/cli_rust_version/in/src/lib.rs b/tests/cargo-upgrade/cli_rust_version/in/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/cargo-upgrade/cli_rust_version/mod.rs b/tests/cargo-upgrade/cli_rust_version/mod.rs new file mode 100644 index 0000000000..b2eef52864 --- /dev/null +++ b/tests/cargo-upgrade/cli_rust_version/mod.rs @@ -0,0 +1,39 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::Project; + +use crate::CargoCommand; +use cargo_test_support::curr_dir; + +#[cargo_test] +fn case() { + cargo_test_support::registry::Package::new("my-package", "0.1.1") + .rust_version("1.60.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.1.2") + .rust_version("1.64.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.1.3") + .rust_version("1.68.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.0") + .rust_version("1.68.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.3.0") + .rust_version("1.72.0") + .publish(); + + let project = Project::from_template(curr_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("upgrade") + .args(["--verbose", "--verbose", "--pinned", "--incompatible"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path(curr_dir!().join("stdout.log")) + .stderr_matches_path(curr_dir!().join("stderr.log")); + + assert_ui().subset_matches(curr_dir!().join("out"), &project_root); +} diff --git a/tests/cargo-upgrade/cli_rust_version/out/Cargo.toml b/tests/cargo-upgrade/cli_rust_version/out/Cargo.toml new file mode 100644 index 0000000000..f881fc42c8 --- /dev/null +++ b/tests/cargo-upgrade/cli_rust_version/out/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +rust-version = "1.64.0" + +[dependencies] +my-package = "0.3.0" diff --git a/tests/cargo-upgrade/cli_rust_version/out/src/lib.rs b/tests/cargo-upgrade/cli_rust_version/out/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/cargo-upgrade/cli_rust_version/stderr.log b/tests/cargo-upgrade/cli_rust_version/stderr.log new file mode 100644 index 0000000000..017c781c4b --- /dev/null +++ b/tests/cargo-upgrade/cli_rust_version/stderr.log @@ -0,0 +1,3 @@ + Updating '[ROOTURL]/registry' index + Checking cargo-list-test-fixture's dependencies + Upgrading recursive dependencies diff --git a/tests/cargo-upgrade/cli_rust_version/stdout.log b/tests/cargo-upgrade/cli_rust_version/stdout.log new file mode 100644 index 0000000000..f2cea5748f --- /dev/null +++ b/tests/cargo-upgrade/cli_rust_version/stdout.log @@ -0,0 +1,3 @@ +name old req compatible latest new req +==== ======= ========== ====== ======= +my-package 0.1.1 0.1.3 0.3.0 0.3.0 diff --git a/tests/cargo-upgrade/ignore_rust_version/in/Cargo.toml b/tests/cargo-upgrade/ignore_rust_version/in/Cargo.toml new file mode 100644 index 0000000000..f1ec569f3d --- /dev/null +++ b/tests/cargo-upgrade/ignore_rust_version/in/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +rust-version = "1.64.0" + +[dependencies] +my-package = "0.1.1" diff --git a/tests/cargo-upgrade/ignore_rust_version/in/src/lib.rs b/tests/cargo-upgrade/ignore_rust_version/in/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/cargo-upgrade/ignore_rust_version/mod.rs b/tests/cargo-upgrade/ignore_rust_version/mod.rs new file mode 100644 index 0000000000..bea60c0f11 --- /dev/null +++ b/tests/cargo-upgrade/ignore_rust_version/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::Project; + +use crate::CargoCommand; +use cargo_test_support::curr_dir; + +#[cargo_test] +fn case() { + cargo_test_support::registry::Package::new("my-package", "0.1.1") + .rust_version("1.60.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.1.2") + .rust_version("1.64.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.1.3") + .rust_version("1.68.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.0") + .rust_version("1.68.0") + .publish(); + + let project = Project::from_template(curr_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("upgrade") + .args(["--verbose", "--verbose", "--pinned", "--incompatible"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path(curr_dir!().join("stdout.log")) + .stderr_matches_path(curr_dir!().join("stderr.log")); + + assert_ui().subset_matches(curr_dir!().join("out"), &project_root); +} diff --git a/tests/cargo-upgrade/ignore_rust_version/out/Cargo.toml b/tests/cargo-upgrade/ignore_rust_version/out/Cargo.toml new file mode 100644 index 0000000000..d2c0cedeb6 --- /dev/null +++ b/tests/cargo-upgrade/ignore_rust_version/out/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +rust-version = "1.64.0" + +[dependencies] +my-package = "0.2.0" diff --git a/tests/cargo-upgrade/ignore_rust_version/out/src/lib.rs b/tests/cargo-upgrade/ignore_rust_version/out/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/cargo-upgrade/ignore_rust_version/stderr.log b/tests/cargo-upgrade/ignore_rust_version/stderr.log new file mode 100644 index 0000000000..017c781c4b --- /dev/null +++ b/tests/cargo-upgrade/ignore_rust_version/stderr.log @@ -0,0 +1,3 @@ + Updating '[ROOTURL]/registry' index + Checking cargo-list-test-fixture's dependencies + Upgrading recursive dependencies diff --git a/tests/cargo-upgrade/ignore_rust_version/stdout.log b/tests/cargo-upgrade/ignore_rust_version/stdout.log new file mode 100644 index 0000000000..4ce02868d7 --- /dev/null +++ b/tests/cargo-upgrade/ignore_rust_version/stdout.log @@ -0,0 +1,3 @@ +name old req compatible latest new req +==== ======= ========== ====== ======= +my-package 0.1.1 0.1.3 0.2.0 0.2.0 diff --git a/tests/cargo-upgrade/main.rs b/tests/cargo-upgrade/main.rs index 3ed1c90cb1..8596624097 100644 --- a/tests/cargo-upgrade/main.rs +++ b/tests/cargo-upgrade/main.rs @@ -6,9 +6,11 @@ extern crate cargo_test_macro; mod alt_registry; +mod cli_rust_version; mod dry_run; mod exclude_dep; mod exclude_renamed; +mod ignore_rust_version; mod implicit_prerelease; mod invalid_dep; mod invalid_flag; @@ -18,6 +20,7 @@ mod locked; mod locked_dry_run; mod lockfile; mod optional_dep; +mod package_rust_version; mod pinned; mod preserve_op; mod preserve_precision_major; diff --git a/tests/cargo-upgrade/package_rust_version/in/Cargo.toml b/tests/cargo-upgrade/package_rust_version/in/Cargo.toml new file mode 100644 index 0000000000..f1ec569f3d --- /dev/null +++ b/tests/cargo-upgrade/package_rust_version/in/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +rust-version = "1.64.0" + +[dependencies] +my-package = "0.1.1" diff --git a/tests/cargo-upgrade/package_rust_version/in/src/lib.rs b/tests/cargo-upgrade/package_rust_version/in/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/cargo-upgrade/package_rust_version/mod.rs b/tests/cargo-upgrade/package_rust_version/mod.rs new file mode 100644 index 0000000000..bea60c0f11 --- /dev/null +++ b/tests/cargo-upgrade/package_rust_version/mod.rs @@ -0,0 +1,36 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::Project; + +use crate::CargoCommand; +use cargo_test_support::curr_dir; + +#[cargo_test] +fn case() { + cargo_test_support::registry::Package::new("my-package", "0.1.1") + .rust_version("1.60.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.1.2") + .rust_version("1.64.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.1.3") + .rust_version("1.68.0") + .publish(); + cargo_test_support::registry::Package::new("my-package", "0.2.0") + .rust_version("1.68.0") + .publish(); + + let project = Project::from_template(curr_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("upgrade") + .args(["--verbose", "--verbose", "--pinned", "--incompatible"]) + .current_dir(cwd) + .assert() + .success() + .stdout_matches_path(curr_dir!().join("stdout.log")) + .stderr_matches_path(curr_dir!().join("stderr.log")); + + assert_ui().subset_matches(curr_dir!().join("out"), &project_root); +} diff --git a/tests/cargo-upgrade/package_rust_version/out/Cargo.toml b/tests/cargo-upgrade/package_rust_version/out/Cargo.toml new file mode 100644 index 0000000000..d2c0cedeb6 --- /dev/null +++ b/tests/cargo-upgrade/package_rust_version/out/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "cargo-list-test-fixture" +version = "0.0.0" +rust-version = "1.64.0" + +[dependencies] +my-package = "0.2.0" diff --git a/tests/cargo-upgrade/package_rust_version/out/src/lib.rs b/tests/cargo-upgrade/package_rust_version/out/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/cargo-upgrade/package_rust_version/stderr.log b/tests/cargo-upgrade/package_rust_version/stderr.log new file mode 100644 index 0000000000..017c781c4b --- /dev/null +++ b/tests/cargo-upgrade/package_rust_version/stderr.log @@ -0,0 +1,3 @@ + Updating '[ROOTURL]/registry' index + Checking cargo-list-test-fixture's dependencies + Upgrading recursive dependencies diff --git a/tests/cargo-upgrade/package_rust_version/stdout.log b/tests/cargo-upgrade/package_rust_version/stdout.log new file mode 100644 index 0000000000..4ce02868d7 --- /dev/null +++ b/tests/cargo-upgrade/package_rust_version/stdout.log @@ -0,0 +1,3 @@ +name old req compatible latest new req +==== ======= ========== ====== ======= +my-package 0.1.1 0.1.3 0.2.0 0.2.0 From 8cf6f14fab6c7d2ec1eb0845bf1c4674271f8cf8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 23 May 2023 17:03:52 -0500 Subject: [PATCH 2/4] feat(upgrade): Respect package.rust-version --- README.md | 18 +-- src/bin/upgrade/upgrade.rs | 41 ++++++- src/fetch.rs | 112 +++++++++++++++++- src/lib.rs | 4 +- tests/cargo-upgrade/cli_rust_version/mod.rs | 8 +- .../cli_rust_version/out/Cargo.toml | 2 +- .../cargo-upgrade/cli_rust_version/stdout.log | 2 +- .../cargo-upgrade/ignore_rust_version/mod.rs | 8 +- .../package_rust_version/out/Cargo.toml | 2 +- .../package_rust_version/stdout.log | 2 +- 10 files changed, 173 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index cd2f449845..d8f1d9fa0a 100644 --- a/README.md +++ b/README.md @@ -121,14 +121,16 @@ Upgrade dependency version requirements in Cargo.toml manifest files Usage: cargo upgrade [OPTIONS] Options: - --dry-run Print changes to be made without making them - --manifest-path Path to the manifest to upgrade - --offline Run without accessing the network - --locked Require `Cargo.toml` to be up to date - -v, --verbose... Use verbose output - -Z Unstable (nightly-only) flags - -h, --help Print help - -V, --version Print version + --dry-run Print changes to be made without making them + --manifest-path Path to the manifest to upgrade + --offline Run without accessing the network + --locked Require `Cargo.toml` to be up to date + -v, --verbose... Use verbose output + --ignore-rust-version Ignore `rust-version` specification in packages + --rust-version Override `rust-version` + -Z Unstable (nightly-only) flags + -h, --help Print help + -V, --version Print version Version: --compatible [] Upgrade to latest compatible version [default: allow] diff --git a/src/bin/upgrade/upgrade.rs b/src/bin/upgrade/upgrade.rs index b2952e13c0..b9dbc4c9d7 100644 --- a/src/bin/upgrade/upgrade.rs +++ b/src/bin/upgrade/upgrade.rs @@ -7,7 +7,7 @@ use anyhow::Context as _; use cargo_edit::{ find, get_compatible_dependency, get_latest_dependency, registry_url, set_dep_version, shell_note, shell_status, shell_warn, shell_write_stdout, update_registry_index, CargoResult, - CrateSpec, Dependency, LocalManifest, Source, + CrateSpec, Dependency, LocalManifest, RustVersion, Source, }; use clap::Args; use indexmap::IndexMap; @@ -38,6 +38,14 @@ pub struct UpgradeArgs { #[arg(short, long, action = clap::ArgAction::Count)] verbose: u8, + /// Ignore `rust-version` specification in packages + #[arg(long)] + ignore_rust_version: bool, + + /// Override `rust-version` + #[arg(long, conflicts_with = "ignore_rust_version")] + rust_version: Option, + /// Unstable (nightly-only) flags #[arg(short = 'Z', value_name = "FLAG", global = true, value_enum)] unstable_features: Vec, @@ -162,12 +170,27 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { let manifests = find_ws_members(&metadata); let mut manifests = manifests .into_iter() - .map(|p| (p.name, p.manifest_path.as_std_path().to_owned())) + .map(|p| { + ( + p.name, + p.manifest_path.as_std_path().to_owned(), + p.rust_version.as_ref().map(RustVersion::from), + ) + }) .collect::>(); - if !manifests.iter().any(|(_, p)| *p == root_manifest_path) { + if !manifests.iter().any(|(_, p, _)| *p == root_manifest_path) { + let workspace_rust_version = manifests + .iter() + .map(|(_, _, msrv)| *msrv) + .min_by_key(|msrv| msrv.unwrap_or(RustVersion::MAX)) + .flatten(); manifests.insert( 0, - ("virtual workspace".to_owned(), root_manifest_path.clone()), + ( + "virtual workspace".to_owned(), + root_manifest_path.clone(), + workspace_rust_version, + ), ); } @@ -187,7 +210,13 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { let mut pinned_present = false; let mut incompatible_present = false; let mut uninteresting_crates = BTreeSet::new(); - for (pkg_name, manifest_path) in &manifests { + for (pkg_name, manifest_path, mut rust_version) in &manifests { + if args.rust_version.is_some() { + rust_version = args.rust_version; + } else if args.ignore_rust_version { + rust_version = None; + } + let mut manifest = LocalManifest::try_new(manifest_path)?; let mut crate_modified = false; let mut table = Vec::new(); @@ -281,6 +310,7 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { get_compatible_dependency( &dependency.name, &old_version_req, + rust_version, manifest_path, registry_url.as_ref(), ) @@ -295,6 +325,7 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { let latest_version = get_latest_dependency( &dependency.name, is_prerelease, + rust_version, manifest_path, registry_url.as_ref(), ) diff --git a/src/fetch.rs b/src/fetch.rs index 9c6e6af731..1cf84a0fa6 100644 --- a/src/fetch.rs +++ b/src/fetch.rs @@ -25,6 +25,7 @@ use super::VersionExt; pub fn get_latest_dependency( crate_name: &str, flag_allow_prerelease: bool, + rust_version: Option, manifest_path: &Path, registry: Option<&Url>, ) -> CargoResult { @@ -70,7 +71,7 @@ pub fn get_latest_dependency( let crate_versions = fuzzy_query_registry_index(crate_name, ®istry)?; - let dep = read_latest_version(&crate_versions, flag_allow_prerelease)?; + let dep = read_latest_version(&crate_versions, flag_allow_prerelease, rust_version)?; if dep.name != crate_name { eprintln!("WARN: Added `{}` instead of `{}`", dep.name, crate_name); @@ -83,6 +84,7 @@ pub fn get_latest_dependency( pub fn get_compatible_dependency( crate_name: &str, version_req: &semver::VersionReq, + rust_version: Option, manifest_path: &Path, registry: Option<&Url>, ) -> CargoResult { @@ -97,7 +99,7 @@ pub fn get_compatible_dependency( let crate_versions = fuzzy_query_registry_index(crate_name, ®istry)?; - let dep = read_compatible_version(&crate_versions, version_req)?; + let dep = read_compatible_version(&crate_versions, version_req, rust_version)?; if dep.name != crate_name { eprintln!("WARN: Added `{}` instead of `{}`", dep.name, crate_name); @@ -106,10 +108,81 @@ pub fn get_compatible_dependency( Ok(dep) } +/// Simplified represetation of `package.rust-version` +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub struct RustVersion { + #[allow(missing_docs)] + pub major: u64, + #[allow(missing_docs)] + pub minor: u64, + #[allow(missing_docs)] + pub patch: u64, +} + +impl RustVersion { + /// Minimum-possible `package.rust-version` + pub const MIN: Self = RustVersion { + major: 1, + minor: 0, + patch: 0, + }; + /// Maximum-possible `package.rust-version` + pub const MAX: Self = RustVersion { + major: u64::MAX, + minor: u64::MAX, + patch: u64::MAX, + }; +} + +impl std::str::FromStr for RustVersion { + type Err = anyhow::Error; + + fn from_str(text: &str) -> Result { + let version_req = text.parse::()?; + anyhow::ensure!( + version_req.comparators.len() == 1, + "rust-version must be a value like `1.32`" + ); + let comp = &version_req.comparators[0]; + anyhow::ensure!( + comp.op == semver::Op::Caret, + "rust-version must be a value like `1.32`" + ); + anyhow::ensure!( + comp.pre == semver::Prerelease::EMPTY, + "rust-version must be a value like `1.32`" + ); + Ok(Self { + major: comp.major, + minor: comp.minor.unwrap_or(0), + patch: comp.patch.unwrap_or(0), + }) + } +} + +impl From<&'_ semver::VersionReq> for RustVersion { + fn from(version_req: &semver::VersionReq) -> Self { + // HACK: `rust-version` is a subset of the `VersionReq` syntax that only ever + // has one comparator with a required minor and optional patch, and uses no + // other features. If in the future this syntax is expanded, this code will need + // to be updated. + assert!(version_req.comparators.len() == 1); + let comp = &version_req.comparators[0]; + assert_eq!(comp.op, semver::Op::Caret); + assert_eq!(comp.pre, semver::Prerelease::EMPTY); + Self { + major: comp.major, + minor: comp.minor.unwrap_or(0), + patch: comp.patch.unwrap_or(0), + } + } +} + #[derive(Debug)] struct CrateVersion { name: String, version: semver::Version, + rust_version: Option, yanked: bool, available_features: BTreeMap>, } @@ -140,6 +213,7 @@ fn fuzzy_query_registry_index( Ok(CrateVersion { name: v.name().to_owned(), version: v.version().parse()?, + rust_version: v.rust_version().map(|r| r.parse()).transpose()?, yanked: v.is_yanked(), available_features: registry_features(v), }) @@ -197,11 +271,20 @@ fn version_is_stable(version: &CrateVersion) -> bool { fn read_latest_version( versions: &[CrateVersion], flag_allow_prerelease: bool, + rust_version: Option, ) -> CargoResult { let latest = versions .iter() .filter(|&v| flag_allow_prerelease || version_is_stable(v)) .filter(|&v| !v.yanked) + .filter(|&v| { + rust_version + .and_then(|rust_version| { + v.rust_version + .map(|v_rust_version| v_rust_version <= rust_version) + }) + .unwrap_or(true) + }) .max_by_key(|&v| v.version.clone()) .ok_or_else(|| { anyhow::format_err!( @@ -221,11 +304,20 @@ fn read_latest_version( fn read_compatible_version( versions: &[CrateVersion], version_req: &semver::VersionReq, + rust_version: Option, ) -> CargoResult { let latest = versions .iter() .filter(|&v| version_req.matches(&v.version)) .filter(|&v| !v.yanked) + .filter(|&v| { + rust_version + .and_then(|rust_version| { + v.rust_version + .map(|v_rust_version| v_rust_version <= rust_version) + }) + .unwrap_or(true) + }) .max_by_key(|&v| v.version.clone()) .ok_or_else(|| { anyhow::format_err!( @@ -318,18 +410,20 @@ fn get_latest_stable_version() { CrateVersion { name: "foo".into(), version: "0.6.0-alpha".parse().unwrap(), + rust_version: None, yanked: false, available_features: BTreeMap::new(), }, CrateVersion { name: "foo".into(), version: "0.5.0".parse().unwrap(), + rust_version: None, yanked: false, available_features: BTreeMap::new(), }, ]; assert_eq!( - read_latest_version(&versions, false) + read_latest_version(&versions, false, None) .unwrap() .version() .unwrap(), @@ -343,18 +437,20 @@ fn get_latest_unstable_or_stable_version() { CrateVersion { name: "foo".into(), version: "0.6.0-alpha".parse().unwrap(), + rust_version: None, yanked: false, available_features: BTreeMap::new(), }, CrateVersion { name: "foo".into(), version: "0.5.0".parse().unwrap(), + rust_version: None, yanked: false, available_features: BTreeMap::new(), }, ]; assert_eq!( - read_latest_version(&versions, true) + read_latest_version(&versions, true, None) .unwrap() .version() .unwrap(), @@ -368,18 +464,20 @@ fn get_latest_version_with_yanked() { CrateVersion { name: "treexml".into(), version: "0.3.1".parse().unwrap(), + rust_version: None, yanked: true, available_features: BTreeMap::new(), }, CrateVersion { name: "true".into(), version: "0.3.0".parse().unwrap(), + rust_version: None, yanked: false, available_features: BTreeMap::new(), }, ]; assert_eq!( - read_latest_version(&versions, false) + read_latest_version(&versions, false, None) .unwrap() .version() .unwrap(), @@ -393,15 +491,17 @@ fn get_no_latest_version_from_json_when_all_are_yanked() { CrateVersion { name: "treexml".into(), version: "0.3.1".parse().unwrap(), + rust_version: None, yanked: true, available_features: BTreeMap::new(), }, CrateVersion { name: "true".into(), version: "0.3.0".parse().unwrap(), + rust_version: None, yanked: true, available_features: BTreeMap::new(), }, ]; - assert!(read_latest_version(&versions, false).is_err()); + assert!(read_latest_version(&versions, false, None).is_err()); } diff --git a/src/lib.rs b/src/lib.rs index 729af0a2c9..805db83ecf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,9 @@ pub use dependency::PathSource; pub use dependency::RegistrySource; pub use dependency::Source; pub use errors::*; -pub use fetch::{get_compatible_dependency, get_latest_dependency, update_registry_index}; +pub use fetch::{ + get_compatible_dependency, get_latest_dependency, update_registry_index, RustVersion, +}; pub use manifest::{find, get_dep_version, set_dep_version, LocalManifest, Manifest}; pub use metadata::manifest_from_pkgid; pub use registry::registry_url; diff --git a/tests/cargo-upgrade/cli_rust_version/mod.rs b/tests/cargo-upgrade/cli_rust_version/mod.rs index b2eef52864..81dd4f42c7 100644 --- a/tests/cargo-upgrade/cli_rust_version/mod.rs +++ b/tests/cargo-upgrade/cli_rust_version/mod.rs @@ -28,7 +28,13 @@ fn case() { snapbox::cmd::Command::cargo_ui() .arg("upgrade") - .args(["--verbose", "--verbose", "--pinned", "--incompatible"]) + .args([ + "--verbose", + "--verbose", + "--pinned", + "--incompatible", + "--rust-version=1.70.0", + ]) .current_dir(cwd) .assert() .success() diff --git a/tests/cargo-upgrade/cli_rust_version/out/Cargo.toml b/tests/cargo-upgrade/cli_rust_version/out/Cargo.toml index f881fc42c8..d2c0cedeb6 100644 --- a/tests/cargo-upgrade/cli_rust_version/out/Cargo.toml +++ b/tests/cargo-upgrade/cli_rust_version/out/Cargo.toml @@ -4,4 +4,4 @@ version = "0.0.0" rust-version = "1.64.0" [dependencies] -my-package = "0.3.0" +my-package = "0.2.0" diff --git a/tests/cargo-upgrade/cli_rust_version/stdout.log b/tests/cargo-upgrade/cli_rust_version/stdout.log index f2cea5748f..4ce02868d7 100644 --- a/tests/cargo-upgrade/cli_rust_version/stdout.log +++ b/tests/cargo-upgrade/cli_rust_version/stdout.log @@ -1,3 +1,3 @@ name old req compatible latest new req ==== ======= ========== ====== ======= -my-package 0.1.1 0.1.3 0.3.0 0.3.0 +my-package 0.1.1 0.1.3 0.2.0 0.2.0 diff --git a/tests/cargo-upgrade/ignore_rust_version/mod.rs b/tests/cargo-upgrade/ignore_rust_version/mod.rs index bea60c0f11..f88bd553b8 100644 --- a/tests/cargo-upgrade/ignore_rust_version/mod.rs +++ b/tests/cargo-upgrade/ignore_rust_version/mod.rs @@ -25,7 +25,13 @@ fn case() { snapbox::cmd::Command::cargo_ui() .arg("upgrade") - .args(["--verbose", "--verbose", "--pinned", "--incompatible"]) + .args([ + "--verbose", + "--verbose", + "--pinned", + "--incompatible", + "--ignore-rust-version", + ]) .current_dir(cwd) .assert() .success() diff --git a/tests/cargo-upgrade/package_rust_version/out/Cargo.toml b/tests/cargo-upgrade/package_rust_version/out/Cargo.toml index d2c0cedeb6..8bbbabc51e 100644 --- a/tests/cargo-upgrade/package_rust_version/out/Cargo.toml +++ b/tests/cargo-upgrade/package_rust_version/out/Cargo.toml @@ -4,4 +4,4 @@ version = "0.0.0" rust-version = "1.64.0" [dependencies] -my-package = "0.2.0" +my-package = "0.1.2" diff --git a/tests/cargo-upgrade/package_rust_version/stdout.log b/tests/cargo-upgrade/package_rust_version/stdout.log index 4ce02868d7..622ed9e9c6 100644 --- a/tests/cargo-upgrade/package_rust_version/stdout.log +++ b/tests/cargo-upgrade/package_rust_version/stdout.log @@ -1,3 +1,3 @@ name old req compatible latest new req ==== ======= ========== ====== ======= -my-package 0.1.1 0.1.3 0.2.0 0.2.0 +my-package 0.1.1 0.1.2 0.1.2 0.1.2 From 20d129f1411a32b8cb1fe4c630d9d3f52dd00a05 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 24 May 2023 16:48:21 -0500 Subject: [PATCH 3/4] refactor(upgrade): Consolidate rust-version overrides --- src/bin/upgrade/upgrade.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/bin/upgrade/upgrade.rs b/src/bin/upgrade/upgrade.rs index b9dbc4c9d7..21eddae2d8 100644 --- a/src/bin/upgrade/upgrade.rs +++ b/src/bin/upgrade/upgrade.rs @@ -171,10 +171,18 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { let mut manifests = manifests .into_iter() .map(|p| { + let rust_version = if args.rust_version.is_some() { + args.rust_version + } else if args.ignore_rust_version { + None + } else { + p.rust_version.as_ref().map(RustVersion::from) + }; + ( p.name, p.manifest_path.as_std_path().to_owned(), - p.rust_version.as_ref().map(RustVersion::from), + rust_version, ) }) .collect::>(); @@ -210,14 +218,8 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { let mut pinned_present = false; let mut incompatible_present = false; let mut uninteresting_crates = BTreeSet::new(); - for (pkg_name, manifest_path, mut rust_version) in &manifests { - if args.rust_version.is_some() { - rust_version = args.rust_version; - } else if args.ignore_rust_version { - rust_version = None; - } - - let mut manifest = LocalManifest::try_new(manifest_path)?; + for (pkg_name, manifest_path, rust_version) in manifests { + let mut manifest = LocalManifest::try_new(&manifest_path)?; let mut crate_modified = false; let mut table = Vec::new(); shell_status("Checking", &format!("{pkg_name}'s dependencies"))?; @@ -226,7 +228,7 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { let mut reason = None; let dep_key = dep_key.get(); - let dependency = match Dependency::from_toml(manifest_path, dep_key, dep_item) { + let dependency = match Dependency::from_toml(&manifest_path, dep_key, dep_item) { Ok(dependency) => dependency, Err(err) => { shell_warn(&format!("ignoring {dep_key}, unsupported entry: {err}"))?; @@ -295,7 +297,7 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { // we're offline. let registry_url = dependency .registry() - .map(|registry| registry_url(manifest_path, Some(registry))) + .map(|registry| registry_url(&manifest_path, Some(registry))) .transpose()?; if !args.offline { if let Some(registry_url) = ®istry_url { @@ -311,7 +313,7 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { &dependency.name, &old_version_req, rust_version, - manifest_path, + &manifest_path, registry_url.as_ref(), ) .ok() @@ -326,7 +328,7 @@ fn exec(args: UpgradeArgs) -> CargoResult<()> { &dependency.name, is_prerelease, rust_version, - manifest_path, + &manifest_path, registry_url.as_ref(), ) .map(|d| { From 389b977274d9878a9726556707e9b6a84bc62ed9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 24 May 2023 16:49:14 -0500 Subject: [PATCH 4/4] refactor: Remove dead CARGO_IS_TEST code --- src/fetch.rs | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/fetch.rs b/src/fetch.rs index 1cf84a0fa6..9b42bb4069 100644 --- a/src/fetch.rs +++ b/src/fetch.rs @@ -1,5 +1,4 @@ use std::collections::BTreeMap; -use std::env; use std::path::Path; use std::time::Duration; @@ -29,37 +28,6 @@ pub fn get_latest_dependency( manifest_path: &Path, registry: Option<&Url>, ) -> CargoResult { - if env::var("CARGO_IS_TEST").is_ok() { - // We are in a simulated reality. Nothing is real here. - // FIXME: Use actual test handling code. - let new_version = if flag_allow_prerelease { - format!("99999.0.0-alpha.1+{crate_name}") - } else { - match crate_name { - "test_breaking" => "0.2.0".to_string(), - "test_nonbreaking" => "0.1.1".to_string(), - other => format!("99999.0.0+{other}"), - } - }; - - let features = if crate_name == "your-face" { - [ - ("nose".to_string(), vec![]), - ("mouth".to_string(), vec![]), - ("eyes".to_string(), vec![]), - ("ears".to_string(), vec![]), - ] - .into_iter() - .collect::>() - } else { - BTreeMap::default() - }; - - return Ok(Dependency::new(crate_name) - .set_source(RegistrySource::new(new_version)) - .set_available_features(features)); - } - if crate_name.is_empty() { anyhow::bail!("Found empty crate name"); }