Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 776164a

Browse files
authored
Merge pull request anchore#427 from anchore/epoch-fix
Allow for RPM package epoch to be optionally provided in the version field
2 parents 2754c88 + 5ea1d78 commit 776164a

File tree

7 files changed

+138
-57
lines changed

7 files changed

+138
-57
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/adrg/xdg v0.2.1
88
github.com/alecthomas/jsonschema v0.0.0-20210301060011-54c507b6f074
99
github.com/anchore/client-go v0.0.0-20210222170800-9c70f9b80bcf
10-
github.com/anchore/go-rpmdb v0.0.0-20210415132930-2460011e83c6
10+
github.com/anchore/go-rpmdb v0.0.0-20210602151223-1f0f707a2894
1111
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
1212
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
1313
github.com/anchore/stereoscope v0.0.0-20210524175238-3b7662f3a66f

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
109109
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
110110
github.com/anchore/client-go v0.0.0-20210222170800-9c70f9b80bcf h1:DYssiUV1pBmKqzKsm4mqXx8artqC0Q8HgZsVI3lMsAg=
111111
github.com/anchore/client-go v0.0.0-20210222170800-9c70f9b80bcf/go.mod h1:FaODhIA06mxO1E6R32JE0TL1JWZZkmjRIAd4ULvHUKk=
112-
github.com/anchore/go-rpmdb v0.0.0-20210415132930-2460011e83c6 h1:wEN3HXc3VuC4wo7Cz27YCpeQ4gaB5ASKwMwM5GdFsew=
113-
github.com/anchore/go-rpmdb v0.0.0-20210415132930-2460011e83c6/go.mod h1:8jNYOxCJC5kyD/Ct4MbzsDN2hOhRoCAzQcb/7KdYYGw=
112+
github.com/anchore/go-rpmdb v0.0.0-20210602151223-1f0f707a2894 h1:VvCq7fFNU8dwWkCTGUykm4p64nVaDCYkKrj87x350Sk=
113+
github.com/anchore/go-rpmdb v0.0.0-20210602151223-1f0f707a2894/go.mod h1:8jNYOxCJC5kyD/Ct4MbzsDN2hOhRoCAzQcb/7KdYYGw=
114114
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0vW0nnNKJfJieyH/TZ9UYAnTZs5/gHTdAe8=
115115
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ=
116116
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods=

syft/pkg/cataloger/package_url_test.go

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,6 @@ func TestPackageURL(t *testing.T) {
3030
},
3131
expected: "pkg:pypi/[email protected]",
3232
},
33-
{
34-
pkg: pkg.Package{
35-
Name: "name",
36-
Version: "v0.1.0",
37-
Type: pkg.PythonPkg,
38-
},
39-
expected: "pkg:pypi/[email protected]",
40-
},
41-
{
42-
pkg: pkg.Package{
43-
Name: "name",
44-
Version: "v0.1.0",
45-
Type: pkg.PythonPkg,
46-
},
47-
expected: "pkg:pypi/[email protected]",
48-
},
49-
{
50-
pkg: pkg.Package{
51-
Name: "name",
52-
Version: "v0.1.0",
53-
Type: pkg.PythonPkg,
54-
},
55-
expected: "pkg:pypi/[email protected]",
56-
},
5733
{
5834
pkg: pkg.Package{
5935
Name: "name",
@@ -96,13 +72,31 @@ func TestPackageURL(t *testing.T) {
9672
Type: pkg.RpmPkg,
9773
Metadata: pkg.RpmdbMetadata{
9874
Name: "name",
99-
Version: "v0.1.0",
100-
Epoch: 2,
75+
Version: "0.1.0",
76+
Epoch: intRef(2),
77+
Arch: "amd64",
78+
Release: "3",
79+
},
80+
},
81+
expected: "pkg:rpm/centos/[email protected]?arch=amd64&epoch=2",
82+
},
83+
{
84+
distro: &distro.Distro{
85+
Type: distro.CentOS,
86+
},
87+
pkg: pkg.Package{
88+
Name: "bad-name",
89+
Version: "bad-v0.1.0",
90+
Type: pkg.RpmPkg,
91+
Metadata: pkg.RpmdbMetadata{
92+
Name: "name",
93+
Version: "0.1.0",
94+
Epoch: nil,
10195
Arch: "amd64",
10296
Release: "3",
10397
},
10498
},
105-
expected: "pkg:rpm/centos/name@2:v0.1.0-3?arch=amd64",
99+
expected: "pkg:rpm/centos/name@0.1.0-3?arch=amd64",
106100
},
107101
{
108102
distro: &distro.Distro{
@@ -136,3 +130,7 @@ func TestPackageURL(t *testing.T) {
136130
})
137131
}
138132
}
133+
134+
func intRef(i int) *int {
135+
return &i
136+
}

