-
-
Save lichray/61c2435b210e7a559bfd3fa51c1c315b to your computer and use it in GitHub Desktop.
Produce a setuptools-compatible package version number based on git tags
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Calculate the current package version number based on git tags. | |
If possible, use the output of `git describe` modified to conform to the | |
versioning scheme that setuptools uses (see PEP 386). Releases must be | |
labelled with annotated tags (signed tags are annotated) of the following | |
format: | |
v<num>(.<num>)+ [ {a|b|c|rc} <num> (.<num>)* ] | |
If `git describe` returns an error (likely because we're in an unpacked copy | |
of a release tarball, rather than a git repository), or returns a tag that | |
does not match the above format, the version is read from a RELEASE-VERSION | |
file. | |
To use this script, simply import it in your setup.py file and use the results | |
of get_version() as your package version: | |
import version | |
setup( | |
version=version.get_version(), | |
. | |
. | |
. | |
) | |
This will automatically update the RELEASE-VERSION file. The RELEASE-VERSION | |
file should *not* be checked into git but it *should* be included in sdist | |
tarballs (as should the version.py file). To do this, run: | |
echo include RELEASE-VERSION version.py >> MANIFEST.in | |
echo RELEASE-VERSION >> .gitignore | |
With that setup, a new release can be labelled by simply invoking: | |
git tag -s v1.0 | |
The original version of this module is due to Douglas Creager, with PEP 386 | |
modifications by Michal Nazarewicz. Here is a nice write-up of the original: | |
http://dcreager.net/2010/02/10/setuptools-git-version-numbers/ | |
""" | |
import re | |
import subprocess | |
import sys | |
__author__ = ('Douglas Creager <[email protected]>', | |
'Michal Nazarewicz <[email protected]>', | |
'Ludwig Schwardt <[email protected]>') | |
__license__ = 'This file is placed into the public domain.' | |
__maintainer__ = 'Ludwig Schwardt' | |
__email__ = '[email protected]' | |
__all__ = ('get_version') | |
RELEASE_VERSION_FILE = 'RELEASE-VERSION' | |
# http://www.python.org/dev/peps/pep-0386/ | |
_PEP386_SHORT_VERSION_RE = r'\d+(?:\.\d+)+(?:(?:[abc]|rc)\d+(?:\.\d+)*)?' | |
_PEP386_VERSION_RE = r'^%s(?:\.post\d+)?(?:\.dev\d+)?$' % ( | |
_PEP386_SHORT_VERSION_RE) | |
_GIT_DESCRIPTION_RE = r'^v(?P<ver>%s)-(?P<commits>\d+)-g(?P<sha>[\da-f]+)$' % ( | |
_PEP386_SHORT_VERSION_RE) | |
def read_git_version(): | |
try: | |
proc = subprocess.Popen(('git', 'describe', '--long', | |
'--match', 'v[0-9]*.*'), | |
stdout=subprocess.PIPE, stderr=subprocess.PIPE) | |
data, _ = proc.communicate() | |
if proc.returncode: | |
return | |
ver = data.splitlines()[0].strip() | |
except subprocess.CalledProcessError: | |
return | |
if not ver: | |
return | |
m = re.search(_GIT_DESCRIPTION_RE, ver) | |
if not m: | |
sys.stderr.write('version: git description (%s) is invalid, ' | |
'ignoring\n' % (ver,)) | |
return | |
commits = int(m.group('commits')) | |
if not commits: | |
return m.group('ver') | |
else: | |
return '%s.post%d.dev%d' % ( | |
m.group('ver'), commits, int(m.group('sha'), 16)) | |
def read_release_version(): | |
try: | |
fd = open(RELEASE_VERSION_FILE) | |
try: | |
ver = fd.readline().strip() | |
finally: | |
fd.close() | |
if not re.search(_PEP386_VERSION_RE, ver): | |
sys.stderr.write('version: release version (%s) is invalid, ' | |
'will use it anyway\n' % (ver,)) | |
return ver | |
except IOError: | |
return | |
def write_release_version(version): | |
fd = open(RELEASE_VERSION_FILE, 'w+') | |
fd.write('%s\n' % (version,)) | |
fd.close() | |
def get_version(): | |
release_version = read_release_version() | |
version = read_git_version() or release_version | |
if not version: | |
raise ValueError('Cannot find the version number') | |
if version != release_version: | |
write_release_version(version) | |
return version | |
if __name__ == '__main__': | |
print get_version() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment