Skip to content

Commit 7d46a37

Browse files
committed
feat(template): add changelog --export-template command
1 parent 6cfafeb commit 7d46a37

File tree

4 files changed

+78
-6
lines changed

4 files changed

+78
-6
lines changed

Diff for: commitizen/changelog.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
Environment,
3838
FileSystemLoader,
3939
PackageLoader,
40+
Template,
4041
)
4142

4243
from commitizen import defaults
@@ -147,17 +148,26 @@ def order_changelog_tree(tree: Iterable, change_type_order: List[str]) -> Iterab
147148
return sorted_tree
148149

149150

151+
def get_changelog_template(
152+
loader: Optional[BaseLoader] = None, template: Optional[str] = None
153+
) -> Template:
154+
loader = ChoiceLoader(
155+
[
156+
FileSystemLoader("."),
157+
loader or PackageLoader("commitizen", "templates"),
158+
]
159+
)
160+
env = Environment(loader=loader, trim_blocks=True)
161+
return env.get_template(template or DEFAULT_TEMPLATE)
162+
163+
150164
def render_changelog(
151165
tree: Iterable,
152166
loader: Optional[BaseLoader] = None,
153167
template: Optional[str] = None,
154168
**kwargs,
155169
) -> str:
156-
loader = ChoiceLoader(
157-
[FileSystemLoader("."), loader or PackageLoader("commitizen", "templates")]
158-
)
159-
env = Environment(loader=loader, trim_blocks=True)
160-
jinja_template = env.get_template(template or DEFAULT_TEMPLATE)
170+
jinja_template = get_changelog_template(loader, template or DEFAULT_TEMPLATE)
161171
changelog: str = jinja_template.render(tree=tree, **kwargs)
162172
return changelog
163173

Diff for: commitizen/cli.py

+5
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ def __call__(self, parser, namespace, kwarg, option_string=None):
293293
"If not set, it will generate changelog from the start"
294294
),
295295
},
296+
{
297+
"name": "--export-template",
298+
"default": None,
299+
"help": "Export the changelog template into this file instead of rendering it",
300+
},
296301
*deepcopy(tpl_arguments),
297302
],
298303
},

Diff for: commitizen/commands/changelog.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os.path
22
from difflib import SequenceMatcher
33
from operator import itemgetter
4+
from pathlib import Path
45
from typing import Callable, Dict, List, Optional
56

67
from commitizen import bump, changelog, defaults, factory, git, out
@@ -49,8 +50,13 @@ def __init__(self, config: BaseConfig, args):
4950
self.tag_format = args.get("tag_format") or self.config.settings.get(
5051
"tag_format"
5152
)
52-
self.template = args.get("template") or self.config.settings.get("template")
53+
self.template = (
54+
args.get("template")
55+
or self.config.settings.get("template")
56+
or self.cz.template
57+
)
5358
self.extras = args.get("extras") or {}
59+
self.export_template_to = args.get("export_template")
5460

5561
def _find_incremental_rev(self, latest_version: str, tags: List[GitTag]) -> str:
5662
"""Try to find the 'start_rev'.
@@ -102,6 +108,11 @@ def write_changelog(
102108
changelog_out = changelog_hook(changelog_out, partial_changelog)
103109
changelog_file.write(changelog_out)
104110

111+
def export_template(self):
112+
tpl = changelog.get_changelog_template(self.cz.template_loader, self.template)
113+
src = Path(tpl.filename)
114+
Path(self.export_template_to).write_text(src.read_text())
115+
105116
def __call__(self):
106117
commit_parser = self.cz.commit_parser
107118
changelog_pattern = self.cz.changelog_pattern
@@ -113,6 +124,9 @@ def __call__(self):
113124
Callable
114125
] = self.cz.changelog_message_builder_hook
115126

127+
if self.export_template_to:
128+
return self.export_template()
129+
116130
if not changelog_pattern or not commit_parser:
117131
raise NoPatternMapError(
118132
f"'{self.config.settings['name']}' rule does not support changelog"

Diff for: tests/commands/test_changelog_command.py

+43
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
from textwrap import dedent
55

66
import pytest
7+
from jinja2 import FileSystemLoader
78
from pytest_mock import MockFixture
89

10+
from commitizen import __file__ as commitizen_init
911
from commitizen import cli, git
1012
from commitizen.changelog import DEFAULT_TEMPLATE
1113
from commitizen.commands.changelog import Changelog
@@ -1086,3 +1088,44 @@ def test_changelog_template_extra_quotes(
10861088

10871089
changelog = project_root / "CHANGELOG.md"
10881090
assert changelog.read_text() == "no-quote - single quotes - double quotes"
1091+
1092+
1093+
def test_export_changelog_template_from_default(
1094+
mocker: MockFixture,
1095+
tmp_commitizen_project: Path,
1096+
):
1097+
project_root = Path(tmp_commitizen_project)
1098+
target = project_root / "changelog.jinja"
1099+
src = Path(commitizen_init).parent / "templates" / DEFAULT_TEMPLATE
1100+
1101+
args = ["cz", "changelog", "--export-template", str(target)]
1102+
1103+
mocker.patch.object(sys, "argv", args)
1104+
cli.main()
1105+
1106+
assert target.exists()
1107+
assert target.read_text() == src.read_text()
1108+
1109+
1110+
def test_export_changelog_template_from_plugin(
1111+
mocker: MockFixture,
1112+
tmp_commitizen_project: Path,
1113+
mock_plugin: BaseCommitizen,
1114+
tmp_path: Path,
1115+
):
1116+
project_root = Path(tmp_commitizen_project)
1117+
target = project_root / "changelog.jinja"
1118+
filename = "template.jinja"
1119+
src = tmp_path / filename
1120+
tpl = "I am a custom template"
1121+
src.write_text(tpl)
1122+
mock_plugin.template_loader = FileSystemLoader(tmp_path)
1123+
mock_plugin.template = filename
1124+
1125+
args = ["cz", "changelog", "--export-template", str(target)]
1126+
1127+
mocker.patch.object(sys, "argv", args)
1128+
cli.main()
1129+
1130+
assert target.exists()
1131+
assert target.read_text() == tpl

0 commit comments

Comments
 (0)