@@ -430,6 +430,71 @@ func filterCandidatesByPriority(candidates []ospackage.PackageInfo) []ospackage.
430430 return filtered
431431}
432432
433+ // filterCandidatesByPriorityWithTarget filters and sorts candidates, prioritizing exact name matches
434+ func filterCandidatesByPriorityWithTarget (candidates []ospackage.PackageInfo , targetName string ) []ospackage.PackageInfo {
435+ log := logger .Logger ()
436+ var filtered []ospackage.PackageInfo
437+
438+ // First pass: filter out blocked packages (priority < 0)
439+ for _ , candidate := range candidates {
440+ if ! shouldBlockPackage (candidate ) {
441+ filtered = append (filtered , candidate )
442+ }
443+ }
444+
445+ // Sort by simple rule: exact name matches first, then provides matches
446+ sort .Slice (filtered , func (i , j int ) bool {
447+ pkgI := filtered [i ]
448+ pkgJ := filtered [j ]
449+
450+ isExactI := pkgI .Name == targetName
451+ isExactJ := pkgJ .Name == targetName
452+
453+ // Simple rule: exact name matches always win over provides
454+ if isExactI != isExactJ {
455+ log .Debugf (" Exact match priority: %s (exact=%v) vs %s (exact=%v) -> %s wins" ,
456+ pkgI .Name , isExactI , pkgJ .Name , isExactJ ,
457+ func () string {
458+ if isExactI {
459+ return pkgI .Name
460+ } else {
461+ return pkgJ .Name
462+ }
463+ }())
464+ return isExactI
465+ }
466+
467+ // For same type (both exact or both provides), use standard APT priority + version
468+ priorityI := getRepositoryPriority (pkgI .URL )
469+ priorityJ := getRepositoryPriority (pkgJ .URL )
470+
471+ // APT priority comparison
472+ if priorityI != priorityJ {
473+ return priorityI > priorityJ
474+ }
475+
476+ // Only compare versions for exact matches (avoid kernel vs dkms version comparison)
477+ if isExactI && isExactJ {
478+ versionCmp := compareVersions (pkgI .Version , pkgJ .Version ) > 0
479+ log .Debugf (" Exact match version comparison: %s (%s) vs %s (%s) -> %s wins" ,
480+ pkgI .Name , pkgI .Version , pkgJ .Name , pkgJ .Version ,
481+ func () string {
482+ if versionCmp {
483+ return pkgI .Name
484+ } else {
485+ return pkgJ .Name
486+ }
487+ }())
488+ return versionCmp
489+ }
490+
491+ // For provides matches, maintain stable order (don't compare different versioning schemes)
492+ return false
493+ })
494+
495+ return filtered
496+ }
497+
433498// comparePriorityBehavior compares two packages based on APT priority behavior
434499// Returns true if pkgA should be preferred over pkgB
435500func comparePriorityBehavior (pkgA , pkgB ospackage.PackageInfo ) bool {
@@ -1047,6 +1112,9 @@ func compareVersions(v1, v2 string) int {
10471112
10481113// ResolvePackage finds the best matching package for a given package name
10491114func ResolveTopPackageConflicts (want string , all []ospackage.PackageInfo ) (ospackage.PackageInfo , bool ) {
1115+ log := logger .Logger ()
1116+ log .Debugf ("ResolveTopPackageConflicts: Searching for package '%s' in %d available packages" , want , len (all ))
1117+
10501118 var candidates []ospackage.PackageInfo
10511119 for _ , pi := range all {
10521120 // 1) exact name and version matched with .deb filenamae, e.g. acct_7.6.4-5+b1_amd64
@@ -1056,6 +1124,7 @@ func ResolveTopPackageConflicts(want string, all []ospackage.PackageInfo) (ospac
10561124 }
10571125 // 2) exact name, e.g. acct
10581126 if pi .Name == want {
1127+ log .Debugf (" Found EXACT NAME candidate: %s (version: %s)" , pi .Name , pi .Version )
10591128 candidates = append (candidates , pi )
10601129 continue
10611130 }
@@ -1121,28 +1190,41 @@ func ResolveTopPackageConflicts(want string, all []ospackage.PackageInfo) (ospac
11211190 // Example: want="mail-transport-agent", pi.Provides=["mail-transport-agent"]
11221191 for _ , provided := range pi .Provides {
11231192 if provided == want {
1193+ log .Debugf (" Found PROVIDES candidate: %s (version: %s, provides: %s)" , pi .Name , pi .Version , provided )
11241194 candidates = append (candidates , pi )
11251195 break
11261196 }
11271197 }
11281198 }
11291199
1200+ log .Debugf ("ResolveTopPackageConflicts: Found %d initial candidates for package '%s'" , len (candidates ), want )
1201+ for i , candidate := range candidates {
1202+ log .Debugf (" Candidate %d: %s (version: %s, provides: %v)" , i + 1 , candidate .Name , candidate .Version , candidate .Provides )
1203+ }
1204+
11301205 if len (candidates ) == 0 {
1206+ log .Debugf ("ResolveTopPackageConflicts: No candidates found for package '%s'" , want )
11311207 return ospackage.PackageInfo {}, false
11321208 }
11331209
1134- // Filter out blocked packages (priority < 0)
1135- candidates = filterCandidatesByPriority (candidates )
1210+ // Filter out blocked packages (priority < 0) and prioritize exact name matches
1211+ candidates = filterCandidatesByPriorityWithTarget (candidates , want )
1212+ log .Debugf ("ResolveTopPackageConflicts: After priority filtering, %d candidates remain for package '%s'" , len (candidates ), want )
1213+ for i , candidate := range candidates {
1214+ log .Debugf (" Filtered candidate %d: %s (version: %s)" , i + 1 , candidate .Name , candidate .Version )
1215+ }
11361216 if len (candidates ) == 0 {
11371217 return ospackage.PackageInfo {}, false
11381218 }
11391219
11401220 // If we got an exact match in step (1), it's the only candidate
11411221 if len (candidates ) == 1 && (candidates [0 ].Name == want || candidates [0 ].Name == want + ".deb" ) {
1222+ log .Debugf ("ResolveTopPackageConflicts: Selected exact match candidate: %s (version: %s)" , candidates [0 ].Name , candidates [0 ].Version )
11421223 return candidates [0 ], true
11431224 }
11441225
11451226 // Candidates already sorted by filterCandidatesByPriority
1227+ log .Debugf ("ResolveTopPackageConflicts: Selected best candidate: %s (version: %s) for package '%s'" , candidates [0 ].Name , candidates [0 ].Version , want )
11461228 return candidates [0 ], true
11471229}
11481230
@@ -1168,8 +1250,8 @@ func findAllCandidates(depName string, all []ospackage.PackageInfo) []ospackage.
11681250 }
11691251 }
11701252
1171- // Apply APT priority filtering and sorting
1172- filtered := filterCandidatesByPriority (candidates )
1253+ // Apply APT priority filtering and sorting with exact name preference
1254+ filtered := filterCandidatesByPriorityWithTarget (candidates , depName )
11731255 return filtered
11741256}
11751257
@@ -1316,6 +1398,7 @@ func matchesRepoBase(parentBase []string, candidateBase string) bool {
13161398
13171399func resolveMultiCandidates (parentPkg ospackage.PackageInfo , candidates []ospackage.PackageInfo ) (ospackage.PackageInfo , error ) {
13181400 // Filter out blocked packages (priority < 0) first
1401+ // All candidates should have the same name here, so no need for target-aware filtering
13191402 candidates = filterCandidatesByPriority (candidates )
13201403 if len (candidates ) == 0 {
13211404 return ospackage.PackageInfo {}, fmt .Errorf ("all candidates are blocked by negative priority" )
0 commit comments