def test_get_commits_without_email(mocker): raw_commit = ( "a515bb8f71c403f6f7d1c17b9d8ebf2ce3959395\n" "\n" "user name\n" "\n" "----------commit-delimiter----------\n" "12d3b4bdaa996ea7067a07660bb5df4772297bdd\n" "feat(users): add username\n" "user name\n" "\n" "----------commit-delimiter----------\n" ) mocker.patch("commitizen.cmd.run", return_value=FakeCommand(out=raw_commit)) commits = git.get_commits() assert commits[0].author == "user name" assert commits[1].author == "user name" assert commits[0].author_email == "" assert commits[1].author_email == "" assert commits[0].title == "" assert commits[1].title == "feat(users): add username"
def test_get_commits_without_breakline_in_each_commit(mocker): raw_commit = ( "ae9ba6fc5526cf478f52ef901418d85505109744\n" "bump: version 2.13.0 → 2.14.0\n" "GitHub Action\n" "[email protected]\n" "----------commit-delimiter----------\n" "ff2f56ca844de72a9d59590831087bf5a97bac84\n" "Merge pull request #332 from cliles/feature/271-redux\n" "User\n" "[email protected]\n" "Feature/271 redux----------commit-delimiter----------\n" "20a54bf1b82cd7b573351db4d1e8814dd0be205d\n" "feat(#271): enable creation of annotated tags when bumping\n" "User 2\n" "[email protected]\n" "----------commit-delimiter----------\n") mocker.patch("commitizen.cmd.run", return_value=FakeCommand(out=raw_commit)) commits = git.get_commits() assert commits[0].author == "GitHub Action" assert commits[1].author == "User" assert commits[2].author == "User 2" assert commits[0].author_email == "*****@*****.**" assert commits[1].author_email == "*****@*****.**" assert commits[2].author_email == "*****@*****.**" assert commits[0].title == "bump: version 2.13.0 → 2.14.0" assert commits[ 1].title == "Merge pull request #332 from cliles/feature/271-redux" assert (commits[2].title == "feat(#271): enable creation of annotated tags when bumping")
def _get_commit_messages(self): # Get commit message from file (--commit-msg-file) if self.commit_msg_file: with open(self.commit_msg_file, "r") as commit_file: commit_msg = commit_file.read() return [commit_msg] # Get commit messages from git log (--rev-range) return [commit.message for commit in git.get_commits(end=self.rev_range)]
def _get_commits(self): # Get commit message from file (--commit-msg-file) if self.commit_msg_file: with open(self.commit_msg_file, "r") as commit_file: commit_title = commit_file.readline() commit_body = commit_file.read() return [git.GitCommit(rev="", title=commit_title, body=commit_body)] # Get commit messages from git log (--rev-range) return git.get_commits(end=self.rev_range)
def __call__(self): commit_parser = self.cz.commit_parser changelog_pattern = self.cz.changelog_pattern start_rev = self.start_rev unreleased_version = self.unreleased_version changelog_meta: Dict = {} if not changelog_pattern or not commit_parser: out.error( f"'{self.config.settings['name']}' rule does not support changelog" ) raise SystemExit(NO_PATTERN_MAP) tags = git.get_tags() if not tags: tags = [] if self.incremental: changelog_meta = changelog.get_metadata(self.file_name) latest_version = changelog_meta.get("latest_version") if latest_version: start_rev = self._find_incremental_rev(latest_version, tags) commits = git.get_commits(start=start_rev, args="--author-date-order") if not commits: out.error("No commits found") raise SystemExit(NO_COMMITS_FOUND) tree = changelog.generate_tree_from_commits(commits, tags, commit_parser, changelog_pattern, unreleased_version) changelog_out = changelog.render_changelog(tree) if self.dry_run: out.write(changelog_out) raise SystemExit(0) lines = [] if self.incremental and os.path.isfile(self.file_name): with open(self.file_name, "r") as changelog_file: lines = changelog_file.readlines() with open(self.file_name, "w") as changelog_file: if self.incremental: new_lines = changelog.incremental_build( changelog_out, lines, changelog_meta) changelog_file.writelines(new_lines) else: changelog_file.write(changelog_out)
def _get_commits(self): # Get commit message from file (--commit-msg-file) if self.commit_msg_file is not None: # Enter this branch if commit_msg_file is "". with open(self.commit_msg_file, "r", encoding="utf-8") as commit_file: msg = commit_file.read() msg = self._filter_comments(msg) msg = msg.lstrip("\n") commit_title = msg.split("\n")[0] commit_body = "\n".join(msg.split("\n")[1:]) return [git.GitCommit(rev="", title=commit_title, body=commit_body)] elif self.commit_msg is not None: # Enter this branch if commit_msg is "". self.commit_msg = self._filter_comments(self.commit_msg) return [git.GitCommit(rev="", title="", body=self.commit_msg)] # Get commit messages from git log (--rev-range) return git.get_commits(end=self.rev_range)
def test_get_commits_with_signature(): config_file = ".git/config" config_backup = ".git/config.bak" shutil.copy(config_file, config_backup) try: # temporarily turn on --show-signature cmd.run("git config log.showsignature true") # retrieve a commit that we know has a signature commit = git.get_commits( start="bec20ebf433f2281c70f1eb4b0b6a1d0ed83e9b2", end="9eae518235d051f145807ddf971ceb79ad49953a", )[0] assert commit.title.startswith("fix") finally: # restore the repo's original config shutil.move(config_backup, config_file)
def __call__(self): # noqa: C901 """Steps executed to bump.""" try: current_version_instance: Version = Version(self.bump_settings["version"]) except TypeError: raise NoVersionSpecifiedError() # Initialize values from sources (conf) current_version: str = self.config.settings["version"] tag_format: str = self.bump_settings["tag_format"] bump_commit_message: str = self.bump_settings["bump_message"] version_files: List[str] = self.bump_settings["version_files"] dry_run: bool = self.arguments["dry_run"] is_yes: bool = self.arguments["yes"] increment: Optional[str] = self.arguments["increment"] prerelease: str = self.arguments["prerelease"] is_files_only: Optional[bool] = self.arguments["files_only"] is_local_version: Optional[bool] = self.arguments["local_version"] current_tag_version: str = bump.create_tag( current_version, tag_format=tag_format ) is_initial = self.is_initial_tag(current_tag_version, is_yes) if is_initial: commits = git.get_commits() else: commits = git.get_commits(current_tag_version) # No commits, there is no need to create an empty tag. # Unless we previously had a prerelease. if not commits and not current_version_instance.is_prerelease: raise NoCommitsFoundError("[NO_COMMITS_FOUND]\n" "No new commits found.") if increment is None: increment = self.find_increment(commits) # Increment is removed when current and next version # are expected to be prereleases. if prerelease and current_version_instance.is_prerelease: increment = None new_version = bump.generate_version( current_version, increment, prerelease=prerelease, is_local_version=is_local_version, ) new_tag_version = bump.create_tag(new_version, tag_format=tag_format) message = bump.create_commit_message( current_version, new_version, bump_commit_message ) # Report found information out.write( f"{message}\n" f"tag to create: {new_tag_version}\n" f"increment detected: {increment}\n" ) if increment is None and new_tag_version == current_tag_version: raise NoneIncrementExit() # Do not perform operations over files or git. if dry_run: raise DryRunExit() bump.update_version_in_files( current_version, str(new_version), version_files, check_consistency=self.check_consistency, ) if self.changelog: changelog_cmd = Changelog( self.config, { "unreleased_version": new_tag_version, "incremental": True, "dry_run": dry_run, }, ) changelog_cmd() c = cmd.run(f"git add {changelog_cmd.file_name}") self.config.set_key("version", str(new_version)) if is_files_only: raise ExpectedExit() c = git.commit(message, args=self._get_commit_args()) if c.return_code != 0: raise BumpCommitFailedError(f'git.commit error: "{c.err.strip()}"') c = git.tag(new_tag_version) if c.return_code != 0: raise BumpTagFailedError(c.err) out.success("Done!")
def __call__(self): """Steps executed to bump.""" try: current_version_instance: Version = Version(self.parameters["version"]) except TypeError: out.error("[NO_VERSION_SPECIFIED]") out.error("Check if current version is specified in config file, like:") out.error("version = 0.4.3") raise SystemExit(NO_VERSION_SPECIFIED) # Initialize values from sources (conf) current_version: str = self.config["version"] tag_format: str = self.parameters["tag_format"] bump_commit_message: str = self.parameters["bump_message"] current_tag_version: str = bump.create_tag( current_version, tag_format=tag_format ) files: list = self.parameters["files"] dry_run: bool = self.parameters["dry_run"] is_yes: bool = self.arguments["yes"] prerelease: str = self.arguments["prerelease"] increment: Optional[str] = self.arguments["increment"] is_initial = self.is_initial_tag(current_tag_version, is_yes) commits = git.get_commits(current_tag_version, from_beginning=is_initial) # No commits, there is no need to create an empty tag. # Unless we previously had a prerelease. if not commits and not current_version_instance.is_prerelease: out.error("[NO_COMMITS_FOUND]") out.error("No new commits found.") raise SystemExit(NO_COMMITS_FOUND) if increment is None: bump_pattern = self.cz.bump_pattern bump_map = self.cz.bump_map if not bump_map or not bump_pattern: out.error(f"'{self.config['name']}' rule does not support bump") raise SystemExit(NO_PATTERN_MAP) increment = bump.find_increment( commits, regex=bump_pattern, increments_map=bump_map ) # Increment is removed when current and next version # are expected to be prereleases. if prerelease and current_version_instance.is_prerelease: increment = None new_version = bump.generate_version( current_version, increment, prerelease=prerelease ) new_tag_version = bump.create_tag(new_version, tag_format=tag_format) message = bump.create_commit_message( current_version, new_version, bump_commit_message ) # Report found information out.write(message) out.write(f"tag to create: {new_tag_version}") out.write(f"increment detected: {increment}") # Do not perform operations over files or git. if dry_run: raise SystemExit() config.set_key("version", new_version.public) bump.update_version_in_files(current_version, new_version.public, files) c = git.commit(message, args="-a") if c.err: out.error(c.err) raise SystemExit(COMMIT_FAILED) c = git.tag(new_tag_version) if c.err: out.error(c.err) raise SystemExit(TAG_FAILED) out.success("Done!")
def __call__(self): commit_parser = self.cz.commit_parser changelog_pattern = self.cz.changelog_pattern start_rev = self.start_rev unreleased_version = self.unreleased_version changelog_meta: Dict = {} change_type_map: Optional[Dict] = self.change_type_map changelog_message_builder_hook: Optional[ Callable] = self.cz.changelog_message_builder_hook changelog_hook: Optional[Callable] = self.cz.changelog_hook if not changelog_pattern or not commit_parser: out.error( f"'{self.config.settings['name']}' rule does not support changelog" ) raise SystemExit(NO_PATTERN_MAP) tags = git.get_tags() if not tags: tags = [] if self.incremental: changelog_meta = changelog.get_metadata(self.file_name) latest_version = changelog_meta.get("latest_version") if latest_version: start_rev = self._find_incremental_rev(latest_version, tags) commits = git.get_commits(start=start_rev, args="--author-date-order") if not commits: out.error("No commits found") raise SystemExit(NO_COMMITS_FOUND) tree = changelog.generate_tree_from_commits( commits, tags, commit_parser, changelog_pattern, unreleased_version, change_type_map=change_type_map, changelog_message_builder_hook=changelog_message_builder_hook, ) changelog_out = changelog.render_changelog(tree) changelog_out = changelog_out.lstrip("\n") if self.dry_run: out.write(changelog_out) raise SystemExit(0) lines = [] if self.incremental and os.path.isfile(self.file_name): with open(self.file_name, "r") as changelog_file: lines = changelog_file.readlines() with open(self.file_name, "w") as changelog_file: partial_changelog: Optional[str] = None if self.incremental: new_lines = changelog.incremental_build( changelog_out, lines, changelog_meta) changelog_out = "".join(new_lines) partial_changelog = changelog_out if changelog_hook: changelog_out = changelog_hook(changelog_out, partial_changelog) changelog_file.write(changelog_out)
def test_get_commits_author_and_email(): create_file_and_commit("fix: username exception") commit = git.get_commits()[0] assert commit.author is not "" assert "@" in commit.author_email
def test_get_commits(): create_file_and_commit("feat(users): add username") create_file_and_commit("fix: username exception") commits = git.get_commits() assert len(commits) == 2
def __call__(self): # noqa: C901 """Steps executed to bump.""" try: current_version_instance: Version = Version(self.bump_settings["version"]) except TypeError: out.error( "[NO_VERSION_SPECIFIED]\n" "Check if current version is specified in config file, like:\n" "version = 0.4.3\n" ) raise SystemExit(NO_VERSION_SPECIFIED) # Initialize values from sources (conf) current_version: str = self.config.settings["version"] tag_format: str = self.bump_settings["tag_format"] bump_commit_message: str = self.bump_settings["bump_message"] version_files: List[str] = self.bump_settings["version_files"] dry_run: bool = self.arguments["dry_run"] is_yes: bool = self.arguments["yes"] increment: Optional[str] = self.arguments["increment"] prerelease: str = self.arguments["prerelease"] is_files_only: Optional[bool] = self.arguments["files_only"] current_tag_version: str = bump.create_tag( current_version, tag_format=tag_format ) is_initial = self.is_initial_tag(current_tag_version, is_yes) if is_initial: commits = git.get_commits() else: commits = git.get_commits(current_tag_version) # No commits, there is no need to create an empty tag. # Unless we previously had a prerelease. if not commits and not current_version_instance.is_prerelease: out.error("[NO_COMMITS_FOUND]\n" "No new commits found.") raise SystemExit(NO_COMMITS_FOUND) if increment is None: increment = self.find_increment(commits) # Increment is removed when current and next version # are expected to be prereleases. if prerelease and current_version_instance.is_prerelease: increment = None new_version = bump.generate_version( current_version, increment, prerelease=prerelease ) new_tag_version = bump.create_tag(new_version, tag_format=tag_format) message = bump.create_commit_message( current_version, new_version, bump_commit_message ) # Report found information out.write( f"message\n" f"tag to create: {new_tag_version}\n" f"increment detected: {increment}\n" ) # Do not perform operations over files or git. if dry_run: raise SystemExit() bump.update_version_in_files( current_version, new_version.public, version_files, check_consistency=self.check_consistency, ) if is_files_only: raise SystemExit() if self.changelog: changelog = Changelog( self.config, { "unreleased_version": new_tag_version, "incremental": True, "dry_run": dry_run, }, ) changelog() self.config.set_key("version", new_version.public) c = git.commit(message, args=self._get_commit_args()) if c.err: out.error('git.commit error: "{}"'.format(c.err.strip())) raise SystemExit(COMMIT_FAILED) c = git.tag(new_tag_version) if c.err: out.error(c.err) raise SystemExit(TAG_FAILED) out.success("Done!")
def __call__( self, current_version, version_filepaths=[], increment=None, prerelease=None, dry_run=False, autoconfirm_initial_tag=True, tag_format=None, bump_commit_message=None, check_consistency=True, update_files_only=False, no_verify=False, ): """ :param str current_version: Semantic version e.g. '0.1.0' """ # THE FOLLOWING CODE DOESN'T HAVE SIDE EFFECTS TO FILESYS OR GIT: current_version_instance = Version(current_version) current_tag_version = bump.create_tag(current_version, tag_format=tag_format) # is_initial = self.is_initial_tag(current_tag_version, autoconfirm_initial_tag) if is_initial: commits = git.get_commits() else: commits = git.get_commits(current_tag_version) # if not commits and not current_version_instance.is_prerelease: raise NoCommitsFoundError("[NO_COMMITS_FOUND]\n" "No new commits found.") # if increment is None: increment = self.find_increment(commits) # if prerelease is not None and current_version_instance.is_prerelease: increment = None # new_version = bump.generate_version(current_version, increment, prerelease=prerelease) new_tag_version = bump.create_tag(new_version, tag_format=tag_format) message = bump.create_commit_message(current_version, new_version, bump_commit_message) # Report found information out.write(f"{message}\n" f"tag to create: {new_tag_version}\n" f"increment detected: {increment}\n") # if increment is None and new_tag_version == current_tag_version: raise NoneIncrementExit() # if dry_run: raise DryRunExit() # SIDE EFFECTS TO FILESYSTEM: UPDATE TAG IN VERSION_FILEPATHS bump.update_version_in_files( current_version, new_version.public, version_filepaths, check_consistency=check_consistency, ) if update_files_only: out.write("[update_files_only=True]: Done updating files " + f"{version_filepaths}. ") raise ExpectedExit() # SIDE EFFECTS TO GIT: TAG AND COMMIT try: commit_args = "-a" if no_verify: commit_args += " --no-verify" c = git.commit(message, args=commit_args) if c.return_code != 0: raise BumpCommitFailedError( f'git.commit error: "{c.err.strip()}"') except Exception as e: # If commit went bad (e.g. due to pre-commit errors), roll # back the version updates in filesystem to prevent future # "inconsistency errors". Swapping seems to do the trick. bump.update_version_in_files( new_version.public, # swapped! current_version, # swapped! version_filepaths, check_consistency=check_consistency, ) out.write( f"\n[ERROR] Resetting version files to {current_version}") raise e # same as git.tag tag_msg = "" # if changelog_path is None else f" -F {changelog_path}" c = cmd.run(f"git tag {new_tag_version}" + tag_msg) if c.return_code != 0: raise BumpTagFailedError(c.err) out.success("Done!")
def __call__( self, chlog_path, latest_version, start_rev=None, incremental=False, dry_run=False, change_type_map=None, ): """ :param start_rev: If None, changelog from beginning """ # THE FOLLOWING CODE DOESN'T HAVE SIDE EFFECTS TO FILESYS OR GIT: commit_parser = self.cz.commit_parser changelog_pattern = self.cz.changelog_pattern changelog_meta = {} changelog_message_builder_hook = self.cz.changelog_message_builder_hook changelog_hook = self.cz.changelog_hook if not changelog_pattern or not commit_parser: raise NoPatternMapError( f"'{self.commiter_name}' rule doesn't support changelog") # tags = git.get_tags() if not tags: tags = [] # if incremental: changelog_meta = changelog.get_metadata(chlog_path) latest_version = changelog_meta.get("latest_version") if latest_version: start_rev = self._find_incremental_rev(latest_version, tags) # commits = git.get_commits(start=start_rev, args="--author-date-order") if not commits: raise NoCommitsFoundError("No commits found") # tree = changelog.generate_tree_from_commits( commits, tags, commit_parser, changelog_pattern, latest_version, change_type_map=change_type_map, changelog_message_builder_hook=changelog_message_builder_hook, ) changelog_out = changelog.render_changelog(tree) changelog_out = changelog_out.lstrip("\n") # if dry_run: out.write(changelog_out) raise DryRunExit() # # CHANGES TO FILESYSTEM: WRITE TO CHLOG_PATH (AFTER READING) lines = [] if incremental and os.path.isfile(chlog_path): with open(chlog_path, "r") as changelog_file: lines = changelog_file.readlines() # with open(chlog_path, "w") as changelog_file: partial_changelog = None if incremental: new_lines = changelog.incremental_build( changelog_out, lines, changelog_meta) changelog_out = "".join(new_lines) partial_changelog = changelog_out if changelog_hook: changelog_out = changelog_hook(changelog_out, partial_changelog) changelog_file.write(changelog_out) out.write(f"Wrote changelog to {chlog_path}!\n")
def __call__(self): # noqa: C901 """Steps executed to bump.""" try: current_version_instance: Version = Version( self.bump_settings["version"]) except TypeError: raise NoVersionSpecifiedError() # Initialize values from sources (conf) current_version: str = self.config.settings["version"] tag_format: str = self.bump_settings["tag_format"] bump_commit_message: str = self.bump_settings["bump_message"] version_files: List[str] = self.bump_settings["version_files"] dry_run: bool = self.arguments["dry_run"] is_yes: bool = self.arguments["yes"] increment: Optional[str] = self.arguments["increment"] prerelease: str = self.arguments["prerelease"] is_files_only: Optional[bool] = self.arguments["files_only"] is_local_version: Optional[bool] = self.arguments["local_version"] current_tag_version: str = bump.normalize_tag(current_version, tag_format=tag_format) is_initial = self.is_initial_tag(current_tag_version, is_yes) if is_initial: commits = git.get_commits() else: commits = git.get_commits(current_tag_version) # If user specified changelog_to_stdout, they probably want the # changelog to be generated as well, this is the most intuitive solution if not self.changelog and self.changelog_to_stdout: self.changelog = True # No commits, there is no need to create an empty tag. # Unless we previously had a prerelease. if not commits and not current_version_instance.is_prerelease: raise NoCommitsFoundError("[NO_COMMITS_FOUND]\n" "No new commits found.") if increment is None: increment = self.find_increment(commits) # It may happen that there are commits, but they are not elegible # for an increment, this generates a problem when using prerelease (#281) if (prerelease and increment is None and not current_version_instance.is_prerelease): raise NoCommitsFoundError( "[NO_COMMITS_FOUND]\n" "No commits found to generate a pre-release.\n" "To avoid this error, manually specify the type of increment with `--increment`" ) # Increment is removed when current and next version # are expected to be prereleases. if prerelease and current_version_instance.is_prerelease: increment = None new_version = bump.generate_version( current_version, increment, prerelease=prerelease, is_local_version=is_local_version, ) new_tag_version = bump.normalize_tag(new_version, tag_format=tag_format) message = bump.create_commit_message(current_version, new_version, bump_commit_message) # Report found information information = (f"{message}\n" f"tag to create: {new_tag_version}\n" f"increment detected: {increment}\n") if self.changelog_to_stdout: # When the changelog goes to stdout, we want to send # the bump information to stderr, this way the # changelog output can be captured out.diagnostic(information) else: out.write(information) if increment is None and new_tag_version == current_tag_version: raise NoneIncrementExit( "[NO_COMMITS_TO_BUMP]\n" "The commits found are not elegible to be bumped") # Do not perform operations over files or git. if dry_run: raise DryRunExit() bump.update_version_in_files( current_version, str(new_version), version_files, check_consistency=self.check_consistency, ) if self.changelog: if self.changelog_to_stdout: changelog_cmd = Changelog( self.config, { "unreleased_version": new_tag_version, "incremental": True, "dry_run": True, }, ) try: changelog_cmd() except DryRunExit: pass changelog_cmd = Changelog( self.config, { "unreleased_version": new_tag_version, "incremental": True, "dry_run": dry_run, }, ) changelog_cmd() c = cmd.run( f"git add {changelog_cmd.file_name} {' '.join(version_files)}") self.config.set_key("version", str(new_version)) if is_files_only: raise ExpectedExit() c = git.commit(message, args=self._get_commit_args()) if self.retry and c.return_code != 0 and self.changelog: # Maybe pre-commit reformatted some files? Retry once logger.debug("1st git.commit error: %s", c.err) logger.info("1st commit attempt failed; retrying once") cmd.run( f"git add {changelog_cmd.file_name} {' '.join(version_files)}") c = git.commit(message, args=self._get_commit_args()) if c.return_code != 0: raise BumpCommitFailedError( f'2nd git.commit error: "{c.err.strip()}"') c = git.tag( new_tag_version, annotated=self.bump_settings.get("annotated_tag", False) or bool(self.config.settings.get("annotated_tag", False)), ) if c.return_code != 0: raise BumpTagFailedError(c.err) # TODO: For v3 output this only as diagnostic and remove this if if self.changelog_to_stdout: out.diagnostic("Done!") else: out.success("Done!")
def __call__(self): commit_parser = self.cz.commit_parser changelog_pattern = self.cz.changelog_pattern start_rev = self.start_rev unreleased_version = self.unreleased_version changelog_meta: Dict = {} change_type_map: Optional[Dict] = self.change_type_map changelog_message_builder_hook: Optional[ Callable ] = self.cz.changelog_message_builder_hook if not changelog_pattern or not commit_parser: raise NoPatternMapError( f"'{self.config.settings['name']}' rule does not support changelog" ) if self.incremental and self.rev_range: raise NotAllowed("--incremental cannot be combined with a rev_range") tags = git.get_tags() if not tags: tags = [] end_rev = "" if self.incremental: changelog_meta = changelog.get_metadata(self.file_name) latest_version = changelog_meta.get("latest_version") if latest_version: start_rev = self._find_incremental_rev(latest_version, tags) if self.rev_range and self.tag_format: start_rev, end_rev = changelog.get_oldest_and_newest_rev( tags, version=self.rev_range, tag_format=self.tag_format, ) commits = git.get_commits( start=start_rev, end=end_rev, args="--author-date-order" ) if not commits: raise NoCommitsFoundError("No commits found") tree = changelog.generate_tree_from_commits( commits, tags, commit_parser, changelog_pattern, unreleased_version, change_type_map=change_type_map, changelog_message_builder_hook=changelog_message_builder_hook, ) if self.change_type_order: tree = changelog.order_changelog_tree(tree, self.change_type_order) changelog_out = changelog.render_changelog(tree) changelog_out = changelog_out.lstrip("\n") if self.dry_run: out.write(changelog_out) raise DryRunExit() lines = [] if self.incremental and os.path.isfile(self.file_name): with open(self.file_name, "r") as changelog_file: lines = changelog_file.readlines() self.write_changelog(changelog_out, lines, changelog_meta)