• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
9from recipe_engine import recipe_api
10
11
12TEST_DEFAULT_ASSET_VERSION = '42'
13
14class SkiaStepApi(recipe_api.RecipeApi):
15
16  def __init__(self, *args, **kwargs):
17    """Initialize the recipe module."""
18    super(SkiaStepApi, self).__init__(*args, **kwargs)
19
20    self._already_ran = {}
21    self._ccache = None
22    self._checked_for_ccache = False
23    self._failed = []
24
25  def check_failure(self):
26    """Raise an exception if any step failed."""
27    if self._failed:
28      raise self.m.step.StepFailure('Failed build steps: %s' %
29                                    ', '.join([f.name for f in self._failed]))
30
31  @property
32  def failed_steps(self):
33    return self._failed[:]
34
35  def run_once(self, fn, *args, **kwargs):
36    if not fn.__name__ in self._already_ran:
37      self._already_ran[fn.__name__] = fn(*args, **kwargs)
38    return self._already_ran[fn.__name__]
39
40  def readfile(self, filename, *args, **kwargs):
41    """Convenience function for reading files."""
42    name = kwargs.pop('name', 'read %s' % self.m.path.basename(filename))
43    return self.m.file.read_text(name, filename, *args, **kwargs)
44
45  def writefile(self, filename, contents):
46    """Convenience function for writing files."""
47    return self.m.file.write_text('write %s' % self.m.path.basename(filename),
48                                  filename, contents)
49
50  def rmtree(self, path):
51    """Wrapper around api.file.rmtree."""
52    self.m.file.rmtree('rmtree %s' % self.m.path.basename(path), path)
53
54  def asset_version(self, asset_name, skia_dir, test_data=None):
55    """Return the contents of VERSION for the given asset as a string.
56
57    If test_data is not specified, reads the property
58    'test_<asset_name>_version' or if not present, uses
59    TEST_DEFAULT_ASSET_VERSION."""
60    version_file = skia_dir.join(
61        'infra', 'bots', 'assets', asset_name, 'VERSION')
62    if not test_data:
63      test_data = self.m.properties.get(
64          'test_%s_version' % asset_name, TEST_DEFAULT_ASSET_VERSION)
65    return self.m.file.read_text('Get %s VERSION' % asset_name,
66                                 version_file,
67                                 test_data=test_data).rstrip()
68
69  def __call__(self, steptype, name, abort_on_failure=True,
70               fail_build_on_failure=True, **kwargs):
71    """Run a step. If it fails, keep going but mark the build status failed."""
72    try:
73      with self.m.env(self.m.vars.default_env):
74        return steptype(name=name, **kwargs)
75    except self.m.step.StepFailure as e:
76      if fail_build_on_failure:
77        self._failed.append(e)
78      if abort_on_failure:
79        raise
80
81  def with_retry(self, steptype, name, attempts, between_attempts_fn=None,
82                 abort_on_failure=True, fail_build_on_failure=True, **kwargs):
83    for attempt in xrange(attempts):
84      step_name = name
85      if attempt > 0:
86        step_name += ' (attempt %d)' % (attempt + 1)
87      try:
88        res = self(steptype, name=step_name, abort_on_failure=True,
89                   fail_build_on_failure=fail_build_on_failure, **kwargs)
90        if attempt > 0 and fail_build_on_failure:
91          del self._failed[-attempt:]
92        return res
93      except self.m.step.StepFailure:
94        if attempt == attempts - 1:
95          if abort_on_failure:
96            raise
97        elif between_attempts_fn:
98          between_attempts_fn(attempt+1)
99