Completed
Pull Request — develop (#5)
by Kale
58s
created

auxlib.SdistCommand   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 10
Duplicated Lines 0 %
Metric Value
dl 0
loc 10
rs 10
wmc 3

2 Methods

Rating   Name   Duplication   Size   Complexity  
A run() 0 2 1
A make_release_tree() 0 6 2
1
# -*- coding: utf-8 -*-
2
from __future__ import print_function, division, absolute_import
3
from logging import getLogger
4
from os.path import basename, dirname, join, isdir
5
from re import match
6
from setuptools.command.build_py import build_py
7
from setuptools.command.sdist import sdist
8
from setuptools.command.test import test as TestCommand
9
from subprocess import CalledProcessError, check_call, check_output
10
import sys
11
12
from .path import absdirname, PackageFile
13
14
log = getLogger(__name__)
15
16
17
def _get_version_from_pkg_info(package_name):
18
    with PackageFile('.version', package_name) as fh:
19
        return fh.read()
20
21
22
def _is_git_dirty():
23
    try:
24
        check_call(('git', 'diff', '--quiet'))
25
        check_call(('git', 'diff', '--cached', '--quiet'))
26
        return False
27
    except CalledProcessError:
28
        return True
29
30
31
def _get_most_recent_git_tag():
32
    try:
33
        return check_output(["git", "describe", "--tags"]).strip()
34
    except CalledProcessError as e:
35
        if e.returncode == 128:
36
            return "0.0.0.0"
37
        else:
38
            raise  # pragma: no cover
39
40
41
def _get_git_hash():
42
    try:
43
        return check_output(["git", "rev-parse", "HEAD"]).strip()[:7]
44
    except CalledProcessError:
45
        return 0
46
47
48
def _get_version_from_git_tag():
49
    """Return a PEP440-compliant version derived from the git status.
50
    If that fails for any reason, return the first 7 chars of the changeset hash.
51
    """
52
    tag = _get_most_recent_git_tag()
53
    m = match(b"(?P<xyz>\d+\.\d+\.\d+)(?:-(?P<dev>\d+)-(?P<hash>.+))?", tag)
54
    version = m.group('xyz').decode('utf-8')
55
    if m.group('dev') or _is_git_dirty():
56
        version += ".dev{dev}+{hash}".format(dev=m.group('dev') or 0,
57
                                             hash=m.group('hash') or _get_git_hash())
58
    return version
59
60
61
def is_git_repo(path, package):
62
    if path == '/' or dirname(basename(path)) == package:
63
        return False
64
    else:
65
        return isdir(join(path, '.git')) or is_git_repo(dirname(path), package)
66
67
68
def get_version(file, package):
69
    """Returns a version string for the current package, derived
70
    either from the SCM (git currently) or from PKG-INFO.
71
72
    This function is expected to run in two contexts. In a development
73
    context, where .git/ exists, the version is pulled from git tags
74
    and written into PKG-INFO to create an sdist or bdist.
75
76
    In an installation context, the PKG-INFO file written above is the
77
    source of version string.
78
79
    """
80
    here = absdirname(file)
81
    if is_git_repo(here, package):
82
        return _get_version_from_git_tag()
83
84
    # fall back to .version file
85
    version_from_pkg = _get_version_from_pkg_info(package)
86
    if version_from_pkg:
87
        return version_from_pkg
88
89
    raise RuntimeError("Could not get package version (no .git or .version file)")
90
91
92
class BuildPyCommand(build_py):
93
    def run(self):
94
        build_py.run(self)
95
        # locate .version in the new build/ directory and replace it with an updated value
96
        target_version_file = join(self.build_lib, self.distribution.metadata.name, ".version")
97
        print("UPDATING %s" % target_version_file)
98
        with open(target_version_file, 'w') as f:
99
            f.write(self.distribution.metadata.version)
100
101
102
class SdistCommand(sdist):
103
    def run(self):
104
        return sdist.run(self)
105
106
    def make_release_tree(self, base_dir, files):
107
        sdist.make_release_tree(self, base_dir, files)
108
        target_version_file = join(base_dir, self.distribution.metadata.name, ".version")
109
        print("UPDATING {0}".format(target_version_file))
110
        with open(target_version_file, 'w') as f:
111
            f.write(self.distribution.metadata.version)
112
113
114
class Tox(TestCommand):
115
    user_options = [('tox-args=', 'a', "Arguments to pass to tox")]
116
117
    def initialize_options(self):
118
        TestCommand.initialize_options(self)
119
        self.tox_args = None
120
121
    def finalize_options(self):
122
        TestCommand.finalize_options(self)
123
        self.test_args = []
124
        self.test_suite = True
125
126
    def run_tests(self):
127
        # import here, cause outside the eggs aren't loaded
128
        import tox
129
        import shlex
130
        args = self.tox_args
131
        if args:
132
            args = shlex.split(self.tox_args)
133
        else:
134
            args = ''
135
        errno = tox.cmdline(args=args)
136
        sys.exit(errno)
137
138
139
if __name__ == "__main__":
140
    print(get_version(__file__, __package__))
141