diff --git a/src/git_changelog/cli.py b/src/git_changelog/cli.py index 70b724e..b9182f9 100644 --- a/src/git_changelog/cli.py +++ b/src/git_changelog/cli.py @@ -101,6 +101,43 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( "-h", "--help", action="help", default=argparse.SUPPRESS, help="Show this help message and exit." ) + parser.add_argument( + "-i", + "--in-place", + action="store_true", + dest="in_place", + default=False, + help="Insert new entries (versions missing from changelog) in-place. " + "An output file must be specified. With custom templates, " + "you must pass two additional arguments: --version-regex and --marker-line. " + "When writing in-place, an 'inplace' variable " + "will be injected in the Jinja context, " + "allowing to adapt the generated contents " + "(for example to skip changelog headers or footers).", + ) + parser.add_argument( + "-g", + "--version-regex", + action="store", + dest="version_regex", + default=None, + help="A regular expression to match versions in the existing changelog " + "(used to find the latest release) when writing in-place. " + "The regular expression must be a Python regex with a 'version' named group. ", + ) + + parser.add_argument( + "-m", + "--marker-line", + action="store", + dest="marker_line", + default=None, + help="A marker line at which to insert new entries " + "(versions missing from changelog). " + "If two marker lines are present in the changelog, " + "the contents between those two lines will be overwritten " + "(useful to update an 'Unreleased' entry for example).", + ) parser.add_argument( "-o", "--output", @@ -160,6 +197,21 @@ def get_parser() -> argparse.ArgumentParser: return parser +def _latest(lines: list[str], regex: Pattern) -> str | None: + for line in lines: + match = regex.search(line) + if match: + return match.groupdict()["version"] + return None + + +def _unreleased(versions: list[Version], last_release: str): + for index, version in enumerate(versions): + if version.tag == last_release: + return versions[:index] + return versions + + def main(args: list[str] | None = None) -> int: """ Run the main program. diff --git a/tests/test_end_to_end.py b/tests/test_end_to_end.py index a053f9c..18646c3 100644 --- a/tests/test_end_to_end.py +++ b/tests/test_end_to_end.py @@ -95,3 +95,32 @@ def test_rendering_custom_sections(repo): if section_type != "feat": assert section_title not in rendered + +def test_rendering_in_place(repo): # noqa: WPS218 + """Render changelog in-place. + + Parameters: + repo: Path to a temporary repository. + """ + _, rendered = build_and_render( + str(repo), + style="angular", + bump_latest=False, + output=repo.joinpath("changelog.md").as_posix(), + template="keepachangelog", + ) + assert len(re.findall("", rendered)) == 2 + assert "Unreleased" in rendered + latest_tag = "91.6.14" + assert latest_tag not in rendered + _git("-C", repo, "tag", latest_tag) + _, rendered = build_and_render( + str(repo), + style="angular", + bump_latest=True, + output=repo.joinpath("changelog.md").as_posix(), + template="keepachangelog", + ) + assert len(re.findall("", rendered)) == 1 + assert "Unreleased" not in rendered + assert latest_tag in rendered