mirror of
https://github.com/anchore/syft.git
synced 2026-02-12 10:36:45 +01:00
Parse donet dependency trees (#2143)
* add dependency information for .NET pkgs Signed-off-by: Benji Visser <benji@093b.org> * update pkg coverage directory test Signed-off-by: Benji Visser <benji@093b.org> * reverse dependsOn relationship Signed-off-by: Benji Visser <benji@093b.org> * update root pkg parsing Signed-off-by: Benji Visser <benji@093b.org> * add comments about the test relationships represented Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> * add docs around relationship sorting functions + update test helpers Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Benji Visser <benji@093b.org> Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
7732cd3b48
commit
fe7a417fb2
@ -1,6 +1,8 @@
|
|||||||
package dotnet
|
package dotnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/anchore/packageurl-go"
|
"github.com/anchore/packageurl-go"
|
||||||
@ -9,13 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations ...file.Location) *pkg.Package {
|
func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations ...file.Location) *pkg.Package {
|
||||||
if lib.Type != "package" {
|
name, version := extractNameAndVersion(nameVersion)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
fields := strings.Split(nameVersion, "/")
|
|
||||||
name := fields[0]
|
|
||||||
version := fields[1]
|
|
||||||
|
|
||||||
m := pkg.DotnetDepsMetadata{
|
m := pkg.DotnetDepsMetadata{
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -41,6 +37,27 @@ func newDotnetDepsPackage(nameVersion string, lib dotnetDepsLibrary, locations .
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getDepsJSONFilePrefix(p string) string {
|
||||||
|
r := regexp.MustCompile(`([^\/]+)\.deps\.json$`)
|
||||||
|
match := r.FindStringSubmatch(p)
|
||||||
|
if len(match) > 1 {
|
||||||
|
return match[1]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractNameAndVersion(nameVersion string) (name, version string) {
|
||||||
|
fields := strings.Split(nameVersion, "/")
|
||||||
|
name = fields[0]
|
||||||
|
version = fields[1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNameAndVersion(name, version string) (nameVersion string) {
|
||||||
|
nameVersion = fmt.Sprintf("%s/%s", name, version)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func packageURL(m pkg.DotnetDepsMetadata) string {
|
func packageURL(m pkg.DotnetDepsMetadata) string {
|
||||||
var qualifiers packageurl.Qualifiers
|
var qualifiers packageurl.Qualifiers
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
"github.com/anchore/syft/syft/artifact"
|
"github.com/anchore/syft/syft/artifact"
|
||||||
"github.com/anchore/syft/syft/file"
|
"github.com/anchore/syft/syft/file"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@ -13,8 +14,18 @@ import (
|
|||||||
|
|
||||||
var _ generic.Parser = parseDotnetDeps
|
var _ generic.Parser = parseDotnetDeps
|
||||||
|
|
||||||
|
type dotnetRuntimeTarget struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type dotnetDepsTarget struct {
|
||||||
|
Dependencies map[string]string `json:"dependencies"`
|
||||||
|
Runtime map[string]struct{} `json:"runtime"`
|
||||||
|
}
|
||||||
type dotnetDeps struct {
|
type dotnetDeps struct {
|
||||||
Libraries map[string]dotnetDepsLibrary `json:"libraries"`
|
RuntimeTarget dotnetRuntimeTarget `json:"runtimeTarget"`
|
||||||
|
Targets map[string]map[string]dotnetDepsTarget `json:"targets"`
|
||||||
|
Libraries map[string]dotnetDepsLibrary `json:"libraries"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type dotnetDepsLibrary struct {
|
type dotnetDepsLibrary struct {
|
||||||
@ -24,27 +35,55 @@ type dotnetDepsLibrary struct {
|
|||||||
HashPath string `json:"hashPath"`
|
HashPath string `json:"hashPath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:funlen
|
||||||
func parseDotnetDeps(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
func parseDotnetDeps(_ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
|
||||||
var pkgs []pkg.Package
|
var pkgs []pkg.Package
|
||||||
|
var pkgMap = make(map[string]pkg.Package)
|
||||||
|
var relationships []artifact.Relationship
|
||||||
|
|
||||||
dec := json.NewDecoder(reader)
|
dec := json.NewDecoder(reader)
|
||||||
|
|
||||||
var p dotnetDeps
|
var depsDoc dotnetDeps
|
||||||
if err := dec.Decode(&p); err != nil {
|
if err := dec.Decode(&depsDoc); err != nil {
|
||||||
return nil, nil, fmt.Errorf("failed to parse deps.json file: %w", err)
|
return nil, nil, fmt.Errorf("failed to parse deps.json file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var names []string
|
rootName := getDepsJSONFilePrefix(reader.AccessPath())
|
||||||
|
if rootName == "" {
|
||||||
|
return nil, nil, fmt.Errorf("unable to determine root package name from deps.json file: %s", reader.AccessPath())
|
||||||
|
}
|
||||||
|
var rootPkg *pkg.Package
|
||||||
|
for nameVersion, lib := range depsDoc.Libraries {
|
||||||
|
name, _ := extractNameAndVersion(nameVersion)
|
||||||
|
if lib.Type == "project" && name == rootName {
|
||||||
|
rootPkg = newDotnetDepsPackage(
|
||||||
|
nameVersion,
|
||||||
|
lib,
|
||||||
|
reader.Location.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rootPkg == nil {
|
||||||
|
return nil, nil, fmt.Errorf("unable to determine root package from deps.json file: %s", reader.AccessPath())
|
||||||
|
}
|
||||||
|
pkgs = append(pkgs, *rootPkg)
|
||||||
|
pkgMap[createNameAndVersion(rootPkg.Name, rootPkg.Version)] = *rootPkg
|
||||||
|
|
||||||
for nameVersion := range p.Libraries {
|
var names []string
|
||||||
|
for nameVersion := range depsDoc.Libraries {
|
||||||
names = append(names, nameVersion)
|
names = append(names, nameVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort the names so that the order of the packages is deterministic
|
// sort the names so that the order of the packages is deterministic
|
||||||
sort.Strings(names)
|
sort.Strings(names)
|
||||||
|
|
||||||
for _, nameVersion := range names {
|
for _, nameVersion := range names {
|
||||||
lib := p.Libraries[nameVersion]
|
// skip the root package
|
||||||
|
name, version := extractNameAndVersion(nameVersion)
|
||||||
|
if name == rootPkg.Name && version == rootPkg.Version {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
lib := depsDoc.Libraries[nameVersion]
|
||||||
dotnetPkg := newDotnetDepsPackage(
|
dotnetPkg := newDotnetDepsPackage(
|
||||||
nameVersion,
|
nameVersion,
|
||||||
lib,
|
lib,
|
||||||
@ -53,8 +92,36 @@ func parseDotnetDeps(_ file.Resolver, _ *generic.Environment, reader file.Locati
|
|||||||
|
|
||||||
if dotnetPkg != nil {
|
if dotnetPkg != nil {
|
||||||
pkgs = append(pkgs, *dotnetPkg)
|
pkgs = append(pkgs, *dotnetPkg)
|
||||||
|
pkgMap[nameVersion] = *dotnetPkg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkgs, nil, nil
|
for pkgNameVersion, target := range depsDoc.Targets[depsDoc.RuntimeTarget.Name] {
|
||||||
|
for depName, depVersion := range target.Dependencies {
|
||||||
|
depNameVersion := createNameAndVersion(depName, depVersion)
|
||||||
|
depPkg, ok := pkgMap[depNameVersion]
|
||||||
|
if !ok {
|
||||||
|
log.Debug("unable to find package in map", depNameVersion)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p, ok := pkgMap[pkgNameVersion]
|
||||||
|
if !ok {
|
||||||
|
log.Debug("unable to find package in map", pkgNameVersion)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rel := artifact.Relationship{
|
||||||
|
From: depPkg,
|
||||||
|
To: p,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
}
|
||||||
|
relationships = append(relationships, rel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the relationships for deterministic output
|
||||||
|
// TODO: ideally this would be replaced with artifact.SortRelationships when one exists and is type agnostic.
|
||||||
|
// this will only consider package-to-package relationships.
|
||||||
|
pkg.SortRelationships(relationships)
|
||||||
|
|
||||||
|
return pkgs, relationships, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,202 +12,363 @@ import (
|
|||||||
func TestParseDotnetDeps(t *testing.T) {
|
func TestParseDotnetDeps(t *testing.T) {
|
||||||
fixture := "test-fixtures/TestLibrary.deps.json"
|
fixture := "test-fixtures/TestLibrary.deps.json"
|
||||||
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture))
|
fixtureLocationSet := file.NewLocationSet(file.NewLocation(fixture))
|
||||||
expected := []pkg.Package{
|
rootPkg := pkg.Package{
|
||||||
{
|
Name: "TestLibrary",
|
||||||
Name: "AWSSDK.Core",
|
Version: "1.0.0",
|
||||||
Version: "3.7.10.6",
|
PURL: "pkg:nuget/TestLibrary@1.0.0",
|
||||||
PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6",
|
Locations: fixtureLocationSet,
|
||||||
Locations: fixtureLocationSet,
|
Language: pkg.Dotnet,
|
||||||
Language: pkg.Dotnet,
|
Type: pkg.DotnetPkg,
|
||||||
Type: pkg.DotnetPkg,
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
Name: "TestLibrary",
|
||||||
Name: "AWSSDK.Core",
|
Version: "1.0.0",
|
||||||
Version: "3.7.10.6",
|
|
||||||
Sha512: "sha512-kHBB+QmosVaG6DpngXQ8OlLVVNMzltNITfsRr68Z90qO7dSqJ2EHNd8dtBU1u3AQQLqqFHOY0lfmbpexeH6Pew==",
|
|
||||||
Path: "awssdk.core/3.7.10.6",
|
|
||||||
HashPath: "awssdk.core.3.7.10.6.nupkg.sha512",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Microsoft.Extensions.DependencyInjection.Abstractions",
|
testCommon := pkg.Package{
|
||||||
Version: "6.0.0",
|
Name: "TestCommon",
|
||||||
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0",
|
Version: "1.0.0",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/TestCommon@1.0.0",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Microsoft.Extensions.DependencyInjection.Abstractions",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "6.0.0",
|
Name: "TestCommon",
|
||||||
Sha512: "sha512-xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==",
|
Version: "1.0.0",
|
||||||
Path: "microsoft.extensions.dependencyinjection.abstractions/6.0.0",
|
|
||||||
HashPath: "microsoft.extensions.dependencyinjection.abstractions.6.0.0.nupkg.sha512",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Microsoft.Extensions.DependencyInjection",
|
awssdkcore := pkg.Package{
|
||||||
Version: "6.0.0",
|
Name: "AWSSDK.Core",
|
||||||
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0",
|
Version: "3.7.10.6",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/AWSSDK.Core@3.7.10.6",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Microsoft.Extensions.DependencyInjection",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "6.0.0",
|
Name: "AWSSDK.Core",
|
||||||
Sha512: "sha512-k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
|
Version: "3.7.10.6",
|
||||||
Path: "microsoft.extensions.dependencyinjection/6.0.0",
|
Sha512: "sha512-kHBB+QmosVaG6DpngXQ8OlLVVNMzltNITfsRr68Z90qO7dSqJ2EHNd8dtBU1u3AQQLqqFHOY0lfmbpexeH6Pew==",
|
||||||
HashPath: "microsoft.extensions.dependencyinjection.6.0.0.nupkg.sha512",
|
Path: "awssdk.core/3.7.10.6",
|
||||||
},
|
HashPath: "awssdk.core.3.7.10.6.nupkg.sha512",
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Microsoft.Extensions.Logging.Abstractions",
|
msftDependencyInjectionAbstractions := pkg.Package{
|
||||||
Version: "6.0.0",
|
Name: "Microsoft.Extensions.DependencyInjection.Abstractions",
|
||||||
PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0",
|
Version: "6.0.0",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection.Abstractions@6.0.0",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Microsoft.Extensions.Logging.Abstractions",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "6.0.0",
|
Name: "Microsoft.Extensions.DependencyInjection.Abstractions",
|
||||||
Sha512: "sha512-/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA==",
|
Version: "6.0.0",
|
||||||
Path: "microsoft.extensions.logging.abstractions/6.0.0",
|
Sha512: "sha512-xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==",
|
||||||
HashPath: "microsoft.extensions.logging.abstractions.6.0.0.nupkg.sha512",
|
Path: "microsoft.extensions.dependencyinjection.abstractions/6.0.0",
|
||||||
},
|
HashPath: "microsoft.extensions.dependencyinjection.abstractions.6.0.0.nupkg.sha512",
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Microsoft.Extensions.Logging",
|
msftDependencyInjection := pkg.Package{
|
||||||
Version: "6.0.0",
|
Name: "Microsoft.Extensions.DependencyInjection",
|
||||||
PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0",
|
Version: "6.0.0",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Microsoft.Extensions.DependencyInjection@6.0.0",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Microsoft.Extensions.Logging",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "6.0.0",
|
Name: "Microsoft.Extensions.DependencyInjection",
|
||||||
Sha512: "sha512-eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
|
Version: "6.0.0",
|
||||||
Path: "microsoft.extensions.logging/6.0.0",
|
Sha512: "sha512-k6PWQMuoBDGGHOQTtyois2u4AwyVcIwL2LaSLlTZQm2CYcJ1pxbt6jfAnpWmzENA/wfrYRI/X9DTLoUkE4AsLw==",
|
||||||
HashPath: "microsoft.extensions.logging.6.0.0.nupkg.sha512",
|
Path: "microsoft.extensions.dependencyinjection/6.0.0",
|
||||||
},
|
HashPath: "microsoft.extensions.dependencyinjection.6.0.0.nupkg.sha512",
|
||||||
},
|
},
|
||||||
|
}
|
||||||
{
|
msftLoggingAbstractions := pkg.Package{
|
||||||
Name: "Microsoft.Extensions.Options",
|
Name: "Microsoft.Extensions.Logging.Abstractions",
|
||||||
Version: "6.0.0",
|
Version: "6.0.0",
|
||||||
PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0",
|
PURL: "pkg:nuget/Microsoft.Extensions.Logging.Abstractions@6.0.0",
|
||||||
Locations: fixtureLocationSet,
|
Locations: fixtureLocationSet,
|
||||||
Language: pkg.Dotnet,
|
Language: pkg.Dotnet,
|
||||||
Type: pkg.DotnetPkg,
|
Type: pkg.DotnetPkg,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Name: "Microsoft.Extensions.Options",
|
Name: "Microsoft.Extensions.Logging.Abstractions",
|
||||||
Version: "6.0.0",
|
Version: "6.0.0",
|
||||||
Sha512: "sha512-dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
|
Sha512: "sha512-/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA==",
|
||||||
Path: "microsoft.extensions.options/6.0.0",
|
Path: "microsoft.extensions.logging.abstractions/6.0.0",
|
||||||
HashPath: "microsoft.extensions.options.6.0.0.nupkg.sha512",
|
HashPath: "microsoft.extensions.logging.abstractions.6.0.0.nupkg.sha512",
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Microsoft.Extensions.Primitives",
|
msftExtensionsLogging := pkg.Package{
|
||||||
Version: "6.0.0",
|
Name: "Microsoft.Extensions.Logging",
|
||||||
PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0",
|
Version: "6.0.0",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Microsoft.Extensions.Logging@6.0.0",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Microsoft.Extensions.Primitives",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "6.0.0",
|
Name: "Microsoft.Extensions.Logging",
|
||||||
Sha512: "sha512-9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
Version: "6.0.0",
|
||||||
Path: "microsoft.extensions.primitives/6.0.0",
|
Sha512: "sha512-eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==",
|
||||||
HashPath: "microsoft.extensions.primitives.6.0.0.nupkg.sha512",
|
Path: "microsoft.extensions.logging/6.0.0",
|
||||||
},
|
HashPath: "microsoft.extensions.logging.6.0.0.nupkg.sha512",
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Newtonsoft.Json",
|
msftExtensionsOptions := pkg.Package{
|
||||||
Version: "13.0.1",
|
Name: "Microsoft.Extensions.Options",
|
||||||
PURL: "pkg:nuget/Newtonsoft.Json@13.0.1",
|
Version: "6.0.0",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Microsoft.Extensions.Options@6.0.0",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Newtonsoft.Json",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "13.0.1",
|
Name: "Microsoft.Extensions.Options",
|
||||||
Sha512: "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
|
Version: "6.0.0",
|
||||||
Path: "newtonsoft.json/13.0.1",
|
Sha512: "sha512-dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==",
|
||||||
HashPath: "newtonsoft.json.13.0.1.nupkg.sha512",
|
Path: "microsoft.extensions.options/6.0.0",
|
||||||
},
|
HashPath: "microsoft.extensions.options.6.0.0.nupkg.sha512",
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Serilog.Sinks.Console",
|
msftExtensionsPrimitives := pkg.Package{
|
||||||
Version: "4.0.1",
|
Name: "Microsoft.Extensions.Primitives",
|
||||||
PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1",
|
Version: "6.0.0",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Microsoft.Extensions.Primitives@6.0.0",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Serilog.Sinks.Console",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "4.0.1",
|
Name: "Microsoft.Extensions.Primitives",
|
||||||
Sha512: "sha512-apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==",
|
Version: "6.0.0",
|
||||||
Path: "serilog.sinks.console/4.0.1",
|
Sha512: "sha512-9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==",
|
||||||
HashPath: "serilog.sinks.console.4.0.1.nupkg.sha512",
|
Path: "microsoft.extensions.primitives/6.0.0",
|
||||||
},
|
HashPath: "microsoft.extensions.primitives.6.0.0.nupkg.sha512",
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "Serilog",
|
newtonsoftJson := pkg.Package{
|
||||||
Version: "2.10.0",
|
Name: "Newtonsoft.Json",
|
||||||
PURL: "pkg:nuget/Serilog@2.10.0",
|
Version: "13.0.1",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Newtonsoft.Json@13.0.1",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "Serilog",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "2.10.0",
|
Name: "Newtonsoft.Json",
|
||||||
Sha512: "sha512-+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==",
|
Version: "13.0.1",
|
||||||
Path: "serilog/2.10.0",
|
Sha512: "sha512-ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==",
|
||||||
HashPath: "serilog.2.10.0.nupkg.sha512",
|
Path: "newtonsoft.json/13.0.1",
|
||||||
},
|
HashPath: "newtonsoft.json.13.0.1.nupkg.sha512",
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "System.Diagnostics.DiagnosticSource",
|
serilogSinksConsole := pkg.Package{
|
||||||
Version: "6.0.0",
|
Name: "Serilog.Sinks.Console",
|
||||||
PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0",
|
Version: "4.0.1",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Serilog.Sinks.Console@4.0.1",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "System.Diagnostics.DiagnosticSource",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "6.0.0",
|
Name: "Serilog.Sinks.Console",
|
||||||
Sha512: "sha512-frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==",
|
Version: "4.0.1",
|
||||||
Path: "system.diagnostics.diagnosticsource/6.0.0",
|
Sha512: "sha512-apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==",
|
||||||
HashPath: "system.diagnostics.diagnosticsource.6.0.0.nupkg.sha512",
|
Path: "serilog.sinks.console/4.0.1",
|
||||||
},
|
HashPath: "serilog.sinks.console.4.0.1.nupkg.sha512",
|
||||||
},
|
},
|
||||||
{
|
}
|
||||||
Name: "System.Runtime.CompilerServices.Unsafe",
|
serilog := pkg.Package{
|
||||||
Version: "6.0.0",
|
Name: "Serilog",
|
||||||
PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0",
|
Version: "2.10.0",
|
||||||
Locations: fixtureLocationSet,
|
PURL: "pkg:nuget/Serilog@2.10.0",
|
||||||
Language: pkg.Dotnet,
|
Locations: fixtureLocationSet,
|
||||||
Type: pkg.DotnetPkg,
|
Language: pkg.Dotnet,
|
||||||
MetadataType: pkg.DotnetDepsMetadataType,
|
Type: pkg.DotnetPkg,
|
||||||
Metadata: pkg.DotnetDepsMetadata{
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
Name: "System.Runtime.CompilerServices.Unsafe",
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
Version: "6.0.0",
|
Name: "Serilog",
|
||||||
Sha512: "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
|
Version: "2.10.0",
|
||||||
Path: "system.runtime.compilerservices.unsafe/6.0.0",
|
Sha512: "sha512-+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==",
|
||||||
HashPath: "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
|
Path: "serilog/2.10.0",
|
||||||
},
|
HashPath: "serilog.2.10.0.nupkg.sha512",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
systemDiagnosticsDiagnosticsource := pkg.Package{
|
||||||
|
Name: "System.Diagnostics.DiagnosticSource",
|
||||||
|
Version: "6.0.0",
|
||||||
|
PURL: "pkg:nuget/System.Diagnostics.DiagnosticSource@6.0.0",
|
||||||
|
Locations: fixtureLocationSet,
|
||||||
|
Language: pkg.Dotnet,
|
||||||
|
Type: pkg.DotnetPkg,
|
||||||
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
|
Name: "System.Diagnostics.DiagnosticSource",
|
||||||
|
Version: "6.0.0",
|
||||||
|
Sha512: "sha512-frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==",
|
||||||
|
Path: "system.diagnostics.diagnosticsource/6.0.0",
|
||||||
|
HashPath: "system.diagnostics.diagnosticsource.6.0.0.nupkg.sha512",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
systemRuntimeCompilerServicesUnsafe := pkg.Package{
|
||||||
|
Name: "System.Runtime.CompilerServices.Unsafe",
|
||||||
|
Version: "6.0.0",
|
||||||
|
PURL: "pkg:nuget/System.Runtime.CompilerServices.Unsafe@6.0.0",
|
||||||
|
Locations: fixtureLocationSet,
|
||||||
|
Language: pkg.Dotnet,
|
||||||
|
Type: pkg.DotnetPkg,
|
||||||
|
MetadataType: pkg.DotnetDepsMetadataType,
|
||||||
|
Metadata: pkg.DotnetDepsMetadata{
|
||||||
|
Name: "System.Runtime.CompilerServices.Unsafe",
|
||||||
|
Version: "6.0.0",
|
||||||
|
Sha512: "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
|
||||||
|
Path: "system.runtime.compilerservices.unsafe/6.0.0",
|
||||||
|
HashPath: "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedRelationships []artifact.Relationship
|
expectedPkgs := []pkg.Package{
|
||||||
pkgtest.TestFileParser(t, fixture, parseDotnetDeps, expected, expectedRelationships)
|
awssdkcore,
|
||||||
|
msftDependencyInjection,
|
||||||
|
msftDependencyInjectionAbstractions,
|
||||||
|
msftExtensionsLogging,
|
||||||
|
msftLoggingAbstractions,
|
||||||
|
msftExtensionsOptions,
|
||||||
|
msftExtensionsPrimitives,
|
||||||
|
newtonsoftJson,
|
||||||
|
serilog,
|
||||||
|
serilogSinksConsole,
|
||||||
|
systemDiagnosticsDiagnosticsource,
|
||||||
|
systemRuntimeCompilerServicesUnsafe,
|
||||||
|
testCommon,
|
||||||
|
rootPkg,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ┌── (✓ = is represented in the test)
|
||||||
|
// ↓
|
||||||
|
//
|
||||||
|
// ✓ TestLibrary/1.0.0 (project)
|
||||||
|
// ✓ ├── [a] Microsoft.Extensions.DependencyInjection/6.0.0 [file version: 6.0.21.52210]
|
||||||
|
// ✓ │ ├── [b] Microsoft.Extensions.DependencyInjection.Abstractions/6.0.0 [file version: 6.0.21.52210]
|
||||||
|
// ✓ │ └── [c!] System.Runtime.CompilerServices.Unsafe/6.0.0 [NO TARGET INFO]
|
||||||
|
// ✓ ├── Microsoft.Extensions.Logging/6.0.0 [file version: 6.0.21.52210]
|
||||||
|
// ✓ │ ├── Microsoft.Extensions.DependencyInjection/6.0.0 ...to [a]
|
||||||
|
// ✓ │ ├── Microsoft.Extensions.DependencyInjection.Abstractions/6.0.0 ...to [b]
|
||||||
|
// ✓ │ ├── Microsoft.Extensions.Logging.Abstractions/6.0.0 [file version: 6.0.21.52210]
|
||||||
|
// ✓ │ ├── Microsoft.Extensions.Options/6.0.0 [file version: 6.0.21.52210]
|
||||||
|
// ✓ │ │ ├── Microsoft.Extensions.DependencyInjection.Abstractions/6.0.0 ...to [b]
|
||||||
|
// ✓ │ │ └── Microsoft.Extensions.Primitives/6.0.0 [file version: 6.0.21.52210]
|
||||||
|
// ✓ │ │ └── System.Runtime.CompilerServices.Unsafe/6.0.0 ...to [c!]
|
||||||
|
// ✓ │ └── System.Diagnostics.DiagnosticSource/6.0.0 [NO RUNTIME INFO]
|
||||||
|
// ✓ │ └── System.Runtime.CompilerServices.Unsafe/6.0.0 ...to [c!]
|
||||||
|
// ✓ ├── Newtonsoft.Json/13.0.1 [file version: 13.0.1.25517]
|
||||||
|
// ✓ ├── [d] Serilog/2.10.0 [file version: 2.10.0.0]
|
||||||
|
// ✓ ├── Serilog.Sinks.Console/4.0.1 [file version: 4.0.1.0]
|
||||||
|
// ✓ │ └── Serilog/2.10.0 ...to [d]
|
||||||
|
// ✓ └── [e!] TestCommon/1.0.0 [NOT SERVICEABLE / NO SHA]
|
||||||
|
// ✓ └── AWSSDK.Core/3.7.10.6 [file version: 3.7.10.6]
|
||||||
|
|
||||||
|
expectedRelationships := []artifact.Relationship{
|
||||||
|
{
|
||||||
|
From: awssdkcore,
|
||||||
|
To: testCommon,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftDependencyInjection,
|
||||||
|
To: msftExtensionsLogging,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftDependencyInjection,
|
||||||
|
To: rootPkg,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftDependencyInjectionAbstractions,
|
||||||
|
To: msftDependencyInjection,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftDependencyInjectionAbstractions,
|
||||||
|
To: msftExtensionsLogging,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftDependencyInjectionAbstractions,
|
||||||
|
To: msftExtensionsOptions,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftExtensionsLogging,
|
||||||
|
To: rootPkg,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftLoggingAbstractions,
|
||||||
|
To: msftExtensionsLogging,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftExtensionsOptions,
|
||||||
|
To: msftExtensionsLogging,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: msftExtensionsPrimitives,
|
||||||
|
To: msftExtensionsOptions,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: newtonsoftJson,
|
||||||
|
To: rootPkg,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: serilog,
|
||||||
|
To: serilogSinksConsole,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: serilog,
|
||||||
|
To: rootPkg,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: serilogSinksConsole,
|
||||||
|
To: rootPkg,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: systemDiagnosticsDiagnosticsource,
|
||||||
|
To: msftExtensionsLogging,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: systemRuntimeCompilerServicesUnsafe,
|
||||||
|
To: msftDependencyInjection,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: systemRuntimeCompilerServicesUnsafe,
|
||||||
|
To: msftExtensionsPrimitives,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: systemRuntimeCompilerServicesUnsafe,
|
||||||
|
To: systemDiagnosticsDiagnosticsource,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
From: testCommon,
|
||||||
|
To: rootPkg,
|
||||||
|
Type: artifact.DependencyOfRelationship,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgtest.TestFileParser(t, fixture, parseDotnetDeps, expectedPkgs, expectedRelationships)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -329,6 +329,10 @@ func (p *CatalogTester) assertPkgs(t *testing.T, pkgs []pkg.Package, relationshi
|
|||||||
opts = append(opts, p.compareOptions...)
|
opts = append(opts, p.compareOptions...)
|
||||||
opts = append(opts, cmp.Reporter(&r))
|
opts = append(opts, cmp.Reporter(&r))
|
||||||
|
|
||||||
|
// order should not matter
|
||||||
|
pkg.Sort(p.expectedPkgs)
|
||||||
|
pkg.Sort(pkgs)
|
||||||
|
|
||||||
if diff := cmp.Diff(p.expectedPkgs, pkgs, opts...); diff != "" {
|
if diff := cmp.Diff(p.expectedPkgs, pkgs, opts...); diff != "" {
|
||||||
t.Log("Specific Differences:\n" + r.String())
|
t.Log("Specific Differences:\n" + r.String())
|
||||||
t.Errorf("unexpected packages from parsing (-expected +actual)\n%s", diff)
|
t.Errorf("unexpected packages from parsing (-expected +actual)\n%s", diff)
|
||||||
@ -341,6 +345,10 @@ func (p *CatalogTester) assertPkgs(t *testing.T, pkgs []pkg.Package, relationshi
|
|||||||
opts = append(opts, p.compareOptions...)
|
opts = append(opts, p.compareOptions...)
|
||||||
opts = append(opts, cmp.Reporter(&r))
|
opts = append(opts, cmp.Reporter(&r))
|
||||||
|
|
||||||
|
// order should not matter
|
||||||
|
pkg.SortRelationships(p.expectedRelationships)
|
||||||
|
pkg.SortRelationships(relationships)
|
||||||
|
|
||||||
if diff := cmp.Diff(p.expectedRelationships, relationships, opts...); diff != "" {
|
if diff := cmp.Diff(p.expectedRelationships, relationships, opts...); diff != "" {
|
||||||
t.Log("Specific Differences:\n" + r.String())
|
t.Log("Specific Differences:\n" + r.String())
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,47 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
import "github.com/anchore/syft/syft/artifact"
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/artifact"
|
||||||
|
)
|
||||||
|
|
||||||
func NewRelationships(catalog *Collection) []artifact.Relationship {
|
func NewRelationships(catalog *Collection) []artifact.Relationship {
|
||||||
rels := RelationshipsByFileOwnership(catalog)
|
rels := RelationshipsByFileOwnership(catalog)
|
||||||
rels = append(rels, RelationshipsEvidentBy(catalog)...)
|
rels = append(rels, RelationshipsEvidentBy(catalog)...)
|
||||||
return rels
|
return rels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SortRelationships takes a set of package-to-package relationships and sorts them in a stable order by name and version.
|
||||||
|
// Note: this does not consider package-to-other, other-to-package, or other-to-other relationships.
|
||||||
|
// TODO: ideally this should be replaced with a more type-agnostic sort function that resides in the artifact package.
|
||||||
|
func SortRelationships(rels []artifact.Relationship) {
|
||||||
|
sort.SliceStable(rels, func(i, j int) bool {
|
||||||
|
return relationshipLess(rels[i], rels[j])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func relationshipLess(i, j artifact.Relationship) bool {
|
||||||
|
iFrom, ok1 := i.From.(Package)
|
||||||
|
iTo, ok2 := i.To.(Package)
|
||||||
|
jFrom, ok3 := j.From.(Package)
|
||||||
|
jTo, ok4 := j.To.(Package)
|
||||||
|
|
||||||
|
if !(ok1 && ok2 && ok3 && ok4) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if iFrom.Name != jFrom.Name {
|
||||||
|
return iFrom.Name < jFrom.Name
|
||||||
|
}
|
||||||
|
if iFrom.Version != jFrom.Version {
|
||||||
|
return iFrom.Version < jFrom.Version
|
||||||
|
}
|
||||||
|
if iTo.Name != jTo.Name {
|
||||||
|
return iTo.Name < jTo.Name
|
||||||
|
}
|
||||||
|
if iTo.Version != jTo.Version {
|
||||||
|
return iTo.Version < jTo.Version
|
||||||
|
}
|
||||||
|
return i.Type < j.Type
|
||||||
|
}
|
||||||
|
|||||||
@ -247,6 +247,8 @@ var dirOnlyTestCases = []testCase{
|
|||||||
"Serilog.Sinks.Console": "4.0.1",
|
"Serilog.Sinks.Console": "4.0.1",
|
||||||
"System.Diagnostics.DiagnosticSource": "6.0.0",
|
"System.Diagnostics.DiagnosticSource": "6.0.0",
|
||||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
|
||||||
|
"TestCommon": "1.0.0",
|
||||||
|
"TestLibrary": "1.0.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user