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 9from recipe_engine import recipe_api 10from recipe_engine import config_types 11 12 13class CheckoutApi(recipe_api.RecipeApi): 14 15 @property 16 def default_checkout_root(self): 17 """The default location for cached persistent checkouts.""" 18 return self.m.vars.cache_dir.join('work') 19 20 def git(self, checkout_root): 21 """Run the steps to perform a pure-git checkout without DEPS.""" 22 skia_dir = checkout_root.join('skia') 23 self.m.git.checkout( 24 self.m.properties['repository'], dir_path=skia_dir, 25 ref=self.m.properties['revision'], submodules=False) 26 if self.m.vars.is_trybot: 27 self.m.git('fetch', 'origin', self.m.properties['patch_ref']) 28 self.m.git('checkout', 'FETCH_HEAD') 29 self.m.git('rebase', self.m.properties['revision']) 30 return self.m.properties['revision'] 31 32 def bot_update(self, checkout_root, gclient_cache=None, 33 checkout_chromium=False, checkout_flutter=False, 34 extra_gclient_env=None, parent_rev=False, 35 flutter_android=False): 36 """Run the steps to obtain a checkout using bot_update. 37 38 Args: 39 checkout_root: Root directory where the code will be synced. 40 gclient_cache: Optional, directory of the gclient cache. 41 checkout_chromium: If True, will check out chromium/src.git in addition 42 to the primary repo. 43 checkout_flutter: If True, will checkout flutter in addition to the 44 primary repo. 45 extra_gclient_env: Map of extra environment variable names to their values 46 to supply while running gclient. 47 parent_rev: If True, checks out the parent of the specified revision, 48 rather than the revision itself, ie. HEAD^ for normal jobs and HEAD 49 (no patch) for try jobs. 50 flutter_android: Indicates that we're checking out flutter for Android. 51 """ 52 if not gclient_cache: 53 gclient_cache = self.m.vars.cache_dir.join('git') 54 if not extra_gclient_env: 55 extra_gclient_env = {} 56 57 cfg_kwargs = {} 58 59 # Use a persistent gclient cache for Swarming. 60 cfg_kwargs['CACHE_DIR'] = gclient_cache 61 62 # Create the checkout path if necessary. 63 # TODO(borenet): 'makedirs checkout_root' 64 self.m.file.ensure_directory('makedirs checkout_path', checkout_root) 65 66 # Initial cleanup. 67 gclient_cfg = self.m.gclient.make_config(**cfg_kwargs) 68 69 main_repo = self.m.properties['repository'] 70 if checkout_flutter: 71 main_repo = 'https://github.com/flutter/engine.git' 72 main_name = self.m.path.basename(main_repo) 73 if main_name.endswith('.git'): 74 main_name = main_name[:-len('.git')] 75 # Special case for flutter because it seems to need a very specific 76 # directory structure to successfully build. 77 if checkout_flutter and main_name == 'engine': 78 main_name = 'src/flutter' 79 main = gclient_cfg.solutions.add() 80 main.name = main_name 81 main.managed = False 82 main.url = main_repo 83 main.revision = self.m.properties.get('revision') or 'origin/master' 84 m = gclient_cfg.got_revision_mapping 85 m[main_name] = 'got_revision' 86 patch_root = main_name 87 patch_repo = main.url 88 if self.m.properties.get('patch_repo'): 89 patch_repo = self.m.properties['patch_repo'] 90 patch_root = patch_repo.split('/')[-1] 91 if patch_root.endswith('.git'): 92 patch_root = patch_root[:-4] 93 94 if checkout_flutter: 95 # Skia is a DEP of Flutter; the 'revision' property is a Skia revision, 96 # and any patch should be applied to Skia, not Flutter. 97 main.revision = 'origin/master' 98 main.managed = True 99 m[main_name] = 'got_flutter_revision' 100 if flutter_android: 101 gclient_cfg.target_os.add('android') 102 103 skia_dep_path = 'src/third_party/skia' 104 gclient_cfg.repo_path_map['https://skia.googlesource.com/skia'] = ( 105 skia_dep_path, 'HEAD') 106 gclient_cfg.revisions[skia_dep_path] = self.m.properties['revision'] 107 m[skia_dep_path] = 'got_revision' 108 patch_root = skia_dep_path 109 110 if checkout_chromium: 111 main.custom_vars['checkout_chromium'] = True 112 extra_gclient_env['GYP_CHROMIUM_NO_ACTION'] = '0' 113 114 # TODO(rmistry): Remove the below block after there is a solution for 115 # crbug.com/616443 116 entries_file = checkout_root.join('.gclient_entries') 117 if self.m.path.exists(entries_file) or self._test_data.enabled: 118 self.m.file.remove('remove %s' % entries_file, 119 entries_file) 120 121 # Run bot_update. 122 if not self.m.vars.is_trybot and parent_rev: 123 main.revision = main.revision + '^' 124 125 patch_refs = None 126 patch_ref = self.m.properties.get('patch_ref') 127 if patch_ref: 128 patch_refs = ['%s@%s' % (self.m.properties['patch_repo'], patch_ref)] 129 130 self.m.gclient.c = gclient_cfg 131 with self.m.context(cwd=checkout_root): 132 update_step = self.m.bot_update.ensure_checkout( 133 patch_root=patch_root, 134 # The logic in ensure_checkout for this arg is fairly naive, so if 135 # patch=False, we'll see "... (without patch)" in the step names, even 136 # for non-trybot runs, which is misleading and confusing. Therefore, 137 # always specify patch=True for non-trybot runs. 138 patch=not (self.m.vars.is_trybot and parent_rev), 139 patch_refs=patch_refs, 140 ) 141 142 if checkout_chromium or checkout_flutter: 143 gclient_env = {'DEPOT_TOOLS_UPDATE': '0'} 144 if extra_gclient_env: 145 gclient_env.update(extra_gclient_env) 146 with self.m.context(cwd=checkout_root, env=gclient_env): 147 self.m.gclient.runhooks() 148 return update_step.presentation.properties['got_revision'] 149