[PATCH 3/4] sb: Align the version processing with rtems-tools.

chrisj at rtems.org chrisj at rtems.org
Sun Nov 17 22:01:01 UTC 2019


From: Chris Johns <chrisj at rtems.org>

- Use the same VERSION file format as rtems-tools so a common release
  generation can be used.

- The version.py is almost the same as rtems-tools. There are some
  minor differences, one is the RTEMS version is present in this
  file while rtems-tool uses config/rtems-release.ini.

Updates #3822
---
 source-builder/sb/bootstrap.py   |   2 +-
 source-builder/sb/build.py       |   2 +-
 source-builder/sb/check.py       |   2 +-
 source-builder/sb/getsources.py  |   2 +-
 source-builder/sb/options.py     |  26 +++-
 source-builder/sb/reports.py     |   4 +-
 source-builder/sb/rtemsconfig.py |   2 +-
 source-builder/sb/setbuilder.py  |   2 +-
 source-builder/sb/version.py     | 244 ++++++++++++++++++++++---------
 9 files changed, 207 insertions(+), 79 deletions(-)

diff --git a/source-builder/sb/bootstrap.py b/source-builder/sb/bootstrap.py
index a91130d..ec7d7c3 100644
--- a/source-builder/sb/bootstrap.py
+++ b/source-builder/sb/bootstrap.py
@@ -244,7 +244,7 @@ def run(args):
                     del os.environ['ACLOCAL_PATH']
         optargs = { '--rtems':       'The RTEMS source directory',
                     '--preinstall':  'Preinstall AM generation' }
-        log.notice('RTEMS Source Builder - RTEMS Bootstrap, %s' % (version.str()))
+        log.notice('RTEMS Source Builder - RTEMS Bootstrap, %s' % (version.string()))
         opts = options.load(sys.argv, optargs, logfile = False)
         if opts.get_arg('--rtems'):
             topdir = opts.get_arg('--rtems')
diff --git a/source-builder/sb/build.py b/source-builder/sb/build.py
index d9753cc..ceb179a 100644
--- a/source-builder/sb/build.py
+++ b/source-builder/sb/build.py
@@ -672,7 +672,7 @@ def run(args):
     try:
         optargs = { '--list-configs': 'List available configurations' }
         opts = options.load(args, optargs)
-        log.notice('RTEMS Source Builder, Package Builder, %s' % (version.str()))
+        log.notice('RTEMS Source Builder, Package Builder, %s' % (version.string()))
         opts.log_info()
         if not check.host_setup(opts):
             if not opts.force():
diff --git a/source-builder/sb/check.py b/source-builder/sb/check.py
index ef8f6a4..9e4e953 100644
--- a/source-builder/sb/check.py
+++ b/source-builder/sb/check.py
@@ -264,7 +264,7 @@ def run():
     import sys
     try:
         _opts = options.load(args = sys.argv, logfile = False)
-        log.notice('RTEMS Source Builder - Check, %s' % (version.str()))
+        log.notice('RTEMS Source Builder - Check, %s' % (version.string()))
 
         orphans = _opts.parse_args('--check-orphans', error = False, extra = False)
         if orphans:
diff --git a/source-builder/sb/getsources.py b/source-builder/sb/getsources.py
index e01d8b6..4700036 100644
--- a/source-builder/sb/getsources.py
+++ b/source-builder/sb/getsources.py
@@ -625,7 +625,7 @@ def run(args = sys.argv):
         argopts = argsp.parse_args(args[2:])
 
         load_log(argopts.log)
-        log.notice('RTEMS Source Builder - Get Sources, %s' % (version.str()))
+        log.notice('RTEMS Source Builder - Get Sources, %s' % (version.string()))
         log.tracing = argopts.trace
 
         opts = load_options(args, argopts)
diff --git a/source-builder/sb/options.py b/source-builder/sb/options.py
index fa07c53..7e506b0 100644
--- a/source-builder/sb/options.py
+++ b/source-builder/sb/options.py
@@ -30,12 +30,14 @@ import re
 import os
 import string
 
+import download
 import error
 import execute
 import git
 import log
 import macros
 import path
