Teach pbr about post versioned dev versions.
Untagged versions should not be presented as final versions, which is what was happening. The rules for dev versions are that they lead up to the next release, so to emit a dev version we have to increment the current version, then we can emit a dev version number. implements: blueprint pbr-semver sem-ver: feature Change-Id: Icf2f1999613e0d26424798697de34811b9cfc4ab
This commit is contained in:
parent
1758998881
commit
81c2000881
|
@ -26,11 +26,17 @@ PBR can and does do a bunch of things for you:
|
|||
Version
|
||||
-------
|
||||
|
||||
Version strings will be inferred from git. If a given revision is tagged,
|
||||
that's the version. If it's not, and you don't provide a version, the version
|
||||
will be very similar to git describe. If you do, then we'll assume that's the
|
||||
version you are working towards, and will generate alpha version strings
|
||||
based on commits since last tag and the current git sha.
|
||||
Versions can be managed two ways - postversioning and preversioning.
|
||||
Postversioning is the default, and preversioning is enabeld by setting
|
||||
``version`` in the setup.cfg ``metadata`` section. In both cases
|
||||
version strings are inferred from git.
|
||||
|
||||
If a given revision is tagged, that's the version. If it's not, then either
|
||||
the current version is incremented to get a target version (postversioning) or
|
||||
the version set in setup.cfg metadata (preversioning) is used as the target
|
||||
version. We then generate dev version strings based on the commits since the
|
||||
last release and include the current git sha to disambiguate multiple dev
|
||||
versions with the same number of commits since the release.
|
||||
|
||||
.. note::
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ from setuptools.command import install_scripts
|
|||
from setuptools.command import sdist
|
||||
|
||||
from pbr import extra_files
|
||||
from pbr import version
|
||||
|
||||
TRUE_VALUES = ('true', '1', 'yes')
|
||||
REQUIREMENTS_FILES = ('requirements.txt', 'tools/pip-requires')
|
||||
|
@ -784,7 +785,7 @@ def _get_revno(git_dir):
|
|||
"""
|
||||
describe = _run_git_command(['describe', '--always'], git_dir)
|
||||
if "-" in describe:
|
||||
return describe.rsplit("-", 2)[-2]
|
||||
return int(describe.rsplit("-", 2)[-2])
|
||||
|
||||
# no tags found
|
||||
revlist = _run_git_command(
|
||||
|
@ -792,12 +793,31 @@ def _get_revno(git_dir):
|
|||
return len(revlist.splitlines())
|
||||
|
||||
|
||||
def _get_version_from_git(pre_version):
|
||||
"""Return a version which is equal to the tag that's on the current
|
||||
revision if there is one, or tag plus number of additional revisions
|
||||
if the current revision has no tag.
|
||||
"""
|
||||
def _get_version_from_git_target(semver, git_dir):
|
||||
"""Calculate a version from a target version in git_dir.
|
||||
|
||||
:param semver: The version we will release next.
|
||||
:param git_dir: The git directory we're working from.
|
||||
:return: A version string like 1.2.3.dev1.g123124
|
||||
"""
|
||||
# Drop any RC etc versions.
|
||||
sha = _run_git_command(
|
||||
['log', '-n1', '--pretty=format:%h'], git_dir)
|
||||
return semver.to_dev(_get_revno(git_dir), sha)
|
||||
|
||||
|
||||
def _get_version_from_git(pre_version=None):
|
||||
"""Calculate a version string from git.
|
||||
|
||||
If the revision is tagged, return that. Otherwise calculate a semantic
|
||||
version description of the tree.
|
||||
|
||||
The number of revisions since the last tag is included in the dev counter
|
||||
in the version for untagged versions.
|
||||
|
||||
:param pre_version: If supplied use this as the target version rather than
|
||||
inferring one from the last tag + commit messages.
|
||||
"""
|
||||
git_dir = _get_git_directory()
|
||||
if git_dir and _git_is_installed():
|
||||
if pre_version:
|
||||
|
@ -806,16 +826,24 @@ def _get_version_from_git(pre_version):
|
|||
['describe', '--exact-match'], git_dir,
|
||||
throw_on_error=True).replace('-', '.')
|
||||
except Exception:
|
||||
sha = _run_git_command(
|
||||
['log', '-n1', '--pretty=format:%h'], git_dir)
|
||||
return "%s.dev%s.g%s" % (pre_version, _get_revno(git_dir), sha)
|
||||
# not released yet - use pre_version as the target
|
||||
semver = version.SemanticVersion.from_pip_string(pre_version)
|
||||
return _get_version_from_git_target(
|
||||
semver, git_dir).release_string()
|
||||
else:
|
||||
description = _run_git_command(
|
||||
['describe', '--always'], git_dir).replace('-', '.')
|
||||
if '.' not in description:
|
||||
# Untagged tree.
|
||||
description = '0.g%s' % description
|
||||
return description
|
||||
try:
|
||||
return _run_git_command(
|
||||
['describe', '--exact-match'], git_dir,
|
||||
throw_on_error=True).replace('-', '.')
|
||||
except Exception:
|
||||
last_version = _run_git_command(
|
||||
['describe', '--abbrev=0'], git_dir)
|
||||
if not last_version:
|
||||
# Untagged tree.
|
||||
last_version = '0'
|
||||
semver = version.SemanticVersion.from_pip_string(last_version)
|
||||
return _get_version_from_git_target(
|
||||
semver.increment(), git_dir).release_string()
|
||||
# If we don't know the version, return an empty string so at least
|
||||
# the downstream users of the value always have the same type of
|
||||
# object to work with.
|
||||
|
@ -852,6 +880,9 @@ def get_version(package_name, pre_version=None):
|
|||
that a source tarball be made from our git repo - or that if someone wants
|
||||
to make a source tarball from a fork of our repo with additional tags in it
|
||||
that they understand and desire the results of doing that.
|
||||
|
||||
:param pre_version: The version field from setup.cfg - if set then this
|
||||
version will be the next release.
|
||||
"""
|
||||
version = os.environ.get(
|
||||
"PBR_VERSION",
|
||||
|
|
|
@ -147,7 +147,8 @@ def _run_cmd(args, cwd):
|
|||
:return: ((stdout, stderr), returncode)
|
||||
"""
|
||||
p = subprocess.Popen(
|
||||
args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
|
||||
args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE, cwd=cwd)
|
||||
streams = tuple(s.decode('latin1').strip() for s in p.communicate())
|
||||
for content in streams:
|
||||
print(content)
|
||||
|
|
|
@ -44,6 +44,7 @@ import tempfile
|
|||
import fixtures
|
||||
import mock
|
||||
import testscenarios
|
||||
from testtools import matchers
|
||||
|
||||
from pbr import packaging
|
||||
from pbr.tests import base
|
||||
|
@ -67,11 +68,53 @@ class TestRepo(fixtures.Fixture):
|
|||
base._run_cmd(
|
||||
['git', 'config', '--global', 'user.email', 'example@example.com'],
|
||||
self._basedir)
|
||||
base._run_cmd(
|
||||
['git', 'config', '--global', 'user.signingkey',
|
||||
'example@example.com'], self._basedir)
|
||||
base._run_cmd(['git', 'add', '.'], self._basedir)
|
||||
|
||||
def commit(self):
|
||||
files = len(os.listdir(self._basedir))
|
||||
path = self._basedir + '/%d' % files
|
||||
open(path, 'wt').close()
|
||||
base._run_cmd(['git', 'add', path], self._basedir)
|
||||
base._run_cmd(['git', 'commit', '-m', 'test commit'], self._basedir)
|
||||
|
||||
def tag(self, version):
|
||||
base._run_cmd(
|
||||
['git', 'tag', '-sm', 'test tag', version], self._basedir)
|
||||
|
||||
|
||||
class GPGKeyFixture(fixtures.Fixture):
|
||||
"""Creates a GPG key for testing.
|
||||
|
||||
It's recommended that this be used in concert with a unique home
|
||||
directory.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(GPGKeyFixture, self).setUp()
|
||||
tempdir = self.useFixture(fixtures.TempDir())
|
||||
config_file = tempdir.path + '/key-config'
|
||||
f = open(config_file, 'wt')
|
||||
try:
|
||||
f.write("""
|
||||
#%no-protection -- these would be ideal but they are documented
|
||||
#%transient-key -- but not implemented in gnupg!
|
||||
%no-ask-passphrase
|
||||
Key-Type: RSA
|
||||
Name-Real: Example Key
|
||||
Name-Comment: N/A
|
||||
Name-Email: example@example.com
|
||||
Expire-Date: 2d
|
||||
Preferences: (setpref)
|
||||
%commit
|
||||
""")
|
||||
finally:
|
||||
f.close()
|
||||
base._run_cmd(
|
||||
['gpg', '--gen-key', '--batch', config_file], tempdir.path)
|
||||
|
||||
|
||||
class TestPackagingInGitRepoWithCommit(base.BaseTestCase):
|
||||
|
||||
|
@ -173,5 +216,34 @@ class TestNestedRequirements(base.BaseTestCase):
|
|||
self.assertEqual(result, ['pbr'])
|
||||
|
||||
|
||||
class TestVersions(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVersions, self).setUp()
|
||||
self.repo = self.useFixture(TestRepo(self.package_dir))
|
||||
self.useFixture(GPGKeyFixture())
|
||||
self.useFixture(base.DiveDir(self.package_dir))
|
||||
|
||||
def test_tagged_version_has_tag_version(self):
|
||||
self.repo.commit()
|
||||
self.repo.tag('1.2.3')
|
||||
version = packaging._get_version_from_git('1.2.3')
|
||||
self.assertEqual('1.2.3', version)
|
||||
|
||||
def test_untagged_version_has_dev_version_postversion(self):
|
||||
self.repo.commit()
|
||||
self.repo.tag('1.2.3')
|
||||
self.repo.commit()
|
||||
version = packaging._get_version_from_git()
|
||||
self.assertThat(version, matchers.StartsWith('1.2.4.dev1.g'))
|
||||
|
||||
def test_untagged_version_has_dev_version_preversion(self):
|
||||
self.repo.commit()
|
||||
self.repo.tag('1.2.3')
|
||||
self.repo.commit()
|
||||
version = packaging._get_version_from_git('1.2.5')
|
||||
self.assertThat(version, matchers.StartsWith('1.2.5.dev1.g'))
|
||||
|
||||
|
||||
def load_tests(loader, in_tests, pattern):
|
||||
return testscenarios.load_tests_apply_scenarios(loader, in_tests, pattern)
|
||||
|
|
Loading…
Reference in New Issue