Skip to content

Commit

Permalink
fix: properly parse conan ref and include user and channel (#2034)
Browse files Browse the repository at this point in the history
* fix: properly parse conan ref and include user and channel

Signed-off-by: Stefan Profanter <[email protected]>

* unexport the conanRef type

Signed-off-by: Alex Goodman <[email protected]>

---------

Signed-off-by: Stefan Profanter <[email protected]>
Signed-off-by: Alex Goodman <[email protected]>
Co-authored-by: Alex Goodman <[email protected]>
  • Loading branch information
Pro and wagoodman authored Aug 23, 2023
1 parent a2b3895 commit 07ac640
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 48 deletions.
95 changes: 70 additions & 25 deletions syft/pkg/cataloger/cpp/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

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
}

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,
Expand All @@ -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,
Expand All @@ -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()
}
2 changes: 1 addition & 1 deletion syft/pkg/cataloger/cpp/parse_conanfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
10 changes: 5 additions & 5 deletions syft/pkg/cataloger/cpp/parse_conanfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ func TestParseConanfile(t *testing.T) {
{
Name: "spdlog",
Version: "1.9.2",
PURL: "pkg:conan/[email protected]",
PURL: "pkg:conan/my_user/[email protected]?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",
},
},
{
Expand All @@ -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/[email protected]",
PURL: "pkg:conan/my_user/[email protected]?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",
},
},
}
Expand Down
43 changes: 36 additions & 7 deletions syft/pkg/cataloger/cpp/parse_conanlock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
"shared": "False",
"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/[email protected]?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",
},
},
Expand Down
23 changes: 16 additions & 7 deletions syft/pkg/cataloger/cpp/test-fixtures/conan.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
6 changes: 3 additions & 3 deletions syft/pkg/cataloger/cpp/test-fixtures/conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 07ac640

Please sign in to comment.