OLD | NEW |
---|---|
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Utility functions used by the bisect tool. | 5 """Utility functions used by the bisect tool. |
6 | 6 |
7 This includes functions related to checking out the depot and outputting | 7 This includes functions related to checking out the depot and outputting |
8 annotations for the Buildbot waterfall. | 8 annotations for the Buildbot waterfall. |
9 """ | 9 """ |
10 | 10 |
11 import errno | 11 import errno |
12 import imp | 12 import imp |
13 import os | 13 import os |
14 import shutil | |
15 import stat | 14 import stat |
16 import subprocess | 15 import subprocess |
17 import sys | 16 import sys |
18 | 17 |
19 DEFAULT_GCLIENT_CUSTOM_DEPS = { | 18 DEFAULT_GCLIENT_CUSTOM_DEPS = { |
20 'src/data/page_cycler': 'https://chrome-internal.googlesource.com/' | 19 'src/data/page_cycler': 'https://chrome-internal.googlesource.com/' |
21 'chrome/data/page_cycler/.git', | 20 'chrome/data/page_cycler/.git', |
22 'src/data/dom_perf': 'https://chrome-internal.googlesource.com/' | 21 'src/data/dom_perf': 'https://chrome-internal.googlesource.com/' |
23 'chrome/data/dom_perf/.git', | 22 'chrome/data/dom_perf/.git', |
24 'src/data/mach_ports': 'https://chrome-internal.googlesource.com/' | 23 'src/data/mach_ports': 'https://chrome-internal.googlesource.com/' |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
301 path: The path name passed to func. | 300 path: The path name passed to func. |
302 _: Exception information from sys.exc_info(). Not used. | 301 _: Exception information from sys.exc_info(). Not used. |
303 """ | 302 """ |
304 if not os.access(path, os.W_OK): | 303 if not os.access(path, os.W_OK): |
305 os.chmod(path, stat.S_IWUSR) | 304 os.chmod(path, stat.S_IWUSR) |
306 func(path) | 305 func(path) |
307 else: | 306 else: |
308 raise | 307 raise |
309 | 308 |
310 | 309 |
311 def RemoveThirdPartyDirectory(dir_name): | |
312 """Removes third_party directory from the source. | |
313 | |
314 At some point, some of the third_parties were causing issues to changes in | |
315 the way they are synced. We remove such folder in order to avoid sync errors | |
316 while bisecting. | |
317 | |
318 Returns: | |
319 True on success, otherwise False. | |
320 """ | |
321 path_to_dir = os.path.join(os.getcwd(), 'third_party', dir_name) | |
322 try: | |
323 if os.path.exists(path_to_dir): | |
324 shutil.rmtree(path_to_dir, onerror=OnAccessError) | |
325 except OSError, e: | |
326 print 'Error #%d while running shutil.rmtree(%s): %s' % ( | |
327 e.errno, path_to_dir, str(e)) | |
328 if e.errno != errno.ENOENT: | |
329 return False | |
330 return True | |
331 | |
332 | |
333 def _CleanupPreviousGitRuns(): | 310 def _CleanupPreviousGitRuns(): |
334 """Cleans up any leftover index.lock files after running git.""" | 311 """Cleans up any leftover index.lock files after running git.""" |
335 # If a previous run of git crashed, or bot was reset, etc., then we might | 312 # If a previous run of git crashed, or bot was reset, etc., then we might |
336 # end up with leftover index.lock files. | 313 # end up with leftover index.lock files. |
337 for path, _, files in os.walk(os.getcwd()): | 314 for path, _, files in os.walk(os.getcwd()): |
338 for cur_file in files: | 315 for cur_file in files: |
339 if cur_file.endswith('index.lock'): | 316 if cur_file.endswith('index.lock'): |
340 path_to_file = os.path.join(path, cur_file) | 317 path_to_file = os.path.join(path, cur_file) |
341 os.remove(path_to_file) | 318 os.remove(path_to_file) |
342 | 319 |
343 | 320 |
344 def RunGClientAndSync(cwd=None): | 321 def RunGClientAndSync(cwd=None): |
345 """Runs gclient and does a normal sync. | 322 """Runs gclient and does a normal sync. |
346 | 323 |
347 Args: | 324 Args: |
348 cwd: Working directory to run from. | 325 cwd: Working directory to run from. |
349 | 326 |
350 Returns: | 327 Returns: |
351 The return code of the call. | 328 The return code of the call. |
352 """ | 329 """ |
353 params = ['sync', '--verbose', '--nohooks', '--reset', '--force'] | 330 params = ['sync', '--verbose', '--nohooks', '--reset', '--force', |
331 '--delete_unversioned_trees'] | |
354 return RunGClient(params, cwd=cwd) | 332 return RunGClient(params, cwd=cwd) |
355 | 333 |
356 | 334 |
335 def ResetToMasterBranch(cwd=None): | |
336 """Checkouts master branch.""" | |
qyearsley
2014/09/27 01:45:34
"Checks out the master branch." or "Moves to the m
prasadv
2014/09/29 17:36:13
Done.
| |
337 current_branch, returncode = RunGit( | |
338 ['rev-parse', '--abbrev-ref', 'HEAD'], cwd=cwd) | |
339 if returncode: | |
340 print 'Failed to Switch to master branch %s' % current_branch | |
341 return False | |
qyearsley
2014/09/27 01:45:34
As you noted, running "git rev-parse --abbrev-ref
prasadv
2014/09/29 17:36:13
Actually we don't need this function, I removed th
| |
342 # Forcibly reset to master branch. | |
343 CheckRunGit(['checkout', '-f', 'master'], cwd=cwd) | |
344 | |
345 return True | |
346 | |
347 | |
357 def SetupGitDepot(opts, custom_deps): | 348 def SetupGitDepot(opts, custom_deps): |
358 """Sets up the depot for the bisection. | 349 """Sets up the depot for the bisection. |
359 | 350 |
360 The depot will be located in a subdirectory called 'bisect'. | 351 The depot will be located in a subdirectory called 'bisect'. |
361 | 352 |
362 Args: | 353 Args: |
363 opts: The options parsed from the command line through parse_args(). | 354 opts: The options parsed from the command line through parse_args(). |
364 custom_deps: A dictionary of additional dependencies to add to .gclient. | 355 custom_deps: A dictionary of additional dependencies to add to .gclient. |
365 | 356 |
366 Returns: | 357 Returns: |
367 True if gclient successfully created the config file and did a sync, False | 358 True if gclient successfully created the config file and did a sync, False |
368 otherwise. | 359 otherwise. |
369 """ | 360 """ |
370 name = 'Setting up Bisection Depot' | 361 name = 'Setting up Bisection Depot' |
362 try: | |
363 if opts.output_buildbot_annotations: | |
364 OutputAnnotationStepStart(name) | |
371 | 365 |
372 if opts.output_buildbot_annotations: | 366 if RunGClientAndCreateConfig(opts, custom_deps): |
373 OutputAnnotationStepStart(name) | 367 return False |
374 | 368 |
375 passed = False | 369 _CleanupPreviousGitRuns() |
376 | 370 RunGClient(['revert']) |
377 if not RunGClientAndCreateConfig(opts, custom_deps): | 371 return not RunGClientAndSync() |
378 passed_deps_check = True | 372 finally: |
379 if os.path.isfile(os.path.join('src', FILE_DEPS_GIT)): | 373 if opts.output_buildbot_annotations: |
380 cwd = os.getcwd() | 374 OutputAnnotationStepClosed() |
381 os.chdir('src') | |
382 if passed_deps_check: | |
383 passed_deps_check = RemoveThirdPartyDirectory('libjingle') | |
384 if passed_deps_check: | |
385 passed_deps_check = RemoveThirdPartyDirectory('skia') | |
386 os.chdir(cwd) | |
387 | |
388 if passed_deps_check: | |
389 _CleanupPreviousGitRuns() | |
390 | |
391 RunGClient(['revert']) | |
392 if not RunGClientAndSync(): | |
393 passed = True | |
394 | |
395 if opts.output_buildbot_annotations: | |
396 print | |
397 OutputAnnotationStepClosed() | |
398 | |
399 return passed | |
400 | 375 |
401 | 376 |
402 def CheckIfBisectDepotExists(opts): | 377 def CheckIfBisectDepotExists(opts): |
403 """Checks if the bisect directory already exists. | 378 """Checks if the bisect directory already exists. |
404 | 379 |
405 Args: | 380 Args: |
406 opts: The options parsed from the command line through parse_args(). | 381 opts: The options parsed from the command line through parse_args(). |
407 | 382 |
408 Returns: | 383 Returns: |
409 Returns True if it exists. | 384 Returns True if it exists. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 | 419 |
445 | 420 |
446 def CreateBisectDirectoryAndSetupDepot(opts, custom_deps): | 421 def CreateBisectDirectoryAndSetupDepot(opts, custom_deps): |
447 """Sets up a subdirectory 'bisect' and then retrieves a copy of the depot | 422 """Sets up a subdirectory 'bisect' and then retrieves a copy of the depot |
448 there using gclient. | 423 there using gclient. |
449 | 424 |
450 Args: | 425 Args: |
451 opts: The options parsed from the command line through parse_args(). | 426 opts: The options parsed from the command line through parse_args(). |
452 custom_deps: A dictionary of additional dependencies to add to .gclient. | 427 custom_deps: A dictionary of additional dependencies to add to .gclient. |
453 """ | 428 """ |
429 if CheckIfBisectDepotExists(opts): | |
430 path_to_dir = os.path.join(os.path.abspath(opts.working_directory), | |
431 'bisect', 'src') | |
qyearsley
2014/09/27 01:45:34
By the way, do you think it's a good idea to make
prasadv
2014/09/29 17:36:14
Done.
| |
432 (output, _) = RunGit(['rev-parse', '--is-inside-work-tree'], | |
433 cwd=path_to_dir) | |
qyearsley
2014/09/27 01:45:33
Under what circumstances are we not "inside work t
prasadv
2014/09/29 17:36:14
This can happen when you are bisect folder but gcl
| |
434 if output.strip() == 'true': | |
435 if not ResetToMasterBranch(path_to_dir): | |
436 raise RuntimeError('Failed to reset branch to master.') | |
437 | |
454 if not _CreateAndChangeToSourceDirectory(opts.working_directory): | 438 if not _CreateAndChangeToSourceDirectory(opts.working_directory): |
455 raise RuntimeError('Could not create bisect directory.') | 439 raise RuntimeError('Could not create bisect directory.') |
456 | 440 |
457 if not SetupGitDepot(opts, custom_deps): | 441 if not SetupGitDepot(opts, custom_deps): |
458 raise RuntimeError('Failed to grab source.') | 442 raise RuntimeError('Failed to grab source.') |
459 | 443 |
460 | 444 |
461 def RunProcess(command): | 445 def RunProcess(command): |
462 """Runs an arbitrary command. | 446 """Runs an arbitrary command. |
463 | 447 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
572 return sys.platform.startswith('linux') | 556 return sys.platform.startswith('linux') |
573 | 557 |
574 | 558 |
575 def IsMacHost(): | 559 def IsMacHost(): |
576 """Checks whether or not the script is running on Mac. | 560 """Checks whether or not the script is running on Mac. |
577 | 561 |
578 Returns: | 562 Returns: |
579 True if running on Mac. | 563 True if running on Mac. |
580 """ | 564 """ |
581 return sys.platform.startswith('darwin') | 565 return sys.platform.startswith('darwin') |
OLD | NEW |