[50fdf12] | 1 | # |
---|
| 2 | # RTEMS Tools Project (http://www.rtems.org/) |
---|
[3bd8def] | 3 | # Copyright 2010-2018 Chris Johns (chrisj@rtems.org) |
---|
[50fdf12] | 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 | # |
---|
[3bd8def] | 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. |
---|
[50fdf12] | 78 | # |
---|
| 79 | |
---|
[b0fa2ae] | 80 | from __future__ import print_function |
---|
| 81 | |
---|
[3bd8def] | 82 | import itertools |
---|
| 83 | import os |
---|
[efc4f09] | 84 | import sys |
---|
| 85 | |
---|
[3bd8def] | 86 | try: |
---|
| 87 | import configparser |
---|
| 88 | except ImportError: |
---|
| 89 | import ConfigParser as configparser |
---|
| 90 | |
---|
[7e5cdea] | 91 | from rtemstoolkit import error |
---|
| 92 | from rtemstoolkit import git |
---|
| 93 | from rtemstoolkit import path |
---|
| 94 | from rtemstoolkit import rtems |
---|
[efc4f09] | 95 | |
---|
| 96 | # |
---|
| 97 | # Default to an internal string. |
---|
| 98 | # |
---|
[3bd8def] | 99 | _version = 'undefined' |
---|
[3828e50] | 100 | _revision = 'not_released' |
---|
| 101 | _version_str = '%s.%s' % (_version, _revision) |
---|
[efc4f09] | 102 | _released = False |
---|
| 103 | _git = False |
---|
[3bd8def] | 104 | _is_loaded = False |
---|
| 105 | |
---|
| 106 | def _top(): |
---|
| 107 | top = os.path.dirname(sys.argv[0]) |
---|
| 108 | if len(top) == 0: |
---|
| 109 | top = '.' |
---|
| 110 | return top |
---|
[efc4f09] | 111 | |
---|
[3bd8def] | 112 | def _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')]: |
---|
[95abe76] | 118 | if path.exists(path.join(ver)): |
---|
[3bd8def] | 119 | v = configparser.SafeConfigParser() |
---|
| 120 | try: |
---|
[95abe76] | 121 | v.read(path.host(ver)) |
---|
[3bd8def] | 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 |
---|
[efc4f09] | 127 | |
---|
| 128 | def _load_released_version(): |
---|
[3bd8def] | 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 |
---|
[efc4f09] | 142 | global _released |
---|
| 143 | global _version_str |
---|
[3bd8def] | 144 | global _is_loaded |
---|
| 145 | |
---|
| 146 | if not _is_loaded: |
---|
| 147 | vc, v = _load_released_version_config() |
---|
| 148 | if v is not None: |
---|
[efc4f09] | 149 | try: |
---|
[3bd8def] | 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: |
---|
[087be8c] | 165 | _revision = int(''.join(itertools.takewhile(str.isdigit, str(rev)))) |
---|
[3bd8def] | 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 |
---|
[efc4f09] | 174 | return _released |
---|
| 175 | |
---|
| 176 | def _load_git_version(): |
---|
[3bd8def] | 177 | global _version |
---|
| 178 | global _revision |
---|
[efc4f09] | 179 | global _git |
---|
| 180 | global _version_str |
---|
[3bd8def] | 181 | repo = git.repo(_top()) |
---|
[efc4f09] | 182 | if repo.valid(): |
---|
| 183 | head = repo.head() |
---|
| 184 | if repo.dirty(): |
---|
[3bd8def] | 185 | modified = 'modified' |
---|
| 186 | sep = ' ' |
---|
[efc4f09] | 187 | else: |
---|
| 188 | modified = '' |
---|
[3bd8def] | 189 | sep = '' |
---|
| 190 | _revision = '%s-%s' % (head[0:12], modified) |
---|
| 191 | _version_str = '%s (%s%s%s)' % (_version, head[0:12], sep, modified) |
---|
[efc4f09] | 192 | _git = True |
---|
| 193 | return _git |
---|
| 194 | |
---|
[3bd8def] | 195 | def 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 | |
---|
| 210 | def 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 | |
---|
[efc4f09] | 226 | def released(): |
---|
| 227 | return _load_released_version() |
---|
| 228 | |
---|
| 229 | def version_control(): |
---|
| 230 | return _load_git_version() |
---|
[50fdf12] | 231 | |
---|
[3bd8def] | 232 | def string(): |
---|
| 233 | _load_released_version() |
---|
| 234 | _load_git_version() |
---|
[efc4f09] | 235 | return _version_str |
---|
[50fdf12] | 236 | |
---|
[3e14594] | 237 | def version(): |
---|
[3bd8def] | 238 | _load_released_version() |
---|
| 239 | _load_git_version() |
---|
[3e14594] | 240 | return _version |
---|
| 241 | |
---|
[3bd8def] | 242 | def revision(): |
---|
| 243 | _load_released_version() |
---|
| 244 | _load_git_version() |
---|
| 245 | return _revision |
---|
| 246 | |
---|
[50fdf12] | 247 | if __name__ == '__main__': |
---|
[95abe76] | 248 | print('Version: %s' % (str(version()))) |
---|
| 249 | if version() == 'undefined': |
---|
| 250 | raise Exception('version is undefined') |
---|