Statistics
| Revision:

gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / dulwich / contrib / release_robot.py @ 959

History | View | Annotate | Download (4.72 KB)

1
# release_robot.py
2
#
3
# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
4
# General Public License as public by the Free Software Foundation; version 2.0
5
# or (at your option) any later version. You can redistribute it and/or
6
# modify it under the terms of either of these two licenses.
7
#
8
# Unless required by applicable law or agreed to in writing, software
9
# distributed under the License is distributed on an "AS IS" BASIS,
10
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
# See the License for the specific language governing permissions and
12
# limitations under the License.
13
#
14
# You should have received a copy of the licenses; if not, see
15
# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
16
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
17
# License, Version 2.0.
18
#
19

    
20
"""Determine last version string from tags.
21

22
Alternate to `Versioneer <https://pypi.python.org/pypi/versioneer/>`_ using
23
`Dulwich <https://pypi.python.org/pypi/dulwich>`_ to sort tags by time from
24
newest to oldest.
25

26
Import this module into the package ``__init__.py`` and then set ``__version__``
27
as follows::
28

29
    from dulwich.contrib.release_robot import get_current_version
30

31
    __version__ = get_current_version()
32
    # other dunder classes like __author__, etc.
33

34
This example assumes the tags have a leading "v" like "v0.3", and that the
35
``.git`` folder is in the project folder that containts the package folder.
36
"""
37

    
38
from dulwich.repo import Repo
39
import time
40
import datetime
41
import os
42
import re
43
import sys
44

    
45
# CONSTANTS
46
DIRNAME = os.path.abspath(os.path.dirname(__file__))
47
PROJDIR = os.path.dirname(DIRNAME)
48
PATTERN = '[ a-zA-Z_\-]*([\d\.]+[\-\w\.]*)'
49

    
50

    
51
def get_recent_tags(projdir=PROJDIR):
52
    """Get list of tags in order from newest to oldest and their datetimes.
53

54
    :param projdir: path to ``.git``
55
    :returns: list of (tag, [datetime, commit, author]) sorted from new to old
56
    """
57
    project = Repo(projdir)  # dulwich repository object
58
    refs = project.get_refs()  # dictionary of refs and their SHA-1 values
59
    tags = {}  # empty dictionary to hold tags, commits and datetimes
60
    # iterate over refs in repository
61
    for key, value in refs.items():
62
        obj = project.get_object(value)  # dulwich object from SHA-1
63
        # check if object is tag
64
        if obj.type_name != 'tag':
65
            # skip ref if not a tag
66
            continue
67
        # strip the leading text from "refs/tag/<tag name>" to get "tag name"
68
        _, tag = key.rsplit('/', 1)
69
        # check if tag object is commit, altho it should always be true
70
        if obj.object[0].type_name == 'commit':
71
            commit = project.get_object(obj.object[1])  # commit object
72
            # get tag commit datetime, but dulwich returns seconds since
73
            # beginning of epoch, so use Python time module to convert it to
74
            # timetuple then convert to datetime
75
            tags[tag] = [
76
                datetime.datetime(*time.gmtime(commit.commit_time)[:6]),
77
                commit.id,
78
                commit.author
79
            ]
80

    
81
    # return list of tags sorted by their datetimes from newest to oldest
82
    return sorted(tags.items(), key=lambda tag: tag[1][0], reverse=True)
83

    
84

    
85
def get_current_version(pattern=PATTERN, projdir=PROJDIR, logger=None):
86
    """Return the most recent tag, using an options regular expression pattern.
87

88
    The default pattern will strip any characters preceding the first semantic
89
    version. *EG*: "Release-0.2.1-rc.1" will be come "0.2.1-rc.1". If no match
90
    is found, then the most recent tag is return without modification.
91

92
    :param pattern: regular expression pattern with group that matches version
93
    :param projdir: path to ``.git``
94
    :param logger: a Python logging instance to capture exception
95
    :returns: tag matching first group in regular expression pattern
96
    """
97
    tags = get_recent_tags(projdir)
98
    try:
99
        tag = tags[0][0]
100
    except IndexError:
101
        return
102
    m = re.match(pattern, tag)
103
    try:
104
        current_version = m.group(1)
105
    except (IndexError, AttributeError) as err:
106
        if logger:
107
            logger.exception(err)
108
        return tag
109
    return current_version
110

    
111

    
112
def test_tag_pattern():
113
    test_cases = {
114
        '0.3': '0.3', 'v0.3': '0.3', 'release0.3': '0.3', 'Release-0.3': '0.3',
115
        'v0.3rc1': '0.3rc1', 'v0.3-rc1': '0.3-rc1', 'v0.3-rc.1': '0.3-rc.1',
116
        'version 0.3': '0.3', 'version_0.3_rc_1': '0.3_rc_1', 'v1': '1',
117
        '0.3rc1': '0.3rc1'
118
    }
119
    for tc, version in test_cases.iteritems():
120
        m = re.match(PATTERN, tc)
121
        assert m.group(1) == version
122

    
123

    
124
if __name__ == '__main__':
125
    if len(sys.argv) > 1:
126
        projdir = sys.argv[1]
127
    else:
128
        projdir = PROJDIR
129
    print(get_current_version(projdir=projdir))