3232from collections.abc import Generator, Iterable, Mapping, MutableMapping, Sequence
3333from dataclasses import dataclass
3434from datetime import date
35+ from itertools import chain
3536from typing import TYPE_CHECKING, Any
3637
3738from jinja2 import (
@@ -88,33 +89,32 @@ def generate_tree_from_commits(
8889 pat = re.compile(changelog_pattern)
8990 map_pat = re.compile(commit_parser, re.MULTILINE)
9091 body_map_pat = re.compile(commit_parser, re.MULTILINE | re.DOTALL)
91- current_tag: GitTag | None = None
9292 rules = rules or TagRules()
9393
9494 # Check if the latest commit is not tagged
95- if commits:
96- latest_commit = commits[0]
97- current_tag = get_commit_tag(latest_commit, tags)
98-
99- current_tag_name: str = unreleased_version or "Unreleased"
100- current_tag_date: str = ""
101- if unreleased_version is not None:
102- current_tag_date = date.today().isoformat()
103- if current_tag is not None and current_tag.name:
104- current_tag_name = current_tag.name
105- current_tag_date = current_tag.date
10695
96+ current_tag = get_commit_tag(commits[0], tags) if commits else None
97+ current_tag_name = unreleased_version or "Unreleased"
98+ current_tag_date = (
99+ date.today().isoformat() if unreleased_version is not None else ""
100+ )
101+
102+ used_tags: set[GitTag] = set()
103+ if current_tag:
104+ used_tags.add(current_tag)
105+ if current_tag.name:
106+ current_tag_name = current_tag.name
107+ current_tag_date = current_tag.date
108+
109+ commit_tag: GitTag | None = None
107110 changes: dict = defaultdict(list)
108- used_tags: list = [current_tag]
109111 for commit in commits:
110- commit_tag = get_commit_tag(commit, tags)
111-
112112 if (
113- commit_tag
113+ ( commit_tag := get_commit_tag(commit, tags))
114114 and commit_tag not in used_tags
115115 and rules.include_in_changelog(commit_tag)
116116 ):
117- used_tags.append (commit_tag)
117+ used_tags.add (commit_tag)
118118 release = {
119119 "version": current_tag_name,
120120 "date": current_tag_date,
@@ -127,24 +127,15 @@ def generate_tree_from_commits(
127127 current_tag_date = commit_tag.date
128128 changes = defaultdict(list)
129129
130- matches = pat.match(commit.message)
131- if not matches:
130+ if not pat.match(commit.message):
132131 continue
133132
134- # Process subject from commit message
135- if message := map_pat.match(commit.message):
136- process_commit_message(
137- changelog_message_builder_hook,
138- message,
139- commit,
140- changes,
141- change_type_map,
142- )
143-
144- # Process body from commit message
145- body_parts = commit.body.split("\n\n")
146- for body_part in body_parts:
147- if message := body_map_pat.match(body_part):
133+ # Process subject and body from commit message
134+ for message in chain(
135+ [map_pat.match(commit.message)],
136+ (body_map_pat.match(block) for block in commit.body.split("\n\n")),
137+ ):
138+ if message:
148139 process_commit_message(
149140 changelog_message_builder_hook,
150141 message,
0 commit comments