diff --git a/docs/cli.md b/docs/cli.md index 5a5fd878f7e..81d3f6de93d 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -698,8 +698,17 @@ The table below illustrates the effect of these rules with concrete examples. | prerelease | 1.0.3a0 | 1.0.3a1 | | prerelease | 1.0.3b0 | 1.0.3b1 | +The option `--next-phase` allows the increment of prerelease phase versions. + +| rule | before | after | +|-------------------------|----------|----------| +| prerelease --next-phase | 1.0.3a0 | 1.0.3b0 | +| prerelease --next-phase | 1.0.3b0 | 1.0.3rc0 | +| prerelease --next-phase | 1.0.3rc0 | 1.0.3 | + ### Options +* `--next-phase`: Increment the phase of the current version. * `--short (-s)`: Output the version number only. * `--dry-run`: Do not update pyproject.toml file. diff --git a/src/poetry/console/commands/version.py b/src/poetry/console/commands/version.py index b6953c99c87..0af2a004719 100644 --- a/src/poetry/console/commands/version.py +++ b/src/poetry/console/commands/version.py @@ -27,7 +27,7 @@ class VersionCommand(Command): "version", "The version number or the rule to update the version.", optional=True, - ) + ), ] options = [ option("short", "s", "Output the version number only"), @@ -36,6 +36,7 @@ class VersionCommand(Command): None, "Do not update pyproject.toml file", ), + option("next-phase", None, "Increment the phase of the current version"), ] help = """\ @@ -62,7 +63,7 @@ def handle(self) -> int: if version: version = self.increment_version( - self.poetry.package.pretty_version, version + self.poetry.package.pretty_version, version, self.option("next-phase") ) if self.option("short"): @@ -91,7 +92,9 @@ def handle(self) -> int: return 0 - def increment_version(self, version: str, rule: str) -> Version: + def increment_version( + self, version: str, rule: str, next_phase: bool = False + ) -> Version: from poetry.core.constraints.version import Version try: @@ -115,7 +118,8 @@ def increment_version(self, version: str, rule: str) -> Version: if parsed.is_unstable(): pre = parsed.pre assert pre is not None - new = Version(parsed.epoch, parsed.release, pre.next()) + pre = pre.next_phase() if next_phase else pre.next() + new = Version(parsed.epoch, parsed.release, pre) else: new = parsed.next_patch().first_prerelease() else: diff --git a/tests/console/commands/test_version.py b/tests/console/commands/test_version.py index a1d59a3910f..8d671273bbb 100644 --- a/tests/console/commands/test_version.py +++ b/tests/console/commands/test_version.py @@ -55,6 +55,25 @@ def test_increment_version( assert command.increment_version(version, rule).text == expected +@pytest.mark.parametrize( + "version, rule, expected", + [ + ("1.2.3", "prerelease", "1.2.4a0"), + ("1.2.3a0", "prerelease", "1.2.3b0"), + ("1.2.3a1", "prerelease", "1.2.3b0"), + ("1.2.3b1", "prerelease", "1.2.3rc0"), + ("1.2.3rc0", "prerelease", "1.2.3"), + ("1.2.3-beta.1", "prerelease", "1.2.3rc0"), + ("1.2.3-beta1", "prerelease", "1.2.3rc0"), + ("1.2.3beta1", "prerelease", "1.2.3rc0"), + ], +) +def test_next_phase_version( + version: str, rule: str, expected: str, command: VersionCommand +) -> None: + assert command.increment_version(version, rule, True).text == expected + + def test_version_show(tester: CommandTester) -> None: tester.execute() assert tester.io.fetch_output() == "simple-project 1.2.3\n" @@ -75,6 +94,13 @@ def test_short_version_update(tester: CommandTester) -> None: assert tester.io.fetch_output() == "2.0.0\n" +def test_phase_version_update(tester: CommandTester) -> None: + assert isinstance(tester.command, VersionCommand) + tester.command.poetry.package._set_version("1.2.4a0") + tester.execute("prerelease --next-phase") + assert tester.io.fetch_output() == "Bumping version from 1.2.4a0 to 1.2.4b0\n" + + def test_dry_run(tester: CommandTester) -> None: assert isinstance(tester.command, VersionCommand) old_pyproject = tester.command.poetry.file.path.read_text()