Introduce minimal source coordinates (#623)

* split source.Location and create source.Coordinates for minimal path addressing

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* move coordinates into separate file

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>

* Update syft/source/coordinates.go

Co-authored-by: Dan Luhring <luhring@users.noreply.github.com>
This commit is contained in:
Alex Goodman
2021-11-18 18:13:22 +00:00
committed by GitHub
co-authored by Dan Luhring
parent 9090c3a772
commit e38cde35ed
31 changed files with 262 additions and 249 deletions
@@ -8,16 +8,16 @@ import (
)
type JSONFileClassifications struct {
Location source.Location `json:"location"`
Location source.Coordinates `json:"location"`
Classification file.Classification `json:"classification"`
}
func NewJSONFileClassifications(data map[source.Location][]file.Classification) []JSONFileClassifications {
func NewJSONFileClassifications(data map[source.Coordinates][]file.Classification) []JSONFileClassifications {
results := make([]JSONFileClassifications, 0)
for location, classifications := range data {
for coordinates, classifications := range data {
for _, classification := range classifications {
results = append(results, JSONFileClassifications{
Location: location,
Location: coordinates,
Classification: classification,
})
}
@@ -25,9 +25,6 @@ func NewJSONFileClassifications(data map[source.Location][]file.Classification)
// sort by real path then virtual path to ensure the result is stable across multiple runs
sort.SliceStable(results, func(i, j int) bool {
if results[i].Location.RealPath == results[j].Location.RealPath {
return results[i].Location.VirtualPath < results[j].Location.VirtualPath
}
return results[i].Location.RealPath < results[j].Location.RealPath
})
return results
@@ -7,24 +7,21 @@ import (
)
type JSONFileContents struct {
Location source.Location `json:"location"`
Contents string `json:"contents"`
Location source.Coordinates `json:"location"`
Contents string `json:"contents"`
}
func NewJSONFileContents(data map[source.Location]string) []JSONFileContents {
func NewJSONFileContents(data map[source.Coordinates]string) []JSONFileContents {
results := make([]JSONFileContents, 0)
for location, contents := range data {
for coordinates, contents := range data {
results = append(results, JSONFileContents{
Location: location,
Location: coordinates,
Contents: contents,
})
}
// sort by real path then virtual path to ensure the result is stable across multiple runs
sort.SliceStable(results, func(i, j int) bool {
if results[i].Location.RealPath == results[j].Location.RealPath {
return results[i].Location.VirtualPath < results[j].Location.VirtualPath
}
return results[i].Location.RealPath < results[j].Location.RealPath
})
return results
@@ -11,7 +11,7 @@ import (
)
type JSONFileMetadata struct {
Location source.Location `json:"location"`
Location source.Coordinates `json:"location"`
Metadata JSONFileMetadataEntry `json:"metadata"`
}
@@ -25,21 +25,21 @@ type JSONFileMetadataEntry struct {
MIMEType string `json:"mimeType"`
}
func NewJSONFileMetadata(data map[source.Location]source.FileMetadata, digests map[source.Location][]file.Digest) ([]JSONFileMetadata, error) {
func NewJSONFileMetadata(data map[source.Coordinates]source.FileMetadata, digests map[source.Coordinates][]file.Digest) ([]JSONFileMetadata, error) {
results := make([]JSONFileMetadata, 0)
for location, metadata := range data {
for coordinates, metadata := range data {
mode, err := strconv.Atoi(fmt.Sprintf("%o", metadata.Mode))
if err != nil {
return nil, fmt.Errorf("invalid mode found in file catalog @ location=%+v mode=%q: %w", location, metadata.Mode, err)
return nil, fmt.Errorf("invalid mode found in file catalog @ location=%+v mode=%q: %w", coordinates, metadata.Mode, err)
}
var digestResults []file.Digest
if digestsForLocation, exists := digests[location]; exists {
if digestsForLocation, exists := digests[coordinates]; exists {
digestResults = digestsForLocation
}
results = append(results, JSONFileMetadata{
Location: location,
Location: coordinates,
Metadata: JSONFileMetadataEntry{
Mode: mode,
Type: metadata.Type,
@@ -54,9 +54,6 @@ func NewJSONFileMetadata(data map[source.Location]source.FileMetadata, digests m
// sort by real path then virtual path to ensure the result is stable across multiple runs
sort.SliceStable(results, func(i, j int) bool {
if results[i].Location.RealPath == results[j].Location.RealPath {
return results[i].Location.VirtualPath < results[j].Location.VirtualPath
}
return results[i].Location.RealPath < results[j].Location.RealPath
})
return results, nil
@@ -37,7 +37,9 @@ func TestJSONPresenter(t *testing.T) {
Version: "1.0.1",
Locations: []source.Location{
{
RealPath: "/a/place/a",
Coordinates: source.Coordinates{
RealPath: "/a/place/a",
},
},
},
Type: pkg.PythonPkg,
@@ -60,7 +62,9 @@ func TestJSONPresenter(t *testing.T) {
Version: "2.0.1",
Locations: []source.Location{
{
RealPath: "/b/place/b",
Coordinates: source.Coordinates{
RealPath: "/b/place/b",
},
},
},
Type: pkg.DebPkg,
@@ -86,49 +90,49 @@ func TestJSONPresenter(t *testing.T) {
cfg := sbom.SBOM{
Artifacts: sbom.Artifacts{
PackageCatalog: catalog,
FileMetadata: map[source.Location]source.FileMetadata{
source.NewLocation("/a/place"): {
FileMetadata: map[source.Coordinates]source.FileMetadata{
source.NewLocation("/a/place").Coordinates: {
Mode: 0775,
Type: "directory",
UserID: 0,
GroupID: 0,
},
source.NewLocation("/a/place/a"): {
source.NewLocation("/a/place/a").Coordinates: {
Mode: 0775,
Type: "regularFile",
UserID: 0,
GroupID: 0,
},
source.NewLocation("/b"): {
source.NewLocation("/b").Coordinates: {
Mode: 0775,
Type: "symbolicLink",
LinkDestination: "/c",
UserID: 0,
GroupID: 0,
},
source.NewLocation("/b/place/b"): {
source.NewLocation("/b/place/b").Coordinates: {
Mode: 0644,
Type: "regularFile",
UserID: 1,
GroupID: 2,
},
},
FileDigests: map[source.Location][]file.Digest{
source.NewLocation("/a/place/a"): {
FileDigests: map[source.Coordinates][]file.Digest{
source.NewLocation("/a/place/a").Coordinates: {
{
Algorithm: "sha256",
Value: "366a3f5653e34673b875891b021647440d0127c2ef041e3b1a22da2a7d4f3703",
},
},
source.NewLocation("/b/place/b"): {
source.NewLocation("/b/place/b").Coordinates: {
{
Algorithm: "sha256",
Value: "1b3722da2a7d90d033b87581a2a3f12021647445653e34666ef041e3b4f3707c",
},
},
},
FileContents: map[source.Location]string{
source.NewLocation("/a/place/a"): "the-contents",
FileContents: map[source.Coordinates]string{
source.NewLocation("/a/place/a").Coordinates: "the-contents",
},
Distro: &distro.Distro{
Type: distro.RedHat,
+5 -8
View File
@@ -8,25 +8,22 @@ import (
)
type JSONSecrets struct {
Location source.Location `json:"location"`
Location source.Coordinates `json:"location"`
Secrets []file.SearchResult `json:"secrets"`
}
func NewJSONSecrets(data map[source.Location][]file.SearchResult) []JSONSecrets {
func NewJSONSecrets(data map[source.Coordinates][]file.SearchResult) []JSONSecrets {
results := make([]JSONSecrets, 0)
for location, secrets := range data {
for coordinates, secrets := range data {
results = append(results, JSONSecrets{
Location: location,
Location: coordinates,
Secrets: secrets,
})
}
// sort by real path then virtual path to ensure the result is stable across multiple runs
sort.SliceStable(results, func(i, j int) bool {
if results[i].Location.RealPath != results[j].Location.RealPath {
return results[i].Location.VirtualPath < results[j].Location.VirtualPath
}
return false
return results[i].Location.RealPath < results[j].Location.RealPath
})
return results
}
@@ -72,7 +72,7 @@
],
"artifacts": [
{
"id": "b84dfe0eb2c5670f",
"id": "962403cfb7be50d7",
"name": "package-1",
"version": "1.0.1",
"type": "python",
@@ -102,7 +102,7 @@
}
},
{
"id": "6619226d6979963f",
"id": "b11f44847bba0ed1",
"name": "package-2",
"version": "2.0.1",
"type": "deb",