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)) |