Skip to content

Commit

Permalink
add dependencies to rpm
Browse files Browse the repository at this point in the history
Added dependencies to rpm.

Reference: #649
Signed-off-by: Alok Kumar <[email protected]>

Signed-off-by: Alok Kumar <[email protected]>
  • Loading branch information
alok1304 committed Jan 10, 2025
1 parent 1d0fe75 commit e16372a
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 11 deletions.
188 changes: 182 additions & 6 deletions src/packagedcode/rpm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from collections import namedtuple
from pathlib import Path

from packageurl import PackageURL
from packagedcode import models
from packagedcode import nevra
from packagedcode.licensing import RESOURCE_TO_PACKAGE_LICENSE_FIELDS
Expand Down Expand Up @@ -44,7 +45,6 @@ def logger_debug(*args):
"""
Support for RPMs, installed databases and spec files.
"""
# TODO: retrieve dependencies

# TODO: parse spec files see:
# http://www.faqs.org/docs/artu/ch05s02.html#id2906931%29.)
Expand Down Expand Up @@ -125,7 +125,6 @@ def to_string(self):
return vr


# TODO: add dependencies!!!
class BaseRpmInstalledDatabaseHandler(models.DatafileHandler):

@classmethod
Expand All @@ -135,13 +134,45 @@ def parse(cls, location, package_only=False):
loc_path = Path(location)
rpmdb_loc = str(loc_path.parent)

rpm_tags = get_rpm_tags(location, include_desc=True)

if TRACE: logger_debug('recognize: rpm_tags', rpm_tags)
if not rpm_tags:
return

dependencies = []
name = rpm_tags.name
version = rpm_tags.version
is_pinned = version is not None and version != ""

# Construct PackageURL without '@version' if version is missing
purl = PackageURL(
type="rpm",
namespace=None, # RPMs typically don't use namespaces
name=name,
version=version if is_pinned else None
)

# Prepare the dependent package model
dependencies.append(
models.DependentPackage(
purl=purl.to_string(),
scope="dependencies",
is_runtime=True,
is_optional=False,
is_pinned=is_pinned,
extracted_requirement=version,
)
)

# dump and parse the rpmdb to XMLish
xmlish_loc = collect_installed_rpmdb_xmlish_from_rpmdb_loc(rpmdb_loc=rpmdb_loc)
package_data = parse_rpm_xmlish(
location=xmlish_loc,
datasource_id=cls.datasource_id,
package_type=cls.default_package_type,
package_only=package_only,
dependencies=dependencies,
)
# TODO: package_data.namespace = cls.default_package_namespace
return package_data
Expand Down Expand Up @@ -225,7 +256,6 @@ def assemble(cls, package_data, resource, codebase, package_adder):
yield resource


# TODO: add dependencies!!!
class RpmInstalledNdbDatabaseHandler(BaseRpmInstalledDatabaseHandler):
# used by recent Suse
datasource_id = 'rpm_installed_database_ndb'
Expand All @@ -237,8 +267,48 @@ class RpmInstalledNdbDatabaseHandler(BaseRpmInstalledDatabaseHandler):
description = 'RPM installed package NDB database'
documentation_url = 'https://fedoraproject.org/wiki/Changes/NewRpmDBFormat'

@classmethod
def parse(cls, location, package_only=False):
rpm_tags = get_rpm_tags(location, include_desc=True)

if TRACE: logger_debug('recognize: rpm_tags', rpm_tags)
if not rpm_tags:
return

dependencies = []
name = rpm_tags.name
version = rpm_tags.version
is_pinned = version is not None and version != ""

# Construct PackageURL without '@version' if version is missing
purl = PackageURL(
type="rpm",
namespace=None, # RPMs typically don't use namespaces
name=name,
version=version if is_pinned else None
)

# Prepare the dependent package model
dependencies.append(
models.DependentPackage(
purl=purl.to_string(),
scope="dependencies",
is_runtime=True,
is_optional=False,
is_pinned=is_pinned,
extracted_requirement=version,
)
)

