mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
fix: properly parse conan ref and include user and channel (#2034)
* fix: properly parse conan ref and include user and channel Signed-off-by: Stefan Profanter <stefan.profanter@agile-robots.com> * unexport the conanRef type Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com> --------- Signed-off-by: Stefan Profanter <stefan.profanter@agile-robots.com> 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
a2b389523d
commit
07ac640ac5
@ -8,23 +8,67 @@ import (
|
|||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newConanfilePackage(m pkg.ConanMetadata, locations ...file.Location) *pkg.Package {
|
type conanRef struct {
|
||||||
fields := strings.Split(strings.TrimSpace(m.Ref), "/")
|
Name string
|
||||||
if len(fields) < 2 {
|
Version string
|
||||||
return nil
|
User string
|
||||||
|
Channel string
|
||||||
|
Revision string
|
||||||
|
Timestamp string
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitConanRef(ref string) *conanRef {
|
||||||
|
// Conan ref format is:
|
||||||
|
// pkg/0.1@user/channel#rrev%timestamp
|
||||||
|
// This method is based on conan's ref.loads method:
|
||||||
|
// https://github.com/conan-io/conan/blob/release/2.0/conans/model/recipe_ref.py#L93C21-L93C21
|
||||||
|
|
||||||
|
var cref conanRef
|
||||||
|
|
||||||
|
// timestamp
|
||||||
|
tokens := strings.Split(ref, "%")
|
||||||
|
text := tokens[0]
|
||||||
|
if len(tokens) == 2 {
|
||||||
|
cref.Timestamp = tokens[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgName, pkgVersion := fields[0], fields[1]
|
// revision
|
||||||
|
tokens = strings.Split(text, "#")
|
||||||
|
ref = tokens[0]
|
||||||
|
if len(tokens) == 2 {
|
||||||
|
cref.Revision = tokens[1]
|
||||||
|
}
|
||||||
|
|
||||||
if pkgName == "" || pkgVersion == "" {
|
// name and version are always given
|
||||||
|
tokens = strings.Split(ref, "@")
|
||||||
|
nameAndVersion := strings.Split(tokens[0], "/")
|
||||||
|
if len(nameAndVersion) < 2 || nameAndVersion[0] == "" || nameAndVersion[1] == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
cref.Name = nameAndVersion[0]
|
||||||
|
cref.Version = nameAndVersion[1]
|
||||||
|
// user and channel
|
||||||
|
if len(tokens) == 2 && tokens[1] != "" {
|
||||||
|
tokens = strings.Split(tokens[1], "/")
|
||||||
|
if len(tokens) == 2 {
|
||||||
|
cref.User = tokens[0]
|
||||||
|
cref.Channel = tokens[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &cref
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConanfilePackage(m pkg.ConanMetadata, locations ...file.Location) *pkg.Package {
|
||||||
|
ref := splitConanRef(m.Ref)
|
||||||
|
if ref == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
p := pkg.Package{
|
p := pkg.Package{
|
||||||
Name: pkgName,
|
Name: ref.Name,
|
||||||
Version: pkgVersion,
|
Version: ref.Version,
|
||||||
Locations: file.NewLocationSet(locations...),
|
Locations: file.NewLocationSet(locations...),
|
||||||
PURL: packageURL(pkgName, pkgVersion),
|
PURL: packageURL(ref),
|
||||||
Language: pkg.CPP,
|
Language: pkg.CPP,
|
||||||
Type: pkg.ConanPkg,
|
Type: pkg.ConanPkg,
|
||||||
MetadataType: pkg.ConanMetadataType,
|
MetadataType: pkg.ConanMetadataType,
|
||||||
@ -37,22 +81,16 @@ func newConanfilePackage(m pkg.ConanMetadata, locations ...file.Location) *pkg.P
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newConanlockPackage(m pkg.ConanLockMetadata, locations ...file.Location) *pkg.Package {
|
func newConanlockPackage(m pkg.ConanLockMetadata, locations ...file.Location) *pkg.Package {
|
||||||
fields := strings.Split(strings.Split(m.Ref, "@")[0], "/")
|
ref := splitConanRef(m.Ref)
|
||||||
if len(fields) < 2 {
|
if ref == nil {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgName, pkgVersion := fields[0], fields[1]
|
|
||||||
|
|
||||||
if pkgName == "" || pkgVersion == "" {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
p := pkg.Package{
|
p := pkg.Package{
|
||||||
Name: pkgName,
|
Name: ref.Name,
|
||||||
Version: pkgVersion,
|
Version: ref.Version,
|
||||||
Locations: file.NewLocationSet(locations...),
|
Locations: file.NewLocationSet(locations...),
|
||||||
PURL: packageURL(pkgName, pkgVersion),
|
PURL: packageURL(ref),
|
||||||
Language: pkg.CPP,
|
Language: pkg.CPP,
|
||||||
Type: pkg.ConanPkg,
|
Type: pkg.ConanPkg,
|
||||||
MetadataType: pkg.ConanLockMetadataType,
|
MetadataType: pkg.ConanLockMetadataType,
|
||||||
@ -64,13 +102,20 @@ func newConanlockPackage(m pkg.ConanLockMetadata, locations ...file.Location) *p
|
|||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
func packageURL(name, version string) string {
|
func packageURL(ref *conanRef) string {
|
||||||
|
qualifiers := packageurl.Qualifiers{}
|
||||||
|
if ref.Channel != "" {
|
||||||
|
qualifiers = append(qualifiers, packageurl.Qualifier{
|
||||||
|
Key: "channel",
|
||||||
|
Value: ref.Channel,
|
||||||
|
})
|
||||||
|
}
|
||||||
return packageurl.NewPackageURL(
|
return packageurl.NewPackageURL(
|
||||||
packageurl.TypeConan,
|
packageurl.TypeConan,
|
||||||
"",
|
ref.User,
|
||||||
name,
|
ref.Name,
|
||||||
version,
|
ref.Version,
|
||||||
nil, // TODO: no qualifiers (...yet)
|
qualifiers,
|
||||||
"",
|
"",
|
||||||
).ToString()
|
).ToString()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ func parseConanfile(_ file.Resolver, _ *generic.Environment, reader file.Locatio
|
|||||||
switch {
|
switch {
|
||||||
case strings.Contains(line, "[requires]"):
|
case strings.Contains(line, "[requires]"):
|
||||||
inRequirements = true
|
inRequirements = true
|
||||||
case strings.ContainsAny(line, "[]#"):
|
case strings.ContainsAny(line, "[]") || strings.HasPrefix(strings.TrimSpace(line), "#"):
|
||||||
inRequirements = false
|
inRequirements = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -52,13 +52,13 @@ func TestParseConanfile(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "spdlog",
|
Name: "spdlog",
|
||||||
Version: "1.9.2",
|
Version: "1.9.2",
|
||||||
PURL: "pkg:conan/spdlog@1.9.2",
|
PURL: "pkg:conan/my_user/spdlog@1.9.2?channel=my_channel",
|
||||||
Locations: fixtureLocationSet,
|
Locations: fixtureLocationSet,
|
||||||
Language: pkg.CPP,
|
Language: pkg.CPP,
|
||||||
Type: pkg.ConanPkg,
|
Type: pkg.ConanPkg,
|
||||||
MetadataType: pkg.ConanMetadataType,
|
MetadataType: pkg.ConanMetadataType,
|
||||||
Metadata: pkg.ConanMetadata{
|
Metadata: pkg.ConanMetadata{
|
||||||
Ref: "spdlog/1.9.2",
|
Ref: "spdlog/1.9.2@my_user/my_channel#1234567%%987654",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -70,19 +70,19 @@ func TestParseConanfile(t *testing.T) {
|
|||||||
Type: pkg.ConanPkg,
|
Type: pkg.ConanPkg,
|
||||||
MetadataType: pkg.ConanMetadataType,
|
MetadataType: pkg.ConanMetadataType,
|
||||||
Metadata: pkg.ConanMetadata{
|
Metadata: pkg.ConanMetadata{
|
||||||
Ref: "sdl/2.0.20",
|
Ref: "sdl/2.0.20#1234567%%987654",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "fltk",
|
Name: "fltk",
|
||||||
Version: "1.3.8",
|
Version: "1.3.8",
|
||||||
PURL: "pkg:conan/fltk@1.3.8",
|
PURL: "pkg:conan/my_user/fltk@1.3.8?channel=my_channel",
|
||||||
Locations: fixtureLocationSet,
|
Locations: fixtureLocationSet,
|
||||||
Language: pkg.CPP,
|
Language: pkg.CPP,
|
||||||
Type: pkg.ConanPkg,
|
Type: pkg.ConanPkg,
|
||||||
MetadataType: pkg.ConanMetadataType,
|
MetadataType: pkg.ConanMetadataType,
|
||||||
Metadata: pkg.ConanMetadata{
|
Metadata: pkg.ConanMetadata{
|
||||||
Ref: "fltk/1.3.8",
|
Ref: "fltk/1.3.8@my_user/my_channel",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,20 +13,49 @@ func TestParseConanlock(t *testing.T) {
|
|||||||
fixture := "test-fixtures/conan.lock"
|
fixture := "test-fixtures/conan.lock"
|
||||||
expected := []pkg.Package{
|
expected := []pkg.Package{
|
||||||
{
|
{
|
||||||
Name: "zlib",
|
Name: "spdlog",
|
||||||
Version: "1.2.12",
|
Version: "1.11.0",
|
||||||
PURL: "pkg:conan/zlib@1.2.12",
|
PURL: "pkg:conan/spdlog@1.11.0",
|
||||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||||
Language: pkg.CPP,
|
Language: pkg.CPP,
|
||||||
Type: pkg.ConanPkg,
|
Type: pkg.ConanPkg,
|
||||||
MetadataType: pkg.ConanLockMetadataType,
|
MetadataType: pkg.ConanLockMetadataType,
|
||||||
Metadata: pkg.ConanLockMetadata{
|
Metadata: pkg.ConanLockMetadata{
|
||||||
Ref: "zlib/1.2.12",
|
Ref: "spdlog/1.11.0",
|
||||||
Options: map[string]string{
|
Options: map[string]string{
|
||||||
"fPIC": "True",
|
"fPIC": "True",
|
||||||
|
"header_only": "False",
|
||||||
|
"no_exceptions": "False",
|
||||||
"shared": "False",
|
"shared": "False",
|
||||||
|
"wchar_filenames": "False",
|
||||||
|
"wchar_support": "False",
|
||||||
|
"fmt:fPIC": "True",
|
||||||
|
"fmt:header_only": "False",
|
||||||
|
"fmt:shared": "False",
|
||||||
|
"fmt:with_fmt_alias": "False",
|
||||||
|
"fmt:with_os_api": "True",
|
||||||
|
},
|
||||||
|
Path: "conanfile.py",
|
||||||
|
Context: "host",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "fmt",
|
||||||
|
Version: "9.1.0",
|
||||||
|
PURL: "pkg:conan/my_user/fmt@9.1.0?channel=my_channel",
|
||||||
|
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||||
|
Language: pkg.CPP,
|
||||||
|
Type: pkg.ConanPkg,
|
||||||
|
MetadataType: pkg.ConanLockMetadataType,
|
||||||
|
Metadata: pkg.ConanLockMetadata{
|
||||||
|
Ref: "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba",
|
||||||
|
Options: map[string]string{
|
||||||
|
"fPIC": "True",
|
||||||
|
"header_only": "False",
|
||||||
|
"shared": "False",
|
||||||
|
"with_fmt_alias": "False",
|
||||||
|
"with_os_api": "True",
|
||||||
},
|
},
|
||||||
Path: "all/conanfile.py",
|
|
||||||
Context: "host",
|
Context: "host",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,15 +2,24 @@
|
|||||||
"graph_lock": {
|
"graph_lock": {
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"0": {
|
"0": {
|
||||||
"ref": "zlib/1.2.12",
|
"ref": "spdlog/1.11.0",
|
||||||
"options": "fPIC=True\nshared=False",
|
"options": "fPIC=True\nheader_only=False\nno_exceptions=False\nshared=False\nwchar_filenames=False\nwchar_support=False\nfmt:fPIC=True\nfmt:header_only=False\nfmt:shared=False\nfmt:with_fmt_alias=False\nfmt:with_os_api=True",
|
||||||
"requires": [],
|
"requires": [
|
||||||
"path": "all/conanfile.py",
|
"1"
|
||||||
|
],
|
||||||
|
"path": "conanfile.py",
|
||||||
|
"context": "host"
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"ref": "fmt/9.1.0@my_user/my_channel#6708c9d84f98d56a6d9f2e6c2d5639ba",
|
||||||
|
"options": "fPIC=True\nheader_only=False\nshared=False\nwith_fmt_alias=False\nwith_os_api=True",
|
||||||
|
"package_id": "2c09c8f84c016041549fcee94e4caae5d89424b6",
|
||||||
|
"prev": "9f5ab13fc7c73e4a9f87e4e213f2cfa4",
|
||||||
"context": "host"
|
"context": "host"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"revisions_enabled": false
|
"revisions_enabled": true
|
||||||
},
|
},
|
||||||
"version": "0.4",
|
"version": "0.4",
|
||||||
"profile_host": "[settings]\narch=x86_64\narch_build=x86_64\nbuild_type=Release\ncompiler=gcc\ncompiler.libcxx=libstdc++\ncompiler.version=9\nos=Linux\nos_build=Linux\n[options]\n[build_requires]\n[env]\n"
|
"profile_host": "[settings]\narch=x86_64\narch.march=None\narch_build=x86_64\nbuild_type=Release\ncompiler=gcc\ncompiler.libcxx=libstdc++11\ncompiler.version=11\nos=Linux\nos_build=Linux\n[options]\n[build_requires]\n[env]\n"
|
||||||
}
|
}
|
||||||
@ -4,9 +4,9 @@
|
|||||||
catch2/2.13.8
|
catch2/2.13.8
|
||||||
docopt.cpp/0.6.3
|
docopt.cpp/0.6.3
|
||||||
fmt/8.1.1
|
fmt/8.1.1
|
||||||
spdlog/1.9.2
|
spdlog/1.9.2@my_user/my_channel#1234567%%987654
|
||||||
sdl/2.0.20
|
sdl/2.0.20#1234567%%987654
|
||||||
fltk/1.3.8
|
fltk/1.3.8@my_user/my_channel
|
||||||
|
|
||||||
[generators]
|
[generators]
|
||||||
cmake_find_package_multi
|
cmake_find_package_multi
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user