Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit c68a231

Browse files
fix: properly bump versions between prereleases
1 parent d1c06eb commit c68a231

File tree

3 files changed

+105
-7
lines changed

3 files changed

+105
-7
lines changed

‎commitizen/commands/bump.py‎

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
NoVersionSpecifiedError,
2424
)
2525
from commitizen.providers import get_provider
26-
from commitizen.version_schemes import get_version_scheme, InvalidVersion
26+
from commitizen.version_schemes import (
27+
get_version_scheme,
28+
InvalidVersion,
29+
VersionProtocol,
30+
)
2731

2832
logger = getLogger("commitizen")
2933

@@ -215,15 +219,27 @@ def __call__(self): # noqa: C901
215219

216220
# Increment is removed when current and next version
217221
# are expected to be prereleases.
218-
if prerelease and current_version.is_prerelease:
219-
increment = None
222+
force_bump = False
223+
if current_version.is_prerelease:
224+
last_final = self.find_previous_final_version(current_version)
225+
if last_final is not None:
226+
commits = git.get_commits(last_final)
227+
increment = self.find_increment(commits)
228+
semver = last_final.increment_base(
229+
increment=increment, force_bump=True
230+
)
231+
if semver != current_version.base_version:
232+
force_bump = True
233+
elif prerelease:
234+
increment = None
220235

221236
new_version = current_version.bump(
222237
increment,
223238
prerelease=prerelease,
224239
prerelease_offset=prerelease_offset,
225240
devrelease=devrelease,
226241
is_local_version=is_local_version,
242+
force_bump=force_bump,
227243
)
228244

229245
new_tag_version = bump.normalize_tag(
@@ -375,3 +391,33 @@ def _get_commit_args(self):
375391
if self.no_verify:
376392
commit_args.append("--no-verify")
377393
return " ".join(commit_args)
394+
395+
def find_previous_final_version(
396+
self, current_version: VersionProtocol
397+
) -> VersionProtocol | None:
398+
tag_format: str = self.bump_settings["tag_format"]
399+
current = bump.normalize_tag(
400+
current_version,
401+
tag_format=tag_format,
402+
scheme=self.scheme,
403+
)
404+
405+
final_versions = []
406+
for tag in git.get_tag_names():
407+
assert tag
408+
try:
409+
version = self.scheme(tag)
410+
if not version.is_prerelease or tag == current:
411+
final_versions.append(version)
412+
except InvalidVersion:
413+
continue
414+
415+
if not final_versions:
416+
return None
417+
418+
final_versions = sorted(final_versions) # type: ignore [type-var]
419+
current_index = final_versions.index(current_version)
420+
previous_index = current_index - 1
421+
if previous_index < 0:
422+
return None
423+
return final_versions[previous_index]

‎commitizen/version_schemes.py‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ def bump(
105105
prerelease_offset: int = 0,
106106
devrelease: int | None = None,
107107
is_local_version: bool = False,
108+
force_bump: bool = False,
108109
) -> Self:
109110
"""
110111
Based on the given increment, generate the next bumped version according to the version scheme
@@ -171,7 +172,9 @@ def generate_devrelease(self, devrelease: int | None) -> str:
171172

172173
return f"dev{devrelease}"
173174

174-
def increment_base(self, increment: str | None = None) -> str:
175+
def increment_base(
176+
self, increment: str | None = None, force_bump: bool = False
177+
) -> str:
175178
prev_release = list(self.release)
176179
increments = [MAJOR, MINOR, PATCH]
177180
base = dict(zip_longest(increments, prev_release, fillvalue=0))
@@ -180,7 +183,7 @@ def increment_base(self, increment: str | None = None) -> str:
180183
# must remove its prerelease tag,
181184
# so it doesn't matter the increment.
182185
# Example: 1.0.0a0 with PATCH/MINOR -> 1.0.0
183-
if not self.is_prerelease:
186+
if not self.is_prereleaseorforce_bump:
184187
if increment == MAJOR:
185188
base[MAJOR] += 1
186189
base[MINOR] = 0
@@ -200,6 +203,7 @@ def bump(
200203
prerelease_offset: int = 0,
201204
devrelease: int | None = None,
202205
is_local_version: bool = False,
206+
force_bump: bool = False,
203207
) -> Self:
204208
"""Based on the given increment a proper semver will be generated.
205209
@@ -217,9 +221,21 @@ def bump(
217221
local_version = self.scheme(self.local).bump(increment)
218222
return self.scheme(f"{self.public}+{local_version}") # type: ignore
219223
else:
220-
base = self.increment_base(increment)
224+
base = self.increment_base(increment, force_bump)
221225
dev_version = self.generate_devrelease(devrelease)
222-
pre_version = self.generate_prerelease(prerelease, offset=prerelease_offset)
226+
release = list(self.release)
227+
if len(release) < 3:
228+
release += [0] * (3 - len(release))
229+
current_semver = ".".join(str(part) for part in release)
230+
if base == current_semver:
231+
pre_version = self.generate_prerelease(
232+
prerelease, offset=prerelease_offset
233+
)
234+
else:
235+
base_version = cast(BaseVersion, self.scheme(base))
236+
pre_version = base_version.generate_prerelease(
237+
prerelease, offset=prerelease_offset
238+
)
223239
# TODO: post version
224240
return self.scheme(f"{base}{pre_version}{dev_version}") # type: ignore
225241

‎tests/commands/test_bump_command.py‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,42 @@ def test_bump_command_prelease(mocker: MockFixture):
223223
assert tag_exists is True
224224

225225

226+
@pytest.mark.usefixtures("tmp_commitizen_project")
227+
def test_bump_command_prelease_increment(mocker: MockFixture):
228+
# FINAL RELEASE
229+
create_file_and_commit("fix: location")
230+
231+
testargs = ["cz", "bump", "--yes"]
232+
mocker.patch.object(sys, "argv", testargs)
233+
cli.main()
234+
assert git.tag_exist("0.1.1")
235+
236+
# PRERELEASE
237+
create_file_and_commit("fix: location")
238+
239+
testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"]
240+
mocker.patch.object(sys, "argv", testargs)
241+
cli.main()
242+
243+
assert git.tag_exist("0.1.2a0")
244+
245+
create_file_and_commit("feat: location")
246+
247+
testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"]
248+
mocker.patch.object(sys, "argv", testargs)
249+
cli.main()
250+
251+
assert git.tag_exist("0.2.0a0")
252+
253+
create_file_and_commit("feat!: breaking")
254+
255+
testargs = ["cz", "bump", "--prerelease", "alpha", "--yes"]
256+
mocker.patch.object(sys, "argv", testargs)
257+
cli.main()
258+
259+
assert git.tag_exist("1.0.0a0")
260+
261+
226262
@pytest.mark.usefixtures("tmp_commitizen_project")
227263
def test_bump_on_git_with_hooks_no_verify_disabled(mocker: MockFixture):
228264
"""Bump commit without --no-verify"""

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /