Skip to content

Commit

Permalink
Avoid updating entity value if the entity is referenced from the new …
Browse files Browse the repository at this point in the history
…value (#388)

Avoid updating entity value if the entity is referenced from the new value

Consider the folowing excerpt from a spec file:
%global rel 1%{?dist}

Release: %{rel}
Previously, calling Specfile.update_tag("Release", "%rel") resulted in the macro definition being updated to %global rel %rel, making the spec file invalid. After this change, the macro definition stays unchanged and the tag is updated to Release: %rel.

Reviewed-by: Laura Barcziová
  • Loading branch information
softwarefactory-project-zuul[bot] authored Jun 26, 2024
2 parents 6137959 + 9a95cab commit 385818b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
32 changes: 32 additions & 0 deletions specfile/specfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from specfile.tags import Tag, Tags
from specfile.value_parser import (
SUBSTITUTION_GROUP_PREFIX,
ConditionalMacroExpansion,
EnclosedMacroSubstitution,
MacroSubstitution,
ValueParser,
Expand Down Expand Up @@ -774,7 +775,35 @@ class Entity:
)
entities.sort(key=lambda e: e.position)

def find_reference(entity, value):
def traverse(nodes):
for node in nodes:
if isinstance(
node,
(
MacroSubstitution,
EnclosedMacroSubstitution,
ConditionalMacroExpansion,
),
):
if (
entity.type == Tag
and entity.name == node.name.lower()
or entity.name == node.name
):
return True
if isinstance(node, ConditionalMacroExpansion):
if traverse(node.body):
return True
return False

return traverse(ValueParser.parse(value))

def update(value, requested_value, position):
if value == requested_value:
# nothing to do
return requested_value

modifiable_entities = {
e.name
for e in entities
Expand Down Expand Up @@ -822,6 +851,9 @@ def update(value, requested_value, position):
if entity.locked:
# avoid infinite recursion
return requested_value
if find_reference(entity, val):
# avoid updating entity value if the entity is referenced from the new value
return requested_value
entity.locked = True
try:
entity.value = update(entity.value, val, entity.position)
Expand Down
4 changes: 4 additions & 0 deletions tests/integration/test_specfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,10 @@ def test_update_tag(spec_macros):
assert spec.version == "%{package_version}"
spec.update_tag("Release", "2%{?dist}")
assert spec.raw_release == "%{release}"
with spec.macro_definitions() as md:
assert md.release.body == "2%{?dist}"
spec.update_tag("Release", "%release")
assert spec.raw_release == "%release"
with spec.macro_definitions() as md:
assert md.release.body == "2%{?dist}"
spec.update_tag(
Expand Down

0 comments on commit 385818b

Please sign in to comment.