Skip to content

Commit

Permalink
Fix parsing composeinfo with almost conflicting UIDs
Browse files Browse the repository at this point in the history
When the metadata contains variants Foo and Foo-Bar, the deserialization
logic always applies a workaround for old metadata that did not
explicitly contain parent-child relationship. Thus Foo-Bar ends up as a
child of Foo, even though they may be unrelated.

The fix is to only apply the workaround when metadata version is too
old.

JIRA: COMPOSE-3814
Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
  • Loading branch information
lubomir committed Sep 4, 2019
1 parent 645b408 commit 5ee546b
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 7 deletions.
25 changes: 18 additions & 7 deletions productmd/composeinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,16 +655,26 @@ def deserialize(self, data):
# variant UIDs should be identical to IDs at the top level
all_variants = data[self._section].keys()

child_variants = set()
for var in data[self._section].values():
for child in var.get("variants", []):
child_variants.add("%s-%s" % (var["uid"], child))

variant_ids = []
for variant_uid, var in data[self._section].items():
if "-" in variant_uid:
head, tail = variant_uid.rsplit("-", 1)
if head in all_variants:
# has parent
continue
# We only want to process top level variants here. For recent
# versions of metadata, the relationships are epxlicitly encoded.
# For old metadata, we have to fall back to checking UIDs.
if self._metadata.header.version_tuple < (1, 0):
if "-" in variant_uid:
head, tail = variant_uid.rsplit("-", 1)
if head in all_variants:
# has parent, skip it
continue
variant_ids.append(variant_uid)
else:
variant_ids.append(variant_uid)
if variant_uid not in child_variants:
variant_ids.append(variant_uid)

variant_ids.sort()
for variant_id in variant_ids:
Expand Down Expand Up @@ -851,10 +861,11 @@ def deserialize(self, data, variant_uid):
paths = data["paths"]
self.paths.deserialize(paths)

variant_uids = []
if "variants" in data:
variant_ids = sorted(data["variants"])
variant_uids = ["%s-%s" % (self.uid, i) for i in variant_ids]
else:
elif self._metadata.header.version_tuple < (1, 0):
# legacy metadata with no "variants" parent-child references
variant_uids = full_data.keys()
variant_uids = [i for i in variant_uids if i.startswith("%s-" % variant_uid)]
Expand Down
36 changes: 36 additions & 0 deletions tests/test_composeinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,42 @@ def test_create_variants_with_dash(self):
self._test_identity(ci)
return ci

def test_create_with_prefixed_uid(self):
ci = ComposeInfo()
ci.release.name = "Fedora"
ci.release.short = "F"
ci.release.version = "22"
ci.release.type = "ga"

ci.compose.id = "F-22-20150522.0"
ci.compose.type = "production"
ci.compose.date = "20150522"
ci.compose.respin = 0

# 2 Tools variants: one for Server, one for Workstation
# but parent variants are not part of the compose
variant = Variant(ci)
variant.id = "Foo"
variant.uid = "Foo"
variant.name = "Foo"
variant.type = "variant"
variant.arches = set(["x86_64"])
ci.variants.add(variant)
ci.variants["Foo"]

variant = Variant(ci)
variant.id = "FooBar"
variant.uid = "Foo-Bar"
variant.name = "Foo-Bar"
variant.type = "variant"
variant.arches = set(["x86_64"])
ci.variants.add(variant)
ci.variants["Foo-Bar"]

ci.dump(self.ci_path)
self._test_identity(ci)
return ci

def test_get_variants(self):
ci = ComposeInfo()
ci.release.name = "Fedora"
Expand Down

0 comments on commit 5ee546b

Please sign in to comment.