package_data = dict(
datasource_id=cls.datasource_id,
type=cls.default_package_type,
dependencies=dependencies,
)

yield models.PackageData.from_data(package_data, package_only)


# TODO: add dependencies!!!
class RpmInstalledSqliteDatabaseHandler(BaseRpmInstalledDatabaseHandler):
# used by newer RHEL/CentOS/Fedora/CoreOS
# Filetype: SQLite 3.x database, ...
Expand All @@ -253,8 +323,48 @@ class RpmInstalledSqliteDatabaseHandler(BaseRpmInstalledDatabaseHandler):
description = 'RPM installed package SQLite database'
documentation_url = 'https://fedoraproject.org/wiki/Changes/Sqlite_Rpmdb'

@classmethod
def parse(cls, location, package_only=False):
rpm_tags = get_rpm_tags(location, include_desc=True)

if TRACE: logger_debug('recognize: rpm_tags', rpm_tags)
if not rpm_tags:
return

dependencies = []
name = rpm_tags.name
version = rpm_tags.version
is_pinned = version is not None and version != ""

# Construct PackageURL without '@version' if version is missing
purl = PackageURL(
type="rpm",
namespace=None, # RPMs typically don't use namespaces
name=name,
version=version if is_pinned else None
)

# Prepare the dependent package model
dependencies.append(
models.DependentPackage(
purl=purl.to_string(),
scope="dependencies",
is_runtime=True,
is_optional=False,
is_pinned=is_pinned,
extracted_requirement=version,
)
)

package_data = dict(
datasource_id=cls.datasource_id,
type=cls.default_package_type,
dependencies=dependencies,
)

yield models.PackageData.from_data(package_data, package_only)


# TODO: add dependencies!!!
class RpmInstalledBdbDatabaseHandler(BaseRpmInstalledDatabaseHandler):
# used by legacy RHEL/CentOS/Fedora/Suse
datasource_id = 'rpm_installed_database_bdb'
Expand All @@ -267,6 +377,47 @@ class RpmInstalledBdbDatabaseHandler(BaseRpmInstalledDatabaseHandler):
description = 'RPM installed package BDB database'
documentation_url = 'https://man7.org/linux/man-pages/man8/rpmdb.8.html'

@classmethod
def parse(cls, location, package_only=False):
rpm_tags = get_rpm_tags(location, include_desc=True)

if TRACE: logger_debug('recognize: rpm_tags', rpm_tags)
if not rpm_tags:
return

dependencies = []
name = rpm_tags.name
version = rpm_tags.version
is_pinned = version is not None and version != ""

# Construct PackageURL without '@version' if version is missing
purl = PackageURL(
type="rpm",
namespace=None, # RPMs typically don't use namespaces
name=name,
version=version if is_pinned else None
)

# Prepare the dependent package model
dependencies.append(
models.DependentPackage(
purl=purl.to_string(),
scope="dependencies",
is_runtime=True,
is_optional=False,
is_pinned=is_pinned,
extracted_requirement=version,
)
)

package_data = dict(
datasource_id=cls.datasource_id,
type=cls.default_package_type,
dependencies=dependencies,
)

yield models.PackageData.from_data(package_data, package_only)


# TODO: implement me!!@
class RpmSpecfileHandler(models.NonAssemblableDatafileHandler):
Expand All @@ -278,7 +429,6 @@ class RpmSpecfileHandler(models.NonAssemblableDatafileHandler):
documentation_url = 'https://en.wikipedia.org/wiki/RPM_Package_Manager'


# TODO: add dependencies!!!
class RpmArchiveHandler(models.DatafileHandler):
datasource_id = 'rpm_archive'
path_patterns = ('*.rpm', '*.src.rpm', '*.srpm', '*.mvl', '*.vip',)
Expand Down Expand Up @@ -354,6 +504,30 @@ def parse(cls, location, package_only=False):

