Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 51 additions & 5 deletions src/cargo/ops/fix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,18 @@ pub fn fix(

let mut target_data =
RustcTargetData::new(original_ws, &opts.compile_opts.build_config.requested_kinds)?;

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();
if let Some(edition_mode) = 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, edition_mode)?;

check_resolver_change(&original_ws, &mut target_data, opts)?;
}
fix_manifests(original_ws, &members)?;
let ws = original_ws.reload(gctx)?;

// Spin up our lock server, which our subprocesses will use to synchronize fixes.
Expand Down Expand Up @@ -290,6 +292,50 @@ fn check_version_control(gctx: &GlobalContext, opts: &FixOptions) -> CargoResult
);
}

fn fix_manifests(ws: &Workspace<'_>, pkgs: &[&Package]) -> CargoResult<()> {
for pkg in pkgs {
if !pkg.manifest().is_embedded()
|| pkg
.manifest()
.original_toml()
.and_then(|m| m.package())
.map(|pkg| pkg.edition.is_some())
.unwrap_or(false)
{
continue;
}
let file = pkg.manifest_path();
let file = file.strip_prefix(ws.root()).unwrap_or(file);
let file = file.display();

let mut manifest_mut = LocalManifest::try_new(pkg.manifest_path())?;
let document = &mut manifest_mut.data;
let mut fixes = 0;

let root = document.as_table_mut();

fixes += 1;
root.entry("package").or_insert_with(|| {
let mut t = toml_edit::Table::new();
t.set_position(Some(-1));
t.into()
});
root["package"]["edition"] = crate::core::features::Edition::LATEST_STABLE
.to_string()
.into();

if 0 < fixes {
let verb = if fixes == 1 { "fix" } else { "fixes" };
let msg = format!("{file} ({fixes} {verb})");
ws.gctx().shell().status("Fixed", msg)?;

manifest_mut.write()?;
}
}

Ok(())
}

fn migrate_manifests(
ws: &Workspace<'_>,
pkgs: &[&Package],
Expand Down
183 changes: 183 additions & 0 deletions tests/testsuite/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3066,3 +3066,186 @@ edition = "future"
"#]],
);
}

#[cargo_test(nightly, reason = "-Zscript is unstable")]
fn script_without_frontmatter() {
let p = cargo_test_support::project()
.file("echo.rs", "fn main() {}")
.build();

p.cargo("fix -Zscript --allow-no-vcs --manifest-path echo.rs")
.masquerade_as_nightly_cargo(&["script"])
.with_stdout_data(str![""])
.with_stderr_data(str![[r#"
[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)
[FIXED] echo.rs (1 fix)
[CHECKING] echo v0.0.0 ([ROOT]/foo/echo.rs)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();

assert_e2e().eq(
p.read_file("echo.rs"),
str![[r#"
---
[package]
edition = "2024"
---

fn main() {}
"#]],
);
}

#[cargo_test(nightly, reason = "-Zscript is unstable")]
fn script_with_frontmatter() {
let p = cargo_test_support::project()
.file(
"echo.rs",
"#!/usr/bin/env cargo
---
[dependencies]
---
fn main() {}",
)
.build();

p.cargo("fix -Zscript --allow-no-vcs --manifest-path echo.rs")
.masquerade_as_nightly_cargo(&["script"])
.with_stdout_data(str![""])
.with_stderr_data(str![[r#"
[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)
[FIXED] echo.rs (1 fix)
[CHECKING] echo v0.0.0 ([ROOT]/foo/echo.rs)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();

assert_e2e().eq(
p.read_file("echo.rs"),
str![[r##"
#!/usr/bin/env cargo
---
[package]
edition = "2024"
[dependencies]
---
fn main() {}
"##]],
);
}

#[cargo_test(nightly, reason = "-Zscript is unstable")]
fn script_with_package_table() {
let p = cargo_test_support::project()
.file(
"echo.rs",
r#"#!/usr/bin/env cargo
---
[package]
name = "foo"
---
fn main() {}"#,
)
.build();

p.cargo("fix -Zscript --allow-no-vcs --manifest-path echo.rs")
.masquerade_as_nightly_cargo(&["script"])
.with_stdout_data(str![""])
.with_stderr_data(str![[r#"
[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)
[FIXED] echo.rs (1 fix)
[CHECKING] foo v0.0.0 ([ROOT]/foo/echo.rs)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();

assert_e2e().eq(
p.read_file("echo.rs"),
str![[r##"
#!/usr/bin/env cargo
---
[package]
name = "foo"
edition = "2024"
---
fn main() {}
"##]],
);
}

#[cargo_test(nightly, reason = "-Zscript is unstable")]
fn script_with_package_dotted() {
let p = cargo_test_support::project()
.file(
"echo.rs",
r#"#!/usr/bin/env cargo
---
package.name = "foo"
---
fn main() {}"#,
)
.build();

p.cargo("fix -Zscript --allow-no-vcs --manifest-path echo.rs")
.masquerade_as_nightly_cargo(&["script"])
.with_stdout_data(str![""])
.with_stderr_data(str![[r#"
[WARNING] `package.edition` is unspecified, defaulting to the latest edition (currently `[..]`)
[FIXED] echo.rs (1 fix)
[CHECKING] foo v0.0.0 ([ROOT]/foo/echo.rs)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();

assert_e2e().eq(
p.read_file("echo.rs"),
str![[r##"
#!/usr/bin/env cargo
---
package.name = "foo"
package.edition = "2024"
---
fn main() {}
"##]],
);
}

#[cargo_test(nightly, reason = "-Zscript is unstable")]
fn script_with_edition() {
let p = cargo_test_support::project()
.file(
"echo.rs",
r#"#!/usr/bin/env cargo
---
package.edition = "2015"
---
fn main() {}"#,
)
.build();

p.cargo("fix -Zscript --allow-no-vcs --manifest-path echo.rs")
.masquerade_as_nightly_cargo(&["script"])
.with_stdout_data(str![""])
.with_stderr_data(str![[r#"
[CHECKING] echo v0.0.0 ([ROOT]/foo/echo.rs)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s

"#]])
.run();

assert_e2e().eq(
p.read_file("echo.rs"),
str![[r##"
#!/usr/bin/env cargo
---
package.edition = "2015"
---
fn main() {}
"##]],
);
}