1 # Copyright (c) 2013 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.
5 """Set of operations/utilities related to checking out the depot, and
6 outputting annotations on the buildbot waterfall. These are intended to be
7 used by the bisection scripts."""
17 "url" : "https://chromium.googlesource.com/chromium/src.git",
18 "deps_file" : ".DEPS.git",
21 "src/data/page_cycler": "https://chrome-internal.googlesource.com/"
22 "chrome/data/page_cycler/.git",
23 "src/data/dom_perf": "https://chrome-internal.googlesource.com/"
24 "chrome/data/dom_perf/.git",
25 "src/tools/perf/data": "https://chrome-internal.googlesource.com/"
26 "chrome/tools/perf/data/.git",
31 GCLIENT_ANDROID
= "\ntarget_os = ['android']"
32 GCLIENT_CUSTOM_DEPS_V8
= {"src/v8_bleeding_edge": "git://github.com/v8/v8.git"}
33 FILE_DEPS_GIT
= '.DEPS.git'
36 'https://chrome-internal.googlesource.com/chromeos/manifest-internal/',
38 'https://git.chromium.org/external/repo.git'
41 REPO_SYNC_COMMAND
= 'git checkout -f $(git rev-list --max-count=1 '\
42 '--before=%d remotes/m/master)'
44 def OutputAnnotationStepStart(name
):
45 """Outputs appropriate annotation to signal the start of a step to
49 name: The name of the step.
52 print '@@@SEED_STEP %s@@@' % name
53 print '@@@STEP_CURSOR %s@@@' % name
54 print '@@@STEP_STARTED@@@'
58 def OutputAnnotationStepClosed():
59 """Outputs appropriate annotation to signal the closing of a step to
62 print '@@@STEP_CLOSED@@@'
66 def CreateAndChangeToSourceDirectory(working_directory
):
67 """Creates a directory 'bisect' as a subdirectory of 'working_directory'. If
68 the function is successful, the current working directory will change to that
69 of the new 'bisect' directory.
72 True if the directory was successfully created (or already existed).
75 os
.chdir(working_directory
)
79 if e
.errno
!= errno
.EEXIST
:
85 def SubprocessCall(cmd
, cwd
=None):
86 """Runs a subprocess with specified parameters.
89 params: A list of parameters to pass to gclient.
90 cwd: Working directory to run from.
93 The return code of the call.
96 # "HOME" isn't normally defined on windows, but is needed
97 # for git to find the user's .netrc file.
98 if not os
.getenv('HOME'):
99 os
.environ
['HOME'] = os
.environ
['USERPROFILE']
100 shell
= os
.name
== 'nt'
101 return subprocess
.call(cmd
, shell
=shell
, cwd
=cwd
)
104 def RunGClient(params
, cwd
=None):
105 """Runs gclient with the specified parameters.
108 params: A list of parameters to pass to gclient.
109 cwd: Working directory to run from.
112 The return code of the call.
114 cmd
= ['gclient'] + params
116 return SubprocessCall(cmd
, cwd
=cwd
)
120 """Runs cros repo command with specified parameters.
123 params: A list of parameters to pass to gclient.
126 The return code of the call.
128 cmd
= ['repo'] + params
130 return SubprocessCall(cmd
)
133 def RunRepoSyncAtTimestamp(timestamp
):
134 """Syncs all git depots to the timestamp specified using repo forall.
137 params: Unix timestamp to sync to.
140 The return code of the call.
142 repo_sync
= REPO_SYNC_COMMAND
% timestamp
143 cmd
= ['forall', '-c', REPO_SYNC_COMMAND
% timestamp
]
147 def RunGClientAndCreateConfig(opts
, custom_deps
=None, cwd
=None):
148 """Runs gclient and creates a config containing both src and src-internal.
151 opts: The options parsed from the command line through parse_args().
152 custom_deps: A dictionary of additional dependencies to add to .gclient.
153 cwd: Working directory to run from.
156 The return code of the call.
158 spec
= GCLIENT_SPEC_DATA
161 for k
, v
in custom_deps
.iteritems():
162 spec
[0]['custom_deps'][k
] = v
164 # Cannot have newlines in string on windows
165 spec
= 'solutions =' + str(spec
)
166 spec
= ''.join([l
for l
in spec
.splitlines()])
168 if opts
.target_platform
== 'android':
169 spec
+= GCLIENT_SPEC_ANDROID
171 return_code
= RunGClient(
172 ['config', '--spec=%s' % spec
, '--git-deps'], cwd
=cwd
)
176 def IsDepsFileBlink():
177 """Reads .DEPS.git and returns whether or not we're using blink.
180 True if blink, false if webkit.
182 locals = {'Var': lambda _
: locals["vars"][_
],
183 'From': lambda *args
: None}
184 execfile(FILE_DEPS_GIT
, {}, locals)
185 return 'blink.git' in locals['vars']['webkit_url']
188 def RemoveThirdPartyWebkitDirectory():
189 """Removes third_party/WebKit.
195 path_to_dir
= os
.path
.join(os
.getcwd(), 'third_party', 'WebKit')
196 if os
.path
.exists(path_to_dir
):
197 shutil
.rmtree(path_to_dir
)
199 if e
.errno
!= errno
.ENOENT
:
204 def RunGClientAndSync(reset
, cwd
=None):
205 """Runs gclient and does a normal sync.
208 reset: Whether to reset any changes to the depot.
209 cwd: Working directory to run from.
212 The return code of the call.
214 params
= ['sync', '--verbose', '--nohooks']
216 params
.extend(['--reset', '--force', '--delete_unversioned_trees'])
217 return RunGClient(params
, cwd
=cwd
)
220 def SetupGitDepot(opts
, reset
):
221 """Sets up the depot for the bisection. The depot will be located in a
222 subdirectory called 'bisect'.
225 opts: The options parsed from the command line through parse_args().
226 reset: Whether to reset any changes to the depot.
229 True if gclient successfully created the config file and did a sync, False
232 name
= 'Setting up Bisection Depot'
234 if opts
.output_buildbot_annotations
:
235 OutputAnnotationStepStart(name
)
239 if not RunGClientAndCreateConfig(opts
):
240 passed_deps_check
= True
241 if os
.path
.isfile(os
.path
.join('src', FILE_DEPS_GIT
)):
244 if not IsDepsFileBlink():
245 passed_deps_check
= RemoveThirdPartyWebkitDirectory()
247 passed_deps_check
= True
250 if passed_deps_check
and not RunGClientAndSync(reset
):
253 if opts
.output_buildbot_annotations
:
255 OutputAnnotationStepClosed()
261 """Sets up cros repo for bisecting chromeos.
264 Returns 0 on success.
270 if e
.errno
!= errno
.EEXIST
:
274 cmd
= ['init', '-u'] + REPO_PARAMS
279 if not RunRepo(['sync']):
286 def SetupAndroidBuildEnvironment(opts
):
287 """Sets up the android build environment.
290 opts: The options parsed from the command line through parse_args().
291 path_to_file: Path to the bisect script's directory.
296 path_to_file
= os
.path
.join('build', 'android', 'envsetup.sh')
297 proc
= subprocess
.Popen(['bash', '-c', 'source %s && env' % path_to_file
],
298 stdout
=subprocess
.PIPE
,
299 stderr
=subprocess
.PIPE
,
301 (out
, _
) = proc
.communicate()
303 for line
in out
.splitlines():
304 (k
, _
, v
) = line
.partition('=')
306 return not proc
.returncode
309 def SetupPlatformBuildEnvironment(opts
):
310 """Performs any platform specific setup.
313 opts: The options parsed from the command line through parse_args().
314 path_to_file: Path to the bisect script's directory.
319 if opts
.target_platform
== 'android':
320 return SetupAndroidBuildEnvironment(opts
)
321 elif opts
.target_platform
== 'cros':
322 return SetupCrosRepo()
327 def CreateBisectDirectoryAndSetupDepot(opts
, reset
=False):
328 """Sets up a subdirectory 'bisect' and then retrieves a copy of the depot
332 opts: The options parsed from the command line through parse_args().
333 reset: Whether to reset any changes to the depot.
336 Returns 0 on success, otherwise 1.
338 if not CreateAndChangeToSourceDirectory(opts
.working_directory
):
339 print 'Error: Could not create bisect directory.'
343 if not SetupGitDepot(opts
, reset
):
344 print 'Error: Failed to grab source.'