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 8522b8c

Browse files
eduardocardosojenstroeger
authored andcommitted
fix: properly bump versions between prereleases
1 parent e9647c7 commit 8522b8c

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
@@ -24,7 +24,11 @@
2424
)
2525
from commitizen.changelog_formats import get_changelog_format
2626
from commitizen.providers import get_provider
27-
from commitizen.version_schemes import InvalidVersion, get_version_scheme
27+
from commitizen.version_schemes import (
28+
get_version_scheme,
29+
InvalidVersion,
30+
VersionProtocol,
31+
)
2832

2933
logger = getLogger("commitizen")
3034

@@ -228,15 +232,27 @@ def __call__(self): # noqa: C901
228232

229233
# Increment is removed when current and next version
230234
# are expected to be prereleases.
231-
if prerelease and current_version.is_prerelease:
232-
increment = None
235+
force_bump = False
236+
if current_version.is_prerelease:
237+
last_final = self.find_previous_final_version(current_version)
238+
if last_final is not None:
239+
commits = git.get_commits(last_final)
240+
increment = self.find_increment(commits)
241+
semver = last_final.increment_base(
242+
increment=increment, force_bump=True
243+
)
244+
if semver != current_version.base_version:
245+
force_bump = True
246+
elif prerelease:
247+
increment = None
233248

234249
new_version = current_version.bump(
235250
increment,
236251
prerelease=prerelease,
237252
prerelease_offset=prerelease_offset,
238253
devrelease=devrelease,
239254
is_local_version=is_local_version,
255+
force_bump=force_bump,
240256
)
241257

242258
new_tag_version = bump.normalize_tag(
@@ -395,3 +411,33 @@ def _get_commit_args(self):
395411
if self.no_verify:
396412
commit_args.append("--no-verify")
397413
return " ".join(commit_args)
414+
415+
def find_previous_final_version(
416+
self, current_version: VersionProtocol
417+
) -> VersionProtocol | None:
418+
tag_format: str = self.bump_settings["tag_format"]
419+
current = bump.normalize_tag(
420+
current_version,
421+
tag_format=tag_format,
422+
scheme=self.scheme,
423+
)
424+
425+
final_versions = []
426+
for tag in git.get_tag_names():
427+
assert tag
428+
try:
429+
version = self.scheme(tag)
430+
if not version.is_prerelease or tag == current:
431+
final_versions.append(version)
432+
except InvalidVersion:
433+
continue
434+
435+
if not final_versions:
436+
return None
437+
438+
final_versions = sorted(final_versions) # type: ignore [type-var]
439+
current_index = final_versions.index(current_version)
440+
previous_index = current_index - 1
441+
if previous_index < 0:
442+
return None
443+
return final_versions[previous_index]

‎commitizen/version_schemes.py‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def bump(
100100
prerelease_offset: int = 0,
101101
devrelease: int | None = None,
102102
is_local_version: bool = False,
103+
force_bump: bool = False,
103104
) -> Self:
104105
"""
105106
Based on the given increment, generate the next bumped version according to the version scheme
@@ -166,7 +167,9 @@ def generate_devrelease(self, devrelease: int | None) -> str:
166167

167168
return f"dev{devrelease}"
168169

169-
def increment_base(self, increment: str | None = None) -> str:
170+
def increment_base(
171+
self, increment: str | None = None, force_bump: bool = False
172+
) -> str:
170173
prev_release = list(self.release)
171174
increments = [MAJOR, MINOR, PATCH]
172175
base = dict(zip_longest(increments, prev_release, fillvalue=0))
@@ -175,7 +178,7 @@ def increment_base(self, increment: str | None = None) -> str:
175178
# must remove its prerelease tag,
176179
# so it doesn't matter the increment.
177180
# Example: 1.0.0a0 with PATCH/MINOR -> 1.0.0
178-
if not self.is_prerelease:
181+
if not self.is_prereleaseorforce_bump:
179182
if increment == MAJOR:
180183
base[MAJOR] += 1
181184
base[MINOR] = 0
@@ -195,6 +198,7 @@ def bump(
195198
prerelease_offset: int = 0,
196199
devrelease: int | None = None,
197200
is_local_version: bool = False,
201+
force_bump: bool = False,
198202
) -> Self:
199203
"""Based on the given increment a proper semver will be generated.
200204
@@ -212,9 +216,21 @@ def bump(
212216
local_version = self.scheme(self.local).bump(increment)
213217
return self.scheme(f"{self.public}+{local_version}") # type: ignore
214218
else:
215-
base = self.increment_base(increment)
219+
base = self.increment_base(increment, force_bump)
216220
dev_version = self.generate_devrelease(devrelease)
217-
pre_version = self.generate_prerelease(prerelease, offset=prerelease_offset)
221+
release = list(self.release)
222+
if len(release) < 3:
223+
release += [0] * (3 - len(release))
224+
current_semver = ".".join(str(part) for part in release)
225+
if base == current_semver:
226+
pre_version = self.generate_prerelease(
227+
prerelease, offset=prerelease_offset
228+
)
229+
else:
230+
base_version = cast(BaseVersion, self.scheme(base))
231+
pre_version = base_version.generate_prerelease(
232+
prerelease, offset=prerelease_offset
233+
)
218234
# TODO: post version
219235
return self.scheme(f"{base}{pre_version}{dev_version}") # type: ignore
220236

‎tests/commands/test_bump_command.py‎

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

229229

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

0 commit comments

Comments
(0)

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