@@ -202,7 +202,11 @@ impl EncodableResolve {
202202 if !all_pkgs. insert ( enc_id. clone ( ) ) {
203203 anyhow:: bail!( "package `{}` is specified twice in the lockfile" , pkg. name) ;
204204 }
205- let id = match pkg. source . as_deref ( ) . or_else ( || path_deps. get ( & pkg. name ) ) {
205+ let id = match pkg
206+ . source
207+ . as_deref ( )
208+ . or_else ( || get_source_id ( & path_deps, pkg) )
209+ {
206210 // We failed to find a local package in the workspace.
207211 // It must have been removed and should be ignored.
208212 None => {
@@ -364,7 +368,11 @@ impl EncodableResolve {
364368
365369 let mut unused_patches = Vec :: new ( ) ;
366370 for pkg in self . patch . unused {
367- let id = match pkg. source . as_deref ( ) . or_else ( || path_deps. get ( & pkg. name ) ) {
371+ let id = match pkg
372+ . source
373+ . as_deref ( )
374+ . or_else ( || get_source_id ( & path_deps, & pkg) )
375+ {
368376 Some ( & src) => PackageId :: try_new ( & pkg. name , & pkg. version , src) ?,
369377 None => continue ,
370378 } ;
@@ -395,7 +403,7 @@ impl EncodableResolve {
395403 version = ResolveVersion :: V2 ;
396404 }
397405
398- Ok ( Resolve :: new (
406+ return Ok ( Resolve :: new (
399407 g,
400408 replacements,
401409 HashMap :: new ( ) ,
@@ -404,11 +412,42 @@ impl EncodableResolve {
404412 unused_patches,
405413 version,
406414 HashMap :: new ( ) ,
407- ) )
415+ ) ) ;
416+
417+ fn get_source_id < ' a > (
418+ path_deps : & ' a HashMap < String , HashMap < semver:: Version , SourceId > > ,
419+ pkg : & ' a EncodableDependency ,
420+ ) -> Option < & ' a SourceId > {
421+ {
422+ if let Some ( source_id) = path_deps. iter ( ) . find_map ( |( name, version_source) | {
423+ // First look for cases where the version and name are the same
424+ if name == & pkg. name {
425+ if let Ok ( pkg_version) = pkg. version . parse :: < semver:: Version > ( ) {
426+ if let Some ( source_id) = version_source. get ( & pkg_version) {
427+ return Some ( source_id) ;
428+ }
429+ }
430+ }
431+ None
432+ } ) {
433+ Some ( source_id)
434+ } else {
435+ // Next look for cases where the name is the same
436+ path_deps. iter ( ) . find_map ( |( name, version_source) | {
437+ if name == & pkg. name {
438+ return version_source. values ( ) . next ( ) ;
439+ }
440+ None
441+ } )
442+ }
443+ }
444+ }
408445 }
409446}
410447
411- fn build_path_deps ( ws : & Workspace < ' _ > ) -> CargoResult < HashMap < String , SourceId > > {
448+ fn build_path_deps (
449+ ws : & Workspace < ' _ > ,
450+ ) -> CargoResult < HashMap < String , HashMap < semver:: Version , SourceId > > > {
412451 // If a crate is **not** a path source, then we're probably in a situation
413452 // such as `cargo install` with a lock file from a remote dependency. In
414453 // that case we don't need to fixup any path dependencies (as they're not
@@ -418,13 +457,15 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
418457 . filter ( |p| p. package_id ( ) . source_id ( ) . is_path ( ) )
419458 . collect :: < Vec < _ > > ( ) ;
420459
421- let mut ret = HashMap :: new ( ) ;
460+ let mut ret: HashMap < String , HashMap < semver :: Version , SourceId > > = HashMap :: new ( ) ;
422461 let mut visited = HashSet :: new ( ) ;
423462 for member in members. iter ( ) {
424- ret. insert (
425- member. package_id ( ) . name ( ) . to_string ( ) ,
426- member. package_id ( ) . source_id ( ) ,
427- ) ;
463+ ret. entry ( member. package_id ( ) . name ( ) . to_string ( ) )
464+ . or_insert_with ( HashMap :: new)
465+ . insert (
466+ member. package_id ( ) . version ( ) . clone ( ) ,
467+ member. package_id ( ) . source_id ( ) ,
468+ ) ;
428469 visited. insert ( member. package_id ( ) . source_id ( ) ) ;
429470 }
430471 for member in members. iter ( ) {
@@ -444,7 +485,7 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
444485 fn build_pkg (
445486 pkg : & Package ,
446487 ws : & Workspace < ' _ > ,
447- ret : & mut HashMap < String , SourceId > ,
488+ ret : & mut HashMap < String , HashMap < semver :: Version , SourceId > > ,
448489 visited : & mut HashSet < SourceId > ,
449490 ) {
450491 for dep in pkg. dependencies ( ) {
@@ -455,7 +496,7 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
455496 fn build_dep (
456497 dep : & Dependency ,
457498 ws : & Workspace < ' _ > ,
458- ret : & mut HashMap < String , SourceId > ,
499+ ret : & mut HashMap < String , HashMap < semver :: Version , SourceId > > ,
459500 visited : & mut HashSet < SourceId > ,
460501 ) {
461502 let id = dep. source_id ( ) ;
@@ -467,7 +508,14 @@ fn build_path_deps(ws: &Workspace<'_>) -> CargoResult<HashMap<String, SourceId>>
467508 Err ( _) => return ,
468509 } ;
469510 let Ok ( pkg) = ws. load ( & path) else { return } ;
470- ret. insert ( pkg. name ( ) . to_string ( ) , pkg. package_id ( ) . source_id ( ) ) ;
511+ visited. insert ( pkg. package_id ( ) . source_id ( ) ) ;
512+ build_pkg ( & pkg, ws, ret, visited) ;
513+ ret. entry ( pkg. package_id ( ) . name ( ) . to_string ( ) )
514+ . or_insert_with ( HashMap :: new)
515+ . insert (
516+ pkg. package_id ( ) . version ( ) . clone ( ) ,
517+ pkg. package_id ( ) . source_id ( ) ,
518+ ) ;
471519 visited. insert ( pkg. package_id ( ) . source_id ( ) ) ;
472520 build_pkg ( & pkg, ws, ret, visited) ;
473521 }
0 commit comments