@@ -74,6 +74,23 @@ def get_commit_tag(commit: GitCommit, tags: list[GitTag]) -> GitTag | None:
74
74
return next ((tag for tag in tags if tag .rev == commit .rev ), None )
75
75
76
76
77
+ def _get_release_info (
78
+ current_tag_name : str ,
79
+ current_tag_date : str ,
80
+ changes : dict [str | None , list ],
81
+ changelog_release_hook : ChangelogReleaseHook | None ,
82
+ commit_tag : GitTag | None ,
83
+ ) -> dict [str , Any ]:
84
+ release = {
85
+ "version" : current_tag_name ,
86
+ "date" : current_tag_date ,
87
+ "changes" : changes ,
88
+ }
89
+ if changelog_release_hook :
90
+ return changelog_release_hook (release , commit_tag )
91
+ return release
92
+
93
+
77
94
def generate_tree_from_commits (
78
95
commits : list [GitCommit ],
79
96
tags : list [GitTag ],
@@ -88,24 +105,24 @@ def generate_tree_from_commits(
88
105
pat = re .compile (changelog_pattern )
89
106
map_pat = re .compile (commit_parser , re .MULTILINE )
90
107
body_map_pat = re .compile (commit_parser , re .MULTILINE | re .DOTALL )
91
- current_tag : GitTag | None = None
92
108
rules = rules or TagRules ()
93
109
110
+ used_tags : set [GitTag ] = set ()
111
+ current_tag_name = unreleased_version or "Unreleased"
112
+ current_tag_date = (
113
+ date .today ().isoformat () if unreleased_version is not None else ""
114
+ )
115
+
94
116
# 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
106
-
107
- changes : dict = defaultdict (list )
108
- used_tags : list = [current_tag ]
117
+ current_tag = get_commit_tag (commits [0 ], tags ) if commits else None
118
+ if current_tag is not None :
119
+ used_tags .add (current_tag )
120
+ if current_tag .name :
121
+ current_tag_name = current_tag .name
122
+ current_tag_date = current_tag .date
123
+
124
+ changes : defaultdict [str | None , list ] = defaultdict (list )
125
+ commit_tag : GitTag | None = None
109
126
for commit in commits :
110
127
commit_tag = get_commit_tag (commit , tags )
111
128
@@ -114,21 +131,21 @@ def generate_tree_from_commits(
114
131
and commit_tag not in used_tags
115
132
and rules .include_in_changelog (commit_tag )
116
133
):
117
- used_tags .append (commit_tag )
118
- release = {
119
- "version" : current_tag_name ,
120
- "date" : current_tag_date ,
121
- "changes" : changes ,
122
- }
123
- if changelog_release_hook :
124
- release = changelog_release_hook (release , commit_tag )
125
- yield release
134
+ used_tags .add (commit_tag )
135
+
136
+ yield _get_release_info (
137
+ current_tag_name ,
138
+ current_tag_date ,
139
+ changes ,
140
+ changelog_release_hook ,
141
+ commit_tag ,
142
+ )
143
+
126
144
current_tag_name = commit_tag .name
127
145
current_tag_date = commit_tag .date
128
146
changes = defaultdict (list )
129
147
130
- matches = pat .match (commit .message )
131
- if not matches :
148
+ if not pat .match (commit .message ):
132
149
continue
133
150
134
151
# Process subject from commit message
@@ -153,14 +170,13 @@ def generate_tree_from_commits(
153
170
change_type_map ,
154
171
)
155
172
156
- release = {
157
- "version" : current_tag_name ,
158
- "date" : current_tag_date ,
159
- "changes" : changes ,
160
- }
161
- if changelog_release_hook :
162
- release = changelog_release_hook (release , commit_tag )
163
- yield release
173
+ yield _get_release_info (
174
+ current_tag_name ,
175
+ current_tag_date ,
176
+ changes ,
177
+ changelog_release_hook ,
178
+ commit_tag ,
179
+ )
164
180
165
181
166
182
def process_commit_message (
@@ -170,21 +186,23 @@ def process_commit_message(
170
186
changes : dict [str | None , list ],
171
187
change_type_map : dict [str , str ] | None = None ,
172
188
):
173
- message : dict = {
189
+ message : dict [ str , str | list [ str ] | Any ] = {
174
190
"sha1" : commit .rev ,
175
191
"parents" : commit .parents ,
176
192
"author" : commit .author ,
177
193
"author_email" : commit .author_email ,
178
194
** parsed .groupdict (),
179
195
}
180
196
181
- if processed := hook (message , commit ) if hook else message :
182
- messages = [processed ] if isinstance (processed , dict ) else processed
183
- for msg in messages :
184
- change_type = msg .pop ("change_type" , None )
185
- if change_type_map :
186
- change_type = change_type_map .get (change_type , change_type )
187
- changes [change_type ].append (msg )
197
+ if not (processed := hook (message , commit ) if hook else message ):
198
+ return
199
+
200
+ processed_messages = [processed ] if isinstance (processed , dict ) else processed
201
+ for msg in processed_messages :
202
+ change_type = msg .pop ("change_type" , None )
203
+ if change_type_map :
204
+ change_type = change_type_map .get (change_type , change_type )
205
+ changes [change_type ].append (msg )
188
206
189
207
190
208
def generate_ordered_changelog_tree (
@@ -228,8 +246,7 @@ def render_changelog(
228
246
** kwargs ,
229
247
) -> str :
230
248
jinja_template = get_changelog_template (loader , template )
231
- changelog : str = jinja_template .render (tree = tree , ** kwargs )
232
- return changelog
249
+ return jinja_template .render (tree = tree , ** kwargs )
233
250
234
251
235
252
def incremental_build (
@@ -256,7 +273,9 @@ def incremental_build(
256
273
for index , line in enumerate (lines ):
257
274
if index == unreleased_start :
258
275
skip = True
259
- elif index == unreleased_end :
276
+ continue
277
+
278
+ if index == unreleased_end :
260
279
skip = False
261
280
if (
262
281
latest_version_position is None
@@ -271,13 +290,15 @@ def incremental_build(
271
290
272
291
if index == latest_version_position :
273
292
output_lines .extend ([new_content , "\n " ])
274
-
275
293
output_lines .append (line )
276
- if not isinstance (latest_version_position , int ):
277
- if output_lines and output_lines [- 1 ].strip ():
278
- # Ensure at least one blank line between existing and new content.
279
- output_lines .append ("\n " )
280
- output_lines .append (new_content )
294
+
295
+ if isinstance (latest_version_position , int ):
296
+ return output_lines
297
+
298
+ if output_lines and output_lines [- 1 ].strip ():
299
+ # Ensure at least one blank line between existing and new content.
300
+ output_lines .append ("\n " )
301
+ output_lines .append (new_content )
281
302
return output_lines
282
303
283
304
@@ -327,8 +348,7 @@ def get_oldest_and_newest_rev(
327
348
if not (newest_tag := rules .find_tag_for (tags , newest )):
328
349
raise NoCommitsFoundError ("Could not find a valid revision range." )
329
350
330
- oldest_tag = None
331
- oldest_tag_name = None
351
+ oldest_tag_name : str | None = None
332
352
if oldest :
333
353
if not (oldest_tag := rules .find_tag_for (tags , oldest )):
334
354
raise NoCommitsFoundError ("Could not find a valid revision range." )
@@ -340,17 +360,19 @@ def get_oldest_and_newest_rev(
340
360
if not tags_range :
341
361
raise NoCommitsFoundError ("Could not find a valid revision range." )
342
362
343
- oldest_rev : str | None = tags_range [- 1 ].name
344
363
newest_rev = newest_tag .name
345
364
346
- # check if it's the first tag created
347
- # and it's also being requested as part of the range
348
- if oldest_rev == tags [- 1 ].name and oldest_rev == oldest_tag_name :
349
- return None , newest_rev
350
-
351
- # when they are the same, and it's also the
352
- # first tag created
353
- if oldest_rev == newest_rev :
354
- return None , newest_rev
365
+ # Return None for oldest_rev if:
366
+ # 1. The oldest tag is the last tag in the list and matches the requested oldest tag, or
367
+ # 2. The oldest and newest tags are the same
368
+ oldest_rev : str | None = (
369
+ None
370
+ if (
371
+ tags_range [- 1 ].name == tags [- 1 ].name
372
+ and tags_range [- 1 ].name == oldest_tag_name
373
+ or tags_range [- 1 ].name == newest_rev
374
+ )
375
+ else tags_range [- 1 ].name
376
+ )
355
377
356
378
return oldest_rev , newest_rev
0 commit comments