summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRonny Pfannschmidt <opensource@ronnypfannschmidt.de>2020-05-16 23:00:45 +0200
committerGitHub <noreply@github.com>2020-05-16 23:00:45 +0200
commit8e6aa2b5fd42cb257c86e6dbe720eaee6d1e2c9b (patch)
tree61f210720e74851c69f0584b0a8f3bc049b1dd1d
parent6ad91d0085acc8091f2336faaf4710c1bae4cf18 (diff)
parent26f8ff952675bc0be3dba59830d04e36bf1d172d (diff)
downloadsetuptools-scm-8e6aa2b5fd42cb257c86e6dbe720eaee6d1e2c9b.tar.gz
Merge pull request #430 from chrisjbillington/release-branch-semver-scheme
Add release-branch-semver scheme
-rw-r--r--README.rst17
-rw-r--r--setup.py1
-rw-r--r--src/setuptools_scm/version.py50
-rw-r--r--testing/test_version.py43
4 files changed, 95 insertions, 16 deletions
diff --git a/README.rst b/README.rst
index bae5db2..074eb6c 100644
--- a/README.rst
+++ b/README.rst
@@ -477,9 +477,20 @@ Version number construction
Available implementations:
- :guess-next-dev: automatically guesses the next development version (default)
- :post-release: generates post release versions (adds :code:`postN`)
- :python-simplified-semver: basic semantic versioning similar to ``guess-next-dev``
+ :guess-next-dev: Automatically guesses the next development version (default).
+ Guesses the upcoming release by incrementing the pre-release segment if present,
+ otherwise by incrementing the micro segment. Then appends :code:`.devN`.
+ :post-release: generates post release versions (adds :code:`.postN`)
+ :python-simplified-semver: Basic semantic versioning. Guesses the upcoming release
+ by incrementing the minor segment and setting the micro segment to zero if the
+ current branch contains the string ``'feature'``, otherwise by incrementing the
+ micro version. Then appends :code:`.devN`. Not compatible with pre-releases.
+ :release-branch-semver: Semantic versioning for projects with release branches. The
+ same as ``guess-next-dev`` (incrementing the pre-release or micro segment) if on
+ a release branch: a branch whose name (ignoring namespace) parses as a version
+ that matches the most recent tag up to the minor segment. Otherwise if on a
+ non-release branch, increments the minor segment and sets the micro segment to
+ zero, then appends :code:`.devN`.
``setuptools_scm.local_scheme``
Configures how the local part of a version is rendered given a
diff --git a/setup.py b/setup.py
index 586d3e5..6e72f74 100644
--- a/setup.py
+++ b/setup.py
@@ -89,6 +89,7 @@ arguments = dict(
guess-next-dev = setuptools_scm.version:guess_next_dev_version
post-release = setuptools_scm.version:postrelease_version
python-simplified-semver = setuptools_scm.version:simplified_semver_version
+ release-branch-semver = setuptools_scm.version:release_branch_semver
[setuptools_scm.local_scheme]
node-and-date = setuptools_scm.version:get_local_node_and_date
diff --git a/src/setuptools_scm/version.py b/src/setuptools_scm/version.py
index aa4bd49..1454a7a 100644
--- a/src/setuptools_scm/version.py
+++ b/src/setuptools_scm/version.py
@@ -2,7 +2,6 @@ from __future__ import print_function
import datetime
import warnings
import re
-from itertools import chain, repeat, islice
from .config import Configuration
from .utils import trace, string_types, utc
@@ -16,11 +15,6 @@ SEMVER_PATCH = 3
SEMVER_LEN = 3
-def _pad(iterable, size, padding=None):
- padded = chain(iterable, repeat(padding))
- return list(islice(padded, size))
-
-
def _parse_version_tag(tag, config):
tagstring = tag if not isinstance(tag, string_types) else str(tag)
match = config.tag_regex.match(tagstring)
@@ -132,6 +126,7 @@ class ScmVersion(object):
dirty=False,
preformatted=False,
branch=None,
+ config=None,
**kw
):
if kw:
@@ -146,6 +141,7 @@ class ScmVersion(object):
self.dirty = dirty
self.preformatted = preformatted
self.branch = branch
+ self.config = config
@property
def extra(self):
@@ -193,7 +189,14 @@ def _parse_tag(tag, preformatted, config):
def meta(
- tag, distance=None, dirty=False, node=None, preformatted=False, config=None, **kw
+ tag,
+ distance=None,
+ dirty=False,
+ node=None,
+ preformatted=False,
+ branch=None,
+ config=None,
+ **kw
):
if not config:
warnings.warn(
@@ -203,7 +206,9 @@ def meta(
parsed_version = _parse_tag(tag, preformatted, config)
trace("version", tag, "->", parsed_version)
assert parsed_version is not None, "cant parse version %s" % tag
- return ScmVersion(parsed_version, distance, node, dirty, preformatted, **kw)
+ return ScmVersion(
+ parsed_version, distance, node, dirty, preformatted, branch, config, **kw
+ )
def guess_next_version(tag_version):
@@ -238,12 +243,14 @@ def guess_next_dev_version(version):
def guess_next_simple_semver(version, retain, increment=True):
- parts = map(int, str(version).split("."))
- parts = _pad(parts, retain, 0)
+ parts = [int(i) for i in str(version).split(".")[:retain]]
+ while len(parts) < retain:
+ parts.append(0)
if increment:
parts[-1] += 1
- parts = _pad(parts, SEMVER_LEN, 0)
- return ".".join(map(str, parts))
+ while len(parts) < SEMVER_LEN:
+ parts.append(0)
+ return ".".join(str(i) for i in parts)
def simplified_semver_version(version):
@@ -260,6 +267,25 @@ def simplified_semver_version(version):
)
+def release_branch_semver(version):
+ if version.exact:
+ return version.format_with("{tag}")
+ if version.branch is not None:
+ # Does the branch name (stripped of namespace) parse as a version?
+ branch_ver = _parse_version_tag(version.branch.split("/")[-1], version.config)
+ if branch_ver is not None:
+ # Does the branch version up to the minor part match the tag? If not it
+ # might be like, an issue number or something and not a version number, so
+ # we only want to use it if it matches.
+ tag_ver_up_to_minor = str(version.tag).split(".")[:SEMVER_MINOR]
+ branch_ver_up_to_minor = branch_ver["version"].split(".")[:SEMVER_MINOR]
+ if branch_ver_up_to_minor == tag_ver_up_to_minor:
+ # We're in a release/maintenance branch, next is a patch/rc/beta bump:
+ return version.format_next_version(guess_next_version)
+ # We're in a development branch, next is a minor bump:
+ return version.format_next_version(guess_next_simple_semver, retain=SEMVER_MINOR)
+
+
def _format_local_with_time(version, time_format):
if version.exact or version.node is None:
diff --git a/testing/test_version.py b/testing/test_version.py
index 459d24b..3f2b10a 100644
--- a/testing/test_version.py
+++ b/testing/test_version.py
@@ -1,6 +1,11 @@
import pytest
from setuptools_scm.config import Configuration
-from setuptools_scm.version import meta, simplified_semver_version, tags_to_versions
+from setuptools_scm.version import (
+ meta,
+ simplified_semver_version,
+ release_branch_semver,
+ tags_to_versions,
+)
c = Configuration()
@@ -44,6 +49,42 @@ def test_next_semver(version, expected_next):
@pytest.mark.parametrize(
+ "version, expected_next",
+ [
+ pytest.param(meta("1.0.0", config=c), "1.0.0", id="exact"),
+ pytest.param(
+ meta("1.0.0", distance=2, branch="master", config=c),
+ "1.1.0.dev2",
+ id="development_branch",
+ ),
+ pytest.param(
+ meta("1.0.0rc1", distance=2, branch="master", config=c),
+ "1.1.0.dev2",
+ id="development_branch_release_candidate",
+ ),
+ pytest.param(
+ meta("1.0.0", distance=2, branch="maintenance/1.0.x", config=c),
+ "1.0.1.dev2",
+ id="release_branch_legacy_version",
+ ),
+ pytest.param(
+ meta("1.0.0", distance=2, branch="release-1.0", config=c),
+ "1.0.1.dev2",
+ id="release_branch_with_prefix",
+ ),
+ pytest.param(
+ meta("1.0.0", distance=2, branch="bugfix/3434", config=c),
+ "1.1.0.dev2",
+ id="false_positive_release_branch",
+ ),
+ ],
+)
+def test_next_release_branch_semver(version, expected_next):
+ computed = release_branch_semver(version)
+ assert computed == expected_next
+
+
+@pytest.mark.parametrize(
"tag, expected",
[
pytest.param("v1.0.0", "1.0.0"),