diff --git a/commitizen/version_schemes.py b/commitizen/version_schemes.py index e9f99c551..b05c9fec2 100644 --- a/commitizen/version_schemes.py +++ b/commitizen/version_schemes.py @@ -153,11 +153,54 @@ def bump( VersionScheme: TypeAlias = type[VersionProtocol] +# See https://github.com/pypa/packaging/blob/14b83e15dbb9caa87c63646ba7808b2b5e460ce6/src/packaging/version.py#L117 +# TODO: add more test cases for this pattern +_VERSION_PATTERN = r"""^\s* + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                          # pre-release
+            [-_\.]?
+            (?P
+                (?!                                       # negative lookahead to prevent matching post, rev, r, dev
+                    [-_\.]?
+                    (post|rev|r|dev)
+                    [-_\.]?
+                    ([0-9]+)?
+                $)
+                [a-z]+?                                   # match any letters to support semver
+            )
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+        (?P                                         # post release
+            (?:-(?P[0-9]+))
+            |
+            (?:
+                [-_\.]?
+                (?Ppost|rev|r)
+                [-_\.]?
+                (?P[0-9]+)?
+            )
+        )?
+        (?P                                          # dev release
+            [-_\.]?
+            (?Pdev)
+            [-_\.]?
+            (?P[0-9]+)?
+        )?
+    )
+    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
+\s*$"""
+
+
 class BaseVersion(_BaseVersion):
     """
     A base class implementing the `VersionProtocol` for PEP440-like versions.
     """
 
+    _regex: re.Pattern = re.compile(_VERSION_PATTERN, re.VERBOSE | re.IGNORECASE)
     parser: ClassVar[re.Pattern] = _DEFAULT_VERSION_PARSER
     """Regex capturing this version scheme into a `version` group"""
 
diff --git a/tests/test_version_scheme_semver.py b/tests/test_version_scheme_semver.py
index 8785717a3..836d4cdf8 100644
--- a/tests/test_version_scheme_semver.py
+++ b/tests/test_version_scheme_semver.py
@@ -64,6 +64,9 @@
     (("1.0.0alpha1", None, "alpha", 0, None), "1.0.0-a2"),
     (("1", None, "rc", 0, None), "1.0.0-rc0"),
     (("1.0.0rc1+e20d7b57f3eb", "PATCH", None, 0, None), "1.0.0"),
+    (("1.0.0-reallyweird", "PATCH", "reallyweird", 0, None), "1.0.0-reallyweird1"),
+    (("v0.7.1-release", "PATCH", "release", 0, None), "0.7.1-release1"),
+    (("v0.0.1-SNAPSHOT", "PATCH", "SNAPSHOT", 0, None), "0.0.1-snapshot1"),
 ]
 
 # test driven development
diff --git a/tests/test_version_scheme_semver2.py b/tests/test_version_scheme_semver2.py
index d18a058a7..632c4db45 100644
--- a/tests/test_version_scheme_semver2.py
+++ b/tests/test_version_scheme_semver2.py
@@ -5,6 +5,8 @@
 
 from commitizen.version_schemes import SemVer2, VersionProtocol
 
+# current_version, increment, prerelease, prerelease_offset, devrelease
+
 simple_flow = [
     (("0.1.0", "PATCH", None, 0, None), "0.1.1"),
     (("0.1.0", "PATCH", None, 0, 1), "0.1.1-dev.1"),
@@ -64,6 +66,7 @@
     (("1.0.0-alpha.1", None, "alpha", 0, None), "1.0.0-alpha.2"),
     (("1", None, "rc", 0, None), "1.0.0-rc.0"),
     (("1.0.0-rc.1+e20d7b57f3eb", "PATCH", None, 0, None), "1.0.0"),
+    (("1.0.0-reallyweird", "PATCH", "reallyweird", 0, None), "1.0.0-reallyweird.1"),
 ]
 
 # test driven development