diff --git a/poetry.lock b/poetry.lock index 8e2f3b9..31ba7da 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "attrs" @@ -358,13 +358,13 @@ files = [ [[package]] name = "packaging" -version = "23.2" +version = "24.0" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] [[package]] @@ -588,4 +588,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "ffaa5697431eb539e0e0d200f490783841c4b9165b28e76bfcc3c1b6a60c16a2" +content-hash = "d0d0b9c8bff17b9764cae637df86e344a4e68feddc65082162cc4473f0a42479" diff --git a/pyproject.toml b/pyproject.toml index 7ac63ba..642e3e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,6 +22,7 @@ docopt = "^0.6.2" cli-ui = ">=0.10.3" schema = "^0.7.1" tomlkit = "^0.11" +packaging = "^24.0" [tool.poetry.dev-dependencies] # Task runner diff --git a/tbump/cli.py b/tbump/cli.py index ad2f819..e2b726e 100644 --- a/tbump/cli.py +++ b/tbump/cli.py @@ -1,6 +1,7 @@ import sys import textwrap import urllib.parse +from contextlib import suppress from dataclasses import dataclass from enum import Enum from pathlib import Path @@ -8,6 +9,8 @@ import cli_ui as ui import docopt +from packaging.version import InvalidVersion +from packaging.version import parse as parse_version from tbump.config import get_config_file from tbump.error import Error @@ -216,6 +219,25 @@ def print_error(self) -> None: ui.error("New version is the same as the previous one") +class OlderNewVersion(Error): + def __init__(self, *, new_version: str, current_version: str) -> None: + self.new_version = new_version + self.current_version = current_version + super().__init__() + + def print_error(self) -> None: + ui.error( + ui.reset, + "New version", + ui.bold, + self.new_version, + ui.reset, + "is older than current version", + ui.bold, + self.current_version, + ) + + def bump(options: BumpOptions, operations: List[str]) -> None: working_path = options.working_path new_version = options.new_version @@ -228,8 +250,7 @@ def bump(options: BumpOptions, operations: List[str]) -> None: ) config = config_file.get_config() - if config.current_version == new_version: - raise NotANewVersion() + check_versions(current=config.current_version, new=new_version) # fmt: off ui.info_1( @@ -289,6 +310,17 @@ def bump(options: BumpOptions, operations: List[str]) -> None: suggest_creating_github_release(config.github_url, tag_name) +def check_versions(*, current: str, new: str) -> None: + if current == new: + raise NotANewVersion() + + with suppress(InvalidVersion): + parsed_current = parse_version(current) + parsed_new = parse_version(new) + if parsed_new < parsed_current: + raise OlderNewVersion(current_version=current, new_version=new) + + def suggest_creating_github_release(github_url: str, tag_name: str) -> None: query_string = urllib.parse.urlencode({"tag": tag_name}) if not github_url.endswith("/"): diff --git a/tbump/test/test_cli.py b/tbump/test/test_cli.py index f1e1092..a5a8908 100644 --- a/tbump/test/test_cli.py +++ b/tbump/test/test_cli.py @@ -4,7 +4,7 @@ import pytest import tomlkit -from tbump.cli import NotANewVersion +from tbump.cli import NotANewVersion, OlderNewVersion from tbump.cli import run as run_tbump from tbump.config import ConfigNotFound, InvalidConfig from tbump.error import Error @@ -327,6 +327,11 @@ def test_not_a_new_versions(test_repo: Path) -> None: run_tbump(["-C", str(test_repo), "1.2.41-alpha-1"]) +def test_new_version_is_older(test_repo: Path) -> None: + with pytest.raises(OlderNewVersion): + run_tbump(["-C", str(test_repo), "1.2.40"]) + + def test_no_tracked_branch_non_interactive(test_repo: Path) -> None: run_git(test_repo, "checkout", "-b", "devel")