@@ -64,9 +64,14 @@ use crate::core::resolver::{
64
64
self , HasDevUnits , Resolve , ResolveOpts , ResolveVersion , VersionOrdering , VersionPreferences ,
65
65
} ;
66
66
use crate :: core:: summary:: Summary ;
67
- use crate :: core:: {
68
- GitReference , PackageId , PackageIdSpec , PackageIdSpecQuery , PackageSet , SourceId , Workspace ,
69
- } ;
67
+ use crate :: core:: Dependency ;
68
+ use crate :: core:: GitReference ;
69
+ use crate :: core:: PackageId ;
70
+ use crate :: core:: PackageIdSpec ;
71
+ use crate :: core:: PackageIdSpecQuery ;
72
+ use crate :: core:: PackageSet ;
73
+ use crate :: core:: SourceId ;
74
+ use crate :: core:: Workspace ;
70
75
use crate :: ops;
71
76
use crate :: sources:: PathSource ;
72
77
use crate :: util:: cache_lock:: CacheLockMode ;
@@ -76,6 +81,9 @@ use anyhow::Context as _;
76
81
use std:: collections:: { HashMap , HashSet } ;
77
82
use tracing:: { debug, trace} ;
78
83
84
+ /// Filter for keep using Package ID from previous lockfile.
85
+ type Keep < ' a > = & ' a dyn Fn ( & PackageId ) -> bool ;
86
+
79
87
/// Result for `resolve_ws_with_opts`.
80
88
pub struct WorkspaceResolve < ' gctx > {
81
89
/// Packages to be downloaded.
@@ -312,7 +320,7 @@ pub fn resolve_with_previous<'gctx>(
312
320
cli_features : & CliFeatures ,
313
321
has_dev_units : HasDevUnits ,
314
322
previous : Option < & Resolve > ,
315
- keep_previous : Option < & dyn Fn ( & PackageId ) -> bool > ,
323
+ keep_previous : Option < Keep < ' _ > > ,
316
324
specs : & [ PackageIdSpec ] ,
317
325
register_patches : bool ,
318
326
) -> CargoResult < Resolve > {
@@ -322,6 +330,16 @@ pub fn resolve_with_previous<'gctx>(
322
330
. gctx ( )
323
331
. acquire_package_cache_lock ( CacheLockMode :: DownloadExclusive ) ?;
324
332
333
+ // Some packages are already loaded when setting up a workspace. This
334
+ // makes it so anything that was already loaded will not be loaded again.
335
+ // Without this there were cases where members would be parsed multiple times
336
+ ws. preload ( registry) ;
337
+
338
+ // In case any members were not already loaded or the Workspace is_ephemeral.
339
+ for member in ws. members ( ) {
340
+ registry. add_sources ( Some ( member. package_id ( ) . source_id ( ) ) ) ?;
341
+ }
342
+
325
343
// Try to keep all from previous resolve if no instruction given.
326
344
let keep_previous = keep_previous. unwrap_or ( & |_| true ) ;
327
345
@@ -372,16 +390,6 @@ pub fn resolve_with_previous<'gctx>(
372
390
registry. lock_patches ( ) ;
373
391
}
374
392
375
- // Some packages are already loaded when setting up a workspace. This
376
- // makes it so anything that was already loaded will not be loaded again.
377
- // Without this there were cases where members would be parsed multiple times
378
- ws. preload ( registry) ;
379
-
380
- // In case any members were not already loaded or the Workspace is_ephemeral.
381
- for member in ws. members ( ) {
382
- registry. add_sources ( Some ( member. package_id ( ) . source_id ( ) ) ) ?;
383
- }
384
-
385
393
let summaries: Vec < ( Summary , ResolveOpts ) > = ws
386
394
. members_with_features ( specs, cli_features) ?
387
395
. into_iter ( )
@@ -397,26 +405,8 @@ pub fn resolve_with_previous<'gctx>(
397
405
} )
398
406
. collect ( ) ;
399
407
400
- let root_replace = ws. root_replace ( ) ;
401
-
402
- let replace = match previous {
403
- Some ( r) => root_replace
404
- . iter ( )
405
- . map ( |( spec, dep) | {
406
- for ( & key, & val) in r. replacements ( ) . iter ( ) {
407
- if spec. matches ( key) && dep. matches_id ( val) && keep ( & val) {
408
- let mut dep = dep. clone ( ) ;
409
- dep. lock_to ( val) ;
410
- return ( spec. clone ( ) , dep) ;
411
- }
412
- }
413
- ( spec. clone ( ) , dep. clone ( ) )
414
- } )
415
- . collect :: < Vec < _ > > ( ) ,
416
- None => root_replace. to_vec ( ) ,
417
- } ;
408
+ let replace = lock_replacements ( ws, previous, & keep) ;
418
409
419
- ws. preload ( registry) ;
420
410
let mut resolved = resolver:: resolve (
421
411
& summaries,
422
412
& replace,
@@ -425,12 +415,9 @@ pub fn resolve_with_previous<'gctx>(
425
415
ResolveVersion :: with_rust_version ( ws. rust_version ( ) ) ,
426
416
Some ( ws. gctx ( ) ) ,
427
417
) ?;
428
- let patches: Vec < _ > = registry
429
- . patches ( )
430
- . values ( )
431
- . flat_map ( |v| v. iter ( ) . cloned ( ) )
432
- . collect ( ) ;
433
- resolved. register_used_patches ( & patches[ ..] ) ;
418
+
419
+ let patches = registry. patches ( ) . values ( ) . flat_map ( |v| v. iter ( ) ) ;
420
+ resolved. register_used_patches ( patches) ;
434
421
435
422
if register_patches && !resolved. unused_patches ( ) . is_empty ( ) {
436
423
emit_warnings_of_unused_patches ( ws, & resolved, registry) ?;
@@ -508,7 +495,7 @@ fn register_previous_locks(
508
495
ws : & Workspace < ' _ > ,
509
496
registry : & mut PackageRegistry < ' _ > ,
510
497
resolve : & Resolve ,
511
- keep : & dyn Fn ( & PackageId ) -> bool ,
498
+ keep : Keep < ' _ > ,
512
499
dev_deps : bool ,
513
500
) {
514
501
let path_pkg = |id : SourceId | {
@@ -805,7 +792,7 @@ fn register_patch_entries(
805
792
ws : & Workspace < ' _ > ,
806
793
previous : Option < & Resolve > ,
807
794
version_prefs : & mut VersionPreferences ,
808
- keep_previous : & dyn Fn ( & PackageId ) -> bool ,
795
+ keep_previous : Keep < ' _ > ,
809
796
) -> CargoResult < HashSet < PackageId > > {
810
797
let mut avoid_patch_ids = HashSet :: new ( ) ;
811
798
for ( url, patches) in ws. root_patch ( ) ?. iter ( ) {
@@ -910,3 +897,30 @@ fn register_patch_entries(
910
897
911
898
Ok ( avoid_patch_ids)
912
899
}
900
+
901
+ /// Locks each `[replace]` entry to a specific Package ID
902
+ /// if the lockfile contains any correspoding previous replacement.
903
+ fn lock_replacements (
904
+ ws : & Workspace < ' _ > ,
905
+ previous : Option < & Resolve > ,
906
+ keep : Keep < ' _ > ,
907
+ ) -> Vec < ( PackageIdSpec , Dependency ) > {
908
+ let root_replace = ws. root_replace ( ) ;
909
+ let replace = match previous {
910
+ Some ( r) => root_replace
911
+ . iter ( )
912
+ . map ( |( spec, dep) | {
913
+ for ( & key, & val) in r. replacements ( ) . iter ( ) {
914
+ if spec. matches ( key) && dep. matches_id ( val) && keep ( & val) {
915
+ let mut dep = dep. clone ( ) ;
916
+ dep. lock_to ( val) ;
917
+ return ( spec. clone ( ) , dep) ;
918
+ }
919
+ }
920
+ ( spec. clone ( ) , dep. clone ( ) )
921
+ } )
922
+ . collect :: < Vec < _ > > ( ) ,
923
+ None => root_replace. to_vec ( ) ,
924
+ } ;
925
+ replace
926
+ }
0 commit comments