OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Performance Test Bisect Tool | 6 """Performance Test Bisect Tool |
7 | 7 |
8 This script bisects a series of changelists using binary search. It starts at | 8 This script bisects a series of changelists using binary search. It starts at |
9 a bad revision where a performance metric has regressed, and asks for a last | 9 a bad revision where a performance metric has regressed, and asks for a last |
10 known-good revision. It will then binary search across this revision range by | 10 known-good revision. It will then binary search across this revision range by |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 command: A list containing the args to git. | 244 command: A list containing the args to git. |
245 | 245 |
246 Returns: | 246 Returns: |
247 A tuple of the output and return code. | 247 A tuple of the output and return code. |
248 """ | 248 """ |
249 command = ['git'] + command | 249 command = ['git'] + command |
250 | 250 |
251 return RunProcess(command) | 251 return RunProcess(command) |
252 | 252 |
253 | 253 |
254 def CheckRunGit(command): | |
255 """Run a git subcommand, returning its output and return code. Asserts if | |
256 the return code of the call is non-zero. | |
257 | |
258 Args: | |
259 command: A list containing the args to git. | |
260 | |
261 Returns: | |
262 A tuple of the output and return code. | |
263 """ | |
264 (output, return_code) = RunGit(command) | |
265 | |
266 assert not return_code, 'An error occurred while running'\ | |
267 ' "git %s"' % ' '.join(command) | |
268 return (output, return_code) | |
tonyg
2013/05/28 23:45:06
Since we know return_code is 0 at this point, I'd
shatch
2013/05/29 16:25:28
Done.
| |
269 | |
270 | |
254 def BuildWithMake(threads, targets, print_output): | 271 def BuildWithMake(threads, targets, print_output): |
255 cmd = ['make', 'BUILDTYPE=Release', '-j%d' % threads] + targets | 272 cmd = ['make', 'BUILDTYPE=Release', '-j%d' % threads] + targets |
256 | 273 |
257 (output, return_code) = RunProcess(cmd, print_output) | 274 (output, return_code) = RunProcess(cmd, print_output) |
258 | 275 |
259 return not return_code | 276 return not return_code |
260 | 277 |
261 | 278 |
262 def BuildWithNinja(threads, targets, print_output): | 279 def BuildWithNinja(threads, targets, print_output): |
263 cmd = ['ninja', '-C', os.path.join('out', 'Release'), | 280 cmd = ['ninja', '-C', os.path.join('out', 'Release'), |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
319 Args: | 336 Args: |
320 revision_range_end: The SHA1 for the end of the range. | 337 revision_range_end: The SHA1 for the end of the range. |
321 revision_range_start: The SHA1 for the beginning of the range. | 338 revision_range_start: The SHA1 for the beginning of the range. |
322 | 339 |
323 Returns: | 340 Returns: |
324 A list of the revisions between |revision_range_start| and | 341 A list of the revisions between |revision_range_start| and |
325 |revision_range_end| (inclusive). | 342 |revision_range_end| (inclusive). |
326 """ | 343 """ |
327 revision_range = '%s..%s' % (revision_range_start, revision_range_end) | 344 revision_range = '%s..%s' % (revision_range_start, revision_range_end) |
328 cmd = ['log', '--format=%H', '-10000', '--first-parent', revision_range] | 345 cmd = ['log', '--format=%H', '-10000', '--first-parent', revision_range] |
329 (log_output, return_code) = RunGit(cmd) | 346 (log_output, return_code) = CheckRunGit(cmd) |
330 | |
331 assert not return_code, 'An error occurred while running'\ | |
332 ' "git %s"' % ' '.join(cmd) | |
333 | 347 |
334 revision_hash_list = log_output.split() | 348 revision_hash_list = log_output.split() |
335 revision_hash_list.append(revision_range_start) | 349 revision_hash_list.append(revision_range_start) |
336 | 350 |
337 return revision_hash_list | 351 return revision_hash_list |
338 | 352 |
339 def SyncToRevision(self, revision, use_gclient=True): | 353 def SyncToRevision(self, revision, use_gclient=True): |
340 """Syncs to the specified revision. | 354 """Syncs to the specified revision. |
341 | 355 |
342 Args: | 356 Args: |
343 revision: The revision to sync to. | 357 revision: The revision to sync to. |
344 use_gclient: Specifies whether or not we should sync using gclient or | 358 use_gclient: Specifies whether or not we should sync using gclient or |
345 just use source control directly. | 359 just use source control directly. |
346 | 360 |
347 Returns: | 361 Returns: |
348 True if successful. | 362 True if successful. |
349 """ | 363 """ |
350 | 364 |
351 if use_gclient: | 365 if use_gclient: |
352 results = self.SyncToRevisionWithGClient(revision) | 366 results = self.SyncToRevisionWithGClient(revision) |
353 else: | 367 else: |
354 results = RunGit(['checkout', revision])[1] | 368 results = RunGit(['checkout', revision])[1] |
tonyg
2013/05/28 23:45:06
CheckRunGit?
shatch
2013/05/29 16:25:28
Not sure under which conditions checkout can fail.
| |
355 | 369 |
356 return not results | 370 return not results |
357 | 371 |
358 def ResolveToRevision(self, revision_to_check, depot, search): | 372 def ResolveToRevision(self, revision_to_check, depot, search): |
359 """If an SVN revision is supplied, try to resolve it to a git SHA1. | 373 """If an SVN revision is supplied, try to resolve it to a git SHA1. |
360 | 374 |
361 Args: | 375 Args: |
362 revision_to_check: The user supplied revision string that may need to be | 376 revision_to_check: The user supplied revision string that may need to be |
363 resolved to a git SHA1. | 377 resolved to a git SHA1. |
364 depot: The depot the revision_to_check is from. | 378 depot: The depot the revision_to_check is from. |
(...skipping 17 matching lines...) Expand all Loading... | |
382 | 396 |
383 if search > 0: | 397 if search > 0: |
384 search_range = xrange(svn_revision, svn_revision + search, 1) | 398 search_range = xrange(svn_revision, svn_revision + search, 1) |
385 else: | 399 else: |
386 search_range = xrange(svn_revision, svn_revision + search, -1) | 400 search_range = xrange(svn_revision, svn_revision + search, -1) |
387 | 401 |
388 for i in search_range: | 402 for i in search_range: |
389 svn_pattern = 'git-svn-id: %s@%d' % (depot_svn, i) | 403 svn_pattern = 'git-svn-id: %s@%d' % (depot_svn, i) |
390 cmd = ['log', '--format=%H', '-1', '--grep', svn_pattern, 'origin/master'] | 404 cmd = ['log', '--format=%H', '-1', '--grep', svn_pattern, 'origin/master'] |
391 | 405 |
392 (log_output, return_code) = RunGit(cmd) | 406 (log_output, return_code) = CheckRunGit(cmd) |
393 | |
394 assert not return_code, 'An error occurred while running'\ | |
395 ' "git %s"' % ' '.join(cmd) | |
396 | 407 |
397 if not return_code: | 408 if not return_code: |
398 log_output = log_output.strip() | 409 log_output = log_output.strip() |
399 | 410 |
400 if log_output: | 411 if log_output: |
401 git_revision = log_output | 412 git_revision = log_output |
402 | 413 |
403 break | 414 break |
404 | 415 |
405 return git_revision | 416 return git_revision |
406 | 417 |
407 def IsInProperBranch(self): | 418 def IsInProperBranch(self): |
408 """Confirms they're in the master branch for performing the bisection. | 419 """Confirms they're in the master branch for performing the bisection. |
409 This is needed or gclient will fail to sync properly. | 420 This is needed or gclient will fail to sync properly. |
410 | 421 |
411 Returns: | 422 Returns: |
412 True if the current branch on src is 'master' | 423 True if the current branch on src is 'master' |
413 """ | 424 """ |
414 cmd = ['rev-parse', '--abbrev-ref', 'HEAD'] | 425 cmd = ['rev-parse', '--abbrev-ref', 'HEAD'] |
415 (log_output, return_code) = RunGit(cmd) | 426 (log_output, return_code) = CheckRunGit(cmd) |
416 | |
417 assert not return_code, 'An error occurred while running'\ | |
418 ' "git %s"' % ' '.join(cmd) | |
419 | 427 |
420 log_output = log_output.strip() | 428 log_output = log_output.strip() |
421 | 429 |
422 return log_output == "master" | 430 return log_output == "master" |
423 | 431 |
424 def SVNFindRev(self, revision): | 432 def SVNFindRev(self, revision): |
425 """Maps directly to the 'git svn find-rev' command. | 433 """Maps directly to the 'git svn find-rev' command. |
426 | 434 |
427 Args: | 435 Args: |
428 revision: The git SHA1 to use. | 436 revision: The git SHA1 to use. |
429 | 437 |
430 Returns: | 438 Returns: |
431 An integer changelist #, otherwise None. | 439 An integer changelist #, otherwise None. |
432 """ | 440 """ |
433 | 441 |
434 cmd = ['svn', 'find-rev', revision] | 442 cmd = ['svn', 'find-rev', revision] |
435 | 443 |
436 (output, return_code) = RunGit(cmd) | 444 (output, return_code) = CheckRunGit(cmd) |
437 | |
438 assert not return_code, 'An error occurred while running'\ | |
439 ' "git %s"' % ' '.join(cmd) | |
440 | 445 |
441 svn_revision = output.strip() | 446 svn_revision = output.strip() |
442 | 447 |
443 if IsStringInt(svn_revision): | 448 if IsStringInt(svn_revision): |
444 return int(svn_revision) | 449 return int(svn_revision) |
445 | 450 |
446 return None | 451 return None |
447 | 452 |
448 def QueryRevisionInfo(self, revision): | 453 def QueryRevisionInfo(self, revision): |
449 """Gathers information on a particular revision, such as author's name, | 454 """Gathers information on a particular revision, such as author's name, |
(...skipping 10 matching lines...) Expand all Loading... | |
460 'subject': %s, | 465 'subject': %s, |
461 } | 466 } |
462 """ | 467 """ |
463 commit_info = {} | 468 commit_info = {} |
464 | 469 |
465 formats = ['%cN', '%cE', '%s', '%cD'] | 470 formats = ['%cN', '%cE', '%s', '%cD'] |
466 targets = ['author', 'email', 'subject', 'date'] | 471 targets = ['author', 'email', 'subject', 'date'] |
467 | 472 |
468 for i in xrange(len(formats)): | 473 for i in xrange(len(formats)): |
469 cmd = ['log', '--format=%s' % formats[i], '-1', revision] | 474 cmd = ['log', '--format=%s' % formats[i], '-1', revision] |
470 (output, return_code) = RunGit(cmd) | 475 (output, return_code) = CheckRunGit(cmd) |
471 commit_info[targets[i]] = output.rstrip() | 476 commit_info[targets[i]] = output.rstrip() |
472 | 477 |
473 assert not return_code, 'An error occurred while running'\ | |
474 ' "git %s"' % ' '.join(cmd) | |
475 | |
476 return commit_info | 478 return commit_info |
477 | 479 |
478 def CheckoutFileAtRevision(self, file_name, revision): | 480 def CheckoutFileAtRevision(self, file_name, revision): |
479 """Performs a checkout on a file at the given revision. | 481 """Performs a checkout on a file at the given revision. |
480 | 482 |
481 Returns: | 483 Returns: |
482 True if successful. | 484 True if successful. |
483 """ | 485 """ |
484 return not RunGit(['checkout', revision, file_name])[1] | 486 return not RunGit(['checkout', revision, file_name])[1] |
485 | 487 |
486 def RevertFileToHead(self, file_name): | 488 def RevertFileToHead(self, file_name): |
487 """Unstages a file and returns it to HEAD. | 489 """Unstages a file and returns it to HEAD. |
488 | 490 |
489 Returns: | 491 Returns: |
490 True if successful. | 492 True if successful. |
491 """ | 493 """ |
492 # Reset doesn't seem to return 0 on success. | 494 # Reset doesn't seem to return 0 on success. |
493 RunGit(['reset', 'HEAD', bisect_utils.FILE_DEPS_GIT]) | 495 RunGit(['reset', 'HEAD', bisect_utils.FILE_DEPS_GIT]) |
494 | 496 |
495 return not RunGit(['checkout', bisect_utils.FILE_DEPS_GIT])[1] | 497 return not RunGit(['checkout', bisect_utils.FILE_DEPS_GIT])[1] |
496 | 498 |
499 def QueryFileRevisionHistory(self, filename, revision_start, revision_end): | |
500 """Returns a list of commits that modified this file. | |
501 | |
502 Args: | |
503 filename: Name of file. | |
504 revision_start: Start of revision range. | |
505 revision_end: End of revision range. | |
506 | |
507 Returns: | |
508 Returns a list of commits that touched this file. | |
509 """ | |
510 cmd = ['log', '--format=%H', '%s^1..%s' % (revision_start, revision_end), | |
511 filename] | |
512 (output, return_code) = CheckRunGit(cmd) | |
513 | |
514 return [o for o in output.split('\n') if o] | |
515 | |
497 class BisectPerformanceMetrics(object): | 516 class BisectPerformanceMetrics(object): |
498 """BisectPerformanceMetrics performs a bisection against a list of range | 517 """BisectPerformanceMetrics performs a bisection against a list of range |
499 of revisions to narrow down where performance regressions may have | 518 of revisions to narrow down where performance regressions may have |
500 occurred.""" | 519 occurred.""" |
501 | 520 |
502 def __init__(self, source_control, opts): | 521 def __init__(self, source_control, opts): |
503 super(BisectPerformanceMetrics, self).__init__() | 522 super(BisectPerformanceMetrics, self).__init__() |
504 | 523 |
505 self.opts = opts | 524 self.opts = opts |
506 self.source_control = source_control | 525 self.source_control = source_control |
507 self.src_cwd = os.getcwd() | 526 self.src_cwd = os.getcwd() |
508 self.depot_cwd = {} | 527 self.depot_cwd = {} |
509 self.cleanup_commands = [] | 528 self.cleanup_commands = [] |
529 self.warnings = [] | |
510 | 530 |
511 # This always starts true since the script grabs latest first. | 531 # This always starts true since the script grabs latest first. |
512 self.was_blink = True | 532 self.was_blink = True |
513 | 533 |
514 for d in DEPOT_NAMES: | 534 for d in DEPOT_NAMES: |
515 # The working directory of each depot is just the path to the depot, but | 535 # The working directory of each depot is just the path to the depot, but |
516 # since we're already in 'src', we can skip that part. | 536 # since we're already in 'src', we can skip that part. |
517 | 537 |
518 self.depot_cwd[d] = self.src_cwd + DEPOT_DEPS_NAME[d]['src'][3:] | 538 self.depot_cwd[d] = self.src_cwd + DEPOT_DEPS_NAME[d]['src'][3:] |
519 | 539 |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1037 | 1057 |
1038 print | 1058 print |
1039 print 'Revisions to bisect on [%s]:' % depot | 1059 print 'Revisions to bisect on [%s]:' % depot |
1040 for revision_id in revision_list: | 1060 for revision_id in revision_list: |
1041 print ' -> %s' % (revision_id, ) | 1061 print ' -> %s' % (revision_id, ) |
1042 print | 1062 print |
1043 | 1063 |
1044 if self.opts.output_buildbot_annotations: | 1064 if self.opts.output_buildbot_annotations: |
1045 bisect_utils.OutputAnnotationStepClosed() | 1065 bisect_utils.OutputAnnotationStepClosed() |
1046 | 1066 |
1067 def NudgeRevisionsIfDEPSChange(self, bad_revision, good_revision): | |
1068 """Checks to see if changes to DEPS file occurred, and that the revision | |
1069 range also includes the change to .DEPS.git. If it doesn't, attempts to | |
1070 expand the revision range to include it. | |
1071 | |
1072 Args: | |
1073 bad_rev: First known bad revision. | |
1074 good_revision: Last known good revision. | |
1075 | |
1076 Returns: | |
1077 A tuple with the new bad and good revisions. | |
1078 """ | |
1079 if self.source_control.IsGit(): | |
1080 changes_to_deps = self.source_control.QueryFileRevisionHistory( | |
1081 'DEPS', good_revision, bad_revision) | |
1082 | |
1083 if changes_to_deps: | |
1084 # DEPS file was changed, search from the oldest change to DEPS file to | |
1085 # bad_revision to see if there are matching .DEPS.git changes. | |
1086 oldest_deps_change = changes_to_deps[-1] | |
1087 changes_to_gitdeps = self.source_control.QueryFileRevisionHistory( | |
1088 bisect_utils.FILE_DEPS_GIT, oldest_deps_change, bad_revision) | |
1089 | |
1090 if len(changes_to_deps) != len(changes_to_gitdeps): | |
1091 # Grab the timestamp of the last DEPS change | |
1092 cmd = ['log', '--format=%ct', '-1', changes_to_deps[0]] | |
1093 (output, return_code) = CheckRunGit(cmd) | |
1094 | |
1095 commit_time = int(output) | |
1096 | |
1097 # Try looking for a commit that touches the .DEPS.git file in the | |
1098 # next 15 minutes after the DEPS file change. | |
1099 cmd = ['log', '--format=%H', '-1', | |
1100 '--before=%d' % (commit_time + 900), '--after=%d' % commit_time, | |
1101 'origin/master', bisect_utils.FILE_DEPS_GIT] | |
1102 (output, return_code) = CheckRunGit(cmd) | |
1103 | |
1104 output = output.strip() | |
1105 if output: | |
1106 self.warnings.append('Detected change to DEPS and modified ' | |
1107 'revision range to include change to .DEPS.git') | |
1108 return (output, good_revision) | |
1109 else: | |
1110 self.warnings.append('Detected change to DEPS but couldn\'t find ' | |
1111 'matching change to .DEPS.git') | |
1112 return (bad_revision, good_revision) | |
1113 | |
1047 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): | 1114 def Run(self, command_to_run, bad_revision_in, good_revision_in, metric): |
1048 """Given known good and bad revisions, run a binary search on all | 1115 """Given known good and bad revisions, run a binary search on all |
1049 intermediate revisions to determine the CL where the performance regression | 1116 intermediate revisions to determine the CL where the performance regression |
1050 occurred. | 1117 occurred. |
1051 | 1118 |
1052 Args: | 1119 Args: |
1053 command_to_run: Specify the command to execute the performance test. | 1120 command_to_run: Specify the command to execute the performance test. |
1054 good_revision: Number/tag of the known good revision. | 1121 good_revision: Number/tag of the known good revision. |
1055 bad_revision: Number/tag of the known bad revision. | 1122 bad_revision: Number/tag of the known bad revision. |
1056 metric: The performance metric to monitor. | 1123 metric: The performance metric to monitor. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1098 'src', -100) | 1165 'src', -100) |
1099 | 1166 |
1100 if bad_revision is None: | 1167 if bad_revision is None: |
1101 results['error'] = 'Could\'t resolve [%s] to SHA1.' % (bad_revision_in,) | 1168 results['error'] = 'Could\'t resolve [%s] to SHA1.' % (bad_revision_in,) |
1102 return results | 1169 return results |
1103 | 1170 |
1104 if good_revision is None: | 1171 if good_revision is None: |
1105 results['error'] = 'Could\'t resolve [%s] to SHA1.' % (good_revision_in,) | 1172 results['error'] = 'Could\'t resolve [%s] to SHA1.' % (good_revision_in,) |
1106 return results | 1173 return results |
1107 | 1174 |
1175 (bad_revision, good_revision) = self.NudgeRevisionsIfDEPSChange( | |
1176 bad_revision, good_revision) | |
1177 | |
1108 if self.opts.output_buildbot_annotations: | 1178 if self.opts.output_buildbot_annotations: |
1109 bisect_utils.OutputAnnotationStepStart('Gathering Revisions') | 1179 bisect_utils.OutputAnnotationStepStart('Gathering Revisions') |
1110 | 1180 |
1111 print 'Gathering revision range for bisection.' | 1181 print 'Gathering revision range for bisection.' |
1112 | 1182 |
1113 # Retrieve a list of revisions to do bisection on. | 1183 # Retrieve a list of revisions to do bisection on. |
1114 src_revision_list = self.GetRevisionList(bad_revision, good_revision) | 1184 src_revision_list = self.GetRevisionList(bad_revision, good_revision) |
1115 | 1185 |
1116 if self.opts.output_buildbot_annotations: | 1186 if self.opts.output_buildbot_annotations: |
1117 bisect_utils.OutputAnnotationStepClosed() | 1187 bisect_utils.OutputAnnotationStepClosed() |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1373 good_std_dev = revision_data[first_working_revision]['value']['std_dev'] | 1443 good_std_dev = revision_data[first_working_revision]['value']['std_dev'] |
1374 good_mean = revision_data[first_working_revision]['value']['mean'] | 1444 good_mean = revision_data[first_working_revision]['value']['mean'] |
1375 bad_mean = revision_data[last_broken_revision]['value']['mean'] | 1445 bad_mean = revision_data[last_broken_revision]['value']['mean'] |
1376 | 1446 |
1377 # A standard deviation of 0 could indicate either insufficient runs | 1447 # A standard deviation of 0 could indicate either insufficient runs |
1378 # or a test that consistently returns the same value. | 1448 # or a test that consistently returns the same value. |
1379 if good_std_dev > 0: | 1449 if good_std_dev > 0: |
1380 deviations = math.fabs(bad_mean - good_mean) / good_std_dev | 1450 deviations = math.fabs(bad_mean - good_mean) / good_std_dev |
1381 | 1451 |
1382 if deviations < 1.5: | 1452 if deviations < 1.5: |
1383 print 'Warning: Regression was less than 1.5 standard deviations '\ | 1453 self.warnings.append('Regression was less than 1.5 standard ' |
1384 'from "good" value. Results may not be accurate.' | 1454 'deviations from "good" value. Results may not be accurate.') |
1385 print | |
1386 elif self.opts.repeat_test_count == 1: | 1455 elif self.opts.repeat_test_count == 1: |
1387 print 'Warning: Tests were only set to run once. This may be '\ | 1456 self.warnings.append('Tests were only set to run once. This ' |
1388 'insufficient to get meaningful results.' | 1457 'may be insufficient to get meaningful results.') |
1389 print | |
1390 | 1458 |
1391 # Check for any other possible regression ranges | 1459 # Check for any other possible regression ranges |
1392 prev_revision_data = revision_data_sorted[0][1] | 1460 prev_revision_data = revision_data_sorted[0][1] |
1393 prev_revision_id = revision_data_sorted[0][0] | 1461 prev_revision_id = revision_data_sorted[0][0] |
1394 possible_regressions = [] | 1462 possible_regressions = [] |
1395 for current_id, current_data in revision_data_sorted: | 1463 for current_id, current_data in revision_data_sorted: |
1396 if current_data['value']: | 1464 if current_data['value']: |
1397 prev_mean = prev_revision_data['value']['mean'] | 1465 prev_mean = prev_revision_data['value']['mean'] |
1398 cur_mean = current_data['value']['mean'] | 1466 cur_mean = current_data['value']['mean'] |
1399 | 1467 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1440 if percent_change is None: | 1508 if percent_change is None: |
1441 percent_change = 0 | 1509 percent_change = 0 |
1442 | 1510 |
1443 print ' %8s %s [%.2f%%, %s x std.dev]' % ( | 1511 print ' %8s %s [%.2f%%, %s x std.dev]' % ( |
1444 previous_data['depot'], previous_id, 100 * percent_change, | 1512 previous_data['depot'], previous_id, 100 * percent_change, |
1445 deviations) | 1513 deviations) |
1446 print ' %8s %s' % ( | 1514 print ' %8s %s' % ( |
1447 current_data['depot'], current_id) | 1515 current_data['depot'], current_id) |
1448 print | 1516 print |
1449 | 1517 |
1518 if self.warnings: | |
1519 print | |
1520 print 'The following warnings were generated:' | |
1521 print | |
1522 for w in self.warnings: | |
1523 print ' - %s' % w | |
1524 print | |
1525 | |
1450 if self.opts.output_buildbot_annotations: | 1526 if self.opts.output_buildbot_annotations: |
1451 bisect_utils.OutputAnnotationStepClosed() | 1527 bisect_utils.OutputAnnotationStepClosed() |
1452 | 1528 |
1453 | 1529 |
1454 def DetermineAndCreateSourceControl(): | 1530 def DetermineAndCreateSourceControl(): |
1455 """Attempts to determine the underlying source control workflow and returns | 1531 """Attempts to determine the underlying source control workflow and returns |
1456 a SourceControl object. | 1532 a SourceControl object. |
1457 | 1533 |
1458 Returns: | 1534 Returns: |
1459 An instance of a SourceControl object, or None if the current workflow | 1535 An instance of a SourceControl object, or None if the current workflow |
1460 is unsupported. | 1536 is unsupported. |
1461 """ | 1537 """ |
1462 | 1538 |
1463 (output, return_code) = RunGit(['rev-parse', '--is-inside-work-tree']) | 1539 (output, return_code) = RunGit(['rev-parse', '--is-inside-work-tree']) |
tonyg
2013/05/28 23:45:06
CheckRunGit?
shatch
2013/05/29 16:25:28
Prefer not to here, since a more descriptive error
| |
1464 | 1540 |
1465 if output.strip() == 'true': | 1541 if output.strip() == 'true': |
1466 return GitSourceControl() | 1542 return GitSourceControl() |
1467 | 1543 |
1468 return None | 1544 return None |
1469 | 1545 |
1470 | 1546 |
1471 def SetNinjaBuildSystemDefault(): | 1547 def SetNinjaBuildSystemDefault(): |
1472 """Makes ninja the default build system to be used by | 1548 """Makes ninja the default build system to be used by |
1473 the bisection script.""" | 1549 the bisection script.""" |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1729 | 1805 |
1730 if not(bisect_results['error']): | 1806 if not(bisect_results['error']): |
1731 return 0 | 1807 return 0 |
1732 else: | 1808 else: |
1733 print 'Error: ' + bisect_results['error'] | 1809 print 'Error: ' + bisect_results['error'] |
1734 print | 1810 print |
1735 return 1 | 1811 return 1 |
1736 | 1812 |
1737 if __name__ == '__main__': | 1813 if __name__ == '__main__': |
1738 sys.exit(main()) | 1814 sys.exit(main()) |
OLD | NEW |