sb: Align the version processing with rtems-tools.

- 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
This commit is contained in:
Chris Johns
2019-11-17 16:39:43 +11:00
parent f0b0a70a48
commit 5f7c53a7bd
9 changed files with 207 additions and 79 deletions

View File

@@ -244,7 +244,7 @@ def run(args):
del os.environ['ACLOCAL_PATH'] del os.environ['ACLOCAL_PATH']
optargs = { '--rtems': 'The RTEMS source directory', optargs = { '--rtems': 'The RTEMS source directory',
'--preinstall': 'Preinstall AM generation' } '--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) opts = options.load(sys.argv, optargs, logfile = False)
if opts.get_arg('--rtems'): if opts.get_arg('--rtems'):
topdir = opts.get_arg('--rtems') topdir = opts.get_arg('--rtems')

View File

@@ -672,7 +672,7 @@ def run(args):
try: try:
optargs = { '--list-configs': 'List available configurations' } optargs = { '--list-configs': 'List available configurations' }
opts = options.load(args, optargs) 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() opts.log_info()
if not check.host_setup(opts): if not check.host_setup(opts):
if not opts.force(): if not opts.force():

View File

@@ -264,7 +264,7 @@ def run():
import sys import sys
try: try:
_opts = options.load(args = sys.argv, logfile = False) _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) orphans = _opts.parse_args('--check-orphans', error = False, extra = False)
if orphans: if orphans:

View File

@@ -625,7 +625,7 @@ def run(args = sys.argv):
argopts = argsp.parse_args(args[2:]) argopts = argsp.parse_args(args[2:])
load_log(argopts.log) 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 log.tracing = argopts.trace
opts = load_options(args, argopts) opts = load_options(args, argopts)

View File

@@ -30,12 +30,14 @@ import re
import os import os
import string import string
import download
import error import error
import execute import execute
import git import git
import log import log
import macros import macros
import path import path
import sources
import sys import sys
import version import version
@@ -361,7 +363,7 @@ class command_line:
def sb_released(self): def sb_released(self):
if version.released(): if version.released():
self.defaults['rsb_released'] = '1' self.defaults['rsb_released'] = '1'
self.defaults['rsb_version'] = version.str() self.defaults['rsb_version'] = version.string()
def sb_git(self): def sb_git(self):
repo = git.repo(self.defaults.expand('%{_sbdir}'), 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])) self.args.append('--with-tools=%s' % (rtems_tools[1]))
rtems_version = self.parse_args('--rtems-version') rtems_version = self.parse_args('--rtems-version')
if rtems_version is None: if rtems_version is None:
rtems_version = version.version() rtems_version = str(version.version())
else: else:
rtems_version = rtems_version[1] rtems_version = rtems_version[1]
self.defaults['rtems_version'] = rtems_version 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 # 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 return o
def run(args): def run(args):
try: try:
_opts = load(args = args, defaults = 'defaults.mc') _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() _opts.log_info()
log.notice('Options:') log.notice('Options:')
log.notice(str(_opts)) log.notice(str(_opts))

View File

@@ -645,7 +645,7 @@ class report:
pass pass
def release_status(self): def release_status(self):
self.formatter.release_status(version.str()) self.formatter.release_status(version.string())
def git_status(self): def git_status(self):
r = git.repo('.', self.opts, self.macros) r = git.repo('.', self.opts, self.macros)
@@ -896,7 +896,7 @@ def run(args):
opts = options.load(args, optargs, logfile = False) opts = options.load(args, optargs, logfile = False)
if opts.get_arg('--output') and len(opts.params()) > 1: if opts.get_arg('--output') and len(opts.params()) > 1:
raise error.general('--output can only be used with a single config') 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() opts.log_info()
if not check.host_setup(opts): if not check.host_setup(opts):
log.warning('forcing build with known host setup problems') log.warning('forcing build with known host setup problems')

View File

@@ -193,7 +193,7 @@ def run(args):
bsp = bsp_config(opts, prefix, opts.get_arg('--rtems-bsp')[1]) bsp = bsp_config(opts, prefix, opts.get_arg('--rtems-bsp')[1])
if opts.get_arg('--list'): 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() opts.log_info()
configs = list(bsp.keys()) configs = list(bsp.keys())
for c in sorted(configs.keys()): for c in sorted(configs.keys()):

