Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions specfile/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,25 +167,33 @@ def extended_timestamp(self) -> bool:
return m is not None

@property
def day_of_month_padding(self) -> str:
"""Padding of day of month in the entry header timestamp"""
def sanitized_day_of_month_padding(self) -> str:
"""
Padding of day of month in the entry header timestamp. Nonsensical padding
(i.e. multiple spaces before double-digit day of month) is corrected.
"""
weekdays = "|".join(WEEKDAYS)
months = "|".join(MONTHS)

m = re.search(
rf"""
({weekdays}) # weekday
[ ]
({months}) # month
[ ]
(?P<wsp>[ ]*) # optional whitespace padding
((?P<zp>0)?\d|[12]\d|3[01]) # possibly zero-padded day of month
(?P<zp>0)? # optional zero-padding
(?P<day>[12]\d|3[01]|[1-9]) # day of month (1-31)
""",
self.header,
re.VERBOSE,
)
if not m:
return ""
return m.group("wsp") + (m.group("zp") or "")
# remove extra padding for double-digit day numbers
whitespace_padding = "" if len(m.group("day")) == 2 else m.group("wsp")
zero_padding = m.group("zp") or ""
return whitespace_padding + zero_padding

@property
def style(self) -> ChangelogStyle:
Expand Down
8 changes: 6 additions & 2 deletions specfile/specfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,9 +641,13 @@ def add_changelog_entry(
elif email is not None:
author += f" <{email}>"
if changelog:
# try to preserve padding of day of month
# compute day of month padding from the longest valid entry
# incorrect padding is stripped; invalid entries are ignored
padding = max(
(e.day_of_month_padding for e in reversed(changelog)),
(
e.sanitized_day_of_month_padding
for e in reversed(changelog)
),
key=len,
)
else:
Expand Down
27 changes: 27 additions & 0 deletions tests/integration/test_specfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,33 @@ def test_add_changelog_entry(
assert sections.changelog[: len(result)] == result


def test_add_changelog_entry_ignores_invalid_padding(specfile_factory, spec_minimal):
"""Test that add_changelog_entry ignores entries with invalid day padding (issue #216)."""
spec = specfile_factory(spec_minimal)

# Simulate scipy scenario: malformed entry with space before double-digit day
with spec.sections() as sections:
sections.changelog.data = [
"* Mon Dec 11 2021 Author <email> - 0.5.1-5", # INVALID
"- Initial version",
"",
"* Tue May 04 2020 Another <email> - 0.1-0", # VALID (zero-padded)
"- First version",
]

# Add new entry with single-digit day - should use zero-padding from valid entry
flexmock(specfile.specfile).should_receive("guess_packager").and_return(
"Test User <test@example.com>"
).once()
spec.add_changelog_entry("test entry", timestamp=datetime.date(2024, 1, 5))

with spec.sections() as sections:
new_entry = sections.changelog[0]
# Should use zero-padding style "Jan 05", not space-padding "Jan 5"
assert "Jan 05" in new_entry
assert "Jan 5" not in new_entry


@pytest.mark.parametrize(
"version, release",
[
Expand Down
9 changes: 7 additions & 2 deletions tests/unit/test_changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,17 @@ def test_entry_has_extended_timestamp(header, extended):
),
(
"* Mon Oct 18 12:34:45 CEST 2021 Nikola Forró <nforro@redhat.com> - 0.2-1",
" ",
"", # Invalid: double-digit day with space padding, returns ""
),
(
"* Mon Dec 11 2006 Author <email> - 1.0",
"",
), # Invalid: space before double-digit
("* Invalid header", ""), # Invalid: unparsable
],
)
def test_entry_day_of_month_padding(header, padding):
assert ChangelogEntry(header, [""]).day_of_month_padding == padding
assert ChangelogEntry(header, [""]).sanitized_day_of_month_padding == padding


@pytest.mark.parametrize(
Expand Down
Loading