Prettify error messages for invalid component names
[matrix.git] / matrix / matrix.py
index 955180a..4bf796a 100644 (file)
@@ -24,10 +24,10 @@ def merge_config(name, value):
                value = getattr(config, name, []) + value
        setattr(config, name, value)
 
-def main():
-       command, targets, options = parse_args()
+def main(version):
+       command, targets, options = parse_args(version)
 
-       for name in ('debug', 'initial_config_dirs'):
+       for name in ('debug', 'initial_config_dirs', 'pull_config_dirs'):
                if name in options:
                        merge_config(name, options[name])
 
@@ -36,27 +36,28 @@ def main():
        for name in options:
                merge_config(name, options[name])
 
-       cache.init()
-       all_targets = components.init()
-
        for i in xrange(len(targets)):
                name = targets[i]
                if name.startswith('src' + os.path.sep):
                        name = name.split(os.path.sep)[1]
                        targets[i] = name
 
-               if name not in config.components:
-                       raise Error('Component "%s" does not exist' % name)
+       cache.init()
+       components.init(targets)
 
        if not targets:
-               targets = all_targets
+               targets = components.by_name.keys()
+               targets.sort()
 
        command_funcs = {
                'install':      build,
                'install-only': build_only,
+               'meta':         meta,
                'clone':        clone,
                'clean':        clean,
+               'update':       update,
                'rebase':       rebase,
+               'update-rebase':update_rebase,
                'pull':         pull,
                'changes':      changes,
                'source-dist':  source_dist,
@@ -72,25 +73,33 @@ def print_help(file, parser):
        parser.print_help(file=file)
        print >>file, '''
 commands:
+  meta          download the components' meta repositories
   clone         download the components' git repositories
   install       download, build and install the components
   install-only  download, build and install the specified components without
                 dependencies
   clean         remove all non-tracked files from the component git repository
                 directories
-  rebase        update repositories from server by rebasing
-  pull          update repositories from server by merging
+  update        download remote repositories from server
+  rebase        rebase local repositories against remote repositories (remotes
+                won't be updated first)
+  update-rebase update remote repositories and rebase local repositories
+  pull          update remote repositories and merge with local repositories
   changes       show commits which are not on the server
   source-dist   download and package the component sources
 '''
 
-def parse_args():
+def parse_args(matrix_version):
        options = {}
 
        def help(option, opt, value, parser):
                print_help(sys.stdout, parser)
                sys.exit(0)
 
+       def version(option, opt, value, parser):
+               print matrix_version
+               sys.exit(0)
+
        def set_flag(option, opt, value, parser):
                options[option.dest] = True
 
@@ -117,6 +126,11 @@ def parse_args():
                action='callback', callback=help)
 
        parser.add_option(
+               '--version',
+               help='print Matrix version',
+               action='callback', callback=version)
+
+       parser.add_option(
                '-v', '--verbose',
                help='show build output',
                dest='verbose', action='callback', callback=set_flag)
@@ -129,14 +143,19 @@ def parse_args():
        parser.add_option(
                '-c', '--config-dir', metavar='DIR',
                help='add a directory for finding config files (may be set ' \
-                    'multiple times; last is searched first)',
+                    'multiple times)',
                dest='initial_config_dirs', action='callback', callback=append,
                type='string')
 
        parser.add_option(
+               '-p', '--pull-config-dirs',
+               help='git-pull config dirs which are backed by Git repositories',
+               dest='pull_config_dirs', action='callback', callback=set_flag)
+
+       parser.add_option(
                '-r', '--root', metavar='URL',
                help='add a location for finding git repos when cloning ' \
-                    '(may be set multiple times; last is searched first)',
+                    '(may be set multiple times)',
                dest='roots', action='callback', callback=append,
                type='string')
 
@@ -179,9 +198,21 @@ def execute(args):
 def remove_tree(path):
        execute(['rm', '-rf', path])
 
+def find_component(name):
+       try:
+               return components.by_name[name]
+       except KeyError:
+               raise Error("Component " + name + " not found");
+
+def meta(targets):
+       for name in targets:
+               c = find_component(name)
+               if not c.meta.exists():
+                       c.meta.clone()
+       
 def clone(targets):
        for name in targets:
-               c = config.components[name]
+               c = find_component(name)
                clone_component(c)
 
 def clone_component(c, overwrite=False):
@@ -207,7 +238,7 @@ def clean(targets):
        changed = False
 
        for name in targets:
-               c = config.components[name]
+               c = find_component(name)
                c.source.clean()
                cache.remove(c)
 
@@ -221,7 +252,7 @@ def for_each_repository(func, targets=None):
        ret = None
 
        for name in targets:
-               c = config.components[name]
+               c = find_component(name)
                if c.source.exists():
                        value = func(c.source)
                        if value:
@@ -232,9 +263,19 @@ def for_each_repository(func, targets=None):
 
        return ret
 
+def update(targets):
+       for_each_repository(lambda repo: repo.update(), targets)
+
 def rebase(targets):
        for_each_repository(lambda repo: repo.rebase(), targets)
 
+def update_rebase(targets):
+       def action(repo):
+               repo.update()
+               repo.rebase()
+
+       for_each_repository(action, targets)
+
 def pull(targets):
        for_each_repository(lambda repo: repo.pull(), targets)
 
@@ -242,7 +283,7 @@ def changes(targets):
        changed = False
 
        for name in targets:
-               c = config.components[name]
+               c = find_component(name)
 
                if c.source.exists():
                        if check_changes(c.source):
@@ -275,7 +316,7 @@ def source_dist(targets):
                os.makedirs(location)
 
        for name in targets:
-               c = config.components[name]
+               c = find_component(name)
                dist_changes(c, location)
                dist_sources(c, location)