mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 08:23:15 +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"
|
||||
)
|
||||
|
||||
func newConanfilePackage(m pkg.ConanMetadata, locations ...file.Location) *pkg.Package {
|
||||
fields := strings.Split(strings.TrimSpace(m.Ref), "/")
|
||||
if len(fields) < 2 {
|
||||
return nil
|
||||
type conanRef struct {
|
||||
Name string
|
||||
Version string
|
||||
User string
|
||||
Channel string
|
||||
Revision string
|
||||
Timestamp string
|
||||
}
|
||||
|
||||
pkgName, pkgVersion := fields[0], fields[1]
|
||||
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
|
||||
|
||||
if pkgName == "" || pkgVersion == "" {
|
||||
var cref conanRef
|
||||
|
||||
// timestamp
|
||||
tokens := strings.Split(ref, "%")
|
||||
text := tokens[0]
|
||||
if len(tokens) == 2 {
|
||||
cref.Timestamp = tokens[1]
|
||||
}
|
||||
|
||||
// revision
|
||||
tokens = strings.Split(text, "#")
|
||||
ref = tokens[0]
|
||||
if len(tokens) == 2 {
|
||||
cref.Revision = tokens[1]
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
p := pkg.Package{
|
||||
Name: pkgName,
|
||||
Version: pkgVersion,
|
||||
Name: ref.Name,
|
||||
Version: ref.Version,
|
||||
Locations: file.NewLocationSet(locations...),
|
||||
PURL: packageURL(pkgName, pkgVersion),
|
||||
PURL: packageURL(ref),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
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 {
|
||||
fields := strings.Split(strings.Split(m.Ref, "@")[0], "/")
|
||||
if len(fields) < 2 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pkgName, pkgVersion := fields[0], fields[1]
|
||||
|
||||
if pkgName == "" || pkgVersion == "" {
|
||||
ref := splitConanRef(m.Ref)
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
p := pkg.Package{
|
||||
Name: pkgName,
|
||||
Version: pkgVersion,
|
||||
Name: ref.Name,
|
||||
Version: ref.Version,
|
||||
Locations: file.NewLocationSet(locations...),
|
||||
PURL: packageURL(pkgName, pkgVersion),
|
||||
PURL: packageURL(ref),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
@ -64,13 +102,20 @@ func newConanlockPackage(m pkg.ConanLockMetadata, locations ...file.Location) *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(
|
||||
packageurl.TypeConan,
|
||||
"",
|
||||
name,
|
||||
version,
|
||||
nil, // TODO: no qualifiers (...yet)
|
||||
ref.User,
|
||||
ref.Name,
|
||||
ref.Version,
|
||||
qualifiers,
|
||||
"",
|
||||
).ToString()
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ func parseConanfile(_ file.Resolver, _ *generic.Environment, reader file.Locatio
|
||||
switch {
|
||||
case strings.Contains(line, "[requires]"):
|
||||
inRequirements = true
|
||||
case strings.ContainsAny(line, "[]#"):
|
||||
case strings.ContainsAny(line, "[]") || strings.HasPrefix(strings.TrimSpace(line), "#"):
|
||||
inRequirements = false
|
||||
}
|
||||
|
||||
|
||||
@ -52,13 +52,13 @@ func TestParseConanfile(t *testing.T) {
|
||||
{
|
||||
Name: "spdlog",
|
||||
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,
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanMetadataType,
|
||||
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,
|
||||
MetadataType: pkg.ConanMetadataType,
|
||||
Metadata: pkg.ConanMetadata{
|
||||
Ref: "sdl/2.0.20",
|
||||
Ref: "sdl/2.0.20#1234567%%987654",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "fltk",
|
||||
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,
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanMetadataType,
|
||||
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"
|
||||
expected := []pkg.Package{
|
||||
{
|
||||
Name: "zlib",
|
||||
Version: "1.2.12",
|
||||
PURL: "pkg:conan/zlib@1.2.12",
|
||||
Name: "spdlog",
|
||||
Version: "1.11.0",
|
||||
PURL: "pkg:conan/spdlog@1.11.0",
|
||||
Locations: file.NewLocationSet(file.NewLocation(fixture)),
|
||||
Language: pkg.CPP,
|
||||
Type: pkg.ConanPkg,
|
||||
MetadataType: pkg.ConanLockMetadataType,
|
||||
Metadata: pkg.ConanLockMetadata{
|
||||
Ref: "zlib/1.2.12",
|
||||
Ref: "spdlog/1.11.0",
|
||||
Options: map[string]string{
|
||||
"fPIC": "True",
|
||||
"header_only": "False",
|
||||
"no_exceptions": "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",
|
||||
},
|
||||
},
|
||||
|
||||
@ -2,15 +2,24 @@
|
||||
"graph_lock": {
|
||||
"nodes": {
|
||||
"0": {
|
||||
"ref": "zlib/1.2.12",
|
||||
"options": "fPIC=True\nshared=False",
|
||||
"requires": [],
|
||||
"path": "all/conanfile.py",
|
||||
"ref": "spdlog/1.11.0",
|
||||
"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": [
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"revisions_enabled": false
|
||||
"revisions_enabled": true
|
||||
},
|
||||
"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
|
||||
docopt.cpp/0.6.3
|
||||
fmt/8.1.1
|
||||
spdlog/1.9.2
|
||||
sdl/2.0.20
|
||||
fltk/1.3.8
|
||||
spdlog/1.9.2@my_user/my_channel#1234567%%987654
|
||||
sdl/2.0.20#1234567%%987654
|
||||
fltk/1.3.8@my_user/my_channel
|
||||
|
||||
[generators]
|
||||
cmake_find_package_multi
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user