sb. Add VERSION support for releasing the RSB.

Add support to release the RSB by adding the VERSION file. The file
is a single line with the version.

Fix the reports to include the version. Update the INI file
support to include the details of the build.

Show the GIT or released version when the command starts.

Closes #2480.
This commit is contained in:
Chris Johns 2015-12-03 22:22:17 +11:00
parent 7164e6195f
commit 47d703fd8c
9 changed files with 164 additions and 48 deletions

View File

@ -45,6 +45,9 @@ version: none, none, ''
release: none, none, '' release: none, none, ''
buildname: none, none, '%{name}' buildname: none, none, '%{name}'
# The default is not release.
is_rsb_release: none, none, '0'
# GNU triples needed to build packages # GNU triples needed to build packages
_host: triplet, required, '' _host: triplet, required, ''
_build: triplet, required, '' _build: triplet, required, ''

View File

@ -242,7 +242,7 @@ def run(args):
try: try:
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, v%s' % (version.str())) log.notice('RTEMS Source Builder - RTEMS Bootstrap, %s' % (version.str()))
opts = options.load(sys.argv, optargs) opts = options.load(sys.argv, optargs)
if opts.get_arg('--rtems'): if opts.get_arg('--rtems'):
topdir = opts.get_arg('--rtems') topdir = opts.get_arg('--rtems')

View File

