Skip to content

Commit 385818b

Browse files
Avoid updating entity value if the entity is referenced from the new 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á
2 parents 6137959 + 9a95cab commit 385818b

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

specfile/specfile.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from specfile.tags import Tag, Tags
3333
from specfile.value_parser import (
3434
SUBSTITUTION_GROUP_PREFIX,
35+
ConditionalMacroExpansion,
3536
EnclosedMacroSubstitution,
3637
MacroSubstitution,
3738
ValueParser,
@@ -774,7 +775,35 @@ class Entity:
774775
)
775776
entities.sort(key=lambda e: e.position)
776777

778+
def find_reference(entity, value):
779+
def traverse(nodes):
780+
for node in nodes:
781+
if isinstance(
782+
node,
783+
(
784+
MacroSubstitution,
785+
EnclosedMacroSubstitution,
786+
ConditionalMacroExpansion,
787+
),
788+
):
789+
if (
790+
entity.type == Tag
791+
and entity.name == node.name.lower()
792+
or entity.name == node.name
793+
):
794+
return True
795+
if isinstance(node, ConditionalMacroExpansion):
796+
if traverse(node.body):
797+
return True
798+
return False
799+
800+
return traverse(ValueParser.parse(value))
801+
777802
def update(value, requested_value, position):
803+
if value == requested_value:
804+
# nothing to do
805+
return requested_value
806+
778807
modifiable_entities = {
779808
e.name
780809
for e in entities
@@ -822,6 +851,9 @@ def update(value, requested_value, position):
822851
if entity.locked:
823852
# avoid infinite recursion
824853
return requested_value
854+
if find_reference(entity, val):
855+
# avoid updating entity value if the entity is referenced from the new value
856+
return requested_value
825857
entity.locked = True
826858
try:
827859
entity.value = update(entity.value, val, entity.position)

tests/integration/test_specfile.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,10 @@ def test_update_tag(spec_macros):
405405
assert spec.version == "%{package_version}"
406406
spec.update_tag("Release", "2%{?dist}")
407407
assert spec.raw_release == "%{release}"
408+
with spec.macro_definitions() as md:
409+
assert md.release.body == "2%{?dist}"
410+
spec.update_tag("Release", "%release")
411+
assert spec.raw_release == "%release"
408412
with spec.macro_definitions() as md:
409413
assert md.release.body == "2%{?dist}"
410414
spec.update_tag(

0 commit comments

Comments
 (0)