@@ -226,7 +226,7 @@ pub struct RecursivePathSource<'gctx> {
226
226
/// Whether this source has loaded all package information it may contain.
227
227
loaded : bool ,
228
228
/// Packages that this sources has discovered.
229
- packages : HashMap < PackageId , Package > ,
229
+ packages : HashMap < PackageId , Vec < Package > > ,
230
230
gctx : & ' gctx GlobalContext ,
231
231
}
232
232
@@ -253,7 +253,7 @@ impl<'gctx> RecursivePathSource<'gctx> {
253
253
/// filesystem if package information haven't yet loaded.
254
254
pub fn read_packages ( & mut self ) -> CargoResult < Vec < Package > > {
255
255
self . load ( ) ?;
256
- Ok ( self . packages . iter ( ) . map ( |( _, v) | v. clone ( ) ) . collect ( ) )
256
+ Ok ( self . packages . iter ( ) . map ( |( _, v) | v[ 0 ] . clone ( ) ) . collect ( ) )
257
257
}
258
258
259
259
/// List all files relevant to building this package inside this source.
@@ -290,6 +290,32 @@ impl<'gctx> RecursivePathSource<'gctx> {
290
290
pub fn load ( & mut self ) -> CargoResult < ( ) > {
291
291
if !self . loaded {
292
292
self . packages = read_packages ( & self . path , self . source_id , self . gctx ) ?;
293
+ for ( pkg_id, pkgs) in self . packages . iter ( ) {
294
+ if 1 < pkgs. len ( ) {
295
+ let ignored = pkgs[ 1 ..]
296
+ . iter ( )
297
+ // We can assume a package with publish = false isn't intended to be seen
298
+ // by users so we can hide the warning about those since the user is unlikely
299
+ // to care about those cases.
300
+ . filter ( |pkg| pkg. publish ( ) . is_none ( ) )
301
+ . collect :: < Vec < _ > > ( ) ;
302
+ if !ignored. is_empty ( ) {
303
+ use std:: fmt:: Write as _;
304
+
305
+ let plural = if ignored. len ( ) == 1 { "" } else { "s" } ;
306
+ let mut msg = String :: new ( ) ;
307
+ let _ =
308
+ writeln ! ( & mut msg, "skipping duplicate package{plural} `{pkg_id}`:" ) ;
309
+ for ignored in ignored {
310
+ let manifest_path = ignored. manifest_path ( ) . display ( ) ;
311
+ let _ = writeln ! ( & mut msg, " {manifest_path}" ) ;
312
+ }
313
+ let manifest_path = pkgs[ 0 ] . manifest_path ( ) . display ( ) ;
314
+ let _ = writeln ! ( & mut msg, "in favor of {manifest_path}" ) ;
315
+ let _ = self . gctx . shell ( ) . warn ( msg) ;
316
+ }
317
+ }
318
+ }
293
319
self . loaded = true ;
294
320
}
295
321
@@ -311,7 +337,12 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
311
337
f : & mut dyn FnMut ( IndexSummary ) ,
312
338
) -> Poll < CargoResult < ( ) > > {
313
339
self . load ( ) ?;
314
- for s in self . packages . values ( ) . map ( |p| p. summary ( ) ) {
340
+ for s in self
341
+ . packages
342
+ . values ( )
343
+ . map ( |pkgs| & pkgs[ 0 ] )
344
+ . map ( |p| p. summary ( ) )
345
+ {
315
346
let matched = match kind {
316
347
QueryKind :: Exact => dep. matches ( s) ,
317
348
QueryKind :: Alternatives => true ,
@@ -340,7 +371,7 @@ impl<'gctx> Source for RecursivePathSource<'gctx> {
340
371
trace ! ( "getting packages; id={}" , id) ;
341
372
self . load ( ) ?;
342
373
let pkg = self . packages . get ( & id) ;
343
- pkg. cloned ( )
374
+ pkg. map ( |pkgs| pkgs [ 0 ] . clone ( ) )
344
375
. map ( MaybePackage :: Ready )
345
376
. ok_or_else ( || internal ( format ! ( "failed to find {} in path source" , id) ) )
346
377
}
@@ -758,7 +789,7 @@ fn read_packages(
758
789
path : & Path ,
759
790
source_id : SourceId ,
760
791
gctx : & GlobalContext ,
761
- ) -> CargoResult < HashMap < PackageId , Package > > {
792
+ ) -> CargoResult < HashMap < PackageId , Vec < Package > > > {
762
793
let mut all_packages = HashMap :: new ( ) ;
763
794
let mut visited = HashSet :: < PathBuf > :: new ( ) ;
764
795
let mut errors = Vec :: < anyhow:: Error > :: new ( ) ;
@@ -899,7 +930,7 @@ fn has_manifest(path: &Path) -> bool {
899
930
900
931
fn read_nested_packages (
901
932
path : & Path ,
902
- all_packages : & mut HashMap < PackageId , Package > ,
933
+ all_packages : & mut HashMap < PackageId , Vec < Package > > ,
903
934
source_id : SourceId ,
904
935
gctx : & GlobalContext ,
905
936
visited : & mut HashSet < PathBuf > ,
@@ -938,24 +969,10 @@ fn read_nested_packages(
938
969
let pkg = Package :: new ( manifest, & manifest_path) ;
939
970
940
971
let pkg_id = pkg. package_id ( ) ;
941
- use std:: collections:: hash_map:: Entry ;
942
- match all_packages. entry ( pkg_id) {
943
- Entry :: Vacant ( v) => {
944
- v. insert ( pkg) ;
945
- }
946
- Entry :: Occupied ( _) => {
947
- // We can assume a package with publish = false isn't intended to be seen
948
- // by users so we can hide the warning about those since the user is unlikely
949
- // to care about those cases.
950
- if pkg. publish ( ) . is_none ( ) {
951
- let _ = gctx. shell ( ) . warn ( format ! (
952
- "skipping duplicate package `{}` found at `{}`" ,
953
- pkg. name( ) ,
954
- path. display( )
955
- ) ) ;
956
- }
957
- }
958
- }
972
+ all_packages
973
+ . entry ( pkg_id)
974
+ . or_insert_with ( Default :: default)
975
+ . push ( pkg) ;
959
976
960
977
// Registry sources are not allowed to have `path=` dependencies because
961
978
// they're all translated to actual registry dependencies.
0 commit comments