Skip to content

Commit 3ae902e

Browse files
committed
Combine files from multiple pulp fields in RpmUnit [RHELDST-34141]
Update RmpUnit's `files` field to contain files from both `files.file` and `repodata.filelists` pulp fields, ensuring all files will be listed there. This is to avoid reporting false positive file depsolving warnings in ubi-manifest, because there are cases in which the `files.file` field is missing, resulting in false positive reports.
1 parent e4b615d commit 3ae902e

File tree

4 files changed

+97
-6
lines changed

4 files changed

+97
-6
lines changed

src/pubtools/pulplib/_impl/model/common.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,15 @@ def _data_to_init_args(cls, data):
174174

175175
for field in fields:
176176
pulp_field = field.metadata.get(PULP2_FIELD)
177-
if pulp_field:
177+
if not pulp_field:
178+
continue
179+
if pulp_field == "_combines":
180+
# Field combines multiple pulp_fields, so we need to
181+
# pass whole Pulp data to converter.
182+
converter = get_converter(field)
183+
value = converter(data)
184+
out[field.name] = value
185+
else:
178186
value = lookup(data, pulp_field, absent)
179187
if value is not absent:
180188
converter = get_converter(field, value)

src/pubtools/pulplib/_impl/model/convert.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import datetime
2+
import xml.etree.ElementTree as ET
23
import functools
34

45
from frozenlist2 import frozenlist
56
from frozendict.core import frozendict # pylint: disable=no-name-in-module
67

8+
from pubtools.pulplib._impl.util import lookup
79
from .attr import PULP2_PY_CONVERTER
810

911

10-
def get_converter(field, value):
12+
def get_converter(field, value=None):
1113
"""Given an attrs target field and an input value from Pulp,
1214
return a converter function which should be used to convert the Pulp value
1315
into a Python representation."""
@@ -73,6 +75,32 @@ def write_timestamp(value):
7375
return value.strftime("%Y-%m-%dT%H:%M:%SZ")
7476

7577

78+
def combine_files_converter(data):
79+
"""Combine files from files.file and repodata.filelists"""
80+
absent = object()
81+
files = set()
82+
83+
from_files = lookup(data, "files.file", absent)
84+
if from_files is not absent:
85+
files.update(from_files)
86+
87+
filelist = lookup(data, "repodata.filelists", absent)
88+
if filelist is not absent:
89+
try:
90+
parsed_filelist = ET.fromstring(filelist)
91+
from_filelists = {
92+
file.text
93+
for file in parsed_filelist.findall("file")
94+
if file.get("type") != "dir"
95+
}
96+
except ET.ParseError:
97+
from_filelists = set()
98+
99+
files.update(from_filelists)
100+
101+
return frozenlist_or_none_converter(sorted(files) if files else None)
102+
103+
76104
def frozenlist_or_none_converter(obj, map_fn=(lambda x: x)):
77105
if obj is not None:
78106
return frozenlist(map_fn(obj))

src/pubtools/pulplib/_impl/model/unit/rpm.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from ..attr import pulp_attrib
77
from ..common import PulpObject, schemaless_init
88
from ..convert import (
9+
combine_files_converter,
910
frozenlist_or_none_converter,
1011
frozenlist_or_none_sorted_converter,
1112
timestamp_converter,
@@ -240,8 +241,8 @@ class RpmUnit(Unit):
240241
files = pulp_attrib(
241242
default=None,
242243
type=list,
243-
converter=frozenlist_or_none_converter,
244-
pulp_field="files.file",
244+
pulp_field="_combines", # combines multiple pulp_fields
245+
pulp_py_converter=combine_files_converter,
245246
validator=optional_list_of(str),
246247
)
247248
"""

tests/unit/test_rpm_unit.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,19 @@ def test_user_metadata_fields():
1919
"cdn_path": "/some/path/to/my.rpm",
2020
"cdn_published": "2021-04-01T01:08:26",
2121
},
22+
"repodata": {
23+
"filelists": """<package arch='x86_64' name='bash' pkgid='123'>\n
24+
<version epoch='0' rel='1' ver='4.0' />\n
25+
<file>/usr/bin/bash</file>\n
26+
<file>/usr/bin/some/script.sh</file>\n
27+
<file>/usr/bin/some/script-provided.py</file>\n
28+
<file type='dir'>/usr/bin/some</file>\n
29+
</package>"""
30+
},
2231
"files": {
2332
"file": [
2433
"/usr/bin/some/script.sh",
25-
"/usr/bin/another/script/provided.py",
34+
"/usr/bin/some/script-provided.py",
2635
],
2736
},
2837
}
@@ -38,7 +47,52 @@ def test_user_metadata_fields():
3847
content_type_id="rpm",
3948
cdn_path="/some/path/to/my.rpm",
4049
cdn_published=datetime.datetime(2021, 4, 1, 1, 8, 26),
41-
files=["/usr/bin/some/script.sh", "/usr/bin/another/script/provided.py"],
50+
files=[
51+
"/usr/bin/bash",
52+
"/usr/bin/some/script-provided.py",
53+
"/usr/bin/some/script.sh",
54+
],
55+
)
56+
57+
58+
def test_user_metadata_fields_malformed_xml():
59+
"""Malformed repodata.filelists is ignored"""
60+
61+
loaded = RpmUnit.from_data(
62+
{
63+
"_content_type_id": "rpm",
64+
"name": "bash",
65+
"filename": "bash-x86_64.rpm",
66+
"version": "4.0",
67+
"release": "1",
68+
"arch": "x86_64",
69+
"repodata": {
70+
"filelists": """<package arch='x86_64' name='bash' pkgid='123'>\n
71+
<version epoch='0' rel='1' ver='4.0' />\n
72+
<file>/usr/bin/bash
73+
<file type='dir'>/usr/bin/some</file>\n
74+
</package>"""
75+
},
76+
"files": {
77+
"file": [
78+
"/usr/bin/some/script.sh",
79+
],
80+
},
81+
}
82+
)
83+
84+
# Malformed repodata.filelists is ignored and only the files from files.file
85+
# field are present
86+
assert loaded == RpmUnit(
87+
name="bash",
88+
filename="bash-x86_64.rpm",
89+
version="4.0",
90+
release="1",
91+
arch="x86_64",
92+
content_type_id="rpm",
93+
files=[
94+
"/usr/bin/some/script.sh",
95+
],
4296
)
4397

4498

0 commit comments

Comments
 (0)