source: rtems-tools/rtemstoolkit/version.py @ 6d30de6

Last change on this file since 6d30de6 was 6d30de6, checked in by Chris Johns <chrisj@…>, on Nov 28, 2018 at 9:13:51 PM

rtemstoolkit: Fix unittests on Windows

  • Fix Windows host support so MSYS pythons can be used.
  • Fix Windows host support for python3.
  • Improve the mailer unittest.
  • Property mode set to 100644
File size: 8.3 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2018 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-tools'.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions are met:
10#
11# 1. Redistributions of source code must retain the above copyright notice,
12# this list of conditions and the following disclaimer.
13#
14# 2. Redistributions in binary form must reproduce the above copyright notice,
15# this list of conditions and the following disclaimer in the documentation
16# and/or other materials provided with the distribution.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28# POSSIBILITY OF SUCH DAMAGE.
29#
30
31#
32# Releasing RTEMS Tools
33# ---------------------
34#
35# Format:
36#
37#  The format is INI. The file requires a `[version`] section and a `revision`
38#  option:
39#
40#   [version]
41#   revision = <version-string>
42#
43#  The `<version-string>` has the `version` and `revision` delimited by a
44#  single `.`. An example file is:
45#
46#   [version]
47#   revision = 5.0.not_released
48#
49#  where the `version` is `5` and the revision is `0` and the package is not
50#  released. The label `not_released` is reversed to mean the package is not
51#  released. A revision string can contain extra characters after the
52#  `revision` number for example `5.0-rc1` or is deploying a package
53#  `5.0-nasa-cfs`
54#
55#  Packages can optionally add specialised sections to a version configuration
56#  files. These can be accessed via the:
57#
58#   load_release_settings: Return the items in a section
59#   load_release_setting: Return an item from a section
60#
61# User deployment:
62#
63#  Create a git archive and then add a suitable VERSION file to the top
64#  directory of the package. The package assumes your python executable is
65#  location in `bin` directory which is one below the top of the package's
66#  install prefix.
67#
68# RTEMS Release:
69#
70#  Set the values in the `rtems-version.ini` file. This is a shared file so
71#  packages and encouraged to add specific settings to other configuration
72#  files.
73#
74# Notes:
75#
76#  This module uses os.apth for paths and assumes all paths are in the host
77#  format.
78#
79
80from __future__ import print_function
81
82import itertools
83import os
84import sys
85
86try:
87    import configparser
88except ImportError:
89    import ConfigParser as configparser
90
91from rtemstoolkit import error
92from rtemstoolkit import git
93from rtemstoolkit import path
94from rtemstoolkit import rtems
95
96#
97# Default to an internal string.
98#
99_version = 'undefined'
100_revision = 'not_released'
101_version_str = '%s.%s' % (_version, _revision)
102_released = False
103_git = False
104_is_loaded = False
105
106def _top():
107    top = os.path.dirname(sys.argv[0])
108    if len(top) == 0:
109        top = '.'
110    return top
111
112def _load_released_version_config():
113    '''Local worker to load a configuration file.'''
114    top = _top()
115    for ver in [os.path.join(top, 'VERSION'),
116                os.path.join('..', 'VERSION'),
117                rtems.configuration_file('rtems-version.ini')]:
118        if path.exists(path.join(ver)):
119            v = configparser.SafeConfigParser()
120            try:
121                v.read(path.host(ver))
122            except Exception as e:
123                raise error.general('Invalid version config format: %s: %s' % (ver,
124                                                                               e))
125            return ver, v
126    return None, None
127
128def _load_released_version():
129    '''Load the release data if present. If not found the package is not released.
130
131    A release can be made by adding a file called `VERSION` to the top level
132    directory of a package. This is useful for user deploying a package and
133    making custom releases.
134
135    The RTEMS project reserves the `rtems-version.ini` file for it's
136    releases. This is the base release and should not be touched by users
137    deploying a package.
138
139    '''
140    global _version
141    global _revision
142    global _released
143    global _version_str
144    global _is_loaded
145
146    if not _is_loaded:
147        vc, v = _load_released_version_config()
148        if v is not None:
149            try:
150                ver_str = v.get('version', 'revision')
151            except Exception as e:
152                raise error.general('Invalid version file: %s: %s' % (vc, e))
153            ver_split = ver_str.split('.')
154            if len(ver_split) < 2:
155                raise error.general('Invalid version release value: %s: %s' % (vc,
156                                                                               ver_str))
157            ver = ver_split[0]
158            rev = '.'.join(ver_split[1:])
159            try:
160                _version = int(ver)
161            except:
162                raise error.general('Invalid version config value: %s: %s' % (vc,
163                                                                              ver))
164            try:
165                _revision = int(''.join(itertools.takewhile(str.isdigit, str(rev))))
166            except Exception as e:
167                raise error.general('Invalid revision config value: %s: %s: %s' % (vc,
168                                                                                   rev,
169                                                                                   e))
170            if not 'not_released' in ver:
171                _released = True
172            _version_str = ver_str
173            _is_loaded = True
174    return _released
175
176def _load_git_version():
177    global _version
178    global _revision
179    global _git
180    global _version_str
181    repo = git.repo(_top())
182    if repo.valid():
183        head = repo.head()
184        if repo.dirty():
185            modified = 'modified'
186            sep = ' '
187        else:
188            modified = ''
189            sep = ''
190        _revision = '%s-%s' % (head[0:12], modified)
191        _version_str = '%s (%s%s%s)' % (_version, head[0:12], sep, modified)
192        _git = True
193    return _git
194
195def load_release_settings(section, error = False):
196    vc, v = _load_released_version_config()
197    items = []
198    if v is not None:
199        try:
200            items = v.items(section)
201        except Exception as e:
202            if not isinstance(error, bool):
203                error(e)
204            elif error:
205                raise error.general('Invalid config section: %s: %s: %s' % (vc,
206                                                                            section,
207                                                                            e))
208    return items
209
210def load_release_setting(section, option, raw = False, error = False):
211    vc, v = _load_released_version_config()
212    value = None
213    if v is not None:
214        try:
215            value = v.get(section, option, raw = raw)
216        except Exception as e:
217            if not isinstance(error, bool):
218                error(e)
219            elif error:
220                raise error.general('Invalid config section: %s: %s: %s.%s' % (vc,
221                                                                               section,
222                                                                               option,
223                                                                               e))
224    return value
225
226def released():
227    return _load_released_version()
228
229def version_control():
230    return _load_git_version()
231
232def string():
233    _load_released_version()
234    _load_git_version()
235    return _version_str
236
237def version():
238    _load_released_version()
239    _load_git_version()
240    return _version
241
242def revision():
243    _load_released_version()
244    _load_git_version()
245    return _revision
246
247if __name__ == '__main__':
248    print('Version: %s' % (str(version())))
249    print('Revision: %s' % (str(revision())))
250    print('String: %s' % (string()))
251    if version() == 'undefined':
252        raise Exception('version is undefined')
Note: See TracBrowser for help on using the repository browser.