@@ -64,9 +64,14 @@ use crate::core::resolver::{
6464 self , HasDevUnits , Resolve , ResolveOpts , ResolveVersion , VersionOrdering , VersionPreferences ,
6565} ;
6666use 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 ;
7075use crate :: ops;
7176use crate :: sources:: PathSource ;
7277use crate :: util:: cache_lock:: CacheLockMode ;
@@ -76,6 +81,9 @@ use anyhow::Context as _;
7681use std:: collections:: { HashMap , HashSet } ;
7782use tracing:: { debug, trace} ;
7883
84+ /// Filter for keep using Package ID from previous lockfile.
85+ type Keep < ' a > = & ' a dyn Fn ( & PackageId ) -> bool ;
86+
7987/// Result for `resolve_ws_with_opts`.
8088pub struct WorkspaceResolve < ' gctx > {
8189 /// Packages to be downloaded.
@@ -312,7 +320,7 @@ pub fn resolve_with_previous<'gctx>(
312320 cli_features : & CliFeatures ,
313321 has_dev_units : HasDevUnits ,
314322 previous : Option < & Resolve > ,
315- keep_previous : Option < & dyn Fn ( & PackageId ) -> bool > ,
323+ keep_previous : Option < Keep < ' _ > > ,
316324 specs : & [ PackageIdSpec ] ,
317325 register_patches : bool ,
318326) -> CargoResult < Resolve > {
@@ -322,6 +330,16 @@ pub fn resolve_with_previous<'gctx>(
322330 . gctx ( )
323331 . acquire_package_cache_lock ( CacheLockMode :: DownloadExclusive ) ?;
324332
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+
325343 // Try to keep all from previous resolve if no instruction given.
326344 let keep_previous = keep_previous. unwrap_or ( & |_| true ) ;
327345
@@ -372,16 +390,6 @@ pub fn resolve_with_previous<'gctx>(
372390 registry. lock_patches ( ) ;
373391 }
374392
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-
385393 let summaries: Vec < ( Summary , ResolveOpts ) > = ws
386394 . members_with_features ( specs, cli_features) ?
387395 . into_iter ( )
@@ -397,26 +405,8 @@ pub fn resolve_with_previous<'gctx>(
397405 } )
398406 . collect ( ) ;
399407
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) ;
418409
419- ws. preload ( registry) ;
420410 let mut resolved = resolver:: resolve (
421411 & summaries,
422412 & replace,
@@ -425,12 +415,9 @@ pub fn resolve_with_previous<'gctx>(
425415 ResolveVersion :: with_rust_version ( ws. rust_version ( ) ) ,
426416 Some ( ws. gctx ( ) ) ,
427417 ) ?;
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) ;
434421
435422 if register_patches && !resolved. unused_patches ( ) . is_empty ( ) {
436423 emit_warnings_of_unused_patches ( ws, & resolved, registry) ?;
@@ -508,7 +495,7 @@ fn register_previous_locks(
508495 ws : & Workspace < ' _ > ,
509496 registry : & mut PackageRegistry < ' _ > ,
510497 resolve : & Resolve ,
511- keep : & dyn Fn ( & PackageId ) -> bool ,
498+ keep : Keep < ' _ > ,
512499 dev_deps : bool ,
513500) {
514501 let path_pkg = |id : SourceId | {
@@ -805,7 +792,7 @@ fn register_patch_entries(
805792 ws : & Workspace < ' _ > ,
806793 previous : Option < & Resolve > ,
807794 version_prefs : & mut VersionPreferences ,
808- keep_previous : & dyn Fn ( & PackageId ) -> bool ,
795+ keep_previous : Keep < ' _ > ,
809796) -> CargoResult < HashSet < PackageId > > {
810797 let mut avoid_patch_ids = HashSet :: new ( ) ;
811798 for ( url, patches) in ws. root_patch ( ) ?. iter ( ) {
@@ -910,3 +897,30 @@ fn register_patch_entries(
910897
911898 Ok ( avoid_patch_ids)
912899}
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