@ -534,7 +534,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 v%s' % (version.str())) log.notice('RTEMS Source Builder, Package Builder, %s' % (version.str()))
if not check.host_setup(opts): if not check.host_setup(opts):
if not opts.force(): if not opts.force():
raise error.general('host build environment is not set up' + raise error.general('host build environment is not set up' +

View File

@ -162,7 +162,7 @@ def run():
import sys import sys
try: try:
_opts = options.load(args = sys.argv) _opts = options.load(args = sys.argv)
log.notice('RTEMS Source Builder - Check, v%s' % (version.str())) log.notice('RTEMS Source Builder - Check, %s' % (version.str()))
if host_setup(_opts): if host_setup(_opts):
print 'Environment is ok' print 'Environment is ok'
else: else:

View File

@ -301,6 +301,12 @@ class command_line:
if path.exists(rsb_macros): if path.exists(rsb_macros):
self.defaults.load(rsb_macros) self.defaults.load(rsb_macros)
def sb_released(self):
if version.released():
self.defaults['is_rsb_released'] = '1'
self.defaults['_sbreleased'] = '1'
self.defaults['_sbversion'] = version.str()
def sb_git(self): def sb_git(self):
repo = git.repo(self.defaults.expand('%{_sbdir}'), self) repo = git.repo(self.defaults.expand('%{_sbdir}'), self)
if repo.valid(): if repo.valid():
@ -613,6 +619,7 @@ def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc'):
for k in overrides: for k in overrides:
o.defaults[k] = overrides[k] o.defaults[k] = overrides[k]
o.sb_released()
o.sb_git() o.sb_git()
o.rtems_options() o.rtems_options()
o.process() o.process()
@ -623,7 +630,7 @@ def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc'):
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, v%s' % (version.str())) log.notice('RTEMS Source Builder - Defaults, %s' % (version.str()))
_opts.log_info() _opts.log_info()
log.notice('Options:') log.notice('Options:')
log.notice(str(_opts)) log.notice(str(_opts))

View File

@ -1,6 +1,6 @@
# #
# RTEMS Tools Project (http://www.rtems.org/) # RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010-2013 Chris Johns (chrisj@rtems.org) # Copyright 2010-2015 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'.
@ -53,6 +53,7 @@ _line_len = 78
_title = 'RTEMS Tools Project <users@rtems.org>' _title = 'RTEMS Tools Project <users@rtems.org>'
_release_status_text = 'RTEMS Source Builder Release'
_git_status_text = 'RTEMS Source Builder Repository Status' _git_status_text = 'RTEMS Source Builder Repository Status'
def _make_path(p, *args): def _make_path(p, *args):
@ -104,7 +105,7 @@ class formatter(object):
def buildset_start(self, nest_level, name): def buildset_start(self, nest_level, name):
self.line('=-' * (_line_len / 2)) self.line('=-' * (_line_len / 2))
self.line('Build Set: %s' % (name)) self.line('Build Set: (%d) %s' % (nest_level, name))
def buildset_end(self, nest_level, name): def buildset_end(self, nest_level, name):
return return
@ -166,6 +167,16 @@ class asciidoc_formatter(formatter):
if intro_text: if intro_text:
self.line('%s' % ('\n'.join(intro_text))) self.line('%s' % ('\n'.join(intro_text)))
def release_status(self, release_string):
self.line('')
self.line("'''")
self.line('')
self.line('.%s' % (_release_status_text))
self.line('*Version*: %s;;' % (release_string))
self.line('')
self.line("'''")
self.line('')
def git_status(self, valid, dirty, head, remotes): def git_status(self, valid, dirty, head, remotes):
self.line('') self.line('')
self.line("'''") self.line("'''")
@ -293,6 +304,14 @@ class text_formatter(formatter):
self.line('=' * _line_len) self.line('=' * _line_len)
self.line('Report: %s' % (name)) self.line('Report: %s' % (name))
def release_status_header(self):
self.line('-' * _line_len)
self.line('%s' % (_release_status_text))
def release_status(self, release_string):
self.release_status_header()
self.line('%s Version: %s' % (self.cini, release_string))
def git_status_header(self): def git_status_header(self):
self.line('-' * _line_len) self.line('-' * _line_len)
self.line('%s' % (_git_status_text)) self.line('%s' % (_git_status_text))
@ -324,6 +343,8 @@ class ini_formatter(text_formatter):
def __init__(self): def __init__(self):
super(ini_formatter, self).__init__() super(ini_formatter, self).__init__()
self.cini = ';' self.cini = ';'
self.ini_pkg = {}
self.name = None
def format(self): def format(self):
return 'ini' return 'ini'
@ -339,25 +360,57 @@ class ini_formatter(text_formatter):
self.line('; %s' % ('\n; '.join(intro_text))) self.line('; %s' % ('\n; '.join(intro_text)))
self.line(';') self.line(';')
def epilogue(self, name):
pkgs = sorted(self.ini_pkg.keys())
for pkg in pkgs:
self.line('')
self.line('[%s]' % (pkg))
items = sorted(self.ini_pkg[pkg].keys())
for item in items:
i = self.ini_pkg[pkg][item]
if len(i) == 1:
self.line('%s = "%s"' % (item, i[0]))
else:
self.line('%s = <<<DATA' % (item))
self.line('\n'.join(i))
self.line('DATA')
self.line('')
def release_status_header(self):
self.line(';')
self.line('; %s' % (_release_status_text))
def git_status_header(self): def git_status_header(self):
self.line(';') self.line(';')
self.line('; %s' % (_git_status_text)) self.line('; %s' % (_git_status_text))
self.line(';') self.line(';')
def config(self, nest_level, name, _config): def config(self, nest_level, name, _config):
return pass
def buildset_start(self, nest_level, name): def buildset_start(self, nest_level, name):
return if name.endswith('.cfg'):
self.name = path.basename(name[:-4])
if self.name not in self.ini_pkg:
self.ini_pkg[self.name] = {}
def buildset_end(self, nest_level, name):
self.name = None
def info(self, nest_level, name, info, separated): def info(self, nest_level, name, info, separated):
return if self.name:
if 'info' not in self.ini_pkg[self.name]:
self.ini_pkg[self.name]['info'] = []
self.ini_pkg[self.name]['info'] += info
def directive(self, nest_level, name, data): def directive(self, nest_level, name, data):
return if self.name:
if name not in self.ini_pkg[self.name]:
self.ini_pkg[self.name][name] = []
self.ini_pkg[self.name][name] += data
def files(self, nest_level, singular, plural, _files): def files(self, nest_level, singular, plural, _files):
return pass
class xml_formatter(formatter): class xml_formatter(formatter):
def __init__(self): def __init__(self):
@ -377,6 +430,11 @@ class xml_formatter(formatter):
def epilogue(self, name): def epilogue(self, name):
self.line('</RTEMSSourceBuilderReport>') self.line('</RTEMSSourceBuilderReport>')
def release_status(self, release_string):
self.line('\t<Release>')
self.line('\t\t<Version>%s</Version>' % (release_string))
self.line('\t</Release>')
def git_status(self, valid, dirty, head, remotes): def git_status(self, valid, dirty, head, remotes):
self.line('\t<Git>') self.line('\t<Git>')
if valid: if valid:
@ -469,7 +527,7 @@ class report:
self.files = { 'buildsets':[], 'configs':[] } self.files = { 'buildsets':[], 'configs':[] }
def output(self, text): def output(self, text):
self.out += text + '\n' self.formatter.line(text)
def is_ini(self): def is_ini(self):
return self.formatter.format() == 'ini' return self.formatter.format() == 'ini'
@ -480,6 +538,9 @@ class report:
def footer(self): def footer(self):
pass pass
def release_status(self):
self.formatter.release_status(version.str())
def git_status(self): def git_status(self):
r = git.repo('.', self.opts, self.macros) r = git.repo('.', self.opts, self.macros)
self.formatter.git_status(r.valid(), r.dirty(), r.head(), r.remotes()) self.formatter.git_status(r.valid(), r.dirty(), r.head(), r.remotes())
@ -487,7 +548,10 @@ class report:
def introduction(self, name, intro_text = None): def introduction(self, name, intro_text = None):
now = datetime.datetime.now().ctime() now = datetime.datetime.now().ctime()
self.formatter.introduction(name, now, intro_text) self.formatter.introduction(name, now, intro_text)
self.git_status() if version.released():
self.release_status()
else:
self.git_status()
def epilogue(self, name): def epilogue(self, name):
self.formatter.epilogue(name) self.formatter.epilogue(name)
@ -504,11 +568,13 @@ class report:
self.formatter.config_end(self.bset_nesting + 1, name) self.formatter.config_end(self.bset_nesting + 1, name)
def buildset_start(self, name): def buildset_start(self, name):
self.bset_nesting += 1
self.files['buildsets'] += [name] self.files['buildsets'] += [name]
self.formatter.buildset_start(self.bset_nesting, name) self.formatter.buildset_start(self.bset_nesting, name)
def buildset_end(self, name): def buildset_end(self, name):
self.formatter.buildset_end(self.bset_nesting, name) self.formatter.buildset_end(self.bset_nesting, name)
self.bset_nesting -= 1
def source(self, macros): def source(self, macros):
def err(msg): def err(msg):
@ -546,6 +612,13 @@ class report:
if directive is not None: if directive is not None:
self.formatter.directive(self.bset_nesting + 2, name, directive) self.formatter.directive(self.bset_nesting + 2, name, directive)
def tree_packages(self, tree, packages = []):
if 'bset' in tree:
for node in sorted(tree['bset'].keys()):
packages += [_tree_name(node)]
packages += self.tree_packages(tree['bset'][node], packages)
return set(packages)
def tree_sources(self, name, tree, sources = []): def tree_sources(self, name, tree, sources = []):
if 'cfg' in tree: if 'cfg' in tree:
packages = {} packages = {}
@ -626,26 +699,6 @@ class report:
prefix_char, prefix_char,
prefix) prefix)
def generate_ini_node(self, name, tree, sections = []):
if name not in sections:
sections += [name]
self.output('')
self.output('[%s]' % (name))
if 'bset' in tree and len(tree['bset']):
self.output(' packages = %s' % \
(', '.join([_tree_name(n) for n in sorted(tree['bset'])])))
if 'cfg' in tree:
packages = {}
if 'sources' in tree['cfg']:
_merge(packages, tree['cfg']['sources'])
if 'patches' in tree['cfg']:
_merge(packages, tree['cfg']['patches'])
for package in packages:
self.output(' %s = %s' % (package, ', '.join([s[0] for s in packages[package]])))
if 'bset' in tree:
for node in sorted(tree['bset'].keys()):
self.generate_ini_node(_tree_name(node), tree['bset'][node], sections)
def generate_ini_source(self, sources): def generate_ini_source(self, sources):
self.output('') self.output('')
self.output('[source]') self.output('[source]')
@ -664,7 +717,6 @@ class report:
self.output(' %s = %s' % (source[0], hash)) self.output(' %s = %s' % (source[0], hash))
def generate_ini(self): def generate_ini(self):
#self.output(pp.pformat(self.tree))
nodes = sorted([node for node in self.tree.keys() if node != 'bset']) nodes = sorted([node for node in self.tree.keys() if node != 'bset'])
self.output(';') self.output(';')
self.output('; Configuration Tree:') self.output('; Configuration Tree:')
@ -681,13 +733,9 @@ class report:
sources = sorted(set(sources)) sources = sorted(set(sources))
self.generate_ini_source(sources) self.generate_ini_source(sources)
self.generate_ini_hash(sources) self.generate_ini_hash(sources)
for node in nodes:
self.generate_ini_node(_tree_name(node), self.tree[node])
def write(self, name): def write(self, name):
self.out = self.formatter.post_process() self.out = self.formatter.post_process()
if self.is_ini():
self.generate_ini()
if name is not None: if name is not None:
try: try:
o = open(path.host(name), "w") o = open(path.host(name), "w")
@ -698,7 +746,6 @@ class report:
raise error.general('writing output file: %s: %s' % (name, err)) raise error.general('writing output file: %s: %s' % (name, err))
def generate(self, name, tree = None, opts = None, macros = None): def generate(self, name, tree = None, opts = None, macros = None):
self.bset_nesting += 1
self.buildset_start(name) self.buildset_start(name)
if tree is None: if tree is None:
tree = self.tree tree = self.tree
@ -715,16 +762,19 @@ class report:
if c.endswith('.bset'): if c.endswith('.bset'):
self.generate(c, tree[name]['bset'], bset.opts, macros) self.generate(c, tree[name]['bset'], bset.opts, macros)
elif c.endswith('.cfg'): elif c.endswith('.cfg'):
self.buildset_start(c)
self.config(config.file(c, bset.opts, macros), self.config(config.file(c, bset.opts, macros),
tree[name]['cfg'], bset.opts, macros) tree[name]['cfg'], bset.opts, macros)
self.buildset_end(c)
else: else:
raise error.general('invalid config type: %s' % (c)) raise error.general('invalid config type: %s' % (c))
self.buildset_end(name) self.buildset_end(name)
self.bset_nesting -= 1
def create(self, inname, outname = None, intro_text = None): def create(self, inname, outname = None, intro_text = None):
self.introduction(inname, intro_text) self.introduction(inname, intro_text)
self.generate(inname) self.generate(inname)
if self.is_ini():
self.generate_ini()
self.epilogue(inname) self.epilogue(inname)
self.write(outname) self.write(outname)
@ -737,7 +787,7 @@ def run(args):
opts = options.load(args, optargs) opts = options.load(args, optargs)
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 v%s' % (version.str()) print 'RTEMS Source Builder, Reporter, %s' % (version.str())
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

@ -191,7 +191,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, v%s' % (version.str())) log.notice('RTEMS Source Builder - RTEMS Configuration, %s' % (version.str()))
opts.log_info() opts.log_info()
configs = bsp.keys() configs = bsp.keys()
for c in sorted(configs.keys()): for c in sorted(configs.keys()):

View File

@ -468,7 +468,7 @@ def run():
'--report-format': 'The report format (text, html, asciidoc).' } '--report-format': 'The report format (text, html, asciidoc).' }
mailer.append_options(optargs) mailer.append_options(optargs)
opts = options.load(sys.argv, optargs) opts = options.load(sys.argv, optargs)
log.notice('RTEMS Source Builder - Set Builder, v%s' % (version.str())) log.notice('RTEMS Source Builder - Set Builder, %s' % (version.str()))
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,6 +1,6 @@
# #
# RTEMS Tools Project (http://www.rtems.org/) # RTEMS Tools Project (http://www.rtems.org/)
# Copyright 2010-2014 Chris Johns (chrisj@rtems.org) # Copyright 2010-2015 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'.
@ -18,17 +18,73 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# #
# Manage paths locally. The internally the path is in Unix or shell format and # To release the RSB create a git archive and then add a suitable VERSION file
# we convert to the native format when performing operations at the Python # to the top directory.
# level. This allows macro expansion to work.
# #
import sys
import error
import git
import path
major = 4 major = 4
minor = 11 minor = 11
revision = 0 revision = 0
#
# Default to an internal string.
#
_version_str = '%d.%d.%d' % (major, minor, revision)
_released = False
_git = False
def _top():
top = path.dirname(sys.argv[0])
if len(top) == 0:
top = '.'
return top
def _load_released_version():
global _released
global _version_str
top = _top()
for ver in [top, '..']:
if path.exists(path.join(ver, 'VERSION')):
try:
with open(path.join(ver, 'VERSION')) as v:
_version_str = v.readline().strip()
v.close()
_released = True
except:
raise error.general('Cannot access the VERSION file')
return _released
def _load_git_version():
global _git
global _version_str
repo = git.repo(_top())
if repo.valid():
head = repo.head()
if repo.dirty():
modified = ' modified'
else:
modified = ''
_version_str = '%d.%d.%d (%s%s)' % (major, minor, revision, head[0:12], modified)
_git = True
return _git
def released():
return _load_released_version()
def version_control():
return _load_git_version()
def str(): def str():
return '%d.%d.%d'% (major, minor, revision) if not _released and not _git:
if not _load_released_version():
_load_git_version()
return _version_str
if __name__ == '__main__': if __name__ == '__main__':
print 'major = %d' % (major) print 'major = %d' % (major)