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 ;
@@ -15,7 +16,6 @@ use super::encode::Metadata;
15
16
///
16
17
/// Each instance of `Resolve` also understands the full set of features used
17
18
/// for each package.
18
- #[ derive( PartialEq ) ]
19
19
pub struct Resolve {
20
20
/// A graph, whose vertices are packages and edges are dependency specifications
21
21
/// from `Cargo.toml`. We need a `Vec` here because the same package
@@ -59,9 +59,12 @@ pub struct Resolve {
59
59
///
60
60
/// It's theorized that we can add more here over time to track larger changes
61
61
/// to the `Cargo.lock` format, but we've yet to see how that strategy pans out.
62
- #[ derive( PartialEq , Clone , Debug ) ]
62
+ #[ derive( PartialEq , Eq , Clone , Copy , Debug , PartialOrd , Ord ) ]
63
63
pub enum ResolveVersion {
64
+ // Historical baseline for when this abstraction was added.
64
65
V1 ,
66
+ // Update around 2019 where `dependencies` arrays got compressed and
67
+ // checksums are listed inline.
65
68
V2 ,
66
69
}
67
70
@@ -210,21 +213,35 @@ unable to verify that `{0}` is the same as when the lockfile was generated
210
213
// Be sure to just copy over any unknown metadata.
211
214
self . metadata = previous. metadata . clone ( ) ;
212
215
213
- // The goal of Cargo is largely to preserve the encoding of
214
- // `Cargo.lock` that it finds on the filesystem. Sometimes `Cargo.lock`
215
- // changes are in the works where they haven't been set as the default
216
- // yet but will become the default soon. We want to preserve those
217
- // 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.
218
220
//
219
- // For this reason if the previous `Cargo.lock` is from the future, or
220
- // otherwise it looks like it's produced with future features we
221
- // understand, then the new resolve will be encoded with the same
222
- // version. Note that new instances of `Resolve` always use the default
223
- // encoding, and this is where we switch it to a future encoding if the
224
- // future encoding isn't yet the default.
225
- if previous. version . from_the_future ( ) {
226
- self . version = previous. version . clone ( ) ;
227
- }
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
+ ) ;
228
245
229
246
Ok ( ( ) )
230
247
}
@@ -358,6 +375,26 @@ unable to verify that `{0}` is the same as when the lockfile was generated
358
375
}
359
376
}
360
377
378
+ impl PartialEq for Resolve {
379
+ fn eq ( & self , other : & Resolve ) -> bool {
380
+ macro_rules! compare {
381
+ ( $( $fields: ident) * | $( $ignored: ident) * ) => {
382
+ let Resolve { $( $fields, ) * $( $ignored, ) * } = self ;
383
+ $( drop( $ignored) ; ) *
384
+ $( $fields == & other. $fields) &&*
385
+ }
386
+ }
387
+ compare ! {
388
+ // fields to compare
389
+ graph replacements reverse_replacements empty_features features
390
+ checksums metadata unused_patches public_dependencies
391
+ |
392
+ // fields to ignore
393
+ version
394
+ }
395
+ }
396
+ }
397
+
361
398
impl fmt:: Debug for Resolve {
362
399
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
363
400
writeln ! ( fmt, "graph: {:?}" , self . graph) ?;
@@ -370,23 +407,26 @@ impl fmt::Debug for Resolve {
370
407
}
371
408
372
409
impl ResolveVersion {
373
- /// The default way to encode `Cargo.lock`.
410
+ /// The default way to encode new `Cargo.lock` files .
374
411
///
375
- /// This is used for new `Cargo.lock` files that are generated without a
376
- /// previous `Cargo.lock` files, and generally matches with what we want to
377
- /// encode.
378
- pub fn default ( ) -> ResolveVersion {
379
- ResolveVersion :: V1
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 {
417
+ ResolveVersion :: V2
380
418
}
381
419
382
- /// 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.
383
423
///
384
- /// This means that this encoding version is not currently the default but
385
- /// intended to become the default "soon".
386
- pub fn from_the_future ( & self ) -> bool {
387
- match self {
388
- ResolveVersion :: V2 => true ,
389
- ResolveVersion :: V1 => false ,
390
- }
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
391
431
}
392
432
}
0 commit comments