diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 524a01725da..619d1273c50 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -741,6 +741,7 @@ unstable_cli_options!( minimal_versions: bool = ("Resolve minimal dependency versions instead of maximum"), msrv_policy: bool = ("Enable rust-version aware policy within cargo"), mtime_on_use: bool = ("Configure Cargo to update the mtime of used files"), + next_lockfile_bump: bool = (HIDDEN), 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"), profile_rustflags: bool = ("Enable the `rustflags` option in profiles in .cargo/config.toml file"), @@ -1110,6 +1111,7 @@ impl CliUnstable { "host-config" => self.host_config = parse_empty(k, v)?, "jobserver-per-rustc" => self.jobserver_per_rustc = parse_empty(k, v)?, "lints" => self.lints = parse_empty(k, v)?, + "next-lockfile-bump" => self.next_lockfile_bump = parse_empty(k, v)?, "minimal-versions" => self.minimal_versions = parse_empty(k, v)?, "msrv-policy" => self.msrv_policy = parse_empty(k, v)?, // can also be set in .cargo/config or with and ENV diff --git a/src/cargo/core/resolver/encode.rs b/src/cargo/core/resolver/encode.rs index 88d0d82961d..98794253acb 100644 --- a/src/cargo/core/resolver/encode.rs +++ b/src/cargo/core/resolver/encode.rs @@ -154,10 +154,18 @@ impl EncodableResolve { /// primary uses is to be used with `resolve_with_previous` to guide the /// resolver to create a complete Resolve. pub fn into_resolve(self, original: &str, ws: &Workspace<'_>) -> CargoResult { + let unstable_lockfile_version_allowed = ws.config().cli_unstable().next_lockfile_bump; let path_deps = build_path_deps(ws)?; let mut checksums = HashMap::new(); let mut version = match self.version { + Some(4) => { + if unstable_lockfile_version_allowed { + ResolveVersion::V4 + } else { + anyhow::bail!("lock file version 4 requires `-Znext-lockfile-bump`",) + } + } Some(3) => ResolveVersion::V3, Some(n) => bail!( "lock file version `{}` was found, but this version of Cargo \ @@ -612,6 +620,7 @@ impl ser::Serialize for Resolve { metadata, patch, version: match self.version() { + ResolveVersion::V4 => Some(4), ResolveVersion::V3 => Some(3), ResolveVersion::V2 | ResolveVersion::V1 => None, }, diff --git a/src/cargo/core/resolver/resolve.rs b/src/cargo/core/resolver/resolve.rs index 6ab957e924f..8405a12450b 100644 --- a/src/cargo/core/resolver/resolve.rs +++ b/src/cargo/core/resolver/resolve.rs @@ -80,6 +80,10 @@ pub enum ResolveVersion { /// V3 by default staring in 1.53. #[default] V3, + /// Unstable. Will collect a certain amount of changes and then go. + /// + /// Changes made: + V4, } impl Resolve { diff --git a/src/cargo/ops/lockfile.rs b/src/cargo/ops/lockfile.rs index e11e492af30..ece0701426a 100644 --- a/src/cargo/ops/lockfile.rs +++ b/src/cargo/ops/lockfile.rs @@ -69,6 +69,14 @@ pub fn write_pkg_lockfile(ws: &Workspace<'_>, resolve: &mut Resolve) -> CargoRes if resolve.version() < ResolveVersion::default() { resolve.set_version(ResolveVersion::default()); out = serialize_resolve(resolve, orig.as_deref()); + } else if resolve.version() > ResolveVersion::default() + && !ws.config().cli_unstable().next_lockfile_bump + { + // The next version hasn't yet stabilized. + anyhow::bail!( + "lock file version `{:?}` requires `-Znext-lockfile-bump`", + resolve.version() + ) } // Ok, if that didn't work just write it out diff --git a/tests/testsuite/lockfile_compat.rs b/tests/testsuite/lockfile_compat.rs index aad8723c3b6..d7107754a18 100644 --- a/tests/testsuite/lockfile_compat.rs +++ b/tests/testsuite/lockfile_compat.rs @@ -888,3 +888,66 @@ perhaps a crate was updated and forgotten to be re-vendored? ) .run(); } + +#[cargo_test] +fn v4_is_unstable() { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + "#, + ), + ) + .file("src/lib.rs", "") + .file("Cargo.lock", "version = 4") + .build(); + + p.cargo("fetch") + .with_status(101) + .with_stderr( + "\ +error: failed to parse lock file at: [CWD]/Cargo.lock + +Caused by: + lock file version 4 requires `-Znext-lockfile-bump` +", + ) + .run(); +} + +#[cargo_test] +fn v4_cannot_be_created_from_scratch() { + let p = project() + .file( + "Cargo.toml", + &format!( + r#" + [package] + name = "foo" + version = "0.0.1" + "#, + ), + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("fetch -Znext-lockfile-bump") + .masquerade_as_nightly_cargo(&["-Znext-lockfile-bump"]) + .run(); + + let lockfile = r#"# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "foo" +version = "0.0.1" +"#; + + let lock = p.read_lockfile(); + assert_match_exact(lockfile, &lock); +}