1# Copyright 2014 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
9import json
10import os
11import re
12import sys
13
14from recipe_engine import recipe_api
15from recipe_engine import config_types
16
17
18class SkiaApi(recipe_api.RecipeApi):
19
20  def setup(self):
21    """Prepare the bot to run."""
22    # Setup dependencies.
23    self.m.vars.setup()
24
25    # Check out the Skia code.
26    self.checkout_steps()
27
28    if not self.m.path.exists(self.m.vars.tmp_dir):
29      self.m.run.run_once(self.m.file.makedirs,
30                          'tmp_dir',
31                          self.m.vars.tmp_dir,
32                          infra_step=True)
33
34    self.m.flavor.setup()
35
36  def update_repo(self, parent_dir, repo):
37    """Update an existing repo. This is safe to call without gen_steps."""
38    repo_path = parent_dir.join(repo.name)
39    if self.m.path.exists(repo_path):  # pragma: nocover
40      if self.m.platform.is_win:
41        git = 'git.bat'
42      else:
43        git = 'git'
44      with self.m.step.context({'cwd': repo_path}):
45        self.m.step('git remote set-url',
46                    cmd=[git, 'remote', 'set-url', 'origin', repo.url],
47                    infra_step=True)
48        self.m.step('git fetch',
49                    cmd=[git, 'fetch'],
50                    infra_step=True)
51        self.m.step('git reset',
52                    cmd=[git, 'reset', '--hard', repo.revision],
53                    infra_step=True)
54        self.m.step('git clean',
55                    cmd=[git, 'clean', '-d', '-f'],
56                    infra_step=True)
57
58  def checkout_steps(self):
59    """Run the steps to obtain a checkout of Skia."""
60    cfg_kwargs = {}
61    if not self.m.vars.persistent_checkout:
62      # We should've obtained the Skia checkout through isolates, so we don't
63      # need to perform the checkout ourselves.
64      return
65
66    # Use a persistent gclient cache for Swarming.
67    cfg_kwargs['CACHE_DIR'] = self.m.vars.gclient_cache
68
69    # Create the checkout path if necessary.
70    if not self.m.path.exists(self.m.vars.checkout_root):
71      self.m.file.makedirs('checkout_path',
72                           self.m.vars.checkout_root,
73                           infra_step=True)
74
75    # Initial cleanup.
76    gclient_cfg = self.m.gclient.make_config(**cfg_kwargs)
77    main_repo = self.m.properties['repository']
78    if self.m.vars.need_pdfium_checkout:
79      main_repo = 'https://pdfium.googlesource.com/pdfium.git'
80    if self.m.vars.need_flutter_checkout:
81      main_repo = 'https://github.com/flutter/engine.git'
82    main_name = self.m.path.basename(main_repo)
83    if main_name.endswith('.git'):
84      main_name = main_name[:-len('.git')]
85      # Special case for flutter because it seems to need a very specific
86      # directory structure to successfully build.
87      if self.m.vars.need_flutter_checkout and main_name == 'engine':
88        main_name = 'src/flutter'
89    main = gclient_cfg.solutions.add()
90    main.name = main_name
91    main.managed = False
92    main.url = main_repo
93    main.revision = self.m.properties.get('revision') or 'origin/master'
94    m = gclient_cfg.got_revision_mapping
95    m[main_name] = 'got_revision'
96    patch_root = main_name
97
98    if self.m.vars.need_pdfium_checkout:
99      # Skia is a DEP of PDFium; the 'revision' property is a Skia revision, and
100      # any patch should be applied to Skia, not PDFium.
101      main.revision = 'origin/master'
102      main.managed = True
103      m[main_name] = 'got_%s_revision' % main_name
104
105      skia_dep_path = 'pdfium/third_party/skia'
106      gclient_cfg.patch_projects['skia'] = (skia_dep_path, 'HEAD')
107      gclient_cfg.revisions[skia_dep_path] = self.m.properties['revision']
108      m[skia_dep_path] = 'got_revision'
109      patch_root = skia_dep_path
110
111    if self.m.vars.need_flutter_checkout:
112      # Skia is a DEP of Flutter; the 'revision' property is a Skia revision,
113      # and any patch should be applied to Skia, not Flutter.
114      main.revision = 'origin/master'
115      main.managed = True
116      m[main_name] = 'got_flutter_revision'
117      if 'Android' in self.m.vars.builder_cfg.get('extra_config', ''):
118        gclient_cfg.target_os.add('android')
119
120      skia_dep_path = 'src/third_party/skia'
121      gclient_cfg.patch_projects['skia'] = (skia_dep_path, 'HEAD')
122      gclient_cfg.revisions[skia_dep_path] = self.m.properties['revision']
123      m[skia_dep_path] = 'got_revision'
124      patch_root = skia_dep_path
125
126    self.update_repo(self.m.vars.checkout_root, main)
127
128    # TODO(rmistry): Remove the below block after there is a solution for
129    #                crbug.com/616443
130    entries_file = self.m.vars.checkout_root.join('.gclient_entries')
131    if self.m.path.exists(entries_file):
132      self.m.file.remove('remove %s' % entries_file,
133                         entries_file,
134                         infra_step=True)  # pragma: no cover
135
136    if self.m.vars.need_chromium_checkout:
137      chromium = gclient_cfg.solutions.add()
138      chromium.name = 'src'
139      chromium.managed = False
140      chromium.url = 'https://chromium.googlesource.com/chromium/src.git'
141      chromium.revision = 'origin/lkgr'
142      self.update_repo(self.m.vars.checkout_root, chromium)
143
144    # Run bot_update.
145
146    # Hack the patch ref if necessary.
147    if self.m.properties.get('patch_storage', '') == 'gerrit':
148      if self.m.bot_update._issue and self.m.bot_update._patchset:
149        self.m.bot_update._gerrit_ref = 'refs/changes/%s/%d/%d' % (
150            str(self.m.bot_update._issue)[-2:],
151            self.m.bot_update._issue,
152            self.m.bot_update._patchset,
153        )
154
155    self.m.gclient.c = gclient_cfg
156    with self.m.step.context({'cwd': self.m.vars.checkout_root}):
157      update_step = self.m.bot_update.ensure_checkout(patch_root=patch_root)
158
159    self.m.vars.got_revision = (
160        update_step.presentation.properties['got_revision'])
161
162    if self.m.vars.need_chromium_checkout:
163      with self.m.step.context({'cwd': self.m.vars.checkout_root,
164                                'env': self.m.vars.gclient_env}):
165        self.m.gclient.runhooks()
166