Skip to content

Commit 2dc3e78

Browse files
Merge branch 'master' into feature/custom-validation
2 parents 8dfe7b6 + 15f0812 commit 2dc3e78

21 files changed

+574
-70
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ repos:
4949
- tomli
5050

5151
- repo: https://github.com/commitizen-tools/commitizen
52-
rev: v3.29.0 # automatically updated by Commitizen
52+
rev: v3.29.1 # automatically updated by Commitizen
5353
hooks:
5454
- id: commitizen
5555
- id: commitizen-branch

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
## v3.29.1 (2024-09-26)
2+
3+
### Fix
4+
5+
- **changelog**: Factorized TAG_FORMAT_REGEXES
6+
- **changelog**: Handle tag format without version pattern
7+
- **changelog**: handle custom tag_format in changelog generation
8+
9+
### Refactor
10+
11+
- Use format strings
12+
113
## v3.29.0 (2024-08-11)
214

315
### Feat

commitizen/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "3.29.0"
1+
__version__ = "3.29.1"

commitizen/changelog.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
from commitizen import out
4545
from commitizen.bump import normalize_tag
4646
from commitizen.cz.base import ChangelogReleaseHook
47+
from commitizen.defaults import get_tag_regexes
4748
from commitizen.exceptions import InvalidConfigurationError, NoCommitsFoundError
4849
from commitizen.git import GitCommit, GitTag
4950
from commitizen.version_schemes import (
@@ -93,16 +94,21 @@ def tag_included_in_changelog(
9394
return True
9495

9596

96-
def get_version_tags(scheme: type[BaseVersion], tags: list[GitTag]) -> list[GitTag]:
97+
def get_version_tags(
98+
scheme: type[BaseVersion], tags: list[GitTag], tag_format: str
99+
) -> list[GitTag]:
97100
valid_tags: list[GitTag] = []
101+
TAG_FORMAT_REGEXS = get_tag_regexes(scheme.parser.pattern)
102+
tag_format_regex = tag_format
103+
for pattern, regex in TAG_FORMAT_REGEXS.items():
104+
tag_format_regex = tag_format_regex.replace(pattern, regex)
98105
for tag in tags:
99-
try:
100-
scheme(tag.name)
101-
except InvalidVersion:
102-
out.warn(f"InvalidVersion {tag}")
103-
else:
106+
if re.match(tag_format_regex, tag.name):
104107
valid_tags.append(tag)
105-
108+
else:
109+
out.warn(
110+
f"InvalidVersion {tag.name} doesn't match configured tag format {tag_format}"
111+
)
106112
return valid_tags
107113

108114

@@ -351,7 +357,6 @@ def get_oldest_and_newest_rev(
351357
oldest, newest = version.split("..")
352358
except ValueError:
353359
newest = version
354-
355360
newest_tag = normalize_tag(newest, tag_format=tag_format, scheme=scheme)
356361

357362
oldest_tag = None

commitizen/changelog_formats/asciidoc.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,19 @@ def parse_version_from_title(self, line: str) -> str | None:
1818
matches = list(re.finditer(self.version_parser, m.group("title")))
1919
if not matches:
2020
return None
21-
return matches[-1].group("version")
21+
if "version" in matches[-1].groupdict():
22+
return matches[-1].group("version")
23+
partial_matches = matches[-1].groupdict()
24+
try:
25+
partial_version = f"{partial_matches['major']}.{partial_matches['minor']}.{partial_matches['patch']}"
26+
except KeyError:
27+
return None
28+
29+
if partial_matches.get("prerelease"):
30+
partial_version = f"{partial_version}-{partial_matches['prerelease']}"
31+
if partial_matches.get("devrelease"):
32+
partial_version = f"{partial_version}{partial_matches['devrelease']}"
33+
return partial_version
2234

2335
def parse_title_level(self, line: str) -> int | None:
2436
m = self.RE_TITLE.match(line)

commitizen/changelog_formats/base.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
from __future__ import annotations
22

33
import os
4+
import re
45
from abc import ABCMeta
56
from re import Pattern
67
from typing import IO, Any, ClassVar
78

89
from commitizen.changelog import Metadata
910
from commitizen.config.base_config import BaseConfig
11+
from commitizen.defaults import get_tag_regexes
1012
from commitizen.version_schemes import get_version_scheme
1113

1214
from . import ChangelogFormat
@@ -25,10 +27,16 @@ def __init__(self, config: BaseConfig):
2527
# See: https://bugs.python.org/issue44807
2628
self.config = config
2729
self.encoding = self.config.settings["encoding"]
30+
self.tag_format = self.config.settings["tag_format"]
2831

2932
@property
3033
def version_parser(self) -> Pattern:
31-
return get_version_scheme(self.config).parser
34+
tag_regex: str = self.tag_format
35+
version_regex = get_version_scheme(self.config).parser.pattern
36+
TAG_FORMAT_REGEXS = get_tag_regexes(version_regex)
37+
for pattern, regex in TAG_FORMAT_REGEXS.items():
38+
tag_regex = tag_regex.replace(pattern, regex)
39+
return re.compile(tag_regex)
3240

3341
def get_metadata(self, filepath: str) -> Metadata:
3442
if not os.path.isfile(filepath):

commitizen/changelog_formats/markdown.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,21 @@ def parse_version_from_title(self, line: str) -> str | None:
1919
m = re.search(self.version_parser, m.group("title"))
2020
if not m:
2121
return None
22-
return m.group("version")
22+
if "version" in m.groupdict():
23+
return m.group("version")
24+
matches = m.groupdict()
25+
try:
26+
partial_version = (
27+
f"{matches['major']}.{matches['minor']}.{matches['patch']}"
28+
)
29+
except KeyError:
30+
return None
31+
32+
if matches.get("prerelease"):
33+
partial_version = f"{partial_version}-{matches['prerelease']}"
34+
if matches.get("devrelease"):
35+
partial_version = f"{partial_version}{matches['devrelease']}"
36+
return partial_version
2337

2438
def parse_title_level(self, line: str) -> int | None:
2539
m = self.RE_TITLE.match(line)

commitizen/changelog_formats/restructuredtext.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def get_metadata_from_file(self, file: IO[Any]) -> Metadata:
4646
third = third.strip().lower()
4747
title: str | None = None
4848
kind: TitleKind | None = None
49-
5049
if self.is_overlined_title(first, second, third):
5150
title = second
5251
kind = (first[0], third[0])
@@ -67,10 +66,29 @@ def get_metadata_from_file(self, file: IO[Any]) -> Metadata:
6766
# Try to find the latest release done
6867
m = re.search(self.version_parser, title)
6968
if m:
70-
version = m.group("version")
71-
meta.latest_version = version
72-
meta.latest_version_position = index
73-
break # there's no need for more info
69+
matches = m.groupdict()
70+
if "version" in matches:
71+
version = m.group("version")
72+
meta.latest_version = version
73+
meta.latest_version_position = index
74+
break # there's no need for more info
75+
try:
76+
partial_version = (
77+
f"{matches['major']}.{matches['minor']}.{matches['patch']}"
78+
)
79+
if matches.get("prerelease"):
80+
partial_version = (
81+
f"{partial_version}-{matches['prerelease']}"
82+
)
83+
if matches.get("devrelease"):
84+
partial_version = (
85+
f"{partial_version}{matches['devrelease']}"
86+
)
87+
meta.latest_version = partial_version
88+
meta.latest_version_position = index
89+
break
90+
except KeyError:
91+
pass
7492
if meta.unreleased_start is not None and meta.unreleased_end is None:
7593
meta.unreleased_end = (
7694
meta.latest_version_position if meta.latest_version else index + 1

commitizen/changelog_formats/textile.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,24 @@ def parse_version_from_title(self, line: str) -> str | None:
1616
m = re.search(self.version_parser, line)
1717
if not m:
1818
return None
19-
return m.group("version")
19+
if "version" in m.groupdict():
20+
return m.group("version")
21+
matches = m.groupdict()
22+
if not all(
23+
[
24+
version_segment in matches
25+
for version_segment in ("major", "minor", "patch")
26+
]
27+
):
28+
return None
29+
30+
partial_version = f"{matches['major']}.{matches['minor']}.{matches['patch']}"
31+
32+
if matches.get("prerelease"):
33+
partial_version = f"{partial_version}-{matches['prerelease']}"
34+
if matches.get("devrelease"):
35+
partial_version = f"{partial_version}{matches['devrelease']}"
36+
return partial_version
2037

2138
def parse_title_level(self, line: str) -> int | None:
2239
m = self.RE_TITLE.match(line)

commitizen/commands/changelog.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,10 @@ def __call__(self):
168168
# Don't continue if no `file_name` specified.
169169
assert self.file_name
170170

171-
tags = changelog.get_version_tags(self.scheme, git.get_tags()) or []
172-
171+
tags = (
172+
changelog.get_version_tags(self.scheme, git.get_tags(), self.tag_format)
173+
or []
174+
)
173175
end_rev = ""
174176
if self.incremental:
175177
changelog_meta = self.changelog_format.get_metadata(self.file_name)
@@ -182,21 +184,18 @@ def __call__(self):
182184
start_rev = self._find_incremental_rev(
183185
strip_local_version(latest_tag_version), tags
184186
)
185-
186187
if self.rev_range:
187188
start_rev, end_rev = changelog.get_oldest_and_newest_rev(
188189
tags,
189190
version=self.rev_range,
190191
tag_format=self.tag_format,
191192
scheme=self.scheme,
192193
)
193-
194194
commits = git.get_commits(start=start_rev, end=end_rev, args="--topo-order")
195195
if not commits and (
196196
self.current_version is None or not self.current_version.is_prerelease
197197
):
198198
raise NoCommitsFoundError("No commits found")
199-
200199
tree = changelog.generate_tree_from_commits(
201200
commits,
202201
tags,

0 commit comments

Comments
 (0)