github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/file/location_set.go (about) 1 package file 2 3 import ( 4 "sort" 5 6 "github.com/mitchellh/hashstructure/v2" 7 "github.com/nextlinux/gosbom/internal/log" 8 ) 9 10 type LocationSet struct { 11 set map[LocationData]LocationMetadata 12 } 13 14 func NewLocationSet(locations ...Location) (s LocationSet) { 15 for _, l := range locations { 16 s.Add(l) 17 } 18 19 return s 20 } 21 22 func (s *LocationSet) Add(locations ...Location) { 23 if s.set == nil { 24 s.set = make(map[LocationData]LocationMetadata) 25 } 26 for _, l := range locations { 27 if m, ok := s.set[l.LocationData]; ok { 28 err := m.merge(l.LocationMetadata) 29 if err != nil { 30 log.Debugf("partial merge of location metadata: %+v", err) 31 } 32 s.set[l.LocationData] = m 33 } else { 34 s.set[l.LocationData] = l.LocationMetadata 35 } 36 } 37 } 38 39 func (s LocationSet) Remove(locations ...Location) { 40 if s.set == nil { 41 return 42 } 43 for _, l := range locations { 44 delete(s.set, l.LocationData) 45 } 46 } 47 48 func (s LocationSet) Contains(l Location) bool { 49 if s.set == nil { 50 return false 51 } 52 _, ok := s.set[l.LocationData] 53 return ok 54 } 55 56 func (s LocationSet) ToSlice() []Location { 57 if s.set == nil { 58 return nil 59 } 60 locations := make([]Location, len(s.set)) 61 idx := 0 62 for dir := range s.set { 63 locations[idx] = Location{ 64 LocationData: dir, 65 LocationMetadata: s.set[dir], 66 } 67 idx++ 68 } 69 sort.Sort(Locations(locations)) 70 return locations 71 } 72 73 func (s *LocationSet) CoordinateSet() CoordinateSet { 74 if s.set == nil { 75 return NewCoordinateSet() 76 } 77 set := NewCoordinateSet() 78 for l := range s.set { 79 set.Add(l.Coordinates) 80 } 81 return set 82 } 83 84 func (s *LocationSet) Empty() bool { 85 if s.set == nil { 86 return true 87 } 88 return len(s.set) == 0 89 } 90 91 func (s LocationSet) Hash() (uint64, error) { 92 // access paths and filesystem IDs are not considered when hashing a location set, only the real paths 93 return hashstructure.Hash(s.CoordinateSet().Paths(), hashstructure.FormatV2, &hashstructure.HashOptions{ 94 ZeroNil: true, 95 SlicesAsSets: true, 96 }) 97 }