+import sources
 import sys
 
 import version
@@ -361,7 +363,7 @@ class command_line:
     def sb_released(self):
         if version.released():
             self.defaults['rsb_released'] = '1'
-        self.defaults['rsb_version'] = version.str()
+        self.defaults['rsb_version'] = version.string()
 
     def sb_git(self):
         repo = git.repo(self.defaults.expand('%{_sbdir}'), self)
@@ -599,7 +601,7 @@ class command_line:
             self.args.append('--with-tools=%s' % (rtems_tools[1]))
         rtems_version = self.parse_args('--rtems-version')
         if rtems_version is None:
-            rtems_version = version.version()
+            rtems_version = str(version.version())
         else:
             rtems_version = rtems_version[1]
         self.defaults['rtems_version'] = rtems_version
@@ -701,14 +703,28 @@ def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc', logfile = Tru
     #
     # Load the release settings
     #
-    version.load_release_settings(o.defaults)
-
+    def setting_error(msg):
+        raise error.general(msg)
+    hashes = version.load_release_settings('hashes', error = setting_error)
+    for hash in hashes:
+        hs = hash[1].split()
+        if len(hs) != 2:
+            raise error.general('invalid release hash in VERSION')
+        sources.hash((hs[0], hash[0], hs[1]), o.defaults, setting_error)
+    release_path = version.load_release_setting('version', 'release_path',
+                                                raw = True, error = setting_error)
+    if release_path is not None:
+        try:
+            release_path = ','.join([rp.strip() for rp in release_path.split(',')])
+        except:
+            raise error.general('invalid release path in VERSION')
+        download.set_release_path(release_path, o.defaults)
     return o
 
 def run(args):
     try:
         _opts = load(args = args, defaults = 'defaults.mc')
-        log.notice('RTEMS Source Builder - Defaults, %s' % (version.str()))
+        log.notice('RTEMS Source Builder - Defaults, %s' % (version.string()))
         _opts.log_info()
         log.notice('Options:')
         log.notice(str(_opts))
diff --git a/source-builder/sb/reports.py b/source-builder/sb/reports.py
index 9d3a342..86a4c3a 100644
--- a/source-builder/sb/reports.py
+++ b/source-builder/sb/reports.py
@@ -645,7 +645,7 @@ class report:
         pass
 
     def release_status(self):
-        self.formatter.release_status(version.str())
+        self.formatter.release_status(version.string())
 
     def git_status(self):
         r = git.repo('.', self.opts, self.macros)
@@ -896,7 +896,7 @@ def run(args):
         opts = options.load(args, optargs, logfile = False)
         if opts.get_arg('--output') and len(opts.params()) > 1:
             raise error.general('--output can only be used with a single config')
-        print('RTEMS Source Builder, Reporter, %s' % (version.str()))
+        print('RTEMS Source Builder, Reporter, %s' % (version.string()))
         opts.log_info()
         if not check.host_setup(opts):
             log.warning('forcing build with known host setup problems')
diff --git a/source-builder/sb/rtemsconfig.py b/source-builder/sb/rtemsconfig.py
index 6ac894e..97ede7f 100644
--- a/source-builder/sb/rtemsconfig.py
+++ b/source-builder/sb/rtemsconfig.py
@@ -193,7 +193,7 @@ def run(args):
         bsp = bsp_config(opts, prefix, opts.get_arg('--rtems-bsp')[1])
 
         if opts.get_arg('--list'):
-            log.notice('RTEMS Source Builder - RTEMS Configuration, %s' % (version.str()))
+            log.notice('RTEMS Source Builder - RTEMS Configuration, %s' % (version.string()))
             opts.log_info()
             configs = list(bsp.keys())
             for c in sorted(configs.keys()):
diff --git a/source-builder/sb/setbuilder.py b/source-builder/sb/setbuilder.py
index 3d10d58..09633bd 100644
--- a/source-builder/sb/setbuilder.py
+++ b/source-builder/sb/setbuilder.py
@@ -698,7 +698,7 @@ def run():
             else:
                 mail['to'] = macro_expand(opts.defaults, '%{_mail_tools_to}')
             mail['from'] = mail['mail'].from_address()
