Skip to content

Commit 013c1af

Browse files
committed
Add support for new lockfile formats on new projects
This commit adds support to Cargo and refactors the lockfile versioning slightly. The goal here is that Cargo continually has two thresholds of lockfile formats to create: * One is used for new lock files at all times * The other is used to update old lock files The logic for these two thresholds is appropriately updated throughout Cargo, and then this commit also preserves the previous update where new lock files will get the new format, but old lockfiles will continue to retain the old format by default.
1 parent 366ae3f commit 013c1af

File tree

4 files changed

+59
-34
lines changed

4 files changed

+59
-34
lines changed

src/cargo/core/resolver/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ pub fn resolve(
151151
cksums,
152152
BTreeMap::new(),
153153
Vec::new(),
154-
ResolveVersion::default(),
154+
ResolveVersion::default_for_new_lockfiles(),
155155
);
156156

157157
check_cycles(&resolve)?;

src/cargo/core/resolver/resolve.rs

+49-28
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::borrow::Borrow;
2+
use std::cmp;
23
use std::collections::{HashMap, HashSet};
34
use std::fmt;
45
use std::iter::FromIterator;
@@ -58,9 +59,12 @@ pub struct Resolve {
5859
///
5960
/// It's theorized that we can add more here over time to track larger changes
6061
/// to the `Cargo.lock` format, but we've yet to see how that strategy pans out.
61-
#[derive(PartialEq, Clone, Debug)]
62+
#[derive(PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)]
6263
pub enum ResolveVersion {
64+
// Historical baseline for when this abstraction was added.
6365
V1,
66+
// Update around 2019 where `dependencies` arrays got compressed and
67+
// checksums are listed inline.
6468
V2,
6569
}
6670

@@ -209,21 +213,35 @@ unable to verify that `{0}` is the same as when the lockfile was generated
209213
// Be sure to just copy over any unknown metadata.
210214
self.metadata = previous.metadata.clone();
211215

212-
// The goal of Cargo is largely to preserve the encoding of
213-
// `Cargo.lock` that it finds on the filesystem. Sometimes `Cargo.lock`
214-
// changes are in the works where they haven't been set as the default
215-
// yet but will become the default soon. We want to preserve those
216-
// features if we find them.
216+
// The goal of Cargo is largely to preserve the encoding of `Cargo.lock`
217+
// that it finds on the filesystem. Sometimes `Cargo.lock` changes are
218+
// in the works where they haven't been set as the default yet but will
219+
// become the default soon.
217220
//
218-
// For this reason if the previous `Cargo.lock` is from the future, or
219-
// otherwise it looks like it's produced with future features we
220-
// understand, then the new resolve will be encoded with the same
221-
// version. Note that new instances of `Resolve` always use the default
222-
// encoding, and this is where we switch it to a future encoding if the
223-
// future encoding isn't yet the default.
224-
if previous.version.from_the_future() {
225-
self.version = previous.version.clone();
226-
}
221+
// The scenarios we could be in are:
222+
//
223+
// * This is a brand new lock file with nothing previous. In that case
224+
// this method isn't actually called at all, but instead
225+
// `default_for_new_lockfiles` called below was encoded during the
226+
// resolution step, so that's what we're gonna use.
227+
//
228+
// * We have an old lock file. In this case we want to switch the
229+
// version to `default_for_old_lockfiles`. That puts us in one of
230+
// three cases:
231+
//
232+
// * Our version is older than the default. This means that we're
233+
// migrating someone forward, so we switch the encoding.
234+
// * Our version is equal to the default, nothing to do!
235+
// * Our version is *newer* than the default. This is where we
236+
// critically keep the new version of encoding.
237+
//
238+
// This strategy should get new lockfiles into the pipeline more quickly
239+
// while ensuring that any time an old cargo sees a future lock file it
240+
// keeps the future lockfile encoding.
241+
self.version = cmp::max(
242+
previous.version,
243+
ResolveVersion::default_for_old_lockfiles(),
244+
);
227245

228246
Ok(())
229247
}
@@ -389,23 +407,26 @@ impl fmt::Debug for Resolve {
389407
}
390408

391409
impl ResolveVersion {
392-
/// The default way to encode `Cargo.lock`.
410+
/// The default way to encode new `Cargo.lock` files.
393411
///
394-
/// This is used for new `Cargo.lock` files that are generated without a
395-
/// previous `Cargo.lock` files, and generally matches with what we want to
396-
/// encode.
397-
pub fn default() -> ResolveVersion {
412+
/// It's important that if a new version of `ResolveVersion` is added that
413+
/// this is not updated until *at least* the support for the version is in
414+
/// the stable release of Rust. It's ok for this to be newer than
415+
/// `default_for_old_lockfiles` below.
416+
pub fn default_for_new_lockfiles() -> ResolveVersion {
398417
ResolveVersion::V2
399418
}
400419

401-
/// Returns whether this encoding version is "from the future".
420+
/// The default way to encode old preexisting `Cargo.lock` files. This is
421+
/// often trailing the new lockfiles one above to give older projects a
422+
/// longer time to catch up.
402423
///
403-
/// This means that this encoding version is not currently the default but
404-
/// intended to become the default "soon".
405-
pub fn from_the_future(&self) -> bool {
406-
match self {
407-
ResolveVersion::V2 => false,
408-
ResolveVersion::V1 => false,
409-
}
424+
/// It's important that this trails behind `default_for_new_lockfiles` for
425+
/// quite some time. This gives projects a quite large window to update in
426+
/// where we don't force updates, so if projects span many versions of Cargo
427+
/// all those versions of Cargo will have support for a new version of the
428+
/// lock file.
429+
pub fn default_for_old_lockfiles() -> ResolveVersion {
430+
ResolveVersion::V1
410431
}
411432
}

tests/testsuite/lockfile_compat.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ fn oldest_lockfile_still_works_with_command(cargo_command: &str) {
2727
name = "bar"
2828
version = "0.1.0"
2929
source = "registry+https://github.com/rust-lang/crates.io-index"
30-
checksum = "[..]"
3130
3231
[[package]]
3332
name = "foo"
3433
version = "0.0.1"
3534
dependencies = [
36-
"bar",
35+
"bar [..]",
3736
]
37+
38+
[metadata]
39+
"[..]" = "[..]"
3840
"#;
3941

4042
let old_lockfile = r#"
@@ -171,14 +173,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
171173
name = "bar"
172174
version = "0.1.0"
173175
source = "registry+https://github.com/rust-lang/crates.io-index"
174-
checksum = "[..]"
175176
176177
[[package]]
177178
name = "foo"
178179
version = "0.0.1"
179180
dependencies = [
180-
"bar",
181+
"bar [..]",
181182
]
183+
184+
[metadata]
185+
"[..]" = "[..]"
182186
"#,
183187
&lock,
184188
);

tests/testsuite/update.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ fn preserve_top_comment() {
572572
let mut lines = lockfile.lines().collect::<Vec<_>>();
573573
lines.insert(2, "# some other comment");
574574
let mut lockfile = lines.join("\n");
575-
lockfile.push_str("\n"); // .lines/.join loses the last newline
575+
lockfile.push_str("\n\n"); // .lines/.join loses the last newline
576576
println!("saving Cargo.lock contents:\n{}", lockfile);
577577

578578
p.change_file("Cargo.lock", &lockfile);

0 commit comments

Comments
 (0)