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 | 959 | jjdelcerro | # 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)) |