Home | History | Annotate | Download | only in run
      1 # Copyright 2016 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 
      6 # pylint: disable=W0201
      7 
      8 
      9 from recipe_engine import recipe_api
     10 
     11 
     12 BUILD_PRODUCTS_ISOLATE_WHITELIST = [
     13   'bookmaker',
     14   'dm',
     15   'dm.exe',
     16   'dm.app',
     17   'nanobench.app',
     18   'get_images_from_skps',
     19   'get_images_from_skps.exe',
     20   'nanobench',
     21   'nanobench.exe',
     22   'skpbench',
     23   '*.so',
     24   '*.dll',
     25   '*.dylib',
     26   'skia_launcher',
     27   'skiaserve',
     28   'lib/*.so',
     29 ]
     30 
     31 
     32 class SkiaStepApi(recipe_api.RecipeApi):
     33 
     34   def __init__(self, *args, **kwargs):
     35     """Initialize the recipe module."""
     36     super(SkiaStepApi, self).__init__(*args, **kwargs)
     37 
     38     self._already_ran = {}
     39     self._ccache = None
     40     self._checked_for_ccache = False
     41     self._failed = []
     42 
     43   def check_failure(self):
     44     """Raise an exception if any step failed."""
     45     if self._failed:
     46       raise self.m.step.StepFailure('Failed build steps: %s' %
     47                                     ', '.join([f.name for f in self._failed]))
     48 
     49   @property
     50   def failed_steps(self):
     51     return self._failed[:]
     52 
     53   def run_once(self, fn, *args, **kwargs):
     54     if not fn.__name__ in self._already_ran:
     55       self._already_ran[fn.__name__] = fn(*args, **kwargs)
     56     return self._already_ran[fn.__name__]
     57 
     58   def readfile(self, filename, *args, **kwargs):
     59     """Convenience function for reading files."""
     60     name = kwargs.pop('name', 'read %s' % self.m.path.basename(filename))
     61     return self.m.file.read_text(name, filename, *args, **kwargs)
     62 
     63   def writefile(self, filename, contents):
     64     """Convenience function for writing files."""
     65     return self.m.file.write_text('write %s' % self.m.path.basename(filename),
     66                                   filename, contents)
     67 
     68   def rmtree(self, path):
     69     """Wrapper around api.file.rmtree."""
     70     self.m.file.rmtree('rmtree %s' % self.m.path.basename(path), path)
     71 
     72   def __call__(self, steptype, name, abort_on_failure=True,
     73                fail_build_on_failure=True, **kwargs):
     74     """Run a step. If it fails, keep going but mark the build status failed."""
     75     try:
     76       with self.m.env(self.m.vars.default_env):
     77         return steptype(name=name, **kwargs)
     78     except self.m.step.StepFailure as e:
     79       if fail_build_on_failure:
     80         self._failed.append(e)
     81       if abort_on_failure:
     82         raise
     83 
     84   def copy_build_products(self, src, dst):
     85     """Copy whitelisted build products from src to dst."""
     86     self.m.python.inline(
     87         name='copy build products',
     88         program='''import errno
     89 import glob
     90 import os
     91 import shutil
     92 import sys
     93 
     94 src = sys.argv[1]
     95 dst = sys.argv[2]
     96 build_products_whitelist = %s
     97 
     98 try:
     99   os.makedirs(dst)
    100 except OSError as e:
    101   if e.errno != errno.EEXIST:
    102     raise
    103 
    104 for pattern in build_products_whitelist:
    105   path = os.path.join(src, pattern)
    106   for f in glob.glob(path):
    107     dst_path = os.path.join(dst, os.path.relpath(f, src))
    108     if not os.path.isdir(os.path.dirname(dst_path)):
    109       os.makedirs(os.path.dirname(dst_path))
    110     print 'Copying build product %%s to %%s' %% (f, dst_path)
    111     shutil.move(f, dst_path)
    112 ''' % str(BUILD_PRODUCTS_ISOLATE_WHITELIST),
    113         args=[src, dst],
    114         infra_step=True)
    115 
    116   def with_retry(self, steptype, name, attempts, between_attempts_fn=None,
    117                  abort_on_failure=True, fail_build_on_failure=True, **kwargs):
    118     for attempt in xrange(attempts):
    119       step_name = name
    120       if attempt > 0:
    121         step_name += ' (attempt %d)' % (attempt + 1)
    122       try:
    123         res = self(steptype, name=step_name, abort_on_failure=True,
    124                    fail_build_on_failure=fail_build_on_failure, **kwargs)
    125         if attempt > 0 and fail_build_on_failure:
    126           del self._failed[-attempt:]
    127         return res
    128       except self.m.step.StepFailure:
    129         if attempt == attempts - 1:
    130           if abort_on_failure:
    131             raise
    132         elif between_attempts_fn:
    133           between_attempts_fn(attempt+1)
    134