| OLD | NEW | 
| (Empty) |  | 
 |    1 #!/usr/bin/python | 
 |    2 # Copyright 2014 The Chromium Authors. All rights reserved. | 
 |    3 # Use of this source code is governed by a BSD-style license that can be | 
 |    4 # found in the LICENSE file. | 
 |    5  | 
 |    6 from __future__ import print_function | 
 |    7  | 
 |    8 import argparse | 
 |    9 import ast | 
 |   10 import os | 
 |   11 import re | 
 |   12 import sys | 
 |   13  | 
 |   14  | 
 |   15 TOOLS_DIR = os.path.abspath(os.path.dirname(__file__)) | 
 |   16 SCRIPTS_DIR = os.path.dirname(TOOLS_DIR) | 
 |   17 BASE_DIR = os.path.dirname(SCRIPTS_DIR) | 
 |   18  | 
 |   19 # This adjusts sys.path, so must be done before we import other modules. | 
 |   20 if not SCRIPTS_DIR in sys.path: | 
 |   21   sys.path.append(SCRIPTS_DIR) | 
 |   22  | 
 |   23 from common import filesystem | 
 |   24  | 
 |   25  | 
 |   26 TEMPLATE_SUBPATH = os.path.join('scripts', 'tools', 'buildbot_tool_templates') | 
 |   27 TEMPLATE_DIR = os.path.join(BASE_DIR, TEMPLATE_SUBPATH) | 
 |   28  | 
 |   29 BUILDER_TEMPLATE = """\ | 
 |   30 c['builders'].append({ | 
 |   31   'name': '%(builder_name)s', | 
 |   32   'factory': m_annotator.BaseFactory('%(recipe)s'), | 
 |   33   'slavebuilddir': '%(slavebuilddir)s'}) | 
 |   34 """ | 
 |   35  | 
 |   36  | 
 |   37 SLAVE_TEMPLATE = """\ | 
 |   38   { | 
 |   39     'master': '%(master_classname)s', | 
 |   40     'hostname': '%(hostname)s', | 
 |   41     'builder': '%(builder_name)s', | 
 |   42     'os': '%(os)s', | 
 |   43     'version': '%(version)s', | 
 |   44     'bits': '%(bits)s', | 
 |   45   }, | 
 |   46 """ | 
 |   47  | 
 |   48  | 
 |   49 def main(argv, fs): | 
 |   50   args = parse_args(argv) | 
 |   51   return args.func(args, fs) | 
 |   52  | 
 |   53  | 
 |   54 def parse_args(argv): | 
 |   55   parser = argparse.ArgumentParser() | 
 |   56   subps = parser.add_subparsers() | 
 |   57  | 
 |   58   subp = subps.add_parser('gen', help=run_gen.__doc__) | 
 |   59   subp.add_argument('master_dirname', nargs=1, | 
 |   60                     help='Path to master config directory (must contain ' | 
 |   61                          'a builders.py file).') | 
 |   62   subp.set_defaults(func=run_gen) | 
 |   63  | 
 |   64   subp = subps.add_parser('help', help=run_help.__doc__) | 
 |   65   subp.add_argument(nargs='?', action='store', dest='subcommand', | 
 |   66                     help='The command to get help for.') | 
 |   67   subp.set_defaults(func=run_help) | 
 |   68  | 
 |   69   return parser.parse_args(argv) | 
 |   70  | 
 |   71  | 
 |   72 def run_gen(args, fs): | 
 |   73   """Generate a new master config.""" | 
 |   74  | 
 |   75   master_dirname = args.master_dirname[0] | 
 |   76   master_subpath = fs.relpath(master_dirname, BASE_DIR) | 
 |   77   builders_path = fs.join(BASE_DIR, master_subpath, 'builders.py') | 
 |   78  | 
 |   79   if not fs.exists(builders_path): | 
 |   80     print("%s not found" % master_dirname, file=sys.stderr) | 
 |   81     return 1 | 
 |   82  | 
 |   83   values = _values_from_file(fs, builders_path) | 
 |   84  | 
 |   85   for filename in fs.listfiles(TEMPLATE_DIR): | 
 |   86     template = fs.read_text_file(fs.join(TEMPLATE_DIR, filename)) | 
 |   87     contents = _expand(template, values, | 
 |   88                        '%s/%s' % (TEMPLATE_SUBPATH, filename), | 
 |   89                        master_subpath) | 
 |   90     fs.write_text_file(fs.join(BASE_DIR, master_subpath, filename), contents) | 
 |   91     print("Wrote %s." % filename) | 
 |   92  | 
 |   93   return 0 | 
 |   94  | 
 |   95  | 
 |   96 def run_help(args, fs): | 
 |   97   """Get help on a subcommand.""" | 
 |   98  | 
 |   99   if args.subcommand: | 
 |  100     return main([args.subcommand, '--help'], fs) | 
 |  101   return main(['--help'], fs) | 
 |  102  | 
 |  103  | 
 |  104 def _values_from_file(fs, builders_path): | 
 |  105   builders = ast.literal_eval(fs.read_text_file(builders_path)) | 
 |  106   master_dirname = fs.basename(fs.dirname(builders_path)) | 
 |  107   master_name_comps = master_dirname.split('.')[1:] | 
 |  108   master_classname =  ''.join(c[0].upper() + c[1:] for c in master_name_comps) | 
 |  109  | 
 |  110   builders_block = "" | 
 |  111   slaves_block = "slaves = [\n" | 
 |  112  | 
 |  113   for builder_name, builder_vals in builders['builders'].items(): | 
 |  114     builders_block += BUILDER_TEMPLATE % { | 
 |  115       'builder_name': builder_name, | 
 |  116       'recipe': builder_vals['recipe'], | 
 |  117       'slavebuilddir': builder_vals['slavebuilddir'] | 
 |  118     } | 
 |  119  | 
 |  120     for pool_name in builder_vals['slave_pools']: | 
 |  121       pool = builders['slave_pools'][pool_name] | 
 |  122       slave_data = pool['slave_data'] | 
 |  123       slaves = pool['slaves'] | 
 |  124       for slave in slaves: | 
 |  125         slaves_block += SLAVE_TEMPLATE % { | 
 |  126             'master_classname': master_classname, | 
 |  127             'hostname': slave, | 
 |  128             'builder_name': builder_name, | 
 |  129             'os': slave_data['os'], | 
 |  130             'version': slave_data['version'], | 
 |  131             'bits': slave_data['bits'], | 
 |  132         } | 
 |  133  | 
 |  134   slaves_block += "]" | 
 |  135  | 
 |  136   v = {} | 
 |  137   v['builders_block'] = builders_block | 
 |  138   v['git_repo_url'] = builders['git_repo_url'] | 
 |  139   v['master_dirname'] = master_dirname | 
 |  140   v['master_classname'] = master_classname | 
 |  141   v['master_base_class'] = builders['master_base_class'] | 
 |  142   v['master_port'] = builders['master_port'] | 
 |  143   v['master_port_alt'] = builders['master_port_alt'] | 
 |  144   v['slave_port'] = builders['slave_port'] | 
 |  145   v['slaves_block'] = slaves_block | 
 |  146   return v | 
 |  147  | 
 |  148  | 
 |  149 def _expand(template, values, source, master_subpath): | 
 |  150   try: | 
 |  151     contents = template % values | 
 |  152   except: | 
 |  153     print("Error populating template %s" % source, file=sys.stderr) | 
 |  154     raise | 
 |  155   return _update_generated_file_disclaimer(contents, source, master_subpath) | 
 |  156  | 
 |  157  | 
 |  158 def _update_generated_file_disclaimer(contents, source, master_subpath): | 
 |  159   pattern = '# This file is used by scripts/tools/buildbot-tool.*' | 
 |  160   replacement = ('# This file was generated from\n' | 
 |  161                  '# %s\n' | 
 |  162                  '# by "scripts/tools/buildbot-tool gen %s".\n' | 
 |  163                  '# DO NOT EDIT BY HAND!\n' % | 
 |  164                  (source, master_subpath)) | 
 |  165   return re.sub(pattern, replacement, contents) | 
 |  166  | 
 |  167  | 
 |  168 if __name__ == '__main__':  # pragma: no cover | 
 |  169   sys.exit(main(sys.argv[1:], filesystem.Filesystem())) | 
| OLD | NEW |