Skip to content

Commit c8ca51a

Browse files
Create PackageManifest class for rpm
Creates PackageManifest class for rpm manifests and overrides the methods for detection and PackageManifest creation. Signed-off-by: Ayan Sinha Mahapatra <ayansmahapatra@gmail.com>
1 parent b014cd9 commit c8ca51a

4 files changed

Lines changed: 111 additions & 107 deletions

File tree

src/packagedcode/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
# Note: the order matters: from the most to the least specific
4040
# Package classes MUST be added to this list to be active
4141
PACKAGE_MANIFEST_TYPES = [
42-
rpm.RpmPackage,
42+
rpm.RPMManifest,
4343
debian.DebianPackage,
4444

4545
models.JavaJar,

src/packagedcode/rpm.py

Lines changed: 102 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import attr
1616
from license_expression import Licensing
1717

18+
from commoncode import filetype
1819
from packagedcode import models
1920
from packagedcode import nevra
2021
from packagedcode.pyrpm import RPM
@@ -73,11 +74,6 @@ def get_rpm_tags(location, include_desc=False):
7374
Return an RPMtags object for the file at location or None.
7475
Include the long RPM description value if `include_desc` is True.
7576
"""
76-
T = typecode.contenttype.get_type(location)
77-
78-
if 'rpm' not in T.filetype_file.lower():
79-
return
80-
8177
with open(location, 'rb') as rpmf:
8278
rpm = RPM(rpmf)
8379
tags = {k: v for k, v in rpm.to_dict().items() if k in RPM_TAGS}
@@ -117,8 +113,7 @@ def to_string(self):
117113

118114
@attr.s()
119115
class RpmPackage(models.Package, models.PackageManifest):
120-
file_patterns = ('*.spec',)
121-
extensions = ('.rpm', '.srpm', '.mvl', '.vip',)
116+
122117
filetypes = ('rpm ',)
123118
mimetypes = ('application/x-rpm',)
124119

@@ -128,10 +123,6 @@ class RpmPackage(models.Package, models.PackageManifest):
128123
default_download_baseurl = None
129124
default_api_baseurl = None
130125

131-
@classmethod
132-
def recognize(cls, location):
133-
yield parse(location)
134-
135126
def compute_normalized_license(self):
136127
_declared, detected = detect_declared_license(self.declared_license)
137128
return detected
@@ -164,82 +155,103 @@ def get_installed_packages(root_dir, detect_licenses=False, **kwargs):
164155
return rpm_installed.parse_rpm_xmlish(xmlish_loc, detect_licenses=detect_licenses)
165156

166157

167-
def parse(location):
168-
"""
169-
Return an RpmPackage object for the file at location or None if
170-
the file is not an RPM.
171-
"""
172-
rpm_tags = get_rpm_tags(location, include_desc=True)
173-
return build_from_tags(rpm_tags)
158+
@attr.s()
159+
class RPMManifest(RpmPackage, models.PackageManifest):
174160

161+
file_patterns = ('*.spec',)
162+
extensions = ('.rpm', '.srpm', '.mvl', '.vip',)
163+
manifest_type = 'rpmmanifest'
175164

176-
def build_from_tags(rpm_tags):
177-
"""
178-
Return an RpmPackage object from an ``rpm_tags`` RPMtags object.
179-
"""
180-
if TRACE: logger_debug('build_from_tags: rpm_tags', rpm_tags)
181-
if not rpm_tags:
182-
return
183-
184-
name = rpm_tags.name
185-
186-
try:
187-
epoch = rpm_tags.epoch and int(rpm_tags.epoch) or None
188-
except ValueError:
189-
epoch = None
190-
191-
evr = EVR(
192-
version=rpm_tags.version or None,
193-
release=rpm_tags.release or None,
194-
epoch=epoch).to_string()
195-
196-
qualifiers = {}
197-
os = rpm_tags.os
198-
if os and os.lower() != 'linux':
199-
qualifiers['os'] = os
200-
201-
arch = rpm_tags.arch
202-
if arch:
203-
qualifiers['arch'] = arch
204-
205-
source_packages = []
206-
if rpm_tags.source_rpm:
207-
sepoch, sname, sversion, srel, sarch = nevra.from_name(rpm_tags.source_rpm)
208-
src_evr = EVR(sversion, srel, sepoch).to_string()
209-
src_qualifiers = {}
210-
if sarch:
211-
src_qualifiers['arch'] = sarch
212-
213-
src_purl = models.PackageURL(
214-
type=RpmPackage.default_type,
215-
name=sname,
216-
version=src_evr,
217-
qualifiers=src_qualifiers
218-
).to_string()
219-
220-
if TRACE: logger_debug('build_from_tags: source_rpm', src_purl)
221-
source_packages = [src_purl]
222-
223-
parties = []
224-
225-
# TODO: also use me to craft a namespace!!!
226-
# TODO: assign a namepsace to Package URL based on distro names.
227-
# CentOS
228-
# Fedora Project
229-
# OpenMandriva Lx
230-
# openSUSE Tumbleweed
231-
# Red Hat
232-
233-
if rpm_tags.distribution:
234-
parties.append(models.Party(name=rpm_tags.distribution, role='distributor'))
235-
236-
if rpm_tags.vendor:
237-
parties.append(models.Party(name=rpm_tags.vendor, role='vendor'))
238-
239-
description = build_description(rpm_tags.summary, rpm_tags.description)
240-
241-
if TRACE:
242-
data = dict(
165+
@classmethod
166+
def is_manifest(cls, location):
167+
"""
168+
Return True if the file at ``location`` is likely a manifest of this type.
169+
"""
170+
T = typecode.contenttype.get_type(location)
171+
return (filetype.is_file(location) and 'rpm' in T.filetype_file.lower())
172+
173+
@classmethod
174+
def recognize(cls, location):
175+
"""
176+
Yield one or more Package manifest objects given a file ``location`` pointing to a
177+
package archive, manifest or similar.
178+
"""
179+
rpm_tags = get_rpm_tags(location, include_desc=True)
180+
181+
if TRACE: logger_debug('build_from_tags: rpm_tags', rpm_tags)
182+
if not rpm_tags:
183+
return
184+
185+
name = rpm_tags.name
186+
187+
try:
188+
epoch = rpm_tags.epoch and int(rpm_tags.epoch) or None
189+
except ValueError:
190+
epoch = None
191+
192+
evr = EVR(
193+
version=rpm_tags.version or None,
194+
release=rpm_tags.release or None,
195+
epoch=epoch).to_string()
196+
197+
qualifiers = {}
198+
os = rpm_tags.os
199+
if os and os.lower() != 'linux':
200+
qualifiers['os'] = os
201+
202+
arch = rpm_tags.arch
203+
if arch:
204+
qualifiers['arch'] = arch
205+
206+
source_packages = []
207+
if rpm_tags.source_rpm:
208+
sepoch, sname, sversion, srel, sarch = nevra.from_name(rpm_tags.source_rpm)
209+
src_evr = EVR(sversion, srel, sepoch).to_string()
210+
src_qualifiers = {}
211+
if sarch:
212+
src_qualifiers['arch'] = sarch
213+
214+
src_purl = models.PackageURL(
215+
type=RpmPackage.default_type,
216+
name=sname,
217+
version=src_evr,
218+
qualifiers=src_qualifiers
219+
).to_string()
220+
221+
if TRACE: logger_debug('build_from_tags: source_rpm', src_purl)
222+
source_packages = [src_purl]
223+
224+
parties = []
225+
226+
# TODO: also use me to craft a namespace!!!
227+
# TODO: assign a namepsace to Package URL based on distro names.
228+
# CentOS
229+
# Fedora Project
230+
# OpenMandriva Lx
231+
# openSUSE Tumbleweed
232+
# Red Hat
233+
234+
if rpm_tags.distribution:
235+
parties.append(models.Party(name=rpm_tags.distribution, role='distributor'))
236+
237+
if rpm_tags.vendor:
238+
parties.append(models.Party(name=rpm_tags.vendor, role='vendor'))
239+
240+
description = build_description(rpm_tags.summary, rpm_tags.description)
241+
242+
if TRACE:
243+
data = dict(
244+
name=name,
245+
version=evr,
246+
description=description or None,
247+
homepage_url=rpm_tags.url or None,
248+
parties=parties,
249+
declared_license=rpm_tags.license or None,
250+
source_packages=source_packages,
251+
)
252+
logger_debug('build_from_tags: data to create a package:\n', data)
253+
254+
package = cls(
243255
name=name,
244256
version=evr,
245257
description=description or None,
@@ -248,22 +260,11 @@ def build_from_tags(rpm_tags):
248260
declared_license=rpm_tags.license or None,
249261
source_packages=source_packages,
250262
)
251-
logger_debug('build_from_tags: data to create a package:\n', data)
252-
253-
package = RpmPackage(
254-
name=name,
255-
version=evr,
256-
description=description or None,
257-
homepage_url=rpm_tags.url or None,
258-
parties=parties,
259-
declared_license=rpm_tags.license or None,
260-
source_packages=source_packages,
261-
)
262-
263-
if TRACE:
264-
logger_debug('build_from_tags: created package:\n', package)
265-
266-
return package
263+
264+
if TRACE:
265+
logger_debug('build_from_tags: created package:\n', package)
266+
267+
return package
267268

268269
############################################################################
269270
# FIXME: this license detection code is mostly copied from debian_copyright.py and alpine.py

tests/packagedcode/data/plugin/help.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ Package: readme
357357

358358
--------------------------------------------
359359
Package: rpm
360-
class: packagedcode.rpm:RpmPackage
360+
class: packagedcode.rpm:RPMManifest
361361
file_patterns: *.spec
362362
extensions: .rpm, .srpm, .mvl, .vip
363363
filetypes: rpm

tests/packagedcode/test_rpm.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class TestRpmBasics(FileBasedTesting):
2121

2222
def test_parse_to_package(self):
2323
test_file = self.get_test_loc('rpm/header/libproxy-bin-0.3.0-4.el6_3.x86_64.rpm')
24-
package = rpm.parse(test_file)
24+
package = rpm.RPMManifest.recognize(test_file)
2525
expected = [
2626
('type', 'rpm'),
2727
('namespace', None),
@@ -126,10 +126,13 @@ def test_get_rpm_tags_(self):
126126
expected = expected._replace(description=None)
127127
assert rpm.get_rpm_tags(test_file, include_desc=False) == expected
128128

129-
def test_packagedcode_rpm_tags_and_info_on_non_rpm_file(self):
129+
def test_rpm_is_manifest_non_rpm_file(self):
130130
test_file = self.get_test_loc('rpm/README.txt')
131-
assert not rpm.get_rpm_tags(test_file, include_desc=True)
132-
assert not rpm.get_rpm_tags(test_file, include_desc=False)
131+
assert not rpm.RPMManifest.is_manifest(test_file)
132+
133+
def test_rpm_is_manifest_rpm_file(self):
134+
test_file = self.get_test_loc('rpm/header/python-glc-0.7.1-1.src.rpm')
135+
assert rpm.RPMManifest.is_manifest(test_file)
133136

134137

135138
def check_json(result, expected_file, regen=False):

0 commit comments

Comments
 (0)