-        log.notice('RTEMS Source Builder - Set Builder, %s' % (version.str()))
+        log.notice('RTEMS Source Builder - Set Builder, %s' % (version.string()))
         opts.log_info()
         if not check.host_setup(opts):
             raise error.general('host build environment is not set up correctly')
diff --git a/source-builder/sb/version.py b/source-builder/sb/version.py
index 34fb421..296f717 100644
--- a/source-builder/sb/version.py
+++ b/source-builder/sb/version.py
@@ -1,36 +1,84 @@
 #
 # RTEMS Tools Project (http://www.rtems.org/)
-# Copyright 2010-2016 Chris Johns (chrisj at rtems.org)
+# Copyright 2010-2018 Chris Johns (chrisj at rtems.org)
 # All rights reserved.
 #
 # This file is part of the RTEMS Tools package in 'rtems-tools'.
 #
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
 #
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #
-# To release the RSB create a git archive and then add a suitable VERSION file
-# to the top directory.
+# Releasing RTEMS Tools
+# ---------------------
+#
+# Format:
+#
+#  The format is INI. The file requires a `[version`] section and a `revision`
+#  option:
+#
+#   [version]
+#   revision = <version-string>
+#
+#  The `<version-string>` has the `version` and `revision` delimited by a
+#  single `.`. An example file is:
+#
+#   [version]
+#   revision = 5.0.not_released
+#
+#  where the `version` is `5` and the revision is `0` and the package is not
+#  released. The label `not_released` is reversed to mean the package is not
+#  released. A revision string can contain extra characters after the
+#  `revision` number for example `5.0-rc1` or is deploying a package
+#  `5.0-nasa-cfs`
+#
+#  Packages can optionally add specialised sections to a version configuration
+#  files. These can be accessed via the:
+#
+#   load_release_settings: Return the items in a section
+#   load_release_setting: Return an item from a section
+#
+# User deployment:
+#
+#  Create a git archive and then add a suitable VERSION file to the top
+#  directory of the package. The package assumes your python executable is
+#  location in `bin` directory which is one below the top of the package's
+#  install prefix.
+#
+# Notes:
+#
+#  This module uses os.apth for paths and assumes all paths are in the host
+#  format.
 #
 
 from __future__ import print_function
 
+import os
 import sys
 
-import download
 import error
 import git
 import path
-import sources
 
 #
 # Default to an internal string.
@@ -40,6 +88,7 @@ _revision = 'not_released'
 _version_str = '%s.%s' % (_version, _revision)
 _released = False
 _git = False
+_is_loaded = False
 
 def _top():
     top = path.dirname(sys.argv[0])
@@ -48,84 +97,147 @@ def _top():
     return top
 
 def _load_released_version_config():
+    '''Local worker to load a configuration file.'''
     top = _top()
-    for ver in [top, '..']:
-        if path.exists(path.join(ver, 'VERSION')):
+    for ver in [path.join(top, 'VERSION'),
+                path.join('..', 'VERSION')]:
+        if path.exists(path.join(ver)):
             try:
                 import configparser
             except ImportError:
                 import ConfigParser as configparser
             v = configparser.SafeConfigParser()
             try:
-                v.read(path.join(ver, 'VERSION'))
-            except:
-                raise error.general('Invalid VERSION file')
-            return v
-    return None
+                v.read(path.host(ver))
+            except Exception as e:
+                raise error.general('Invalid version config format: %s: %s' % (ver,
+                                                                               e))
+            return ver, v
+    return None, None
 
 def _load_released_version():
+    '''Load the release data if present. If not found the package is not released.
+
+    A release can be made by adding a file called `VERSION` to the top level
+    directory of a package. This is useful for user deploying a package and
+    making custom releases.
+
+    The RTEMS project reserves the `rtems-version.ini` file for it's
+    releases. This is the base release and should not be touched by users
+    deploying a package.
+
+    '''
+    global _version
+    global _revision
     global _released
     global _version_str
