@@ -1045,9 +1045,69 @@ func compareVersions(v1, v2 string) int {
10451045 return cmp
10461046}
10471047
1048+ func isKernelPackageRequest (want string ) bool {
1049+ for pattern := range KernelPackages {
1050+ if pattern == want {
1051+ return true
1052+ }
1053+
1054+ if ! isGlobPattern (pattern ) {
1055+ continue
1056+ }
1057+
1058+ matched , err := path .Match (pattern , want )
1059+ if err == nil && matched {
1060+ return true
1061+ }
1062+ }
1063+
1064+ return false
1065+ }
1066+
1067+ func stripEpoch (version string ) string {
1068+ if colonIdx := strings .Index (version , ":" ); colonIdx != - 1 {
1069+ return version [colonIdx + 1 :]
1070+ }
1071+ return version
1072+ }
1073+
1074+ func matchesKernelVersion (candidateVersion string ) bool {
1075+ if KernelVersion == "" {
1076+ return false
1077+ }
1078+
1079+ versionNoEpoch := stripEpoch (candidateVersion )
1080+ if versionNoEpoch == KernelVersion {
1081+ return true
1082+ }
1083+
1084+ if ! strings .HasPrefix (versionNoEpoch , KernelVersion ) {
1085+ return false
1086+ }
1087+
1088+ if len (versionNoEpoch ) == len (KernelVersion ) {
1089+ return true
1090+ }
1091+
1092+ nextChar := versionNoEpoch [len (KernelVersion )]
1093+ return nextChar == '.' || nextChar == '-' || nextChar == '_' || nextChar == '+' || nextChar == '~'
1094+ }
1095+
1096+ func filterKernelCandidates (candidates []ospackage.PackageInfo ) []ospackage.PackageInfo {
1097+ var matched []ospackage.PackageInfo
1098+ for _ , candidate := range candidates {
1099+ if matchesKernelVersion (candidate .Version ) {
1100+ matched = append (matched , candidate )
1101+ }
1102+ }
1103+ return matched
1104+ }
1105+
10481106// ResolvePackage finds the best matching package for a given package name
10491107func ResolveTopPackageConflicts (want string , all []ospackage.PackageInfo ) (ospackage.PackageInfo , bool ) {
1108+ log := logger .Logger ()
10501109 var candidates []ospackage.PackageInfo
1110+ isKernelPackage := isKernelPackageRequest (want )
10511111 for _ , pi := range all {
10521112 // 1) exact name and version matched with .deb filenamae, e.g. acct_7.6.4-5+b1_amd64
10531113 if filepath .Base (pi .URL ) == want + ".deb" {
@@ -1137,6 +1197,21 @@ func ResolveTopPackageConflicts(want string, all []ospackage.PackageInfo) (ospac
11371197 return ospackage.PackageInfo {}, false
11381198 }
11391199
1200+ if isKernelPackage && KernelVersion != "" {
1201+ var beforeFilter []ospackage.PackageInfo
1202+ beforeFilter = append (beforeFilter , candidates ... )
1203+ candidates = filterKernelCandidates (candidates )
1204+ if len (candidates ) == 0 {
1205+ var availableVersions []string
1206+ for _ , pkg := range beforeFilter {
1207+ availableVersions = append (availableVersions , pkg .Version )
1208+ }
1209+ log .Errorf ("kernel version mismatch: package %q requires kernel version %q, but available versions are: %v" ,
1210+ want , KernelVersion , availableVersions )
1211+ return ospackage.PackageInfo {}, false
1212+ }
1213+ }
1214+
11401215 // If we got an exact match in step (1), it's the only candidate
11411216 if len (candidates ) == 1 && (candidates [0 ].Name == want || candidates [0 ].Name == want + ".deb" ) {
11421217 return candidates [0 ], true
@@ -1146,6 +1221,52 @@ func ResolveTopPackageConflicts(want string, all []ospackage.PackageInfo) (ospac
11461221 return candidates [0 ], true
11471222}
11481223
1224+ // ResolveWildcardPackageConflicts expands a wildcard request to the best package
1225+ // for each matched base package name.
1226+ func ResolveWildcardPackageConflicts (want string , all []ospackage.PackageInfo ) ([]ospackage.PackageInfo , bool ) {
1227+ if ! isGlobPattern (want ) {
1228+ pkg , found := ResolveTopPackageConflicts (want , all )
1229+ if ! found {
1230+ return nil , false
1231+ }
1232+ return []ospackage.PackageInfo {pkg }, true
1233+ }
1234+
1235+ baseNames := make (map [string ]struct {})
1236+ for _ , pi := range all {
1237+ matched , err := path .Match (want , pi .Name )
1238+ if err != nil || ! matched {
1239+ continue
1240+ }
1241+ baseNames [pi .Name ] = struct {}{}
1242+ }
1243+
1244+ if len (baseNames ) == 0 {
1245+ return nil , false
1246+ }
1247+
1248+ var results []ospackage.PackageInfo
1249+ for baseName := range baseNames {
1250+ pkg , found := ResolveTopPackageConflicts (baseName , all )
1251+ if found {
1252+ results = append (results , pkg )
1253+ }
1254+ }
1255+
1256+ if len (results ) == 0 {
1257+ return nil , false
1258+ }
1259+
1260+ sort .Slice (results , func (i , j int ) bool {
1261+ if results [i ].Name == results [j ].Name {
1262+ return compareVersions (results [i ].Version , results [j ].Version ) > 0
1263+ }
1264+ return results [i ].Name < results [j ].Name
1265+ })
1266+
1267+ return results , true
1268+ }
1269+
11491270// Helper function to find all candidates for a dependency
11501271func findAllCandidates (depName string , all []ospackage.PackageInfo ) []ospackage.PackageInfo {
11511272 var candidates []ospackage.PackageInfo
0 commit comments