Implement repa update
[tools/repa.git] / repa / main.py
1 #!/usr/bin/env python
2 #
3 # This file is part of REPA: Release Engineering Process Assistant.
4 #
5 # Copyright (C) 2013 Intel Corporation
6 #
7 # REPA is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # version 2 as published by the Free Software Foundation.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
20
21 """
22 REPA: Release Engineering Process Assistant.
23
24 Copyright (C) Intel Corporation 2013
25 Licence: GPL version 2
26 Author: Ed Bartosh <eduard.bartosh@intel.com>
27
28 Main module.
29 Command line parsing, script entry point.
30 """
31
32 import sys
33 import pkg_resources
34 import ConfigParser
35
36 from os.path import expanduser
37 from argparse import ArgumentParser
38
39 from repa.common import RepaException
40
41
42 def parse_args(argv):
43     """
44     Parse command line. Read config.
45     Set arguments to config values.
46     """
47     # create parser to parse -section
48     parser = ArgumentParser(add_help=False)
49     parser.add_argument('-section', default='general')
50
51     # read config section, specified in command line
52     parsed, argv = parser.parse_known_args(argv)
53     config = read_config(section=parsed.section)
54
55     # recreate parser to parse rest of the command line
56     parser = \
57         ArgumentParser(prog='repa',
58                        description='Release Engineering Process Assistant')
59     parser.add_argument('--version', action='version',
60                         version='%(prog)s version 0.6')
61     parser.add_argument('-s', '--section', default='general',
62                         help='config section to use')
63     parser.add_argument('-p', '--project', help='target project',
64                         default=config.get('project'))
65     parser.add_argument('-c', '--colorize', action='store_true',
66                         help='colorize the output',
67                         default=config.get('colorize', '').lower() == 'on')
68
69     subparsers = parser.add_subparsers(help='sub-command help')
70     for entry in pkg_resources.iter_entry_points(group='repa_commands'):
71         cmd = entry.load()()
72         parser_cmd = subparsers.add_parser(cmd.name,
73                                            description=cmd.description,
74                                            help=cmd.help)
75         if hasattr(cmd, 'add_arguments'):
76             cmd.add_arguments(parser_cmd, config)
77         parser_cmd.set_defaults(func=cmd.run)
78
79     args = parser.parse_args(argv)
80
81     return update_args(config, args)
82
83
84 def read_config(paths=('/etc/repa.conf', expanduser('~/.repa.conf')),
85                 section='general',
86                 mandatory=('apiurl', 'apiuser', 'apipasswd', 'project',
87                            'jenkins_url', 'jenkins_user', 'jenkins_passwd')):
88     """
89     Read repa config.
90     Configuration is read from the set of files provided.
91     Optional section name can be specified to read options from
92     """
93     conf = ConfigParser.RawConfigParser()
94     if not conf.read(paths):
95         raise RepaException("Configuration file not found")
96     if not conf.has_section(section):
97         raise RepaException("Section '%s' doesn't exist in config" % section)
98
99     # read configuration from 'general' and then from specified section
100     # to have defaults set properly
101     config = dict(conf.items('general'))
102     if section != 'general':
103         config.update(conf.items(section))
104
105     # Check mandatory config options
106     missed = set(mandatory).difference(set(config.keys()))
107     if missed:
108         raise RepaException("Missing mandatory config options: %s" % \
109                                 ','.join(missed))
110     return config
111
112 def update_args(config, args):
113     """Set configuration options as args attributes."""
114     for key, val in config.iteritems():
115         if not hasattr(args, key):
116             setattr(args, key, val)
117     return args
118
119 def sub_main(argv, cmd):
120     """Subcommand entry point."""
121     parser = ArgumentParser(description=cmd.description)
122     config = read_config()
123     cmd.add_arguments(parser, config)
124     args = parser.parse_args(argv)
125     return cmd.run(update_args(config, args))
126
127
128 def main(argv=sys.argv[1:]):
129     """Command line entry point."""
130     try:
131         args = parse_args(argv)
132         return args.func(args)
133     except (RepaException, KeyboardInterrupt) as error:
134         print >> sys.stderr, error
135
136
137 if __name__ == '__main__':
138     sys.exit(main(sys.argv[1:]))