-    v = _load_released_version_config()
-    if v is not None:
-        try:
-            _version_str = v.get('version', 'release')
-        except:
-            raise error.general('Invalid VERSION file')
-        _released = True
+    global _is_loaded
+
+    if not _is_loaded:
+        vc, v = _load_released_version_config()
+        if v is not None:
+            try:
+                ver_str = v.get('version', 'revision')
+            except Exception as e:
+                raise error.general('Invalid version file: %s: %s' % (vc, e))
+            ver_split = ver_str.split('.', 1)
+            if len(ver_split) < 2:
+                raise error.general('Invalid version release value: %s: %s' % (vc,
+                                                                               ver_str))
+            ver = ver_split[0]
+            rev = ver_split[1]
+            try:
+                _version = int(ver)
+            except:
+                raise error.general('Invalid version config value: %s: %s' % (vc,
+                                                                              ver))
+            _revision = rev
+            if 'not_released' not in ver:
+                _released = True
+            _version_str = ver_str
+            _is_loaded = True
     return _released
 
 def _load_git_version():
+    global _version
+    global _revision
     global _git
     global _version_str
-    repo = git.repo(_top())
-    if repo.valid():
-        head = repo.head()
-        if repo.dirty():
-            modified = ' modified'
-        else:
-            modified = ''
-        _version_str = '%s (%s%s)' % (_version, head[0:12], modified)
-        _git = True
+    global _is_loaded
+
+    if not _is_loaded:
+        repo = git.repo(_top())
+        if repo.valid():
+            head = repo.head()
+            if repo.dirty():
+                modified = 'modified'
+                revision_sep = '-'
+                sep = ' '
+            else:
+                modified = ''
+                revision_sep = ''
+                sep = ''
+            _revision = '%s%s%s' % (head[0:12], revision_sep, modified)
+            _version_str = '%s (%s%s%s)' % (_version, head[0:12], sep, modified)
+            _git = True
+            _is_loaded = True
     return _git
 
+def load_release_settings(section, error = False):
+    vc, v = _load_released_version_config()
+    items = []
+    if v is not None:
+        try:
+            items = v.items(section)
+        except Exception as e:
+            if not isinstance(error, bool):
+                error(e)
+            elif error:
+                raise error.general('Invalid config section: %s: %s: %s' % (vc,
+                                                                            section,
+                                                                            e))
+    return items
+
+def load_release_setting(section, option, raw = False, error = False):
+    vc, v = _load_released_version_config()
+    value = None
+    if v is not None:
+        try:
+            value = v.get(section, option, raw = raw)
+        except Exception as e:
+            if not isinstance(error, bool):
+                error(e)
+            elif error:
+                raise error.general('Invalid config section: %s: %s: %s.%s' % (vc,
+                                                                               section,
+                                                                               option,
+                                                                               e))
+    return value
+
 def released():
     return _load_released_version()
 
 def version_control():
     return _load_git_version()
 
-def str():
-    if not _released and not _git:
-        if not _load_released_version():
-            _load_git_version()
+def string():
+    _load_released_version()
+    _load_git_version()
     return _version_str
 
-def load_release_settings(macros):
-    def setting_error(msg):
-        raise error.general(msg)
-
-    if released():
-        v = _load_released_version_config()
-        if v is not None:
-            try:
-                hashes = v.items('hashes')
-            except:
-                hashes = []
-            for hash in hashes:
-                hs = hash[1].split()
-                if len(hs) != 2:
-                    raise error.general('invalid release hash in VERSION')
-                sources.hash((hs[0], hash[0], hs[1]), macros, setting_error)
-            try:
-                release_path = v.get('version', 'release_path', raw = True)
-                release_path = ','.join([rp.strip() for rp in release_path.split(',')])
-            except:
-                release_path = None
-            download.set_release_path(release_path, macros)
-
 def version():
+    _load_released_version()
+    _load_git_version()
     return _version
 
+def revision():
+    _load_released_version()
+    _load_git_version()
+    return _revision
+
 if __name__ == '__main__':
-    print('Version: %s' % (str()))
+    print('Version: %s' % (str(version())))
+    print('Revision: %s' % (str(revision())))
+    print('String: %s' % (string()))
+    if version() == 'undefined':
+        raise Exception('version is undefined')
-- 
2.19.1



More information about the devel mailing list