From b2ed90e0692281facf781a0d51af3ae66a1d4340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Tue, 4 Jun 2024 12:19:11 +0200 Subject: [PATCH] Improve compatibility with rpm 4.20alpha MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rpm 4.20alpha (now in rawhide) obsoletes `%patchN` macros and spec files containing them are unparseable. Stop using such macros in integration tests and add support for the `%patch N` variant. Signed-off-by: Nikola Forró --- specfile/prep.py | 40 +++++++++++++++++++-------- tests/data/spec_macros/test.spec | 6 ++-- tests/data/spec_traditional/test.spec | 6 ++-- tests/integration/test_specfile.py | 11 ++++---- tests/unit/test_prep.py | 24 +++++++++++----- 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/specfile/prep.py b/specfile/prep.py index 8ef2b9b..8a1311e 100644 --- a/specfile/prep.py +++ b/specfile/prep.py @@ -112,19 +112,26 @@ class PatchMacro(PrepMacro): @property def number(self) -> int: """Number of the %patch macro.""" - if self.options.P is not None: - return int(self.options.P) tokens = re.split(r"(\d+)", self.name, maxsplit=1) if len(tokens) > 1: return int(tokens[1]) + if self.options.P is not None: + return int(self.options.P) + if self.options.positional: + return int(self.options.positional[0]) return 0 @number.setter def number(self, value: int) -> None: - if self.options.P is not None: + tokens = re.split(r"(\d+)", self.name, maxsplit=1) + if len(tokens) > 1: + self.name = f"{tokens[0]}{value}" + elif self.options.P is not None: self.options.P = value - return - self.name = f"{self.CANONICAL_NAME}{value}" + elif self.options.positional: + self.options.positional[0] = value + else: + self.name = f"{self.CANONICAL_NAME}{value}" class AutosetupMacro(PrepMacro): @@ -280,12 +287,18 @@ def __delattr__(self, name: str) -> None: return super().__delattr__(name) return delattr(self.macros, name) - def add_patch_macro(self, number: int, **kwargs: Any) -> None: + def add_patch_macro( + self, + number: Optional[int] = None, + old_style_number: bool = False, + **kwargs: Any, + ) -> None: """ Adds a new _%patch_ macro with given number and options. Args: - number: Macro number. + number: Optional macro number. + old_style_number: Whether the number should be part of macro name. P: The _-P_ option (patch number). p: The _-p_ option (strip number). R: The _-R_ option (reverse). @@ -297,19 +310,24 @@ def add_patch_macro(self, number: int, **kwargs: Any) -> None: o: The _-o_ option (output file). Z: The _-Z_ option (set UTC times). """ + name = PatchMacro.CANONICAL_NAME options = Options([], PatchMacro.OPTSTRING, PatchMacro.DEFAULTS) + if number is not None: + if old_style_number: + name += str(number) + else: + options.positional.append(number) for k, v in kwargs.items(): setattr(options, k, v) - macro = PatchMacro(PatchMacro.CANONICAL_NAME, options, " ") - macro.number = number + macro = PatchMacro(name, options, " ") index, _ = min( ((i, m) for i, m in enumerate(self.macros) if isinstance(m, PatchMacro)), - key=lambda im: abs(im[1].number - number), + key=lambda im: abs(im[1].number - macro.number), default=(len(self.macros), None), ) if ( index < len(self.macros) - and cast(PatchMacro, self.macros[index]).number <= number + and cast(PatchMacro, self.macros[index]).number <= macro.number ): index += 1 self.macros.insert(index, macro) diff --git a/tests/data/spec_macros/test.spec b/tests/data/spec_macros/test.spec index f04e375..f8cef6d 100644 --- a/tests/data/spec_macros/test.spec +++ b/tests/data/spec_macros/test.spec @@ -40,9 +40,9 @@ Test package %prep %setup -q -n %{name}-%{version} %setup -c -T -D -b 1 -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 +%patch -P0 -p1 +%patch -P1 -p1 +%patch -P2 -p1 %changelog diff --git a/tests/data/spec_traditional/test.spec b/tests/data/spec_traditional/test.spec index 9b20d89..fc0926a 100644 --- a/tests/data/spec_traditional/test.spec +++ b/tests/data/spec_traditional/test.spec @@ -17,9 +17,9 @@ Test package %prep %setup -q -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 +%patch -P0 -p1 +%patch -P1 -p1 +%patch -P2 -p1 %changelog diff --git a/tests/integration/test_specfile.py b/tests/integration/test_specfile.py index dc94a1f..b047c28 100644 --- a/tests/integration/test_specfile.py +++ b/tests/integration/test_specfile.py @@ -41,12 +41,13 @@ def test_prep_traditional(spec_traditional): assert len([m for m in prep.macros if isinstance(m, PatchMacro)]) == 2 prep.add_patch_macro(0, p=2, b=".test") assert len(prep.macros) == 4 - assert prep.patch0.options.p == 2 - assert prep.patch0.options.b == ".test" - prep.patch0.options.b = ".test2" - prep.patch0.options.E = True + assert prep.macros[1].options.positional == [0] + assert prep.macros[1].options.p == 2 + assert prep.macros[1].options.b == ".test" + prep.macros[1].options.b = ".test2" + prep.macros[1].options.E = True with spec.sections() as sections: - assert sections.prep[1] == "%patch0 -p2 -b .test2 -E" + assert sections.prep[1] == "%patch 0 -p2 -b .test2 -E" def test_prep_autosetup(spec_autosetup): diff --git a/tests/unit/test_prep.py b/tests/unit/test_prep.py index 1f6711f..4f9e259 100644 --- a/tests/unit/test_prep.py +++ b/tests/unit/test_prep.py @@ -17,7 +17,10 @@ ("%patch0028", "-p2", 28), ("%patch", "-p1", 0), ("%patch", "-P1", 1), - ("%patch3", "-P5", 5), + ("%patch3", "-P5", 3), + ("%patch0", "-P1 2", 0), + ("%patch", "-P1 2", 1), + ("%patch", "2", 2), ], ) def test_patch_macro_number(name, options, number): @@ -40,48 +43,55 @@ def test_prep_macros_find(): @pytest.mark.parametrize( - "lines_before, number, options, lines_after", + "lines_before, number, old_style_number, options, lines_after", [ ( ["%setup -q"], 0, + True, dict(p=1), ["%setup -q", "%patch0 -p1"], ), ( ["%setup -q", "%patch0 -p1"], 0, + True, dict(p=2), ["%setup -q", "%patch0 -p1", "%patch0 -p2"], ), ( ["%setup -q", "%patch999 -p1"], 28, + False, dict(p=1), - ["%setup -q", "%patch28 -p1", "%patch999 -p1"], + ["%setup -q", "%patch 28 -p1", "%patch999 -p1"], ), ( ["%setup -q", "%patch999 -p1"], 1001, + False, dict(p=1), - ["%setup -q", "%patch999 -p1", "%patch1001 -p1"], + ["%setup -q", "%patch999 -p1", "%patch 1001 -p1"], ), ( ["%setup -q", "%{!?skip_first_patch:%patch0 -p1}", "%patch999 -p1"], 28, + False, dict(p=2, b=".patch28"), [ "%setup -q", "%{!?skip_first_patch:%patch0 -p1}", - "%patch28 -p2 -b .patch28", + "%patch 28 -p2 -b .patch28", "%patch999 -p1", ], ), ], ) -def test_prep_add_patch_macro(lines_before, number, options, lines_after): +def test_prep_add_patch_macro( + lines_before, number, old_style_number, options, lines_after +): prep = Prep.parse(Section("prep", data=lines_before)) - prep.add_patch_macro(number, **options) + prep.add_patch_macro(number, old_style_number, **options) assert prep.get_raw_section_data() == lines_after