diff --git a/vcs-versioning/changelog.d/523.bugfix.md b/vcs-versioning/changelog.d/523.bugfix.md new file mode 100644 index 00000000..aa2ef635 --- /dev/null +++ b/vcs-versioning/changelog.d/523.bugfix.md @@ -0,0 +1,5 @@ +The ``semver-pep440`` and ``semver-pep440-release-branch`` version schemes now +correctly handle ``.dev0`` tags and pre-release tags. Exact checkout on a tag +returns the tag as-is (``2.0.dev0`` stays ``2.0.dev0``, ``1.0.0rc1`` stays +``1.0.0rc1``). Non-exact ``.dev0`` tags are treated as explicit version anchors, +producing ``X.Y.0.devN`` instead of incorrectly bumping past the anchored version. diff --git a/vcs-versioning/src/vcs_versioning/_version_schemes/_standard.py b/vcs-versioning/src/vcs_versioning/_version_schemes/_standard.py index e96f2bd3..f88a00b2 100644 --- a/vcs-versioning/src/vcs_versioning/_version_schemes/_standard.py +++ b/vcs-versioning/src/vcs_versioning/_version_schemes/_standard.py @@ -44,6 +44,11 @@ def guess_next_dev_version(version: ScmVersion) -> str: def guess_next_simple_semver( version: ScmVersion, retain: int, increment: bool = True ) -> str: + if increment and getattr(version.tag, "dev", None) == 0: + parts = list(version.tag.release) + while len(parts) < SEMVER_LEN: + parts.append(0) + return ".".join(str(i) for i in parts) parts = list(version.tag.release[:retain]) while len(parts) < retain: parts.append(0) @@ -56,15 +61,12 @@ def guess_next_simple_semver( def simplified_semver_version(version: ScmVersion) -> str: if version.exact: - return guess_next_simple_semver(version, retain=SEMVER_LEN, increment=False) - elif version.branch is not None and "feature" in version.branch: + return version.format_with("{tag}") + if version.branch is not None and "feature" in version.branch: return version.format_next_version( guess_next_simple_semver, retain=SEMVER_MINOR ) - else: - return version.format_next_version( - guess_next_simple_semver, retain=SEMVER_PATCH - ) + return version.format_next_version(guess_next_simple_semver, retain=SEMVER_PATCH) def release_branch_semver_version(version: ScmVersion) -> str: diff --git a/vcs-versioning/testing_vcs/test_version.py b/vcs-versioning/testing_vcs/test_version.py index a1a27bca..1bf710aa 100644 --- a/vcs-versioning/testing_vcs/test_version.py +++ b/vcs-versioning/testing_vcs/test_version.py @@ -27,7 +27,9 @@ ("version", "expected_next"), [ pytest.param(meta("1.0.0", config=c), "1.0.0", id="exact"), - pytest.param(meta("1.0", config=c), "1.0.0", id="short_tag"), + pytest.param(meta("1.0", config=c), "1.0", id="short_tag"), + pytest.param(meta("1.0.0rc1", config=c), "1.0.0rc1", id="exact_rc"), + pytest.param(meta("2.0.dev0", config=c), "2.0.dev0", id="exact_dev0"), pytest.param( meta("1.0.0", distance=2, branch="default", config=c), "1.0.1.dev2", @@ -58,6 +60,21 @@ "1.0.1.dev2", id="non-normalized-allowed", ), + pytest.param( + meta("2.0.dev0", distance=5, branch="default", config=c), + "2.0.0.dev5", + id="dev0_anchor_default_branch", + ), + pytest.param( + meta("2.0.dev0", distance=5, branch="feature/fun", config=c), + "2.0.0.dev5", + id="dev0_anchor_feature_branch", + ), + pytest.param( + meta("3.0.dev0", distance=1, branch="default", config=c), + "3.0.0.dev1", + id="dev0_anchor_single_commit", + ), ], ) def test_next_semver(version: ScmVersion, expected_next: str) -> None: @@ -69,6 +86,8 @@ def test_next_semver(version: ScmVersion, expected_next: str) -> None: ("version", "expected_next"), [ pytest.param(meta("1.0.0", config=c), "1.0.0", id="exact"), + pytest.param(meta("2.0.dev0", config=c), "2.0.dev0", id="exact_dev0"), + pytest.param(meta("1.0.0rc1", config=c), "1.0.0rc1", id="exact_rc"), pytest.param( meta("1.0.0", distance=2, branch="master", config=c), "1.1.0.dev2", @@ -99,6 +118,16 @@ def test_next_semver(version: ScmVersion, expected_next: str) -> None: "1.1.0.dev2", id="false_positive_release_branch", ), + pytest.param( + meta("2.0.dev0", distance=5, branch="master", config=c), + "2.0.0.dev5", + id="dev0_anchor_development_branch", + ), + pytest.param( + meta("2.0.dev0", distance=5, branch="release-2.0", config=c), + "2.0.dev5", + id="dev0_anchor_release_branch", + ), ], ) def test_next_release_branch_semver(version: ScmVersion, expected_next: str) -> None: