diff --git a/rhodecode/bin/rhodecode_config.py b/rhodecode/bin/rhodecode_config.py new file mode 100644 --- /dev/null +++ b/rhodecode/bin/rhodecode_config.py @@ -0,0 +1,138 @@ +""" +config generator + +""" +from __future__ import with_statement +import os +import sys +import uuid +import argparse +from mako.template import Template +TMPL = 'template.ini.mako' +here = os.path.dirname(os.path.abspath(__file__)) + +def argparser(argv): + usage = ( + "rhodecode-config [-h] [--filename=FILENAME] [--template=TEMPLATE] \n" + "VARS optional specify extra template variable that will be available in " + "template. Use comma separated key=val format eg.\n" + "key1=val1,port=5000,host=127.0.0.1,elements='a\,b\,c'\n" + ) + + parser = argparse.ArgumentParser( + description='RhodeCode CONFIG generator with variable replacement', + usage=usage + ) + + ## config + group = parser.add_argument_group('CONFIG') + group.add_argument('--filename', help='Output ini filename.') + group.add_argument('--template', help='Mako template file to use instead of ' + 'the default builtin template') + group.add_argument('--raw', help='Store given mako template as raw without ' + 'parsing. Use this to create custom template ' + 'initially', action='store_true') + group.add_argument('--show-defaults', help='Show all default variables for ' + 'builtin template', action='store_true') + args, other = parser.parse_known_args() + return parser, args, other + + +def _escape_split(text, sep): + """ + Allows for escaping of the separator: e.g. arg='foo\, bar' + + It should be noted that the way bash et. al. do command line parsing, those + single quotes are required. a shameless ripoff from fabric project. + + """ + escaped_sep = r'\%s' % sep + + if escaped_sep not in text: + return text.split(sep) + + before, _, after = text.partition(escaped_sep) + startlist = before.split(sep) # a regular split is fine here + unfinished = startlist[-1] + startlist = startlist[:-1] + + # recurse because there may be more escaped separators + endlist = _escape_split(after, sep) + + # finish building the escaped value. we use endlist[0] becaue the first + # part of the string sent in recursion is the rest of the escaped value. + unfinished += sep + endlist[0] + + return startlist + [unfinished] + endlist[1:] # put together all the parts + +def _run(argv): + parser, args, other = argparser(argv) + if not len(sys.argv) > 1: + print parser.print_help() + sys.exit(0) + # defaults that can be overwritten by arguments + tmpl_stored_args = { + 'http_server': 'waitress', + 'lang': 'en', + 'database_engine': 'sqlite', + 'host': '127.0.0.1', + 'port': 5000, + 'error_aggregation_service': None + } + if other: + # parse arguments, we assume only first is correct + kwargs = {} + for el in _escape_split(other[0], ','): + kv = _escape_split(el, '=') + if len(kv) == 2: + k, v = kv + kwargs[k] = v + # update our template stored args + tmpl_stored_args.update(kwargs) + + # use default that cannot be replaced + tmpl_stored_args.update({ + 'uuid': lambda: uuid.uuid4().hex, + 'here': os.path.abspath(os.curdir), + }) + if args.show_defaults: + for k,v in tmpl_stored_args.iteritems(): + print '%s=%s' % (k, v) + sys.exit(0) + try: + # built in template + tmpl_file = os.path.join(here, TMPL) + if args.template: + tmpl_file = args.template + + with open(tmpl_file, 'rb') as f: + tmpl_data = f.read() + if args.raw: + tmpl = tmpl_data + else: + tmpl = Template(tmpl_data).render(**tmpl_stored_args) + with open(args.filename, 'wb') as f: + f.write(tmpl) + print 'Wrote new config file in %s' % (os.path.abspath(args.filename)) + + except Exception: + from mako import exceptions + print exceptions.text_error_template().render() + +def main(argv=None): + """ + Main execution function for cli + + :param argv: + """ + if argv is None: + argv = sys.argv + + try: + return _run(argv) + except Exception: + raise + + +if __name__ == '__main__': + sys.exit(main(sys.argv))