00152bee |
# -*- coding: utf-8 -*-
# This file is part of 'miniver': https://github.com/jbweston/miniver
#
from collections import namedtuple
|
6f63c0a5 |
import os
import subprocess
import sys
|
00152bee |
from distutils.command.build import build as build_orig
from setuptools.command.sdist import sdist as sdist_orig
|
6f63c0a5 |
|
00152bee |
Version = namedtuple('Version', ('release', 'dev', 'labels'))
|
6f63c0a5 |
|
00152bee |
# No public API
__all__ = []
|
6f63c0a5 |
|
00152bee |
package_root = os.path.dirname(os.path.realpath(__file__))
package_name = os.path.basename(package_root)
distr_root = os.path.dirname(package_root)
|
6f63c0a5 |
|
00152bee |
STATIC_VERSION_FILE = '_static_version.py'
|
6f63c0a5 |
|
00152bee |
def get_version(version_file=STATIC_VERSION_FILE):
version_info = {}
with open(os.path.join(package_root, version_file), 'rb') as f:
exec(f.read(), {}, version_info)
version = version_info['version']
version_is_from_git = (version == "__use_git__")
if version_is_from_git:
version = get_version_from_git()
if not version:
version = get_version_from_git_archive(version_info)
if not version:
version = Version("unknown", None, None)
return semver_format(version)
else:
return version
|
6f63c0a5 |
|
00152bee |
def semver_format(version_info):
release, dev, labels = version_info
|
6f63c0a5 |
|
00152bee |
version_parts = [release]
if dev:
if release.endswith('-dev'):
version_parts.append(dev)
elif release.contains('-'):
version_parts.append('.dev{}'.format(dev))
else:
version_parts.append('-dev{}'.format(dev))
|
6f63c0a5 |
|
00152bee |
if labels:
version_parts.append('+')
version_parts.append(".".join(labels))
|
6f63c0a5 |
|
00152bee |
return "".join(version_parts)
|
6f63c0a5 |
|
00152bee |
def get_version_from_git():
try:
p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'],
cwd=distr_root,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError:
return
if p.wait() != 0:
return
if not os.path.samefile(p.communicate()[0].decode().rstrip('\n'),
distr_root):
# The top-level directory of the current Git repository is not the same
# as the root directory of the Kwant distribution: do not extract the
# version from Git.
return
# git describe --first-parent does not take into account tags from branches
# that were merged-in.
for opts in [['--first-parent'], []]:
|
6f63c0a5 |
try:
|
00152bee |
p = subprocess.Popen(['git', 'describe', '--long'] + opts,
cwd=distr_root,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError:
return
if p.wait() == 0:
|
6f63c0a5 |
break
else:
|
00152bee |
return
description = p.communicate()[0].decode().strip('v').rstrip('\n')
|
6f63c0a5 |
|
00152bee |
release, dev, git = description.rsplit('-', 2)
labels = []
if dev == "0":
dev = None
|
6f63c0a5 |
else:
|
00152bee |
labels.append(git)
|
6f63c0a5 |
|
00152bee |
try:
p = subprocess.Popen(['git', 'diff', '--quiet'], cwd=distr_root)
except OSError:
labels.append('confused') # This should never happen.
|
6f63c0a5 |
else:
|
00152bee |
if p.wait() == 1:
labels.append('dirty')
|
6f63c0a5 |
|
00152bee |
return Version(release, dev, labels)
|
6f63c0a5 |
|
00152bee |
# TODO: change this logic when there is a git pretty-format
# that gives the same output as 'git describe'.
# Currently we can only tell the tag the current commit is
# pointing to, or its hash (with no version info)
# if it is not tagged.
def get_version_from_git_archive(version_info):
try:
refnames = version_info['refnames']
git_hash = version_info['git_hash']
except KeyError:
# These fields are not present if we are running from an sdist.
# Execution should never reach here, though
return None
if git_hash.startswith('$Format') or refnames.startswith('$Format'):
# variables not expanded during 'git archive'
return None
VTAG = 'tag: v'
refs = set(r.strip() for r in refnames.split(","))
version_tags = set(r[len(VTAG):] for r in refs if r.startswith(VTAG))
if version_tags:
release, *_ = sorted(version_tags) # prefer e.g. "2.0" over "2.0rc1"
return Version(release, dev=None, labels=None)
|
6f63c0a5 |
else:
|
00152bee |
return Version('unknown', dev=None, labels=[f'g{git_hash}'])
|
6f63c0a5 |
|
00152bee |
__version__ = get_version()
|
6f63c0a5 |
|
00152bee |
# The following section defines a module global 'cmdclass',
# which can be used from setup.py. The 'package_name' and
# '__version__' module globals are used (but not modified).
|
6f63c0a5 |
|
00152bee |
def _write_version(fname):
# This could be a hard link, so try to delete it first. Is there any way
# to do this atomically together with opening?
|
6f63c0a5 |
try:
|
00152bee |
os.remove(fname)
except OSError:
|
6f63c0a5 |
pass
|
00152bee |
with open(fname, 'w') as f:
f.write("# This file has been created by setup.py.\n"
"version = '{}'\n".format(__version__))
|
6f63c0a5 |
|
00152bee |
class _build(build_orig):
def run(self):
super().run()
_write_version(os.path.join(self.build_lib, package_name,
STATIC_VERSION_FILE))
class _sdist(sdist_orig):
def make_release_tree(self, base_dir, files):
super().make_release_tree(base_dir, files)
_write_version(os.path.join(base_dir, package_name,
STATIC_VERSION_FILE))
|
6f63c0a5 |
|
00152bee |
cmdclass = dict(sdist=_sdist, build=_build)
|