configurable config file lookup path
authorTimo Savola <tsavola@movial.fi>
Wed, 30 Apr 2008 09:53:41 +0000 (12:53 +0300)
committerTimo Savola <tsavola@movial.fi>
Wed, 30 Apr 2008 09:59:05 +0000 (12:59 +0300)
config.confdirs lists directories to look for parse()'d files (last will
be searched first).  --confdir command-line option can be used to append
directories (it obviously takes effect before parsing any config files).
the top-level directory is always last on the search path.

parse() now takes a glob-pattern.

matrix/config.py
matrix/matrix.py

index 45d1c82..e642e1e 100644 (file)
@@ -2,7 +2,14 @@
 # Authors: Timo Savola <tsavola@movial.fi>
 #          Kalle Vahlman <kalle.vahlman@movial.fi>
 
-import os
+import sre
+from glob import glob
+from os import getenv
+from os.path import basename, exists, isabs, join
+
+Error = RuntimeError
+
+exclude = sre.compile(r'^[.#].*|.*[~#]$')
 
 class Board(object):
        def __init__(self, name, arch, gcc_march,
@@ -38,38 +45,44 @@ def PlatformProvidedComponent(*args, **kwargs):
        config.components[c.name] = c
        return c
 
-def parse(name, required=False):
-       if os.path.isabs(name):
-               path = os.path.join(config.top_dir, name)
+def parse(pattern, required=False):
+       if isabs(pattern):
+               dirs = [None]
        else:
-               path = name
+               dirs = [join(config.top_dir, dir) for dir in config.confdirs]
+               dirs.insert(0, config.top_dir)
+
+       paths = {}
+       for dir in dirs:
+               for path in glob(join(dir, pattern)):
+                       name = basename(path)
+                       if not exclude.match(name):
+                               paths[name] = path
+
+       names = paths.keys()
+       names.sort()
+       for name in names:
+               path = paths[name]
 
-       if os.path.exists(path):
                if config.debug:
                        print 'Parsing', path
 
                execfile(path, actions, config.__dict__)
-       else:
-               msg = 'Config file not found: %s' % name
+
+       if not paths:
+               msg = 'Config file(s) not found: %s' % pattern
                if required:
-                       raise RuntimeError(msg)
+                       raise Error(msg)
                elif config.debug:
                        print msg
 
-actions = dict(
-       Board = Board,
-       Component = Component,
-       PlatformProvidedComponent = PlatformProvidedComponent,
-       parse = parse,
-)
-
 class Config(object):
        def __init__(self):
-               self.top_dir = os.environ.get('MATRIX_TOPDIR', '')
-
-               __cache_dir = os.path.join(self.top_dir, 'build-cache')
-               self.cache_dir = os.environ.get('MATRIX_CACHEDIR', __cache_dir)
+               self.confdirs = []
 
+               self.top_dir = getenv('MATRIX_TOPDIR', '')
+               __cache_dir = join(self.top_dir, 'build-cache')
+               self.cache_dir = getenv('MATRIX_CACHEDIR', __cache_dir)
                self.script_dir = None
 
                self.boards = {}
@@ -85,4 +98,11 @@ class Config(object):
                self.jobs = 1
                self.make_jobs = 1
 
+actions = dict(
+       Board = Board,
+       Component = Component,
+       PlatformProvidedComponent = PlatformProvidedComponent,
+       parse = parse,
+)
+
 config = Config()
index 265f2cb..877ca5a 100644 (file)
@@ -19,19 +19,22 @@ from build import build, build_only
 
 Error = RuntimeError
 
+def merge_config(name, value):
+       if type(value) == list:
+               value = value + getattr(config, name, [])
+       setattr(config, name, value)
+
 def main():
        command, targets, options = parse_args()
 
-       if 'debug' in options:
-               config.debug = options['debug']
+       for name in ('debug', 'confdirs'):
+               if name in options:
+                       merge_config(name, options[name])
 
-       config_parse('config', True)
+       config_parse('main', True)
 
        for name in options:
-               value = options[name]
-               if type(value) == list:
-                       value = value + getattr(config, name, [])
-               setattr(config, name, value)
+               merge_config(name, options[name])
 
        cache.init()
        all_targets = components.init()
@@ -82,25 +85,27 @@ commands:
 '''
 
 def parse_args():
-       values = dict(roots=[])
-
-       class ValueProxy(object):
-               def __setattr__(self, name, value):
-                       values[name] = value
+       options = {}
 
        def help(option, opt, value, parser):
                print_help(sys.stdout, parser)
                sys.exit(0)
 
-       def add_root(option, opt, value, parser):
-               values['roots'].insert(0, value)
+       def set_flag(option, opt, value, parser):
+               options[option.dest] = True
 
        def set_jobs(option, opt, value, parser):
                if value < 1:
                        raise optparse.OptionValueError(
                                'option %s: invalid job count: %d' % \
                                (opt, value))
-               values[option.dest] = value
+               options[option.dest] = value
+
+       def prepend(option, opt, value, parser):
+               l = options.get(option.dest, [])
+               if not l:
+                       options[option.dest] = l
+               l.insert(0, value)
 
        parser = optparse.OptionParser(
                usage='%prog [<options>] <command> [<components>]',
@@ -114,29 +119,36 @@ def parse_args():
        parser.add_option(
                '-v', '--verbose',
                help='show build output',
-               dest='verbose', action='store_true')
+               dest='verbose', action='callback', callback=set_flag)
 
        parser.add_option(
                '-d', '--debug',
                help='debug output',
-               dest='debug', action='store_true')
+               dest='debug', action='callback', callback=set_flag)
+
+       parser.add_option(
+               '-c', '--confdir', metavar='DIR',
+               help='add a directory for finding config files (may be set ' \
+                    'multiple times; last is searched first)',
+               dest='confdirs', action='callback', callback=prepend,
+               type='string')
 
        parser.add_option(
-               '-r', '--root',
+               '-r', '--root', metavar='URL',
                help='add a location for finding git repos when cloning ' \
-                    '(may be specified multiple times)', metavar='URL',
-               dest='roots', action='callback', callback=add_root,
+                    '(may be set multiple times; last is searched first)',
+               dest='roots', action='callback', callback=prepend,
                type='string')
 
        parser.add_option(
                '-f', '--force',
                help='build (or be quiet about) components with dirty files',
-               dest='force', action='store_true')
+               dest='force', action='callback', callback=set_flag)
 
        parser.add_option(
                '-k', '--keep-going',
                help='build as much as possible after an error',
-               dest='keep_going', action='store_true')
+               dest='keep_going', action='callback', callback=set_flag)
 
        parser.add_option(
                '-j', '--jobs',
@@ -150,12 +162,12 @@ def parse_args():
                dest='make_jobs', action='callback', callback=set_jobs,
                type='int')
 
-       proxy, args = parser.parse_args(values=ValueProxy())
+       values, args = parser.parse_args(values=None)
        if not args:
                print_help(sys.stderr, parser)
                sys.exit(1)
 
-       return args[0], args[1:], values
+       return args[0], args[1:], options
 
 def execute(args):
        if config.debug: