source: rtems-source-builder/source-builder/sb/reports.py @ 0d59530

4.11
Last change on this file since 0d59530 was ce60578, checked in by Chris Johns <chrisj@…>, on 05/21/15 at 11:49:25

sb: Fix reporting and installing the reports when building.

Switch the default report to text format.
Fix the report to support the set builder.

  • Property mode set to 100644
File size: 26.9 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2013 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# Permission to use, copy, modify, and/or distribute this software for any
9# purpose with or without fee is hereby granted, provided that the above
10# copyright notice and this permission notice appear in all copies.
11#
12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#
21# This code builds a package given a config file. It only builds to be
22# installed not to be package unless you run a packager around this.
23#
24
25import copy
26import datetime
27import os
28import sys
29
30import pprint
31pp = pprint.PrettyPrinter(indent = 2)
32
33try:
34    import build
35    import check
36    import config
37    import error
38    import git
39    import log
40    import options
41    import path
42    import setbuilder
43    import sources
44    import version
45except KeyboardInterrupt:
46    print 'user terminated'
47    sys.exit(1)
48except:
49    print 'error: unknown application load error'
50    sys.exit(1)
51
52_line_len = 78
53
54_title = 'RTEMS Tools Project <users@rtems.org>'
55
56_git_status_text = 'RTEMS Source Builder Repository Status'
57
58def _make_path(p, *args):
59    for arg in args:
60        p = path.join(p, arg)
61    return os.path.abspath(path.host(p))
62
63class formatter(object):
64    def __init__(self):
65        self.content = ''
66
67    def line(self, text):
68        self.content += text + '\n'
69
70    def add(self, text):
71        self.content += text
72
73    def set_sbpath(self, sbpath):
74        self.sbpath = sbpath
75
76    def format(self):
77        raise error.general('internal error: formatter.format() not implemented')
78
79    def ext(self):
80        raise error.general('internal error: formatter.ext() not implemented')
81
82    def introduction(self, name, now, intro_text):
83        self.line('=' * _line_len)
84        self.line('%s %s' % (_title, now))
85        if intro_text:
86            self.line('')
87            self.line('%s' % ('\n'.join(intro_text)))
88        self.line('=' * _line_len)
89        self.line('Report: %s' % (name))
90
91    def epilogue(self, name):
92        return
93
94    def config_start(self, nest_level, name):
95        return
96
97    def config(self, nest_level, name, _config):
98        self.line('-' * _line_len)
99        self.line('Package: %s' % (name))
100        self.line(' Config: %s' % (_config.file_name()))
101
102    def config_end(self, nest_level, name):
103        return
104
105    def buildset_start(self, nest_level, name):
106        self.line('=-' * (_line_len / 2))
107        self.line('Build Set: %s' % (name))
108
109    def buildset_end(self, nest_level, name):
110        return
111
112    def info(self, nest_level, name, info, separated):
113        self.line(' ' + name + ':')
114        for l in info:
115            self.line('  ' + l)
116
117    def directive(self, nest_level, name, data):
118        self.line(' %s:' % (name))
119        for l in data:
120            self.line('  ' + l)
121
122    def files(self, nest_level, sigular, plural, _files):
123        self.line('  ' + plural + ': %d' % (len(_files)))
124        i = 0
125        for name in _files:
126            for s in _files[name]:
127                i += 1
128                self.line('   %2d: %s' % (i, s[0]))
129                if s[1] is None:
130                    h = 'No checksum'
131                else:
132                    hash = s[1].split()
133                    h = '%s: %s' % (hash[0], hash[1])
134                self.line('       %s' % (h))
135
136    def post_process(self):
137        return self.content
138
139class asciidoc_formatter(formatter):
140    def __init__(self):
141        super(asciidoc_formatter, self).__init__()
142
143    def format(self):
144        return 'asciidoc'
145
146    def ext(self):
147        return '.txt'
148
149    def introduction(self, name, now, intro_text):
150        h = 'RTEMS Source Builder Report'
151        self.line(h)
152        self.line('=' * len(h))
153        self.line(':doctype: book')
154        self.line(':toc2:')
155        self.line(':toclevels: 5')
156        self.line(':icons:')
157        self.line(':numbered:')
158        self.line(':data-uri:')
159        self.line('')
160        self.line(_title)
161        self.line(now)
162        self.line('')
163        image = _make_path(self.sbpath, options.basepath, 'images', 'rtemswhitebg.jpg')
164        self.line('image:%s["RTEMS",width="20%%"]' % (image))
165        self.line('')
166        if intro_text:
167            self.line('%s' % ('\n'.join(intro_text)))
168
169    def git_status(self, valid, dirty, head, remotes):
170        self.line('')
171        self.line("'''")
172        self.line('')
173        self.line('.%s' % (_git_status_text))
174        if valid:
175            self.line('*Remotes*:;;')
176            for r in remotes:
177                if 'url' in remotes[r]:
178                    text = remotes[r]['url']
179                else:
180                    text = 'no URL found'
181                text = '%s: %s' % (r, text)
182                self.line('. %s' % (text))
183            self.line('*Status*:;;')
184            if dirty:
185                self.line('_Repository is dirty_')
186            else:
187                self.line('Clean')
188            self.line('*Head*:;;')
189            self.line('Commit: %s' % (head))
190        else:
191            self.line('_Not a valid GIT repository_')
192        self.line('')
193        self.line("'''")
194        self.line('')
195
196    def config(self, nest_level, name, _config):
197        self.line('*Package*: _%s_ +' % (name))
198        self.line('*Config*: %s' % (_config.file_name()))
199        self.line('')
200
201    def config_end(self, nest_level, name):
202        self.line('')
203        self.line("'''")
204        self.line('')
205
206    def buildset_start(self, nest_level, name):
207        h = '%s' % (name)
208        self.line('=%s %s' % ('=' * nest_level, h))
209
210    def info(self, nest_level, name, info, separated):
211        end = ''
212        if separated:
213            self.line('*%s:*::' % (name))
214            self.line('')
215        else:
216            self.line('*%s:* ' % (name))
217            end = ' +'
218        spaces = ''
219        for l in info:
220            self.line('%s%s%s' % (spaces, l, end))
221        if separated:
222            self.line('')
223
224    def directive(self, nest_level, name, data):
225        self.line('')
226        self.line('*%s*:' % (name))
227        self.line('--------------------------------------------')
228        for l in data:
229            self.line(l)
230        self.line('--------------------------------------------')
231
232    def files(self, nest_level, singular, plural, _files):
233        self.line('')
234        self.line('*' + plural + ':*::')
235        if len(_files) == 0:
236            self.line('No ' + plural.lower())
237        for name in _files:
238            for s in _files[name]:
239                self.line('. %s' % (s[0]))
240                if s[1] is None:
241                    h = 'No checksum'
242                else:
243                    hash = s[1].split()
244                    h = '%s: %s' % (hash[0], hash[1])
245                self.line('+\n%s\n' % (h))
246
247class html_formatter(asciidoc_formatter):
248    def __init__(self):
249        super(html_formatter, self).__init__()
250
251    def format(self):
252        return 'html'
253
254    def ext(self):
255        return '.html'
256
257    def post_process(self):
258        import StringIO
259        infile = StringIO.StringIO(self.content)
260        outfile = StringIO.StringIO()
261        try:
262            import asciidocapi
263        except:
264            raise error.general('installation error: no asciidocapi found')
265        asciidoc_py = _make_path(self.sbpath, options.basepath, 'asciidoc', 'asciidoc.py')
266        try:
267            asciidoc = asciidocapi.AsciiDocAPI(asciidoc_py)
268        except:
269            raise error.general('application error: asciidocapi failed')
270        asciidoc.execute(infile, outfile)
271        out = outfile.getvalue()
272        infile.close()
273        outfile.close()
274        return out
275
276class text_formatter(formatter):
277    def __init__(self):
278        super(text_formatter, self).__init__()
279        self.cini = ''
280
281    def format(self):
282        return 'text'
283
284    def ext(self):
285        return '.txt'
286
287    def introduction(self, name, now, intro_text):
288        self.line('=' * _line_len)
289        self.line('%s %s' % (_title, now))
290        if intro_text:
291            self.line('')
292            self.line('%s' % ('\n'.join(intro_text)))
293        self.line('=' * _line_len)
294        self.line('Report: %s' % (name))
295
296    def git_status_header(self):
297        self.line('-' * _line_len)
298        self.line('%s' % (_git_status_text))
299
300    def git_status(self, valid, dirty, head, remotes):
301        self.git_status_header()
302        if valid:
303            self.line('%s Remotes:' % (self.cini))
304            rc = 0
305            for r in remotes:
306                rc += 1
307                if 'url' in remotes[r]:
308                    text = remotes[r]['url']
309                else:
310                    text = 'no URL found'
311                text = '%s: %s' % (r, text)
312                self.line('%s  %2d: %s' % (self.cini, rc, text))
313            self.line('%s Status:' % (self.cini))
314            if dirty:
315                self.line('%s  Repository is dirty' % (self.cini))
316            else:
317                self.line('%s  Clean' % (self.cini))
318            self.line('%s Head:' % (self.cini))
319            self.line('%s  Commit: %s' % (self.cini, head))
320        else:
321            self.line('%s Not a valid GIT repository' % (self.cini))
322
323class ini_formatter(text_formatter):
324    def __init__(self):
325        super(ini_formatter, self).__init__()
326        self.cini = ';'
327
328    def format(self):
329        return 'ini'
330
331    def ext(self):
332        return '.ini'
333
334    def introduction(self, name, now, intro_text):
335        self.line(';')
336        self.line('; %s %s' % (_title, now))
337        if intro_text:
338            self.line(';')
339            self.line('; %s' % ('\n; '.join(intro_text)))
340            self.line(';')
341
342    def git_status_header(self):
343        self.line(';')
344        self.line('; %s' % (_git_status_text))
345        self.line(';')
346
347    def config(self, nest_level, name, _config):
348        return
349
350    def buildset_start(self, nest_level, name):
351        return
352
353    def info(self, nest_level, name, info, separated):
354        return
355
356    def directive(self, nest_level, name, data):
357        return
358
359    def files(self, nest_level, singular, plural, _files):
360        return
361
362class xml_formatter(formatter):
363    def __init__(self):
364        super(xml_formatter, self).__init__()
365
366    def format(self):
367        return 'xml'
368
369    def ext(self):
370        return '.xml'
371
372    def introduction(self, name, now, intro_text):
373        self.line('<RTEMSSourceBuilderReport>')
374        if intro_text:
375            self.line('\t<Introduction>%s</Introduction>' % (intro_text))
376
377    def epilogue(self, name):
378        self.line('</RTEMSSourceBuilderReport>')
379
380    def git_status(self, valid, dirty, head, remotes):
381        self.line('\t<Git>')
382        if valid:
383            if dirty:
384                self.line('\t\t<Status>dirty</Status>')
385            else:
386                self.line('\t\t<Status>clean</Status>')
387            self.line('\t\t<Commit>' + head + '</Commit>')
388        else:
389            self.line('\t\t<Status>invalid</Status>')
390        self.line('\t</Git>')
391
392    def config_start(self, nest_level, name):
393        self.line('\t' * nest_level + '<Package name="' + name + '">')
394
395    def config(self, nest_level, name, _config):
396        self.line('\t' * nest_level + '<Config>' + _config.file_name() + '</Config>')
397
398    def config_end(self, nest_level, name):
399        self.line('\t' * nest_level + '</Package>')
400
401    def buildset_start(self, nest_level, name):
402        self.line('\t' * nest_level + '<BuildSet name="' + name + '">')
403
404    def buildset_end(self, nest_level, name):
405        self.line('\t' * nest_level + '</BuildSet>')
406
407    def info(self, nest_level, name, info, separated):
408        self.add('\t' * nest_level + '<' + name.replace(' ', '') + '>')
409        for l in info:
410            self.add(l)
411        self.line('</' + name + '>')
412
413    def directive(self, nest_level, name, data):
414        self.line('\t' * nest_level + '<' + name + '><![CDATA[')
415        for l in data:
416            self.line(l.replace(']]>', ']]]><![CDATA[]>'))
417        self.line(']]></' + name + '>')
418
419    def files(self, nest_level, sigular, plural, _files):
420        for name in _files:
421            for s in _files[name]:
422                self.add('\t' * nest_level + '<' + sigular)
423                if not (s[1] is None):
424                    hash = s[1].split()
425                    self.add(' ' + hash[0] + '="' + hash[1] + '"')
426                self.line('>' + s[0] + '</' + sigular + '>')
427
428def _tree_name(path_):
429    return path.splitext(path.basename(path_))[0]
430
431def _merge(_dict, new):
432    new = copy.deepcopy(new)
433    for i in new:
434        if i not in _dict:
435            _dict[i] = new[i]
436        else:
437            _dict[i] += new[i]
438
439class report:
440    """Report the build details about a package given a config file."""
441
442    def __init__(self, formatter, _configs, opts, macros = None):
443        if type(formatter) == str:
444            if formatter == 'text':
445                self.formatter = text_formatter()
446            elif formatter == 'asciidoc':
447                self.formatter = asciidoc_formatter()
448            elif formatter == 'html':
449                self.formatter = html_formatter()
450            elif formatter == 'ini':
451                self.formatter = ini_formatter()
452            elif formatter == 'xml':
453                self.formatter = xml_formatter()
454            else:
455                raise error.general('invalid format: %s' % (formatter))
456        else:
457            self.formatter = formatter
458        self.configs = _configs
459        self.opts = opts
460        if macros is None:
461            self.macros = opts.defaults
462        else:
463            self.macros = macros
464        self.sbpath = self.macros.expand('%{_sbdir}')
465        self.formatter.set_sbpath(self.sbpath)
466        self.bset_nesting = 0
467        self.out = ''
468        self.tree = {}
469        self.files = { 'buildsets':[], 'configs':[] }
470
471    def output(self, text):
472        self.out += text + '\n'
473
474    def is_ini(self):
475        return self.formatter.format() == 'ini'
476
477    def header(self):
478        pass
479
480    def footer(self):
481        pass
482
483    def git_status(self):
484        r = git.repo('.', self.opts, self.macros)
485        self.formatter.git_status(r.valid(), r.dirty(), r.head(), r.remotes())
486
487    def introduction(self, name, intro_text = None):
488        now = datetime.datetime.now().ctime()
489        self.formatter.introduction(name, now, intro_text)
490        self.git_status()
491
492    def epilogue(self, name):
493        self.formatter.epilogue(name)
494
495    def config_start(self, name, _config):
496        self.files['configs'] += [name]
497        for cf in _config.includes():
498            cfbn = path.basename(cf)
499            if cfbn not in self.files['configs']:
500                self.files['configs'] += [cfbn]
501        self.formatter.config_start(self.bset_nesting + 1, name)
502
503    def config_end(self, name, _config):
504        self.formatter.config_end(self.bset_nesting + 1, name)
505
506    def buildset_start(self, name):
507        self.files['buildsets'] += [name]
508        self.formatter.buildset_start(self.bset_nesting, name)
509
510    def buildset_end(self, name):
511        self.formatter.buildset_end(self.bset_nesting, name)
512
513    def source(self, macros):
514        def err(msg):
515            raise error.general('%s' % (msg))
516        _srcs = {}
517        for p in sources.get_source_names(macros, err):
518            if 'setup' in sources.get_source_keys(p, macros, err):
519                _srcs[p] = \
520                    [s for s in sources.get_sources(p, macros, err) if not s.startswith('%setup')]
521                _srcs[p] = [macros.expand(s) for s in _srcs[p]]
522        srcs = {}
523        for p in _srcs:
524            srcs[p] = [(s, sources.get_hash(path.basename(s).lower(), macros)) for s in _srcs[p]]
525        return srcs
526
527    def patch(self, macros):
528        def err(msg):
529            raise error.general('%s' % (msg))
530        _patches = {}
531        for n in sources.get_patch_names(macros, err):
532            if 'setup' in sources.get_patch_keys(n, macros, err):
533                _patches[n] = \
534                    [p for p in sources.get_patches(n, macros, err) if not p.startswith('%setup')]
535                _patches[n] = [macros.expand(p.split()[-1]) for p in _patches[n]]
536        patches = {}
537        for n in _patches:
538            patches[n] = [(p, sources.get_hash(path.basename(p).lower(), macros)) for p in _patches[n]]
539        return patches
540
541    def output_info(self, name, info, separated = False):
542        if info is not None:
543            self.formatter.info(self.bset_nesting + 2, name, info, separated)
544
545    def output_directive(self, name, directive):
546        if directive is not None:
547            self.formatter.directive(self.bset_nesting + 2, name, directive)
548
549    def tree_sources(self, name, tree, sources = []):
550        if 'cfg' in tree:
551            packages = {}
552            if 'sources' in tree['cfg']:
553                _merge(packages, tree['cfg']['sources'])
554            if 'patches' in tree['cfg']:
555                _merge(packages, tree['cfg']['patches'])
556            for package in packages:
557                for source in packages[package]:
558                    if not source[0].startswith('git') and not source[0].startswith('cvs'):
559                        sources += [(path.basename(source[0]), source[0], source[1])]
560        if 'bset' in tree:
561            for node in sorted(tree['bset'].keys()):
562                self.tree_sources(_tree_name(node), tree['bset'][node], sources)
563        return sources
564
565    def config(self, _config, tree, opts, macros):
566        packages = _config.packages()
567        package = packages['main']
568        name = package.name()
569        if len(name) == 0:
570            return
571        sources = self.source(macros)
572        patches = self.patch(macros)
573        if tree is not None:
574            tree['file'] += [_config.file_name()]
575            if len(sources):
576                if 'sources' in tree:
577                    tree['sources'] = dict(tree['sources'].items() + sources.items())
578                else:
579                    tree['sources'] = sources
580            if len(patches):
581                if 'patches' in tree:
582                    tree['patches'] = dict(tree['patches'].items() + patches.items())
583                else:
584                    tree['patches'] = patches
585        self.config_start(name, _config)
586        self.formatter.config(self.bset_nesting + 2, name, _config)
587        self.output_info('Summary', package.get_info('summary'), True)
588        self.output_info('URL', package.get_info('url'))
589        self.output_info('Version', package.get_info('version'))
590        self.output_info('Release', package.get_info('release'))
591        self.output_info('Build Arch', package.get_info('buildarch'))
592        self.formatter.files(self.bset_nesting + 2, "Source", "Sources", sources)
593        self.formatter.files(self.bset_nesting + 2, "Patch", "Patches", patches)
594        self.output_directive('Preparation', package.prep())
595        self.output_directive('Build', package.build())
596        self.output_directive('Install', package.install())
597        self.output_directive('Clean', package.clean())
598        self.config_end(name, _config)
599
600    def generate_ini_tree(self, name, tree, prefix_char, prefix = ''):
601        if prefix_char == '|':
602            c = '|'
603        else:
604            c = '+'
605        self.output('; %s  %s- %s' % (prefix, c, name))
606        prefix += '  %s ' % (prefix_char)
607        if 'cfg' in tree:
608            files = sorted(tree['cfg']['file'])
609            if len(files):
610                for f in range(0, len(files) - 1):
611                    self.output('; %s  |- %s' % (prefix, files[f]))
612                if 'bset' in tree and len(tree['bset'].keys()):
613                    c = '|'
614                else:
615                    c = '+'
616                self.output('; %s  %s- %s' % (prefix, c, files[f + 1]))
617        if 'bset' in tree:
618            nodes = sorted(tree['bset'].keys())
619            for node in range(0, len(nodes)):
620                if node == len(nodes) - 1:
621                    prefix_char = ' '
622                else:
623                    prefix_char = '|'
624                self.generate_ini_tree(nodes[node],
625                                       tree['bset'][nodes[node]],
626                                       prefix_char,
627                                       prefix)
628
629    def generate_ini_node(self, name, tree, sections = []):
630        if name not in sections:
631            sections += [name]
632            self.output('')
633            self.output('[%s]' % (name))
634            if 'bset' in tree and len(tree['bset']):
635                self.output(' packages = %s' % \
636                                (', '.join([_tree_name(n) for n in sorted(tree['bset'])])))
637            if 'cfg' in tree:
638                packages = {}
639                if 'sources' in tree['cfg']:
640                    _merge(packages, tree['cfg']['sources'])
641                if 'patches' in tree['cfg']:
642                    _merge(packages, tree['cfg']['patches'])
643                for package in packages:
644                    self.output(' %s = %s' % (package, ', '.join([s[0] for s in packages[package]])))
645            if 'bset' in tree:
646                for node in sorted(tree['bset'].keys()):
647                    self.generate_ini_node(_tree_name(node), tree['bset'][node], sections)
648
649    def generate_ini_source(self, sources):
650        self.output('')
651        self.output('[source]')
652        for source in sources:
653            self.output(' %s = %s' % (source[0], source[1]))
654
655    def generate_ini_hash(self, sources):
656        self.output('')
657        self.output('[hash]')
658        for source in sources:
659            if source[2] is None:
660                hash = ''
661            else:
662                hash = source[2].split()
663                hash = '%s:%s' % (hash[0], hash[1])
664            self.output(' %s = %s' % (source[0], hash))
665
666    def generate_ini(self):
667        #self.output(pp.pformat(self.tree))
668        nodes = sorted([node for node in self.tree.keys() if node != 'bset'])
669        self.output(';')
670        self.output('; Configuration Tree:')
671        for node in range(0, len(nodes)):
672            if node == len(nodes) - 1:
673                prefix_char = ' '
674            else:
675                prefix_char = '|'
676            self.generate_ini_tree(nodes[node], self.tree[nodes[node]], prefix_char)
677        self.output(';')
678        sources = []
679        for node in nodes:
680            sources += self.tree_sources(_tree_name(node), self.tree[node])
681        sources = sorted(set(sources))
682        self.generate_ini_source(sources)
683        self.generate_ini_hash(sources)
684        for node in nodes:
685            self.generate_ini_node(_tree_name(node), self.tree[node])
686
687    def write(self, name):
688        self.out = self.formatter.post_process()
689        if self.is_ini():
690            self.generate_ini()
691        if name is not None:
692            try:
693                o = open(path.host(name), "w")
694                o.write(self.out)
695                o.close()
696                del o
697            except IOError, err:
698                raise error.general('writing output file: %s: %s' % (name, err))
699
700    def generate(self, name, tree = None, opts = None, macros = None):
701        self.bset_nesting += 1
702        self.buildset_start(name)
703        if tree is None:
704            tree = self.tree
705        if opts is None:
706            opts = self.opts
707        if macros is None:
708            macros = self.macros
709        bset = setbuilder.buildset(name, self.configs, opts, macros)
710        if name in tree:
711            raise error.general('duplicate build set in tree: %s' % (name))
712        tree[name] = { 'bset': { }, 'cfg': { 'file': []  } }
713        for c in bset.load():
714            macros = copy.copy(bset.macros)
715            if c.endswith('.bset'):
716                self.generate(c, tree[name]['bset'], bset.opts, macros)
717            elif c.endswith('.cfg'):
718                self.config(config.file(c, bset.opts, macros),
719                            tree[name]['cfg'], bset.opts, macros)
720            else:
721                raise error.general('invalid config type: %s' % (c))
722        self.buildset_end(name)
723        self.bset_nesting -= 1
724
725    def create(self, inname, outname = None, intro_text = None):
726        self.introduction(inname, intro_text)
727        self.generate(inname)
728        self.epilogue(inname)
729        self.write(outname)
730
731def run(args):
732    try:
733        optargs = { '--list-bsets':   'List available build sets',
734                    '--list-configs': 'List available configurations',
735                    '--format':       'Output format (text, html, asciidoc, ini, xml)',
736                    '--output':       'File name to output the report' }
737        opts = options.load(args, optargs)
738        if opts.get_arg('--output') and len(opts.params()) > 1:
739            raise error.general('--output can only be used with a single config')
740        print 'RTEMS Source Builder, Reporter v%s' % (version.str())
741        opts.log_info()
742        if not check.host_setup(opts):
743            log.warning('forcing build with known host setup problems')
744        configs = build.get_configs(opts)
745        if not setbuilder.list_bset_cfg_files(opts, configs):
746            output = opts.get_arg('--output')
747            if output is not None:
748                output = output[1]
749            formatter = text_formatter()
750            format_opt = opts.get_arg('--format')
751            if format_opt:
752                if len(format_opt) != 2:
753                    raise error.general('invalid format option: %s' % ('='.join(format_opt)))
754                if format_opt[1] == 'text':
755                    pass
756                elif format_opt[1] == 'asciidoc':
757                    formatter = asciidoc_formatter()
758                elif format_opt[1] == 'html':
759                    formatter = html_formatter()
760                elif format_opt[1] == 'ini':
761                    formatter = ini_formatter()
762                elif format_opt[1] == 'xml':
763                    formatter = xml_formatter()
764                else:
765                    raise error.general('invalid format: %s' % (format_opt[1]))
766            r = report(formatter, configs, opts)
767            for _config in opts.params():
768                if output is None:
769                    outname = path.splitext(_config)[0] + formatter.ext()
770                    outname = outname.replace('/', '-')
771                else:
772                    outname = output
773                config = build.find_config(_config, configs)
774                if config is None:
775                    raise error.general('config file not found: %s' % (inname))
776                r.create(config, outname)
777            del r
778        else:
779            raise error.general('invalid config type: %s' % (config))
780    except error.general, gerr:
781        print gerr
782        sys.exit(1)
783    except error.internal, ierr:
784        print ierr
785        sys.exit(1)
786    except error.exit, eerr:
787        pass
788    except KeyboardInterrupt:
789        log.notice('abort: user terminated')
790        sys.exit(1)
791    sys.exit(0)
792
793if __name__ == "__main__":
794    run(sys.argv)
Note: See TracBrowser for help on using the repository browser.