Home | History | Annotate | Download | only in utils
      1 #!/usr/bin/python
      2 import common
      3 import sys, os, shutil, optparse, logging
      4 from autotest_lib.client.common_lib import error, utils
      5 from autotest_lib.client.common_lib import logging_config, logging_manager
      6 """
      7 Compile All Autotest GWT Clients Living in autotest/frontend/client/src
      8 """
      9 
     10 _AUTOTEST_DIR = common.autotest_dir
     11 _DEFAULT_GWT_DIRS = ['/usr/local/lib/gwt', '/opt/google-web-toolkit']
     12 _DEFAULT_APP_DIR = os.path.join(_AUTOTEST_DIR, 'frontend/client')
     13 _DEFAULT_INSTALL_DIR = os.path.join(_DEFAULT_APP_DIR, 'www')
     14 _TMP_COMPILE_DIR = _DEFAULT_INSTALL_DIR + '.new'
     15 
     16 _COMPILE_LINE = ('java  -Xmx512M %(extra_args)s '
     17                  '-cp "%(app_dir)s/src:%(app_dir)s/bin:%(gwt_dir)s/gwt-user.jar'
     18                  ':%(gwt_dir)s/gwt-dev.jar" -Djava.awt.headless=true '
     19                  'com.google.gwt.dev.Compiler -war "%(compile_dir)s" '
     20                  '%(project_client)s')
     21 
     22 class CompileClientsLoggingConfig(logging_config.LoggingConfig):
     23     def configure_logging(self, results_dir=None, verbose=False):
     24         super(CompileClientsLoggingConfig, self).configure_logging(
     25                                                                use_console=True,
     26                                                                verbose=verbose)
     27 
     28 def enumerate_projects():
     29     """List projects in _DEFAULT_APP_DIR."""
     30     src_path = os.path.join(_DEFAULT_APP_DIR, 'src')
     31     projects = {}
     32     for project in os.listdir(src_path):
     33         projects[project] = []
     34         project_path = os.path.join(src_path, project)
     35         for file in os.listdir(project_path):
     36             if file.endswith('.gwt.xml'):
     37                 projects[project].append(file[:-8])
     38     return projects
     39 
     40 
     41 def find_gwt_dir():
     42     """See if GWT is installed in site-packages or in the system,
     43        site-packages is favored over a system install or a /usr/local install.
     44     """
     45     site_gwt = os.path.join(_AUTOTEST_DIR, 'site-packages', 'gwt')
     46     gwt_dirs = [site_gwt] + _DEFAULT_GWT_DIRS
     47 
     48     for gwt_dir in gwt_dirs:
     49         if os.path.isdir(gwt_dir):
     50             return gwt_dir
     51     logging.error('Unable to find GWT. '
     52                   'You can use utils/build_externals.py to install it.')
     53     sys.exit(1)
     54 
     55 
     56 def install_completed_client(compiled_dir, project_client):
     57     """Remove old client directory if it exists,  move installed client to the
     58        old directory and move newly compield client to the installed client
     59        dir.
     60        @param compiled_dir: Where the new client was compiled
     61        @param project_client: project.client pair e.g. autotest.AfeClient
     62        @returns True if installation was successful or False if it failed
     63     """
     64     tmp_client_dir = os.path.join(_TMP_COMPILE_DIR, project_client)
     65     install_dir = os.path.join(_DEFAULT_INSTALL_DIR, project_client)
     66     old_install_dir = os.path.join(_DEFAULT_INSTALL_DIR,
     67                                    project_client + '.old')
     68     if not os.path.exists(_DEFAULT_INSTALL_DIR):
     69         os.mkdir(_DEFAULT_INSTALL_DIR)
     70 
     71     if os.path.isdir(tmp_client_dir):
     72         if os.path.isdir(old_install_dir):
     73             shutil.rmtree(old_install_dir)
     74         if os.path.isdir(install_dir):
     75             os.rename(install_dir, old_install_dir)
     76         try:
     77             os.rename(tmp_client_dir, install_dir)
     78             return True
     79         except Exception, err:
     80             # If we can't rename the client raise an exception
     81             # and put the old client back
     82             shutil.rmtree(install_dir)
     83             shutil.copytree(old_install_dir, install_dir)
     84             logging.error('Copying old client: %s', err)
     85     else:
     86         logging.error('Compiled directory is gone, something went wrong')
     87 
     88     return False
     89 
     90 
     91 def compile_and_install_client(project_client, extra_args='',
     92                                install_client=True):
     93     """Compile the client into a temporary directory, if successful
     94        call install_completed_client to install the new client.
     95        @param project_client: project.client pair e.g. autotest.AfeClient
     96        @param install_client: Boolean, if True install the clients
     97        @return True if install and compile was successful False if it failed
     98     """
     99     java_args = {}
    100     java_args['compile_dir'] = _TMP_COMPILE_DIR
    101     java_args['app_dir'] = _DEFAULT_APP_DIR
    102     java_args['gwt_dir'] = find_gwt_dir()
    103     java_args['extra_args'] = extra_args
    104     java_args['project_client'] = project_client
    105     cmd = _COMPILE_LINE % java_args
    106 
    107     logging.info('Compiling client %s', project_client)
    108     try:
    109         utils.run(cmd, verbose=True)
    110         if install_client:
    111             return install_completed_client(java_args['compile_dir'],
    112                                             project_client)
    113         return True
    114     except error.CmdError:
    115         logging.error('Error compiling %s, leaving old client', project_client)
    116 
    117     return False
    118 
    119 
    120 def compile_all_projects(extra_args=''):
    121     """Compile all projects available as defined by enumerate_projects.
    122        @returns list of failed client installations
    123     """
    124     failed_clients = []
    125     for project,clients in enumerate_projects().iteritems():
    126         for client in clients:
    127             project_client = '%s.%s' % (project, client)
    128             if not compile_and_install_client(project_client, extra_args):
    129                 failed_clients.append(project_client)
    130 
    131     return failed_clients
    132 
    133 
    134 def print_projects():
    135     logging.info('Projects that can be compiled:')
    136     for project,clients in enumerate_projects().iteritems():
    137         for client in clients:
    138             logging.info('%s.%s', project, client)
    139 
    140 
    141 def main():
    142     logging_manager.configure_logging(CompileClientsLoggingConfig(),
    143                                       verbose=True)
    144     parser = optparse.OptionParser()
    145     parser.add_option('-l', '--list-projects',
    146                       action='store_true', dest='list_projects',
    147                       default=False,
    148                       help='List all projects and clients that can be compiled')
    149     parser.add_option('-a', '--compile-all',
    150                       action='store_true', dest='compile_all',
    151                      default=False,
    152                      help='Compile all available projects and clients')
    153     parser.add_option('-c', '--compile',
    154                       dest='compile_list', action='store',
    155                       help='List of clients to compiled (e.g. -c "x.X c.C")')
    156     parser.add_option('-e', '--extra-args',
    157                       dest='extra_args', action='store',
    158                       default='',
    159                       help='Extra arguments to pass to java')
    160     parser.add_option('-d', '--no-install', dest='install_client',
    161                       action='store_false', default=True,
    162                       help='Do not install the clients just compile them')
    163     options, args = parser.parse_args()
    164 
    165     if len(sys.argv) < 2:
    166         parser.print_help()
    167         sys.exit(0)
    168     elif options.list_projects:
    169         print_projects()
    170         sys.exit(0)
    171     elif options.compile_all and options.compile_list:
    172         logging.error('Options -c and -a are mutually exclusive')
    173         parser.print_help()
    174         sys.exit(1)
    175 
    176     failed_clients = []
    177     if options.compile_all:
    178         failed_clients = compile_all_projects(options.extra_args)
    179     elif options.compile_list:
    180         for client in options.compile_list.split():
    181             if not compile_and_install_client(client, options.extra_args,
    182                                               options.install_client):
    183                 failed_clients.append(client)
    184 
    185     if os.path.exists(_TMP_COMPILE_DIR):
    186         shutil.rmtree(_TMP_COMPILE_DIR)
    187 
    188     if failed_clients:
    189         logging.error('The following clients failed: %s',
    190                       '\n'.join(failed_clients))
    191         sys.exit(1)
    192 
    193 
    194 if __name__ == '__main__':
    195     main()
    196