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/data/mach_ports": "https://chrome-internal.googlesource.com/"
26 "chrome/data/mach_ports/.git",
27 "src/tools/perf/data": "https://chrome-internal.googlesource.com/"
28 "chrome/tools/perf/data/.git",
29 "src/third_party/adobe/flash/binaries/ppapi/linux":
30 "https://chrome-internal.googlesource.com/"
31 "chrome/deps/adobe/flash/binaries/ppapi/linux/.git",
32 "src/third_party/adobe/flash/binaries/ppapi/linux_x64":
33 "https://chrome-internal.googlesource.com/"
34 "chrome/deps/adobe/flash/binaries/ppapi/linux_x64/.git",
35 "src/third_party/adobe/flash/binaries/ppapi/mac":
36 "https://chrome-internal.googlesource.com/"
37 "chrome/deps/adobe/flash/binaries/ppapi/mac/.git",
38 "src/third_party/adobe/flash/binaries/ppapi/mac_64":
39 "https://chrome-internal.googlesource.com/"
40 "chrome/deps/adobe/flash/binaries/ppapi/mac_64/.git",
41 "src/third_party/adobe/flash/binaries/ppapi/win":
42 "https://chrome-internal.googlesource.com/"
43 "chrome/deps/adobe/flash/binaries/ppapi/win/.git",
44 "src/third_party/adobe/flash/binaries/ppapi/win_x64":
45 "https://chrome-internal.googlesource.com/"
46 "chrome/deps/adobe/flash/binaries/ppapi/win_x64/.git",
51 GCLIENT_SPEC_ANDROID
= "\ntarget_os = ['android']"
52 GCLIENT_CUSTOM_DEPS_V8
= {"src/v8_bleeding_edge": "git://github.com/v8/v8.git"}
53 FILE_DEPS_GIT
= '.DEPS.git'
56 'https://chrome-internal.googlesource.com/chromeos/manifest-internal/',
58 'https://git.chromium.org/external/repo.git'
61 REPO_SYNC_COMMAND
= 'git checkout -f $(git rev-list --max-count=1 '\
62 '--before=%d remotes/m/master)'
66 def OutputAnnotationStepStart(name
):
67 """Outputs appropriate annotation to signal the start of a step to
71 name: The name of the step.
74 print '@@@SEED_STEP %s@@@' % name
75 print '@@@STEP_CURSOR %s@@@' % name
76 print '@@@STEP_STARTED@@@'
81 def OutputAnnotationStepClosed():
82 """Outputs appropriate annotation to signal the closing of a step to
85 print '@@@STEP_CLOSED@@@'
90 def CreateAndChangeToSourceDirectory(working_directory
):
91 """Creates a directory 'bisect' as a subdirectory of 'working_directory'. If
92 the function is successful, the current working directory will change to that
93 of the new 'bisect' directory.
96 True if the directory was successfully created (or already existed).
99 os
.chdir(working_directory
)
103 if e
.errno
!= errno
.EEXIST
:
109 def SubprocessCall(cmd
, cwd
=None):
110 """Runs a subprocess with specified parameters.
113 params: A list of parameters to pass to gclient.
114 cwd: Working directory to run from.
117 The return code of the call.
120 # "HOME" isn't normally defined on windows, but is needed
121 # for git to find the user's .netrc file.
122 if not os
.getenv('HOME'):
123 os
.environ
['HOME'] = os
.environ
['USERPROFILE']
124 shell
= os
.name
== 'nt'
125 return subprocess
.call(cmd
, shell
=shell
, cwd
=cwd
)
128 def RunGClient(params
, cwd
=None):
129 """Runs gclient with the specified parameters.
132 params: A list of parameters to pass to gclient.
133 cwd: Working directory to run from.
136 The return code of the call.
138 cmd
= ['gclient'] + params
140 return SubprocessCall(cmd
, cwd
=cwd
)
144 """Runs cros repo command with specified parameters.
147 params: A list of parameters to pass to gclient.
150 The return code of the call.
152 cmd
= ['repo'] + params
154 return SubprocessCall(cmd
)
157 def RunRepoSyncAtTimestamp(timestamp
):
158 """Syncs all git depots to the timestamp specified using repo forall.
161 params: Unix timestamp to sync to.
164 The return code of the call.
166 repo_sync
= REPO_SYNC_COMMAND
% timestamp
167 cmd
= ['forall', '-c', REPO_SYNC_COMMAND
% timestamp
]
171 def RunGClientAndCreateConfig(opts
, custom_deps
=None, cwd
=None):
172 """Runs gclient and creates a config containing both src and src-internal.
175 opts: The options parsed from the command line through parse_args().
176 custom_deps: A dictionary of additional dependencies to add to .gclient.
177 cwd: Working directory to run from.
180 The return code of the call.
182 spec
= GCLIENT_SPEC_DATA
185 for k
, v
in custom_deps
.iteritems():
186 spec
[0]['custom_deps'][k
] = v
188 # Cannot have newlines in string on windows
189 spec
= 'solutions =' + str(spec
)
190 spec
= ''.join([l
for l
in spec
.splitlines()])
192 if opts
.target_platform
== 'android':
193 spec
+= GCLIENT_SPEC_ANDROID
195 return_code
= RunGClient(
196 ['config', '--spec=%s' % spec
, '--git-deps'], cwd
=cwd
)
200 def IsDepsFileBlink():
201 """Reads .DEPS.git and returns whether or not we're using blink.
204 True if blink, false if webkit.
206 locals = {'Var': lambda _
: locals["vars"][_
],
207 'From': lambda *args
: None}
208 execfile(FILE_DEPS_GIT
, {}, locals)
209 return 'blink.git' in locals['vars']['webkit_url']
212 def RemoveThirdPartyWebkitDirectory():
213 """Removes third_party/WebKit.
219 path_to_dir
= os
.path
.join(os
.getcwd(), 'third_party', 'WebKit')
220 if os
.path
.exists(path_to_dir
):
221 shutil
.rmtree(path_to_dir
)
223 if e
.errno
!= errno
.ENOENT
:
228 def RunGClientAndSync(cwd
=None):
229 """Runs gclient and does a normal sync.
232 cwd: Working directory to run from.
235 The return code of the call.
237 params
= ['sync', '--verbose', '--nohooks', '--reset', '--force']
238 return RunGClient(params
, cwd
=cwd
)
241 def SetupGitDepot(opts
):
242 """Sets up the depot for the bisection. The depot will be located in a
243 subdirectory called 'bisect'.
246 opts: The options parsed from the command line through parse_args().
249 True if gclient successfully created the config file and did a sync, False
252 name
= 'Setting up Bisection Depot'
254 if opts
.output_buildbot_annotations
:
255 OutputAnnotationStepStart(name
)
259 if not RunGClientAndCreateConfig(opts
):
260 passed_deps_check
= True
261 if os
.path
.isfile(os
.path
.join('src', FILE_DEPS_GIT
)):
264 if not IsDepsFileBlink():
265 passed_deps_check
= RemoveThirdPartyWebkitDirectory()
267 passed_deps_check
= True
270 if passed_deps_check
:
271 RunGClient(['revert'])
272 if not RunGClientAndSync():
275 if opts
.output_buildbot_annotations
:
277 OutputAnnotationStepClosed()
283 """Sets up cros repo for bisecting chromeos.
286 Returns 0 on success.
292 if e
.errno
!= errno
.EEXIST
:
296 cmd
= ['init', '-u'] + REPO_PARAMS
301 if not RunRepo(['sync']):
308 def CopyAndSaveOriginalEnvironmentVars():
309 """Makes a copy of the current environment variables."""
310 # TODO: Waiting on crbug.com/255689, will remove this after.
312 for k
, v
in os
.environ
.iteritems():
314 vars_to_remove
.append(k
)
315 vars_to_remove
.append('CHROME_SRC')
316 vars_to_remove
.append('CHROMIUM_GYP_FILE')
317 vars_to_remove
.append('GYP_CROSSCOMPILE')
318 vars_to_remove
.append('GYP_DEFINES')
319 vars_to_remove
.append('GYP_GENERATORS')
320 vars_to_remove
.append('GYP_GENERATOR_FLAGS')
321 vars_to_remove
.append('OBJCOPY')
322 for k
in vars_to_remove
:
323 if os
.environ
.has_key(k
):
327 ORIGINAL_ENV
= os
.environ
.copy()
330 def SetupAndroidBuildEnvironment(opts
):
331 """Sets up the android build environment.
334 opts: The options parsed from the command line through parse_args().
335 path_to_file: Path to the bisect script's directory.
341 # Revert the environment variables back to default before setting them up
343 env_vars
= os
.environ
.copy()
344 for k
, _
in env_vars
.iteritems():
346 for k
, v
in ORIGINAL_ENV
.iteritems():
349 path_to_file
= os
.path
.join('build', 'android', 'envsetup.sh')
350 proc
= subprocess
.Popen(['bash', '-c', 'source %s && env' % path_to_file
],
351 stdout
=subprocess
.PIPE
,
352 stderr
=subprocess
.PIPE
,
354 (out
, _
) = proc
.communicate()
356 for line
in out
.splitlines():
357 (k
, _
, v
) = line
.partition('=')
359 return not proc
.returncode
362 def SetupPlatformBuildEnvironment(opts
):
363 """Performs any platform specific setup.
366 opts: The options parsed from the command line through parse_args().
367 path_to_file: Path to the bisect script's directory.
372 if opts
.target_platform
== 'android':
373 CopyAndSaveOriginalEnvironmentVars()
374 return SetupAndroidBuildEnvironment(opts
)
375 elif opts
.target_platform
== 'cros':
376 return SetupCrosRepo()
381 def CreateBisectDirectoryAndSetupDepot(opts
):
382 """Sets up a subdirectory 'bisect' and then retrieves a copy of the depot
386 opts: The options parsed from the command line through parse_args().
387 reset: Whether to reset any changes to the depot.
390 Returns 0 on success, otherwise 1.
392 if not CreateAndChangeToSourceDirectory(opts
.working_directory
):
393 print 'Error: Could not create bisect directory.'
397 if not SetupGitDepot(opts
):
398 print 'Error: Failed to grab source.'