View File

@@ -698,7 +698,7 @@ def run():
else: else:
mail['to'] = macro_expand(opts.defaults, '%{_mail_tools_to}') mail['to'] = macro_expand(opts.defaults, '%{_mail_tools_to}')
mail['from'] = mail['mail'].from_address() 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() opts.log_info()
if not check.host_setup(opts): if not check.host_setup(opts):
raise error.general('host build environment is not set up correctly') raise error.general('host build environment is not set up correctly')

View File

@@ -1,36 +1,84 @@
# #
# RTEMS Tools Project (http://www.rtems.org/) # RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010-2016 Chris Johns (chrisj@rtems.org) # Copyright 2010-2018 Chris Johns (chrisj@rtems.org)
# All rights reserved. # All rights reserved.
# #
# This file is part of the RTEMS Tools package in 'rtems-tools'. # This file is part of the RTEMS Tools package in 'rtems-tools'.
# #
# Permission to use, copy, modify, and/or distribute this software for any # Redistribution and use in source and binary forms, with or without
# purpose with or without fee is hereby granted, provided that the above # modification, are permitted provided that the following conditions are met:
# copyright notice and this permission notice appear in all copies. #
# 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 # Releasing RTEMS Tools
# to the top directory. # ---------------------
#
# 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 from __future__ import print_function
import os
import sys import sys
import download
import error import error
import git import git
import path import path
import sources
# #
# Default to an internal string. # Default to an internal string.
@@ -40,6 +88,7 @@ _revision = 'not_released'
_version_str = '%s.%s' % (_version, _revision) _version_str = '%s.%s' % (_version, _revision)
_released = False _released = False
_git = False _git = False
_is_loaded = False
def _top(): def _top():
top = path.dirname(sys.argv[0]) top = path.dirname(sys.argv[0])
@@ -48,84 +97,147 @@ def _top():
return top return top
def _load_released_version_config(): def _load_released_version_config():
'''Local worker to load a configuration file.'''
top = _top() top = _top()
for ver in [top, '..']: for ver in [path.join(top, 'VERSION'),
if path.exists(path.join(ver, 'VERSION')): path.join('..', 'VERSION')]:
if path.exists(path.join(ver)):
try: try:
import configparser import configparser
except ImportError: except ImportError:
import ConfigParser as configparser import ConfigParser as configparser
v = configparser.SafeConfigParser() v = configparser.SafeConfigParser()
try: try:
v.read(path.join(ver, 'VERSION')) v.read(path.host(ver))
except: except Exception as e:
raise error.general('Invalid VERSION file') raise error.general('Invalid version config format: %s: %s' % (ver,
return v e))
return None return ver, v
return None, None
def _load_released_version(): 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 _released
global _version_str global _version_str
v = _load_released_version_config() global _is_loaded
if v is not None:
try: if not _is_loaded:
_version_str = v.get('version', 'release') vc, v = _load_released_version_config()
except: if v is not None:
raise error.general('Invalid VERSION file') try:
_released = True 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 return _released
def _load_git_version(): def _load_git_version():
global _version
global _revision
global _git global _git
global _version_str global _version_str
repo = git.repo(_top()) global _is_loaded
if repo.valid():
head = repo.head() if not _is_loaded:
if repo.dirty(): repo = git.repo(_top())
modified = ' modified' if repo.valid():
else: head = repo.head()
modified = '' if repo.dirty():
_version_str = '%s (%s%s)' % (_version, head[0:12], modified) modified = 'modified'
_git = True 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 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(): def released():
return _load_released_version() return _load_released_version()
def version_control(): def version_control():
return _load_git_version() return _load_git_version()
def str(): def string():
if not _released and not _git: _load_released_version()
if not _load_released_version(): _load_git_version()
_load_git_version()
return _version_str 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(): def version():
_load_released_version()
_load_git_version()
return _version return _version
def revision():
_load_released_version()
_load_git_version()
return _revision
if __name__ == '__main__': 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')