syft/pkg/cataloger/rpmdb/parse_rpmdb.go

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,27 @@ func parseRpmDB(resolver source.FilePathResolver, dbLocation source.Location, re
4747
allPkgs := make([]pkg.Package, 0)
4848

4949
for _, entry := range pkgList {
50+
metadata := pkg.RpmdbMetadata{
51+
Name: entry.Name,
52+
Version: entry.Version,
53+
Epoch: entry.Epoch,
54+
Arch: entry.Arch,
55+
Release: entry.Release,
56+
SourceRpm: entry.SourceRpm,
57+
Vendor: entry.Vendor,
58+
License: entry.License,
59+
Size: entry.Size,
60+
Files: extractRpmdbFileRecords(resolver, entry),
61+
}
62+
5063
p := pkg.Package{
5164
Name: entry.Name,
52-
Version: fmt.Sprintf("%s-%s", entry.Version, entry.Release), // this is what engine does, instead of fmt.Sprintf("%d:%s-%s.%s", entry.Epoch, entry.Version, entry.Release, entry.Arch)
65+
Version: toELVersion(metadata),
5366
Locations: []source.Location{dbLocation},
5467
FoundBy: catalogerName,
5568
Type: pkg.RpmPkg,
5669
MetadataType: pkg.RpmdbMetadataType,
57-
Metadata: pkg.RpmdbMetadata{
58-
Name: entry.Name,
59-
Version: entry.Version,
60-
Epoch: entry.Epoch,
61-
Arch: entry.Arch,
62-
Release: entry.Release,
63-
SourceRpm: entry.SourceRpm,
64-
Vendor: entry.Vendor,
65-
License: entry.License,
66-
Size: entry.Size,
67-
Files: extractRpmdbFileRecords(resolver, entry),
68-
},
70+
Metadata: metadata,
6971
}
7072

7173
allPkgs = append(allPkgs, p)
@@ -74,6 +76,19 @@ func parseRpmDB(resolver source.FilePathResolver, dbLocation source.Location, re
7476
return allPkgs, nil
7577
}
7678

79+
// The RPM naming scheme is [name]-[version]-[release]-[arch], where version is implicitly expands to [epoch]:[version].
80+
// RPM version comparison depends on comparing at least the version and release fields together as a subset of the
81+
// naming scheme. This toELVersion function takes a RPM DB package information and converts it into a minimally comparable
82+
// version string, containing epoch (optional), version, and release information. Epoch is an optional field and can be
83+
// assumed to be 0 when not provided for comparison purposes, however, if the underlying RPM DB entry does not have
84+
// an epoch specified it would be slightly disingenuous to display a value of 0.
85+
func toELVersion(metadata pkg.RpmdbMetadata) string {
86+
if metadata.Epoch != nil {
87+
return fmt.Sprintf("%d:%s-%s", *metadata.Epoch, metadata.Version, metadata.Release)
88+
}
89+
return fmt.Sprintf("%s-%s", metadata.Version, metadata.Release)
90+
}
91+
7792
func extractRpmdbFileRecords(resolver source.FilePathResolver, entry *rpmdb.PackageInfo) []pkg.RpmdbFileRecord {
7893
var records = make([]pkg.RpmdbFileRecord, 0)
7994

syft/pkg/cataloger/rpmdb/parse_rpmdb_test.go

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"os"
66
"testing"
77

8+
"github.com/stretchr/testify/assert"
9+
810
"github.com/anchore/syft/syft/file"
911

1012
"github.com/anchore/syft/syft/source"
@@ -70,7 +72,7 @@ func TestParseRpmDB(t *testing.T) {
7072
MetadataType: pkg.RpmdbMetadataType,
7173
Metadata: pkg.RpmdbMetadata{
7274
Name: "dive",
73-
Epoch: 0,
75+
Epoch: nil,
7476
Arch: "x86_64",
7577
Release: "1",
7678
Version: "0.9.2",
@@ -97,7 +99,7 @@ func TestParseRpmDB(t *testing.T) {
9799
MetadataType: pkg.RpmdbMetadataType,
98100
Metadata: pkg.RpmdbMetadata{
99101
Name: "dive",
100-
Epoch: 0,
102+
Epoch: nil,
101103
Arch: "x86_64",
102104
Release: "1",
103105
Version: "0.9.2",
@@ -157,3 +159,51 @@ func TestParseRpmDB(t *testing.T) {
157159
}
158160

159161
}
162+
163+
func TestToElVersion(t *testing.T) {
164+
tests := []struct {
165+
name string
166+
entry pkg.RpmdbMetadata
167+
expected string
168+
}{
169+
{
170+
name: "no epoch",
171+
entry: pkg.RpmdbMetadata{
172+
Version: "1.2.3-4",
173+
Release: "el7",
174+
Arch: "x86-64",
175+
},
176+
expected: "1.2.3-4-el7",
177+
},
178+
{
179+
name: "with 0 epoch",
180+
entry: pkg.RpmdbMetadata{
181+
Version: "1.2.3-4",
182+
Release: "el7",
183+
Arch: "x86-64",
184+
Epoch: intRef(0),
185+
},
186+
expected: "0:1.2.3-4-el7",
187+
},
188+
{
189+
name: "with non-zero epoch",
190+
entry: pkg.RpmdbMetadata{
191+
Version: "1.2.3-4",
192+
Release: "el7",
193+
Arch: "x86-64",
194+
Epoch: intRef(12),
195+
},
196+
expected: "12:1.2.3-4-el7",
197+
},
198+
}
199+
200+
for _, test := range tests {
201+
t.Run(test.name, func(t *testing.T) {
202+
assert.Equal(t, test.expected, toELVersion(test.entry))
203+
})
204+
}
205+
}
206+
207+
func intRef(i int) *int {
208+
return &i
209+
}

syft/pkg/rpmdb_metadata.go

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package pkg
33
import (
44
"fmt"
55
"sort"
6+
"strconv"
67

78
"github.com/anchore/syft/syft/file"
89

@@ -20,7 +21,7 @@ var _ fileOwner = (*RpmdbMetadata)(nil)
2021
type RpmdbMetadata struct {
2122
Name string `json:"name"`
2223
Version string `json:"version"`
23-
Epoch int `json:"epoch"`
24+
Epoch *int `json:"epoch"`
2425
Arch string `json:"architecture"`
2526
Release string `json:"release"`
2627
SourceRpm string `json:"sourceRpm"`
@@ -50,17 +51,30 @@ func (m RpmdbMetadata) PackageURL(d *distro.Distro) string {
5051
return ""
5152
}
5253

54+
qualifiers := packageurl.Qualifiers{
55+
{
56+
Key: "arch",
57+
Value: m.Arch,
58+
},
59+
}
60+
61+
if m.Epoch != nil {
62+
qualifiers = append(qualifiers,
63+
packageurl.Qualifier{
64+
Key: "epoch",
65+
Value: strconv.Itoa(*m.Epoch),
66+
},
67+
)
68+
}
69+
5370
pURL := packageurl.NewPackageURL(
5471
packageurl.TypeRPM,
5572
d.Type.String(),
5673
m.Name,
57-
fmt.Sprintf("%d:%s-%s", m.Epoch, m.Version, m.Release),
58-
packageurl.Qualifiers{
59-
{
60-
Key: "arch",
61-
Value: m.Arch,
62-
},
63-
},
74+
// for purl the epoch is a qualifier, not part of the version
75+
// see https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst under the RPM section
76+
fmt.Sprintf("%s-%s", m.Version, m.Release),
77+
qualifiers,
6478
"")
6579
return pURL.ToString()
6680
}

syft/pkg/rpmdb_metadata_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ func TestRpmMetadata_pURL(t *testing.T) {
2525
Version: "v",
2626
Arch: "a",
2727
Release: "r",
28-
Epoch: 1,
28+
Epoch: intRef(1),
2929
},
30-
expected: "pkg:rpm/centos/p@1:v-r?arch=a",
30+
expected: "pkg:rpm/centos/p@v-r?arch=a&epoch=1",
3131
},
3232
{
3333
distro: distro.Distro{
@@ -38,9 +38,9 @@ func TestRpmMetadata_pURL(t *testing.T) {
3838
Version: "v",
3939
Arch: "a",
4040
Release: "r",
41-
Epoch: 1,
41+
Epoch: nil,
4242
},
43-
expected: "pkg:rpm/redhat/p@1:v-r?arch=a",
43+
expected: "pkg:rpm/redhat/p@v-r?arch=a",
4444
},
4545
}
4646

@@ -97,3 +97,7 @@ func TestRpmMetadata_fileOwner(t *testing.T) {
9797
})
9898
}
9999
}
100+
101+
func intRef(i int) *int {
102+
return &i
103+
}

0 commit comments

Comments
 (0)