mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
Break cli/contributing/changelog/archive/__main__.py into four single-responsibility modules under the same package: * versioning.py — pad_version / unpad_version / archive_filename (the canonical <padded-semver>-<date>.md filename schema). * archive_dir.py — existing_archives, archived_releases_from_directory, build_index_section (filesystem operations on docs/changelog/). * changelog_md.py — split_into_entries, md_body_after_header, trim_and_archive (CHANGELOG.md parsing and trimming, plus the always-rebuild-index logic). * package_mirror.py — mirror_to_debian_changelog, mirror_to_rpm_spec_changelog (Debian and RPM regeneration from CHANGELOG.md kept entries, with the trailing notice that points at docs.infinito.nexus and lists archived versions as plain text). __main__.py shrinks to argparse plus a thin orchestration layer that parses CHANGELOG.md once, runs trim_and_archive, reads the populated archive directory, and mirrors into the package files. Add `mirror_to_debian_changelog` and `mirror_to_rpm_spec_changelog` content-idempotency: skip the write when the regenerated content already matches what is on disk so re-runs leave file mtimes unchanged. Verified end-to-end: a follow-up run on a fully-processed tree leaves all three files (CHANGELOG.md, Debian changelog, RPM spec) byte-identical and mtime-stable. Replace `datetime.strptime` calls with `date.fromisoformat` so the DTZ007 lint stays clean: we only need calendar-date parsing for display formatting, not timezone-aware moments. Tests follow the same split: one test_<module>.py per source module, 40 tests in total. Shared fixtures live in _helpers.py (underscore prefix exempts it from the test-file-naming lint), and each test class explicitly mixes TempRepoMixin with unittest.TestCase so the test-files-have-tests AST lint sees the direct unittest base. Update docs/contributing/actions/release.md so the procedure description matches the current behaviour: package changelogs are "mirrored" (not "trimmed") from CHANGELOG.md, and the idempotence section calls out byte-idempotency on each of the three files. Run the CLI once against the live tree to bring packaging/debian/ changelog and packaging/fedora/infinito-nexus.spec back into sync with CHANGELOG.md and the docs/changelog/ archive directory. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
46 lines
1.5 KiB
Python
46 lines
1.5 KiB
Python
"""Version-string padding and the archive filename schema.
|
|
|
|
Archive files are named ``<padded-semver>-<date>.md`` so that a plain
|
|
directory listing already sorts them in chronological order. The
|
|
padding zero-fills each numeric component of the semver to three
|
|
digits, so ``7.0.0`` becomes ``007.000.000``. Pre-release and build
|
|
suffixes (``1.2.3-rc1``, ``1.2.3+meta``) are preserved verbatim and
|
|
tacked onto the padded core version.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
|
|
_NUMERIC_COMPONENT_RE = re.compile(r"^\d+$")
|
|
|
|
|
|
def pad_version(version: str) -> str:
|
|
"""Zero-pad each numeric component of *version* to three digits."""
|
|
parts = re.split(r"([-+])", version, maxsplit=1)
|
|
core = parts[0]
|
|
sep = parts[1] if len(parts) > 1 else ""
|
|
suffix = parts[2] if len(parts) > 2 else ""
|
|
padded = ".".join(
|
|
c.zfill(3) if _NUMERIC_COMPONENT_RE.match(c) else c for c in core.split(".")
|
|
)
|
|
return f"{padded}{sep}{suffix}"
|
|
|
|
|
|
def unpad_version(padded: str) -> str:
|
|
"""Inverse of :func:`pad_version`. ``007.000.000`` → ``7.0.0``."""
|
|
parts = re.split(r"([-+])", padded, maxsplit=1)
|
|
core = parts[0]
|
|
sep = parts[1] if len(parts) > 1 else ""
|
|
suffix = parts[2] if len(parts) > 2 else ""
|
|
unpadded = ".".join(
|
|
(c.lstrip("0") or "0") if _NUMERIC_COMPONENT_RE.match(c) else c
|
|
for c in core.split(".")
|
|
)
|
|
return f"{unpadded}{sep}{suffix}"
|
|
|
|
|
|
def archive_filename(version: str, date: str) -> str:
|
|
"""Return the canonical archive filename for ``(version, date)``."""
|
|
return f"{pad_version(version)}-{date}.md"
|