github.com/google/osv-scalibr@v0.4.1/annotator/osduplicate/osduplicate.go (about) 1 // Copyright 2025 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package osduplicate implements utility functions for identifying inventory duplicates found in OS packages. 16 package osduplicate 17 18 import ( 19 "strings" 20 21 "github.com/google/osv-scalibr/extractor" 22 scalibrfs "github.com/google/osv-scalibr/fs" 23 "github.com/google/osv-scalibr/inventory" 24 ) 25 26 // BuildLocationToPKGsMap sets up a map of package locations (relative to the specified scan root) 27 // to package pointers from the inventory. 28 func BuildLocationToPKGsMap(results *inventory.Inventory, scanRoot *scalibrfs.ScanRoot) map[string][]*extractor.Package { 29 locationToPKGs := map[string][]*extractor.Package{} 30 31 // Get root prefix to compare absolute package locations with 32 rootPrefix := scanRoot.Path 33 if !strings.HasSuffix(rootPrefix, "/") { 34 rootPrefix += "/" 35 } 36 pkgLoop: 37 for _, pkg := range results.Packages { 38 if len(pkg.Locations) == 0 { 39 continue 40 } 41 // Skip packages found by OS extractors since those are not OS duplicates. 42 for _, p := range pkg.Plugins { 43 if strings.HasPrefix(p, "os/") { 44 continue pkgLoop 45 } 46 } 47 // The descriptor file (e.g. lockfile) is always stored in the first element. 48 // TODO(b/400910349): Separate locations into a dedicated "descriptor file" 49 // and "other files" field. 50 loc := pkg.Locations[0] 51 52 // If ScanConfig.StoreAbsolutePath is on, this will be an absolute path. 53 // Convert to relative in these cases. 54 // Root starts and ends in a slash while relative paths don't, so this will only 55 // take effect for absolute paths. 56 loc = strings.TrimPrefix(loc, rootPrefix) 57 58 if prev, ok := locationToPKGs[loc]; ok { 59 locationToPKGs[loc] = append(prev, pkg) 60 } else { 61 locationToPKGs[loc] = []*extractor.Package{pkg} 62 } 63 } 64 return locationToPKGs 65 }