|
1 | 1 | use std::borrow::Borrow;
|
| 2 | +use std::cmp; |
2 | 3 | use std::collections::{HashMap, HashSet};
|
3 | 4 | use std::fmt;
|
4 | 5 | use std::iter::FromIterator;
|
@@ -58,9 +59,12 @@ pub struct Resolve {
|
58 | 59 | ///
|
59 | 60 | /// It's theorized that we can add more here over time to track larger changes
|
60 | 61 | /// 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)] |
62 | 63 | pub enum ResolveVersion {
|
| 64 | + // Historical baseline for when this abstraction was added. |
63 | 65 | V1,
|
| 66 | + // Update around 2019 where `dependencies` arrays got compressed and |
| 67 | + // checksums are listed inline. |
64 | 68 | V2,
|
65 | 69 | }
|
66 | 70 |
|
@@ -209,21 +213,35 @@ unable to verify that `{0}` is the same as when the lockfile was generated
|
209 | 213 | // Be sure to just copy over any unknown metadata.
|
210 | 214 | self.metadata = previous.metadata.clone();
|
211 | 215 |
|
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. |
217 | 220 | //
|
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 | + ); |
227 | 245 |
|
228 | 246 | Ok(())
|
229 | 247 | }
|
@@ -389,23 +407,26 @@ impl fmt::Debug for Resolve {
|
389 | 407 | }
|
390 | 408 |
|
391 | 409 | impl ResolveVersion {
|
392 |
| - /// The default way to encode `Cargo.lock`. |
| 410 | + /// The default way to encode new `Cargo.lock` files. |
393 | 411 | ///
|
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 { |
398 | 417 | ResolveVersion::V2
|
399 | 418 | }
|
400 | 419 |
|
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. |
402 | 423 | ///
|
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 |
410 | 431 | }
|
411 | 432 | }
|
0 commit comments