Skip to content

Commit ae65ce3

Browse files
committed
Add convenience method for adding a patch
Signed-off-by: Nikola Forró <[email protected]>
1 parent 9d8ab58 commit ae65ce3

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

specfile/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,7 @@ class MacroOptionsException(SpecfileException):
3333

3434
class DuplicateSourceException(SpecfileException):
3535
"""Exception related to adding a duplicate source."""
36+
37+
38+
class SourceNumberException(SpecfileException):
39+
"""Exception related to source numbers."""

specfile/specfile.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import arrow
1313

1414
from specfile.changelog import Changelog, ChangelogEntry
15-
from specfile.exceptions import SpecfileException
15+
from specfile.exceptions import SourceNumberException, SpecfileException
1616
from specfile.prep import Prep
1717
from specfile.rpm import RPM, Macros
1818
from specfile.sections import Sections
@@ -416,3 +416,39 @@ def set_version_and_release(self, version: str, release: str = "1") -> None:
416416
with self.tags() as tags:
417417
tags.version.value = version
418418
tags.release.value = self._get_updated_release(tags.release.value, release)
419+
420+
def add_patch(
421+
self,
422+
location: str,
423+
number: Optional[int] = None,
424+
comment: Optional[str] = None,
425+
initial_number: int = 0,
426+
number_digits: int = 4,
427+
) -> None:
428+
"""
429+
Adds a patch.
430+
431+
Args:
432+
location: Patch location (filename or URL).
433+
number: Patch number. It will be auto-assigned if not specified.
434+
If specified, it must be higher than any existing patch number.
435+
comment: Associated comment.
436+
initial_number: Auto-assigned number to start with if there are no patches.
437+
number_digits: Number of digits in the patch number.
438+
439+
Raises:
440+
SourceNumberException when the specified patch number is not higher
441+
than any existing patch number.
442+
"""
443+
with self.patches(default_source_number_digits=number_digits) as patches:
444+
highest_number = max((p.number for p in patches), default=-1)
445+
if number is not None:
446+
if number <= highest_number:
447+
raise SourceNumberException(
448+
"Patch number must be higher than any existing patch number"
449+
)
450+
else:
451+
number = max(highest_number + 1, initial_number)
452+
index = patches.insert_numbered(number, location)
453+
if comment:
454+
patches[index].comments.extend(comment.splitlines())

tests/integration/test_specfile.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,33 @@ def test_set_version_and_release(spec_minimal, version, release):
220220
assert spec._spec.sourceHeader[rpm.RPMTAG_RELEASE] == spec.expanded_raw_release
221221

222222

223+
@pytest.mark.parametrize(
224+
"location, number, comment",
225+
[
226+
("patchX.patch", None, None),
227+
("patchX.patch", 0, None),
228+
("patch2.patch", None, None),
229+
("patch3.patch", 3, "patch3"),
230+
],
231+
)
232+
def test_add_patch(spec_autosetup, location, number, comment):
233+
spec = Specfile(spec_autosetup)
234+
if number == 0 or location == "patch2.patch":
235+
with pytest.raises(SpecfileException):
236+
spec.add_patch(location, number, comment)
237+
else:
238+
spec.add_patch(location, number, comment)
239+
with spec.patches() as patches:
240+
assert patches[-1].location == location
241+
if number is not None:
242+
assert patches[-1].number == number
243+
else:
244+
assert patches[-1].number == 3
245+
with spec.sections() as sections:
246+
if comment is not None:
247+
assert sections.package[-4] == f"# {comment}"
248+
249+
223250
def test_remove_patches(spec_commented_patches):
224251
spec = Specfile(spec_commented_patches)
225252
with spec.patches() as patches:

0 commit comments

Comments
 (0)