@@ -522,18 +522,20 @@ private class DuplicateProductsChecker {
522
522
init ( packageBuilders: [ ResolvedPackageBuilder ] ) {
523
523
for packageBuilder in packageBuilders {
524
524
let pkgID = packageBuilder. package . identity. description. lowercased ( )
525
- packageIDToBuilder [ pkgID] = packageBuilder
525
+ self . packageIDToBuilder [ pkgID] = packageBuilder
526
526
}
527
527
}
528
528
529
529
func run( lookupByProductIDs: Bool = false , observabilityScope: ObservabilityScope ) throws {
530
530
var productToPkgMap = [ String: [ String] ] ( )
531
- for (_ , pkgBuilder) in packageIDToBuilder {
531
+ for (pkgID , pkgBuilder) in packageIDToBuilder {
532
532
let useProductIDs = pkgBuilder. package . manifest. disambiguateByProductIDs || lookupByProductIDs
533
533
let depProductRefs = pkgBuilder. package . targets. map { $0. dependencies} . flatMap { $0} . compactMap { $0. product}
534
534
for depRef in depProductRefs {
535
535
if let depPkg = depRef. package ? . lowercased ( ) {
536
- checkedPkgIDs. append ( depPkg)
536
+ if !checkedPkgIDs. contains ( depPkg) {
537
+ checkedPkgIDs. append ( depPkg)
538
+ }
537
539
let depProductIDs = packageIDToBuilder [ depPkg] ? . package . products. filter { $0. identity == depRef. identity } . map { useProductIDs && $0. isDefaultLibrary ? $0. identity : $0. name } ?? [ ]
538
540
for depID in depProductIDs {
539
541
productToPkgMap [ depID, default: [ ] ] . append ( depPkg)
@@ -543,18 +545,30 @@ private class DuplicateProductsChecker {
543
545
productToPkgMap [ depRef. name, default: [ ] ] . append ( contentsOf: depPkgs)
544
546
checkedPkgIDs. append ( contentsOf: depPkgs)
545
547
}
548
+ if !checkedPkgIDs. contains ( pkgID. lowercased ( ) ) {
549
+ checkedPkgIDs. append ( pkgID. lowercased ( ) )
550
+ }
546
551
}
547
552
for (depIDOrName, depPkgs) in productToPkgMap. filter ( { Set ( $0. value) . count > 1 } ) {
548
553
let name = depIDOrName. components ( separatedBy: " _ " ) . dropFirst ( ) . joined ( separator: " _ " )
549
554
throw PackageGraphError . duplicateProduct ( product: name. isEmpty ? depIDOrName : name, packages: depPkgs. sorted ( ) )
550
555
}
551
556
}
552
557
553
- let uncheckedPkgs = packageIDToBuilder. filter { !checkedPkgIDs. contains ( $0. key) }
554
- for (pkgID, pkgBuilder) in uncheckedPkgs {
555
- let productIDOrNames = pkgBuilder. products. map { pkgBuilder. package . manifest. disambiguateByProductIDs && $0. product. isDefaultLibrary ? $0. product. identity : $0. product. name }
556
- for productIDOrName in productIDOrNames {
557
- productToPkgMap [ productIDOrName, default: [ ] ] . append ( pkgID)
558
+ // Check packages that exist but are not in a dependency graph
559
+ let untrackedPkgs = packageIDToBuilder. filter { !checkedPkgIDs. contains ( $0. key. lowercased ( ) ) }
560
+ for (pkgID, pkgBuilder) in untrackedPkgs {
561
+ for product in pkgBuilder. products {
562
+ // Check if checking product ID only is safe
563
+ let useIDOnly = lookupByProductIDs && product. product. isDefaultLibrary
564
+ if !useIDOnly {
565
+ // This untracked pkg could have a product name conflicting with a
566
+ // product name from another package, but since it's not depended on
567
+ // by other packages, keep track of both this product's name and ID
568
+ // just in case other packages are < .v5_8
569
+ productToPkgMap [ product. product. name, default: [ ] ] . append ( pkgID)
570
+ }
571
+ productToPkgMap [ product. product. identity, default: [ ] ] . append ( pkgID)
558
572
}
559
573
}
560
574
0 commit comments