11from __future__ import annotations
22
3- import os
4- import os .path
53from difflib import SequenceMatcher
64from operator import itemgetter
75from pathlib import Path
@@ -66,7 +64,7 @@ def __init__(self, config: BaseConfig, arguments: ChangelogArgs) -> None:
6664 f"or the setting `changelog_file` in { self .config .path } "
6765 )
6866 self .file_name = (
69- os . path . join ( str ( self .config .path .parent ) , changelog_file_name )
67+ Path ( self .config .path .parent , changelog_file_name ). as_posix ( )
7068 if self .config .path is not None
7169 else changelog_file_name
7270 )
@@ -229,16 +227,32 @@ def __call__(self) -> None:
229227 latest_full_release_info = self .changelog_format .get_latest_full_release (
230228 self .file_name
231229 )
232- if latest_full_release_info .index :
233- changelog_meta .unreleased_start = 0
230+ # Determine if there are prereleases to merge:
231+ # - Only prereleases in changelog (no full release found), OR
232+ # - First version in changelog is before first full release (prereleases exist)
233+ if latest_full_release_info .index is not None and (
234+ latest_full_release_info .name is None
235+ or (
236+ changelog_meta .latest_version_position is not None
237+ and changelog_meta .latest_version_position
238+ < latest_full_release_info .index
239+ )
240+ ):
241+ # Use the existing unreleased_start if available (from get_metadata()).
242+ # Otherwise, use the position of the first version entry (prerelease)
243+ # to preserve the changelog header.
244+ if changelog_meta .unreleased_start is None :
245+ changelog_meta .unreleased_start = (
246+ changelog_meta .latest_version_position
247+ )
234248 changelog_meta .latest_version_position = latest_full_release_info .index
235249 changelog_meta .unreleased_end = latest_full_release_info .index - 1
236250
237- start_rev = latest_full_release_info .name or ""
238- if not start_rev and latest_full_release_info . index :
239- # Only pre-releases in changelog
240- changelog_meta .latest_version_position = None
241- changelog_meta .unreleased_end = latest_full_release_info .index + 1
251+ start_rev = latest_full_release_info .name or ""
252+ if not start_rev :
253+ # Only pre-releases in changelog
254+ changelog_meta .latest_version_position = None
255+ changelog_meta .unreleased_end = latest_full_release_info .index + 1
242256
243257 commits = git .get_commits (start = start_rev , end = end_rev , args = "--topo-order" )
244258 if not commits and (
@@ -268,6 +282,7 @@ def __call__(self) -> None:
268282 self .cz .template_loader ,
269283 self .template ,
270284 ** {
285+ "incremental" : self .incremental , # extra variable for the template
271286 ** self .cz .template_extras ,
272287 ** self .config .settings ["extras" ],
273288 ** self .extras ,
@@ -282,9 +297,10 @@ def __call__(self) -> None:
282297 raise DryRunExit ()
283298
284299 lines = []
285- if self .incremental and os .path .isfile (self .file_name ):
286- with open (
287- self .file_name , encoding = self .config .settings ["encoding" ]
300+ changelog_path = Path (self .file_name )
301+ if self .incremental and changelog_path .is_file ():
302+ with changelog_path .open (
303+ encoding = self .config .settings ["encoding" ]
288304 ) as changelog_file :
289305 lines = changelog_file .readlines ()
290306
0 commit comments