description = build_description(summary=rpm_tags.summary, description=rpm_tags.description)

dependencies = []
name = rpm_tags.name
version = rpm_tags.version
is_pinned = version is not None and version != ""

# Construct PackageURL without '@version' if version is missing
purl = PackageURL(
type="rpm",
namespace=None, # RPMs typically don't use namespaces
name=name,
version=version if is_pinned else None
)

# Prepare the dependent package model
dependencies.append(
models.DependentPackage(
purl=purl.to_string(),
scope="dependencies",
is_runtime=True,
is_optional=False,
is_pinned=is_pinned,
extracted_requirement=version,
)
)
if TRACE:
data = dict(
name=name,
Expand All @@ -363,6 +537,7 @@ def parse(cls, location, package_only=False):
parties=parties,
extracted_license_statement=rpm_tags.license or None,
source_packages=source_packages,
dependencies=dependencies,
)
logger_debug('recognize: data to create a package:\n', data)

Expand All @@ -377,6 +552,7 @@ def parse(cls, location, package_only=False):
parties=parties,
extracted_license_statement=rpm_tags.license or None,
source_packages=source_packages,
dependencies=dependencies,
)

if TRACE:
Expand Down
14 changes: 13 additions & 1 deletion tests/packagedcode/data/plugin/rpm-package-expected.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,19 @@
"is_private": false,
"is_virtual": false,
"extra_data": {},
"dependencies": [],
"dependencies": [
{
"purl": "pkg:rpm/[email protected]",
"extracted_requirement": "2.0",
"scope": "dependencies",
"is_runtime": true,
"is_optional": false,
"is_pinned": true,
"is_direct": true,
"resolved_package": {},
"extra_data": {}
}
],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,19 @@
"is_private": false,
"is_virtual": false,
"extra_data": {},
"dependencies": [],
"dependencies": [
{
"purl": "pkg:rpm/[email protected]",
"extracted_requirement": "0.3.0",
"scope": "dependencies",
"is_runtime": true,
"is_optional": false,
"is_pinned": true,
"is_direct": true,
"resolved_package": {},
"extra_data": {}
}
],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,19 @@
"is_private": false,
"is_virtual": false,
"extra_data": {},
"dependencies": [],
"dependencies": [
{
"purl": "pkg:rpm/[email protected]",
"extracted_requirement": "0.3.0",
"scope": "dependencies",
"is_runtime": true,
"is_optional": false,
"is_pinned": true,
"is_direct": true,
"resolved_package": {},
"extra_data": {}
}
],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,23 @@
"purl": "pkg:rpm/[email protected]"
}
],
"dependencies": [],
"dependencies": [
{
"purl": "pkg:rpm/[email protected]",
"extracted_requirement": "2.4",
"scope": "dependencies",
"is_runtime": true,
"is_optional": false,
"is_pinned": true,
"is_direct": true,
"resolved_package": {},
"extra_data": {},
"dependency_uid": "pkg:rpm/[email protected]?uuid=4c055d32-6a8c-465e-9c76-f2714b7ce23f",
"for_package_uid": "pkg:rpm/[email protected]?uuid=1903aca6-54da-49d6-a219-ff432eff4398",
"datafile_path": "fping-2.4-0.b2.rhfc1.dag.i386.rpm",
"datasource_id": "rpm_archive"
}
],
"files": [
{
"path": "fping-2.4-0.b2.rhfc1.dag.i386.rpm",
Expand Down Expand Up @@ -158,7 +174,19 @@
"is_private": false,
"is_virtual": false,
"extra_data": {},
"dependencies": [],
"dependencies": [
{
"purl": "pkg:rpm/[email protected]",
"extracted_requirement": "2.4",
"scope": "dependencies",
"is_runtime": true,
"is_optional": false,
"is_pinned": true,
"is_direct": true,
"resolved_package": {},
"extra_data": {}
}
],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": null,
Expand Down

0 comments on commit e16372a

Please sign in to comment.