1cb93a386Sopenharmony_ci# Copyright 2014 The Chromium Authors. All rights reserved. 2cb93a386Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be 3cb93a386Sopenharmony_ci# found in the LICENSE file. 4cb93a386Sopenharmony_ci 5cb93a386Sopenharmony_ci 6cb93a386Sopenharmony_ci# pylint: disable=W0201 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci 9cb93a386Sopenharmony_cifrom recipe_engine import recipe_api 10cb93a386Sopenharmony_cifrom recipe_engine import config_types 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_ciclass CheckoutApi(recipe_api.RecipeApi): 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci @property 16cb93a386Sopenharmony_ci def default_checkout_root(self): 17cb93a386Sopenharmony_ci """The default location for cached persistent checkouts.""" 18cb93a386Sopenharmony_ci return self.m.vars.cache_dir.join('work') 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci def assert_git_is_from_cipd(self): 21cb93a386Sopenharmony_ci """Fail if git is not obtained from CIPD.""" 22cb93a386Sopenharmony_ci self.m.run(self.m.python.inline, 'Assert that Git is from CIPD', program=''' 23cb93a386Sopenharmony_cifrom __future__ import print_function 24cb93a386Sopenharmony_ciimport subprocess 25cb93a386Sopenharmony_ciimport sys 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ciwhich = 'where' if sys.platform == 'win32' else 'which' 28cb93a386Sopenharmony_cigit = subprocess.check_output([which, 'git']) 29cb93a386Sopenharmony_ciprint('git was found at %s' % git) 30cb93a386Sopenharmony_ciif 'cipd_bin_packages' not in git: 31cb93a386Sopenharmony_ci print('Git must be obtained through CIPD.', file=sys.stderr) 32cb93a386Sopenharmony_ci sys.exit(1) 33cb93a386Sopenharmony_ci''') 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci def git(self, checkout_root): 36cb93a386Sopenharmony_ci """Run the steps to perform a pure-git checkout without DEPS.""" 37cb93a386Sopenharmony_ci self.assert_git_is_from_cipd() 38cb93a386Sopenharmony_ci skia_dir = checkout_root.join('skia') 39cb93a386Sopenharmony_ci self.m.git.checkout( 40cb93a386Sopenharmony_ci self.m.properties['repository'], dir_path=skia_dir, 41cb93a386Sopenharmony_ci ref=self.m.properties['revision'], submodules=False) 42cb93a386Sopenharmony_ci if self.m.vars.is_trybot: 43cb93a386Sopenharmony_ci self.m.git('fetch', 'origin', self.m.properties['patch_ref']) 44cb93a386Sopenharmony_ci self.m.git('checkout', 'FETCH_HEAD') 45cb93a386Sopenharmony_ci self.m.git('rebase', self.m.properties['revision']) 46cb93a386Sopenharmony_ci return self.m.properties['revision'] 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci def bot_update(self, checkout_root, gclient_cache=None, 49cb93a386Sopenharmony_ci checkout_chromium=False, checkout_flutter=False, 50cb93a386Sopenharmony_ci extra_gclient_env=None, 51cb93a386Sopenharmony_ci flutter_android=False): 52cb93a386Sopenharmony_ci """Run the steps to obtain a checkout using bot_update. 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci Args: 55cb93a386Sopenharmony_ci checkout_root: Root directory where the code will be synced. 56cb93a386Sopenharmony_ci gclient_cache: Optional, directory of the gclient cache. 57cb93a386Sopenharmony_ci checkout_chromium: If True, will check out chromium/src.git in addition 58cb93a386Sopenharmony_ci to the primary repo. 59cb93a386Sopenharmony_ci checkout_flutter: If True, will checkout flutter in addition to the 60cb93a386Sopenharmony_ci primary repo. 61cb93a386Sopenharmony_ci extra_gclient_env: Map of extra environment variable names to their values 62cb93a386Sopenharmony_ci to supply while running gclient. 63cb93a386Sopenharmony_ci flutter_android: Indicates that we're checking out flutter for Android. 64cb93a386Sopenharmony_ci """ 65cb93a386Sopenharmony_ci self.assert_git_is_from_cipd() 66cb93a386Sopenharmony_ci if not gclient_cache: 67cb93a386Sopenharmony_ci gclient_cache = self.m.vars.cache_dir.join('git') 68cb93a386Sopenharmony_ci if not extra_gclient_env: 69cb93a386Sopenharmony_ci extra_gclient_env = {} 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci cfg_kwargs = {} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci # Use a persistent gclient cache for Swarming. 74cb93a386Sopenharmony_ci cfg_kwargs['CACHE_DIR'] = gclient_cache 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci if checkout_flutter: 77cb93a386Sopenharmony_ci # Delete the flutter cache to start from scratch every time. 78cb93a386Sopenharmony_ci # See skbug.com/9994. 79cb93a386Sopenharmony_ci self.m.run.rmtree(checkout_root) 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci # Create the checkout path if necessary. 82cb93a386Sopenharmony_ci # TODO(borenet): 'makedirs checkout_root' 83cb93a386Sopenharmony_ci self.m.file.ensure_directory('makedirs checkout_path', checkout_root) 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_ci # Initial cleanup. 86cb93a386Sopenharmony_ci gclient_cfg = self.m.gclient.make_config(**cfg_kwargs) 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci main_repo = self.m.properties['repository'] 89cb93a386Sopenharmony_ci if checkout_flutter: 90cb93a386Sopenharmony_ci main_repo = 'https://github.com/flutter/engine.git' 91cb93a386Sopenharmony_ci main_name = self.m.path.basename(main_repo) 92cb93a386Sopenharmony_ci if main_name.endswith('.git'): 93cb93a386Sopenharmony_ci main_name = main_name[:-len('.git')] 94cb93a386Sopenharmony_ci # Special case for flutter because it seems to need a very specific 95cb93a386Sopenharmony_ci # directory structure to successfully build. 96cb93a386Sopenharmony_ci if checkout_flutter and main_name == 'engine': 97cb93a386Sopenharmony_ci main_name = 'src/flutter' 98cb93a386Sopenharmony_ci main = gclient_cfg.solutions.add() 99cb93a386Sopenharmony_ci main.name = main_name 100cb93a386Sopenharmony_ci main.managed = False 101cb93a386Sopenharmony_ci main.url = main_repo 102cb93a386Sopenharmony_ci main.revision = self.m.properties.get('revision') or 'origin/main' 103cb93a386Sopenharmony_ci m = gclient_cfg.got_revision_mapping 104cb93a386Sopenharmony_ci m[main_name] = 'got_revision' 105cb93a386Sopenharmony_ci patch_root = main_name 106cb93a386Sopenharmony_ci patch_repo = main.url 107cb93a386Sopenharmony_ci if self.m.properties.get('patch_repo'): 108cb93a386Sopenharmony_ci patch_repo = self.m.properties['patch_repo'] 109cb93a386Sopenharmony_ci patch_root = patch_repo.split('/')[-1] 110cb93a386Sopenharmony_ci if patch_root.endswith('.git'): 111cb93a386Sopenharmony_ci patch_root = patch_root[:-4] 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci if checkout_flutter: 114cb93a386Sopenharmony_ci # Skia is a DEP of Flutter; the 'revision' property is a Skia revision, 115cb93a386Sopenharmony_ci # and any patch should be applied to Skia, not Flutter. 116cb93a386Sopenharmony_ci main.revision = 'origin/master' 117cb93a386Sopenharmony_ci main.managed = True 118cb93a386Sopenharmony_ci m[main_name] = 'got_flutter_revision' 119cb93a386Sopenharmony_ci if flutter_android: 120cb93a386Sopenharmony_ci gclient_cfg.target_os.add('android') 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci skia_dep_path = 'src/third_party/skia' 123cb93a386Sopenharmony_ci gclient_cfg.repo_path_map['https://skia.googlesource.com/skia'] = ( 124cb93a386Sopenharmony_ci skia_dep_path, 'HEAD') 125cb93a386Sopenharmony_ci gclient_cfg.revisions[skia_dep_path] = self.m.properties['revision'] 126cb93a386Sopenharmony_ci m[skia_dep_path] = 'got_revision' 127cb93a386Sopenharmony_ci patch_root = skia_dep_path 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci if checkout_chromium: 130cb93a386Sopenharmony_ci main.custom_vars['checkout_chromium'] = True 131cb93a386Sopenharmony_ci extra_gclient_env['GYP_CHROMIUM_NO_ACTION'] = '0' 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci # TODO(rmistry): Remove the below block after there is a solution for 134cb93a386Sopenharmony_ci # crbug.com/616443 135cb93a386Sopenharmony_ci entries_file = checkout_root.join('.gclient_entries') 136cb93a386Sopenharmony_ci if self.m.path.exists(entries_file) or self._test_data.enabled: 137cb93a386Sopenharmony_ci self.m.file.remove('remove %s' % entries_file, 138cb93a386Sopenharmony_ci entries_file) 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci # Run bot_update. 141cb93a386Sopenharmony_ci patch_refs = None 142cb93a386Sopenharmony_ci patch_ref = self.m.properties.get('patch_ref') 143cb93a386Sopenharmony_ci if patch_ref: 144cb93a386Sopenharmony_ci patch_refs = ['%s@%s:%s' % (self.m.properties['patch_repo'], 145cb93a386Sopenharmony_ci self.m.properties['revision'], 146cb93a386Sopenharmony_ci patch_ref)] 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_ci self.m.gclient.c = gclient_cfg 149cb93a386Sopenharmony_ci with self.m.context(cwd=checkout_root): 150cb93a386Sopenharmony_ci update_step = self.m.bot_update.ensure_checkout( 151cb93a386Sopenharmony_ci patch_root=patch_root, 152cb93a386Sopenharmony_ci # The logic in ensure_checkout for this arg is fairly naive, so if 153cb93a386Sopenharmony_ci # patch=False, we'll see "... (without patch)" in the step names, even 154cb93a386Sopenharmony_ci # for non-trybot runs, which is misleading and confusing. Therefore, 155cb93a386Sopenharmony_ci # always specify patch=True. 156cb93a386Sopenharmony_ci patch=True, 157cb93a386Sopenharmony_ci patch_refs=patch_refs, 158cb93a386Sopenharmony_ci ) 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci if checkout_chromium or checkout_flutter: 161cb93a386Sopenharmony_ci gclient_env = {'DEPOT_TOOLS_UPDATE': '0'} 162cb93a386Sopenharmony_ci if extra_gclient_env: 163cb93a386Sopenharmony_ci gclient_env.update(extra_gclient_env) 164cb93a386Sopenharmony_ci with self.m.context(cwd=checkout_root, env=gclient_env): 165cb93a386Sopenharmony_ci self.m.gclient.runhooks() 166cb93a386Sopenharmony_ci return update_step.presentation.properties['got_revision'] 167