From 8181bc827484334a6ecbba6d2a9f82ba30a2a9ee Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 19:24:26 -0500 Subject: [PATCH 01/10] refactor(toml): Delay project warnings until Edition is parsed --- src/cargo/util/toml/mod.rs | 41 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 9cf3bc9e957..890801f1fa3 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -935,26 +935,9 @@ fn to_real_manifest( ); }; - let original_package = match (&original_toml.package, &original_toml.project) { - (Some(_), Some(project)) => { - warnings.push(format!( - "manifest at `{}` contains both `project` and `package`, \ - this could become a hard error in the future", - package_root.display() - )); - project.clone() - } - (Some(package), None) => package.clone(), - (None, Some(project)) => { - warnings.push(format!( - "manifest at `{}` contains `[project]` instead of `[package]`, \ - this could become a hard error in the future", - package_root.display() - )); - project.clone() - } - (None, None) => bail!("no `package` section found"), - }; + let original_package = original_toml + .package() + .ok_or_else(|| anyhow::format_err!("no `package` section found"))?; let package_name = &original_package.name; if package_name.contains(':') { @@ -1044,6 +1027,24 @@ fn to_real_manifest( ))); } + match (&original_toml.package, &original_toml.project) { + (Some(_), Some(_)) => { + warnings.push(format!( + "manifest at `{}` contains both `project` and `package`, \ + this could become a hard error in the future", + package_root.display() + )); + } + (None, Some(_)) => { + warnings.push(format!( + "manifest at `{}` contains `[project]` instead of `[package]`, \ + this could become a hard error in the future", + package_root.display() + )); + } + (Some(_), None) | (None, None) => {} + } + if resolved_package.metabuild.is_some() { features.require(Feature::metabuild())?; } From 77f96f5c6111661da87b48c58b321f0b7d7bf8c3 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 19:29:32 -0500 Subject: [PATCH 02/10] fix(toml): Simplify [project] warning --- src/cargo/util/toml/mod.rs | 18 ++---------------- tests/testsuite/check.rs | 4 ++-- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 890801f1fa3..3a091c2e0d1 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1027,22 +1027,8 @@ fn to_real_manifest( ))); } - match (&original_toml.package, &original_toml.project) { - (Some(_), Some(_)) => { - warnings.push(format!( - "manifest at `{}` contains both `project` and `package`, \ - this could become a hard error in the future", - package_root.display() - )); - } - (None, Some(_)) => { - warnings.push(format!( - "manifest at `{}` contains `[project]` instead of `[package]`, \ - this could become a hard error in the future", - package_root.display() - )); - } - (Some(_), None) | (None, None) => {} + if original_toml.project.is_some() { + warnings.push(format!("`[project]` is deprecated in favor of `[package]`")); } if resolved_package.metabuild.is_some() { diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index de6a324acd3..3fdc84fdf8c 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -1002,7 +1002,7 @@ fn warn_manifest_package_and_project() { p.cargo("check") .with_stderr( "\ -[WARNING] manifest at `[CWD]` contains both `project` and `package`, this could become a hard error in the future +[WARNING] `[project]` is deprecated in favor of `[package]` [CHECKING] foo v0.0.1 ([CWD]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] ", @@ -1083,7 +1083,7 @@ fn warn_manifest_with_project() { p.cargo("check") .with_stderr( "\ -[WARNING] manifest at `[CWD]` contains `[project]` instead of `[package]`, this could become a hard error in the future +[WARNING] `[project]` is deprecated in favor of `[package]` [CHECKING] foo v0.0.1 ([CWD]) [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] ", From c9325c9bd9dc315daa35519ef44e73c2c9a1fe02 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 19:31:47 -0500 Subject: [PATCH 03/10] refactor(toml): Move project tests next to each other --- tests/testsuite/check.rs | 52 ++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index 3fdc84fdf8c..8f79187f8d9 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -979,6 +979,32 @@ fn rustc_workspace_wrapper_excludes_published_deps() { .run(); } +#[cargo_test] +fn warn_manifest_with_project() { + let p = project() + .file( + "Cargo.toml", + r#" + [project] + name = "foo" + version = "0.0.1" + edition = "2015" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .with_stderr( + "\ +[WARNING] `[project]` is deprecated in favor of `[package]` +[CHECKING] foo v0.0.1 ([CWD]) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] +", + ) + .run(); +} + #[cargo_test] fn warn_manifest_package_and_project() { let p = project() @@ -1065,32 +1091,6 @@ fn git_manifest_package_and_project() { .run(); } -#[cargo_test] -fn warn_manifest_with_project() { - let p = project() - .file( - "Cargo.toml", - r#" - [project] - name = "foo" - version = "0.0.1" - edition = "2015" - "#, - ) - .file("src/main.rs", "fn main() {}") - .build(); - - p.cargo("check") - .with_stderr( - "\ -[WARNING] `[project]` is deprecated in favor of `[package]` -[CHECKING] foo v0.0.1 ([CWD]) -[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..] -", - ) - .run(); -} - #[cargo_test] fn git_manifest_with_project() { let p = project(); From 2f4d3df54d66ea55a3b12f7ce173c993272ae5aa Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 19:37:07 -0500 Subject: [PATCH 04/10] fix(toml): Error on use of [project] on 2024 Edition --- src/cargo/util/toml/mod.rs | 8 +++++++- tests/testsuite/check.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 3a091c2e0d1..020b08d2ac5 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1028,7 +1028,13 @@ fn to_real_manifest( } if original_toml.project.is_some() { - warnings.push(format!("`[project]` is deprecated in favor of `[package]`")); + if Edition::Edition2024 <= edition { + anyhow::bail!( + "`[project]` is not supported as of the 2024 Edition, please use `[package]`" + ); + } else { + warnings.push(format!("`[project]` is deprecated in favor of `[package]`")); + } } if resolved_package.metabuild.is_some() { diff --git a/tests/testsuite/check.rs b/tests/testsuite/check.rs index 8f79187f8d9..da8239fd748 100644 --- a/tests/testsuite/check.rs +++ b/tests/testsuite/check.rs @@ -1005,6 +1005,37 @@ fn warn_manifest_with_project() { .run(); } +#[cargo_test(nightly, reason = "edition2024")] +fn error_manifest_with_project_on_2024() { + let p = project() + .file( + "Cargo.toml", + r#" + cargo-features = ["edition2024"] + + [project] + name = "foo" + version = "0.0.1" + edition = "2024" + "#, + ) + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("check") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_status(101) + .with_stderr( + "\ +[ERROR] failed to parse manifest at `[CWD]/Cargo.toml` + +Caused by: + `[project]` is not supported as of the 2024 Edition, please use `[package]` +", + ) + .run(); +} + #[cargo_test] fn warn_manifest_package_and_project() { let p = project() From 9fb428bd0548e076e485aa166efb8d33a7fc9de2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 20:45:57 -0500 Subject: [PATCH 05/10] refactor(fix): Move workspace loading closer to use --- src/bin/cargo/commands/fix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/cargo/commands/fix.rs b/src/bin/cargo/commands/fix.rs index 30d07cf1944..74c341c7341 100644 --- a/src/bin/cargo/commands/fix.rs +++ b/src/bin/cargo/commands/fix.rs @@ -60,7 +60,6 @@ pub fn cli() -> Command { } pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { - let ws = args.workspace(gctx)?; // This is a legacy behavior that causes `cargo fix` to pass `--test`. let test = matches!( args.get_one::("profile").map(String::as_str), @@ -70,6 +69,7 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { // Unlike other commands default `cargo fix` to all targets to fix as much // code as we can. + let ws = args.workspace(gctx)?; let mut opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?; if !opts.filter.is_specific() { From ca699d264af16f520b66ae664c920e653c709a68 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 20:47:24 -0500 Subject: [PATCH 06/10] refactor(fix): Flatten workspace loading This misses out on features that shouldn't be relevant to fix, like avoid-dev-deps. However, this prepares the way for workspace re-loading. --- src/bin/cargo/commands/fix.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bin/cargo/commands/fix.rs b/src/bin/cargo/commands/fix.rs index 74c341c7341..f9651e7fe2e 100644 --- a/src/bin/cargo/commands/fix.rs +++ b/src/bin/cargo/commands/fix.rs @@ -1,5 +1,6 @@ use crate::command_prelude::*; +use cargo::core::Workspace; use cargo::ops; pub fn cli() -> Command { @@ -69,7 +70,8 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { // Unlike other commands default `cargo fix` to all targets to fix as much // code as we can. - let ws = args.workspace(gctx)?; + let root_manifest = args.root_manifest(gctx)?; + let ws = Workspace::new(&root_manifest, gctx)?; let mut opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?; if !opts.filter.is_specific() { From 1ec14557471172774b8ec460f14098c738b11585 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 20:49:53 -0500 Subject: [PATCH 07/10] refactor(fix): Reload the workspace This opens the door for fixing the workspace --- src/bin/cargo/commands/fix.rs | 5 ++++- src/cargo/core/workspace.rs | 4 ++++ src/cargo/ops/fix.rs | 18 +++++++++++++----- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/bin/cargo/commands/fix.rs b/src/bin/cargo/commands/fix.rs index f9651e7fe2e..8a901de8ae5 100644 --- a/src/bin/cargo/commands/fix.rs +++ b/src/bin/cargo/commands/fix.rs @@ -71,7 +71,8 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { // Unlike other commands default `cargo fix` to all targets to fix as much // code as we can. let root_manifest = args.root_manifest(gctx)?; - let ws = Workspace::new(&root_manifest, gctx)?; + let mut ws = Workspace::new(&root_manifest, gctx)?; + ws.set_honor_rust_version(args.honor_rust_version()); let mut opts = args.compile_options(gctx, mode, Some(&ws), ProfileChecking::LegacyTestOnly)?; if !opts.filter.is_specific() { @@ -80,7 +81,9 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult { } ops::fix( + gctx, &ws, + &root_manifest, &mut ops::FixOptions { edition: args.flag("edition"), idioms: args.flag("edition-idioms"), diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 7b92d2e3706..8a0596cb5fd 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -611,6 +611,10 @@ impl<'gctx> Workspace<'gctx> { self.honor_rust_version = honor_rust_version; } + pub fn honor_rust_version(&self) -> Option { + self.honor_rust_version + } + pub fn resolve_honors_rust_version(&self) -> bool { self.gctx().cli_unstable().msrv_policy && self.honor_rust_version.unwrap_or(true) } diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 6c34abc37cf..4fb9551c53c 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -87,11 +87,19 @@ pub struct FixOptions { pub broken_code: bool, } -pub fn fix(ws: &Workspace<'_>, opts: &mut FixOptions) -> CargoResult<()> { - check_version_control(ws.gctx(), opts)?; +pub fn fix( + gctx: &GlobalContext, + original_ws: &Workspace<'_>, + root_manifest: &Path, + opts: &mut FixOptions, +) -> CargoResult<()> { + check_version_control(gctx, opts)?; + if opts.edition { - check_resolver_change(ws, opts)?; + check_resolver_change(&original_ws, opts)?; } + let mut ws = Workspace::new(&root_manifest, gctx)?; + ws.set_honor_rust_version(original_ws.honor_rust_version()); // Spin up our lock server, which our subprocesses will use to synchronize fixes. let lock_server = LockServer::new()?; @@ -128,7 +136,7 @@ pub fn fix(ws: &Workspace<'_>, opts: &mut FixOptions) -> CargoResult<()> { server.configure(&mut wrapper); } - let rustc = ws.gctx().load_global_rustc(Some(ws))?; + let rustc = ws.gctx().load_global_rustc(Some(&ws))?; wrapper.arg(&rustc.path); // This is calling rustc in cargo fix-proxy-mode, so it also need to retry. // The argfile handling are located at `FixArgs::from_args`. @@ -138,7 +146,7 @@ pub fn fix(ws: &Workspace<'_>, opts: &mut FixOptions) -> CargoResult<()> { // repeating build until there are no more changes to be applied opts.compile_opts.build_config.primary_unit_rustc = Some(wrapper); - ops::compile(ws, &opts.compile_opts)?; + ops::compile(&ws, &opts.compile_opts)?; Ok(()) } From d5606b2278cbb040f7d05632cc7056d7892762c0 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 21:00:28 -0500 Subject: [PATCH 08/10] test(fix): Show current project/package behavior --- tests/testsuite/fix.rs | 104 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index a20ded1965b..007125e76f9 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -1942,3 +1942,107 @@ fn fix_only_once_for_duplicates() { 1 from newly-applied unsafe blocks" ); } + +#[cargo_test] +fn migrate_project_to_package() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["edition2024"] + +# Before project +[ project ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table +"#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_stderr( + "\ +[WARNING] `[project]` is deprecated in favor of `[package]` +[CHECKING] foo v0.0.0 ([CWD]) +[MIGRATING] src/lib.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s +", + ) + .run(); + assert_eq!( + p.read_file("Cargo.toml"), + r#" +cargo-features = ["edition2024"] + +# Before project +[ project ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table +"# + ); +} + +#[cargo_test] +fn migrate_removes_project() { + let p = project() + .file( + "Cargo.toml", + r#" +cargo-features = ["edition2024"] + +# Before package +[ package ] # After package header +# After package header line +name = "foo" +edition = "2021" +# After package table + +# Before project +[ project ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table +"#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fix --edition --allow-no-vcs") + .masquerade_as_nightly_cargo(&["edition2024"]) + .with_stderr( + "\ +[WARNING] `[project]` is deprecated in favor of `[package]` +[CHECKING] foo v0.0.0 ([CWD]) +[MIGRATING] src/lib.rs from 2021 edition to 2024 +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s +", + ) + .run(); + assert_eq!( + p.read_file("Cargo.toml"), + r#" +cargo-features = ["edition2024"] + +# Before package +[ package ] # After package header +# After package header line +name = "foo" +edition = "2021" +# After package table + +# Before project +[ project ] # After project header +# After project header line +name = "foo" +edition = "2021" +# After project table +"# + ); +} From 98298d49666e5ce444add13cc212fa36357209ab Mon Sep 17 00:00:00 2001 From: Ed Page Date: Fri, 12 Apr 2024 09:37:26 -0500 Subject: [PATCH 09/10] feat(fix): Report manifest migrations --- src/cargo/ops/fix.rs | 31 ++++++++++++++++++++++++++++++- tests/testsuite/fix.rs | 14 ++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index 4fb9551c53c..dc4223f31b9 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -53,7 +53,8 @@ use tracing::{debug, trace, warn}; use crate::core::compiler::RustcTargetData; use crate::core::resolver::features::{DiffMap, FeatureOpts, FeatureResolver, FeaturesFor}; use crate::core::resolver::{HasDevUnits, Resolve, ResolveBehavior}; -use crate::core::{Edition, MaybePackage, PackageId, Workspace}; +use crate::core::PackageIdSpecQuery as _; +use crate::core::{Edition, MaybePackage, Package, PackageId, Workspace}; use crate::ops::resolve::WorkspaceResolve; use crate::ops::{self, CompileOptions}; use crate::util::diagnostic_server::{Message, RustfixDiagnosticServer}; @@ -96,6 +97,13 @@ pub fn fix( check_version_control(gctx, opts)?; if opts.edition { + let specs = opts.compile_opts.spec.to_package_id_specs(&original_ws)?; + let members: Vec<&Package> = original_ws + .members() + .filter(|m| specs.iter().any(|spec| spec.matches(m.package_id()))) + .collect(); + migrate_manifests(original_ws, &members)?; + check_resolver_change(&original_ws, opts)?; } let mut ws = Workspace::new(&root_manifest, gctx)?; @@ -223,6 +231,27 @@ fn check_version_control(gctx: &GlobalContext, opts: &FixOptions) -> CargoResult ); } +fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> { + for pkg in pkgs { + let existing_edition = pkg.manifest().edition(); + let prepare_for_edition = existing_edition.saturating_next(); + if existing_edition == prepare_for_edition + || (!prepare_for_edition.is_stable() && !ws.gctx().nightly_features_allowed) + { + continue; + } + let file = pkg.manifest_path(); + let file = file.strip_prefix(ws.root()).unwrap_or(file); + let file = file.display(); + ws.gctx().shell().status( + "Migrating", + format!("{file} from {existing_edition} edition to {prepare_for_edition}"), + )?; + } + + Ok(()) +} + fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<()> { let root = ws.root_maybe(); match root { diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index 007125e76f9..916f1d1519c 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -172,6 +172,7 @@ fn prepare_for_2018() { .build(); let stderr = "\ +[MIGRATING] Cargo.toml from 2015 edition to 2018 [CHECKING] foo v0.0.1 ([..]) [MIGRATING] src/lib.rs from 2015 edition to 2018 [FIXED] src/lib.rs (2 fixes) @@ -211,6 +212,7 @@ fn local_paths() { p.cargo("fix --edition --allow-no-vcs") .with_stderr( "\ +[MIGRATING] Cargo.toml from 2015 edition to 2018 [CHECKING] foo v0.0.1 ([..]) [MIGRATING] src/lib.rs from 2015 edition to 2018 [FIXED] src/lib.rs (1 fix) @@ -298,6 +300,7 @@ fn specify_rustflags() { .env("RUSTFLAGS", "-C linker=cc") .with_stderr( "\ +[MIGRATING] Cargo.toml from 2015 edition to 2018 [CHECKING] foo v0.0.1 ([..]) [MIGRATING] src/lib.rs from 2015 edition to 2018 [FIXED] src/lib.rs (1 fix) @@ -770,6 +773,7 @@ https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-proje .masquerade_as_nightly_cargo(&["always_nightly"]) .with_stderr(&format!( "\ +[MIGRATING] Cargo.toml from {latest_stable} edition to {next} [CHECKING] foo [..] [MIGRATING] src/lib.rs from {latest_stable} edition to {next} [FINISHED] [..] @@ -804,11 +808,11 @@ fn prepare_for_latest_stable() { p.cargo("fix --edition --allow-no-vcs") .with_stderr(&format!( "\ +[MIGRATING] Cargo.toml from {previous} edition to {latest_stable} [CHECKING] foo [..] -[MIGRATING] src/lib.rs from {} edition to {} +[MIGRATING] src/lib.rs from {previous} edition to {latest_stable} [FINISHED] [..] ", - previous, latest_stable )) .run(); } @@ -911,6 +915,7 @@ fn fix_overlapping() { p.cargo("fix --allow-no-vcs --edition --lib") .with_stderr( "\ +[MIGRATING] Cargo.toml from 2015 edition to 2018 [CHECKING] foo [..] [MIGRATING] src/lib.rs from 2015 edition to 2018 [FIXED] src/lib.rs (2 fixes) @@ -1202,6 +1207,7 @@ fn only_warn_for_relevant_crates() { p.cargo("fix --allow-no-vcs --edition") .with_stderr( "\ +[MIGRATING] Cargo.toml from 2015 edition to 2018 [LOCKING] 2 packages to latest compatible versions [CHECKING] a v0.1.0 ([..]) [CHECKING] foo v0.1.0 ([..]) @@ -1398,6 +1404,7 @@ fn edition_v2_resolver_report() { p.cargo("fix --edition --allow-no-vcs") .with_stderr_unordered("\ +[MIGRATING] Cargo.toml from 2018 edition to 2021 [UPDATING] [..] [LOCKING] 4 packages to latest compatible versions [DOWNLOADING] crates ... @@ -1477,6 +1484,7 @@ fn fix_edition_2021() { p.cargo("fix --edition --allow-no-vcs") .with_stderr( "\ +[MIGRATING] Cargo.toml from 2018 edition to 2021 [CHECKING] foo v0.1.0 [..] [MIGRATING] src/lib.rs from 2018 edition to 2021 [FIXED] src/lib.rs (1 fix) @@ -1966,6 +1974,7 @@ edition = "2021" .masquerade_as_nightly_cargo(&["edition2024"]) .with_stderr( "\ +[MIGRATING] Cargo.toml from 2021 edition to 2024 [WARNING] `[project]` is deprecated in favor of `[package]` [CHECKING] foo v0.0.0 ([CWD]) [MIGRATING] src/lib.rs from 2021 edition to 2024 @@ -2018,6 +2027,7 @@ edition = "2021" .masquerade_as_nightly_cargo(&["edition2024"]) .with_stderr( "\ +[MIGRATING] Cargo.toml from 2021 edition to 2024 [WARNING] `[project]` is deprecated in favor of `[package]` [CHECKING] foo v0.0.0 ([CWD]) [MIGRATING] src/lib.rs from 2021 edition to 2024 From cbd9def9dc4cb70f500b538d2d6d9b29fbd46f1c Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 11 Apr 2024 21:35:06 -0500 Subject: [PATCH 10/10] feat(fix): Migrate from project to package on Edition 2024 --- src/cargo/ops/fix.rs | 35 +++++++++++++++++++++++++++++++++++ tests/testsuite/fix.rs | 13 +++---------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/cargo/ops/fix.rs b/src/cargo/ops/fix.rs index dc4223f31b9..aaf731b4e85 100644 --- a/src/cargo/ops/fix.rs +++ b/src/cargo/ops/fix.rs @@ -247,11 +247,46 @@ fn migrate_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> { "Migrating", format!("{file} from {existing_edition} edition to {prepare_for_edition}"), )?; + + if Edition::Edition2024 <= prepare_for_edition { + let mut document = pkg.manifest().document().clone().into_mut(); + let mut fixes = 0; + + let root = document.as_table_mut(); + if rename_table(root, "project", "package") { + fixes += 1; + } + + if 0 < fixes { + let verb = if fixes == 1 { "fix" } else { "fixes" }; + let msg = format!("{file} ({fixes} {verb})"); + ws.gctx().shell().status("Fixed", msg)?; + + let s = document.to_string(); + let new_contents_bytes = s.as_bytes(); + cargo_util::paths::write_atomic(pkg.manifest_path(), new_contents_bytes)?; + } + } } Ok(()) } +fn rename_table(parent: &mut dyn toml_edit::TableLike, old: &str, new: &str) -> bool { + let Some(old_key) = parent.key(old).cloned() else { + return false; + }; + + let project = parent.remove(old).expect("returned early"); + if !parent.contains_key(new) { + parent.insert(new, project); + let mut new_key = parent.key_mut(new).expect("just inserted"); + *new_key.dotted_decor_mut() = old_key.dotted_decor().clone(); + *new_key.leaf_decor_mut() = old_key.leaf_decor().clone(); + } + true +} + fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<()> { let root = ws.root_maybe(); match root { diff --git a/tests/testsuite/fix.rs b/tests/testsuite/fix.rs index 916f1d1519c..485511ab764 100644 --- a/tests/testsuite/fix.rs +++ b/tests/testsuite/fix.rs @@ -1975,7 +1975,7 @@ edition = "2021" .with_stderr( "\ [MIGRATING] Cargo.toml from 2021 edition to 2024 -[WARNING] `[project]` is deprecated in favor of `[package]` +[FIXED] Cargo.toml (1 fix) [CHECKING] foo v0.0.0 ([CWD]) [MIGRATING] src/lib.rs from 2021 edition to 2024 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s @@ -1988,7 +1988,7 @@ edition = "2021" cargo-features = ["edition2024"] # Before project -[ project ] # After project header +[ package ] # After project header # After project header line name = "foo" edition = "2021" @@ -2028,7 +2028,7 @@ edition = "2021" .with_stderr( "\ [MIGRATING] Cargo.toml from 2021 edition to 2024 -[WARNING] `[project]` is deprecated in favor of `[package]` +[FIXED] Cargo.toml (1 fix) [CHECKING] foo v0.0.0 ([CWD]) [MIGRATING] src/lib.rs from 2021 edition to 2024 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [..]s @@ -2045,13 +2045,6 @@ cargo-features = ["edition2024"] # After package header line name = "foo" edition = "2021" -# After package table - -# Before project -[ project ] # After project header -# After project header line -name = "foo" -edition = "2021" # After project table "# );