4141 Template ,
4242)
4343
44- from commitizen import out
45- from commitizen .bump import normalize_tag
4644from commitizen .cz .base import ChangelogReleaseHook
47- from commitizen .defaults import get_tag_regexes
4845from commitizen .exceptions import InvalidConfigurationError , NoCommitsFoundError
4946from commitizen .git import GitCommit , GitTag
50- from commitizen .version_schemes import (
51- DEFAULT_SCHEME ,
52- BaseVersion ,
53- InvalidVersion ,
54- )
47+ from commitizen .tags import TagRules
5548
5649if TYPE_CHECKING :
5750 from commitizen .cz .base import MessageBuilderHook
58- from commitizen .version_schemes import VersionScheme
5951
6052
6153@dataclass
@@ -68,50 +60,19 @@ class Metadata:
6860 unreleased_end : int | None = None
6961 latest_version : str | None = None
7062 latest_version_position : int | None = None
63+ latest_version_tag : str | None = None
64+
65+ def __post_init__ (self ):
66+ if self .latest_version and not self .latest_version_tag :
67+ # Test syntactic sugar
68+ # latest version tag is optional if same as latest version
69+ self .latest_version_tag = self .latest_version
7170
7271
7372def get_commit_tag (commit : GitCommit , tags : list [GitTag ]) -> GitTag | None :
7473 return next ((tag for tag in tags if tag .rev == commit .rev ), None )
7574
7675
77- def tag_included_in_changelog (
78- tag : GitTag ,
79- used_tags : list ,
80- merge_prerelease : bool ,
81- scheme : VersionScheme = DEFAULT_SCHEME ,
82- ) -> bool :
83- if tag in used_tags :
84- return False
85-
86- try :
87- version = scheme (tag .name )
88- except InvalidVersion :
89- return False
90-
91- if merge_prerelease and version .is_prerelease :
92- return False
93-
94- return True
95-
96-
97- def get_version_tags (
98- scheme : type [BaseVersion ], tags : list [GitTag ], tag_format : str
99- ) -> list [GitTag ]:
100- 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 )
105- for tag in tags :
106- if re .match (tag_format_regex , tag .name ):
107- valid_tags .append (tag )
108- else :
109- out .warn (
110- f"InvalidVersion { tag .name } doesn't match configured tag format { tag_format } "
111- )
112- return valid_tags
113-
114-
11576def generate_tree_from_commits (
11677 commits : list [GitCommit ],
11778 tags : list [GitTag ],
@@ -121,13 +82,13 @@ def generate_tree_from_commits(
12182 change_type_map : dict [str , str ] | None = None ,
12283 changelog_message_builder_hook : MessageBuilderHook | None = None ,
12384 changelog_release_hook : ChangelogReleaseHook | None = None ,
124- merge_prerelease : bool = False ,
125- scheme : VersionScheme = DEFAULT_SCHEME ,
85+ rules : TagRules | None = None ,
12686) -> Iterable [dict ]:
12787 pat = re .compile (changelog_pattern )
12888 map_pat = re .compile (commit_parser , re .MULTILINE )
12989 body_map_pat = re .compile (commit_parser , re .MULTILINE | re .DOTALL )
13090 current_tag : GitTag | None = None
91+ rules = rules or TagRules ()
13192
13293 # Check if the latest commit is not tagged
13394 if commits :
@@ -147,8 +108,10 @@ def generate_tree_from_commits(
147108 for commit in commits :
148109 commit_tag = get_commit_tag (commit , tags )
149110
150- if commit_tag is not None and tag_included_in_changelog (
151- commit_tag , used_tags , merge_prerelease , scheme = scheme
111+ if (
112+ commit_tag
113+ and commit_tag not in used_tags
114+ and rules .include_in_changelog (commit_tag )
152115 ):
153116 used_tags .append (commit_tag )
154117 release = {
@@ -342,8 +305,7 @@ def get_smart_tag_range(
342305def get_oldest_and_newest_rev (
343306 tags : list [GitTag ],
344307 version : str ,
345- tag_format : str ,
346- scheme : VersionScheme | None = None ,
308+ rules : TagRules ,
347309) -> tuple [str | None , str | None ]:
348310 """Find the tags for the given version.
349311
@@ -357,22 +319,28 @@ def get_oldest_and_newest_rev(
357319 oldest , newest = version .split (".." )
358320 except ValueError :
359321 newest = version
360- newest_tag = normalize_tag (newest , tag_format = tag_format , scheme = scheme )
322+ if not (newest_tag := rules .find_tag_for (tags , newest )):
323+ raise NoCommitsFoundError ("Could not find a valid revision range." )
361324
362325 oldest_tag = None
326+ oldest_tag_name = None
363327 if oldest :
364- oldest_tag = normalize_tag (oldest , tag_format = tag_format , scheme = scheme )
328+ if not (oldest_tag := rules .find_tag_for (tags , oldest )):
329+ raise NoCommitsFoundError ("Could not find a valid revision range." )
330+ oldest_tag_name = oldest_tag .name
365331
366- tags_range = get_smart_tag_range (tags , newest = newest_tag , oldest = oldest_tag )
332+ tags_range = get_smart_tag_range (
333+ tags , newest = newest_tag .name , oldest = oldest_tag_name
334+ )
367335 if not tags_range :
368336 raise NoCommitsFoundError ("Could not find a valid revision range." )
369337
370338 oldest_rev : str | None = tags_range [- 1 ].name
371- newest_rev = newest_tag
339+ newest_rev = newest_tag . name
372340
373341 # check if it's the first tag created
374342 # and it's also being requested as part of the range
375- if oldest_rev == tags [- 1 ].name and oldest_rev == oldest_tag :
343+ if oldest_rev == tags [- 1 ].name and oldest_rev == oldest_tag_name :
376344 return None , newest_rev
377345
378346 # when they are the same, and it's also the
0 commit comments