4242 Template ,
4343)
4444
45- from commitizen import out
46- from commitizen .bump import normalize_tag
4745from commitizen .cz .base import ChangelogReleaseHook
48- from commitizen .defaults import get_tag_regexes
4946from commitizen .exceptions import InvalidConfigurationError , NoCommitsFoundError
5047from commitizen .git import GitCommit , GitTag
51- from commitizen .version_schemes import (
52- DEFAULT_SCHEME ,
53- BaseVersion ,
54- InvalidVersion ,
55- )
48+ from commitizen .tags import TagRules
5649
5750if TYPE_CHECKING :
5851 from commitizen .cz .base import MessageBuilderHook
59- from commitizen .version_schemes import VersionScheme
6052
6153
6254@dataclass
@@ -69,50 +61,19 @@ class Metadata:
6961 unreleased_end : int | None = None
7062 latest_version : str | None = None
7163 latest_version_position : int | None = None
64+ latest_version_tag : str | None = None
65+
66+ def __post_init__ (self ):
67+ if self .latest_version and not self .latest_version_tag :
68+ # Test syntactic sugar
69+ # latest version tag is optional if same as latest version
70+ self .latest_version_tag = self .latest_version
7271
7372
7473def get_commit_tag (commit : GitCommit , tags : list [GitTag ]) -> GitTag | None :
7574 return next ((tag for tag in tags if tag .rev == commit .rev ), None )
7675
7776
78- def tag_included_in_changelog (
79- tag : GitTag ,
80- used_tags : list ,
81- merge_prerelease : bool ,
82- scheme : VersionScheme = DEFAULT_SCHEME ,
83- ) -> bool :
84- if tag in used_tags :
85- return False
86-
87- try :
88- version = scheme (tag .name )
89- except InvalidVersion :
90- return False
91-
92- if merge_prerelease and version .is_prerelease :
93- return False
94-
95- return True
96-
97-
98- def get_version_tags (
99- scheme : type [BaseVersion ], tags : list [GitTag ], tag_format : str
100- ) -> list [GitTag ]:
101- valid_tags : list [GitTag ] = []
102- TAG_FORMAT_REGEXS = get_tag_regexes (scheme .parser .pattern )
103- tag_format_regex = tag_format
104- for pattern , regex in TAG_FORMAT_REGEXS .items ():
105- tag_format_regex = tag_format_regex .replace (pattern , regex )
106- for tag in tags :
107- if re .match (tag_format_regex , tag .name ):
108- valid_tags .append (tag )
109- else :
110- out .warn (
111- f"InvalidVersion { tag .name } doesn't match configured tag format { tag_format } "
112- )
113- return valid_tags
114-
115-
11677def generate_tree_from_commits (
11778 commits : list [GitCommit ],
11879 tags : list [GitTag ],
@@ -122,13 +83,13 @@ def generate_tree_from_commits(
12283 change_type_map : dict [str , str ] | None = None ,
12384 changelog_message_builder_hook : MessageBuilderHook | None = None ,
12485 changelog_release_hook : ChangelogReleaseHook | None = None ,
125- merge_prerelease : bool = False ,
126- scheme : VersionScheme = DEFAULT_SCHEME ,
86+ rules : TagRules | None = None ,
12787) -> Iterable [dict ]:
12888 pat = re .compile (changelog_pattern )
12989 map_pat = re .compile (commit_parser , re .MULTILINE )
13090 body_map_pat = re .compile (commit_parser , re .MULTILINE | re .DOTALL )
13191 current_tag : GitTag | None = None
92+ rules = rules or TagRules ()
13293
13394 # Check if the latest commit is not tagged
13495 if commits :
@@ -148,8 +109,10 @@ def generate_tree_from_commits(
148109 for commit in commits :
149110 commit_tag = get_commit_tag (commit , tags )
150111
151- if commit_tag is not None and tag_included_in_changelog (
152- commit_tag , used_tags , merge_prerelease , scheme = scheme
112+ if (
113+ commit_tag
114+ and commit_tag not in used_tags
115+ and rules .include_in_changelog (commit_tag )
153116 ):
154117 used_tags .append (commit_tag )
155118 release = {
@@ -343,8 +306,7 @@ def get_smart_tag_range(
343306def get_oldest_and_newest_rev (
344307 tags : list [GitTag ],
345308 version : str ,
346- tag_format : str ,
347- scheme : VersionScheme | None = None ,
309+ rules : TagRules ,
348310) -> tuple [str | None , str | None ]:
349311 """Find the tags for the given version.
350312
@@ -358,22 +320,28 @@ def get_oldest_and_newest_rev(
358320 oldest , newest = version .split (".." )
359321 except ValueError :
360322 newest = version
361- newest_tag = normalize_tag (newest , tag_format = tag_format , scheme = scheme )
323+ if not (newest_tag := rules .find_tag_for (tags , newest )):
324+ raise NoCommitsFoundError ("Could not find a valid revision range." )
362325
363326 oldest_tag = None
327+ oldest_tag_name = None
364328 if oldest :
365- oldest_tag = normalize_tag (oldest , tag_format = tag_format , scheme = scheme )
329+ if not (oldest_tag := rules .find_tag_for (tags , oldest )):
330+ raise NoCommitsFoundError ("Could not find a valid revision range." )
331+ oldest_tag_name = oldest_tag .name
366332
367- tags_range = get_smart_tag_range (tags , newest = newest_tag , oldest = oldest_tag )
333+ tags_range = get_smart_tag_range (
334+ tags , newest = newest_tag .name , oldest = oldest_tag_name
335+ )
368336 if not tags_range :
369337 raise NoCommitsFoundError ("Could not find a valid revision range." )
370338
371339 oldest_rev : str | None = tags_range [- 1 ].name
372- newest_rev = newest_tag
340+ newest_rev = newest_tag . name
373341
374342 # check if it's the first tag created
375343 # and it's also being requested as part of the range
376- if oldest_rev == tags [- 1 ].name and oldest_rev == oldest_tag :
344+ if oldest_rev == tags [- 1 ].name and oldest_rev == oldest_tag_name :
377345 return None , newest_rev
378346
379347 # when they are the same, and it's also the
0 commit comments