OLD | NEW |
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 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 | 5 |
6 """Top-level presubmit script for Skia. | 6 """Top-level presubmit script for Skia. |
7 | 7 |
8 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts | 8 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts |
9 for more details about the presubmit API built into gcl. | 9 for more details about the presubmit API built into gcl. |
10 """ | 10 """ |
11 | 11 |
| 12 import csv |
12 import fnmatch | 13 import fnmatch |
13 import os | 14 import os |
14 import re | 15 import re |
15 import subprocess | 16 import subprocess |
16 import sys | 17 import sys |
17 import traceback | 18 import traceback |
18 | 19 |
19 | 20 |
20 REVERT_CL_SUBJECT_PREFIX = 'Revert ' | 21 REVERT_CL_SUBJECT_PREFIX = 'Revert ' |
21 | 22 |
22 SKIA_TREE_STATUS_URL = 'http://skia-tree-status.appspot.com' | 23 SKIA_TREE_STATUS_URL = 'http://skia-tree-status.appspot.com' |
23 | 24 |
| 25 CQ_KEYWORDS_THAT_NEED_APPENDING = ('CQ_INCLUDE_TRYBOTS', 'CQ_EXTRA_TRYBOTS', |
| 26 'CQ_EXCLUDE_TRYBOTS', 'CQ_TRYBOTS') |
| 27 |
24 # Please add the complete email address here (and not just 'xyz@' or 'xyz'). | 28 # Please add the complete email address here (and not just 'xyz@' or 'xyz'). |
25 PUBLIC_API_OWNERS = ( | 29 PUBLIC_API_OWNERS = ( |
26 'reed@chromium.org', | 30 'reed@chromium.org', |
27 'reed@google.com', | 31 'reed@google.com', |
28 'bsalomon@chromium.org', | 32 'bsalomon@chromium.org', |
29 'bsalomon@google.com', | 33 'bsalomon@google.com', |
30 'djsollen@chromium.org', | 34 'djsollen@chromium.org', |
31 'djsollen@google.com', | 35 'djsollen@google.com', |
32 ) | 36 ) |
33 | 37 |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 'tree status. Automatically added \'NOTREECHECKS=true\' to the ' | 359 'tree status. Automatically added \'NOTREECHECKS=true\' to the ' |
356 'CL\'s description')) | 360 'CL\'s description')) |
357 if not re.search( | 361 if not re.search( |
358 r'^NOTRY=true$', new_description, re.M | re.I): | 362 r'^NOTRY=true$', new_description, re.M | re.I): |
359 new_description += "\nNOTRY=true" | 363 new_description += "\nNOTRY=true" |
360 results.append( | 364 results.append( |
361 output_api.PresubmitNotifyResult( | 365 output_api.PresubmitNotifyResult( |
362 'Trybots do not yet work for non-master branches. ' | 366 'Trybots do not yet work for non-master branches. ' |
363 'Automatically added \'NOTRY=true\' to the CL\'s description')) | 367 'Automatically added \'NOTRY=true\' to the CL\'s description')) |
364 | 368 |
| 369 # Read and process the HASHTAGS file. |
| 370 with open('HASHTAGS', 'rb') as hashtags_csv: |
| 371 hashtags_reader = csv.reader(hashtags_csv, delimiter=',') |
| 372 for row in hashtags_reader: |
| 373 if not row or row[0].startswith('#'): |
| 374 # Ignore empty lines and comments |
| 375 continue |
| 376 hashtag = row[0] |
| 377 # Search for the hashtag in the description. |
| 378 if re.search('#%s' % hashtag, new_description, re.M | re.I): |
| 379 for mapped_text in row[1:]: |
| 380 # Special case handling for CQ_KEYWORDS_THAT_NEED_APPENDING. |
| 381 appended_description = _HandleAppendingCQKeywords( |
| 382 hashtag, mapped_text, new_description, results, output_api) |
| 383 if appended_description: |
| 384 new_description = appended_description |
| 385 continue |
| 386 |
| 387 # Add the mapped text if it does not already exist in the |
| 388 # CL's description. |
| 389 if not re.search( |
| 390 r'^%s$' % mapped_text, new_description, re.M | re.I): |
| 391 new_description += '\n%s' % mapped_text |
| 392 results.append( |
| 393 output_api.PresubmitNotifyResult( |
| 394 'Found \'#%s\', automatically added \'%s\' to the CL\'s ' |
| 395 'description' % (hashtag, mapped_text))) |
365 | 396 |
366 # If the description has changed update it. | 397 # If the description has changed update it. |
367 if new_description != original_description: | 398 if new_description != original_description: |
368 rietveld_obj.update_description(issue, new_description) | 399 rietveld_obj.update_description(issue, new_description) |
369 | 400 |
370 return results | 401 return results |
371 | 402 |
372 | 403 |
| 404 def _HandleAppendingCQKeywords(hashtag, keyword_and_value, description, |
| 405 results, output_api): |
| 406 """Handles the CQ keywords that need appending if specified in hashtags.""" |
| 407 keyword = keyword_and_value.split('=')[0] |
| 408 if keyword in CQ_KEYWORDS_THAT_NEED_APPENDING: |
| 409 # If the keyword is already in the description then append to it. |
| 410 match = re.search( |
| 411 r'^%s=(.*)$' % keyword, description, re.M | re.I) |
| 412 if match: |
| 413 old_values = match.group(1).split(';') |
| 414 new_value = keyword_and_value.split('=')[1] |
| 415 if new_value in old_values: |
| 416 # Do not need to do anything here. |
| 417 return description |
| 418 # Update the description with the new values. |
| 419 new_description = description.replace( |
| 420 match.group(0), "%s;%s" % (match.group(0), new_value)) |
| 421 results.append( |
| 422 output_api.PresubmitNotifyResult( |
| 423 'Found \'#%s\', automatically appended \'%s\' to %s in ' |
| 424 'the CL\'s description' % (hashtag, new_value, keyword))) |
| 425 return new_description |
| 426 return None |
| 427 |
| 428 |
373 def CheckChangeOnCommit(input_api, output_api): | 429 def CheckChangeOnCommit(input_api, output_api): |
374 """Presubmit checks for the change on commit. | 430 """Presubmit checks for the change on commit. |
375 | 431 |
376 The following are the presubmit checks: | 432 The following are the presubmit checks: |
377 * Check change has one and only one EOL. | 433 * Check change has one and only one EOL. |
378 * Ensures that the Skia tree is open in | 434 * Ensures that the Skia tree is open in |
379 http://skia-tree-status.appspot.com/. Shows a warning if it is in 'Caution' | 435 http://skia-tree-status.appspot.com/. Shows a warning if it is in 'Caution' |
380 state and an error if it is in 'Closed' state. | 436 state and an error if it is in 'Closed' state. |
381 """ | 437 """ |
382 results = [] | 438 results = [] |
383 results.extend(_CommonChecks(input_api, output_api)) | 439 results.extend(_CommonChecks(input_api, output_api)) |
384 results.extend( | 440 results.extend( |
385 _CheckTreeStatus(input_api, output_api, json_url=( | 441 _CheckTreeStatus(input_api, output_api, json_url=( |
386 SKIA_TREE_STATUS_URL + '/banner-status?format=json'))) | 442 SKIA_TREE_STATUS_URL + '/banner-status?format=json'))) |
387 results.extend(_CheckLGTMsForPublicAPI(input_api, output_api)) | 443 results.extend(_CheckLGTMsForPublicAPI(input_api, output_api)) |
388 results.extend(_CheckOwnerIsInAuthorsFile(input_api, output_api)) | 444 results.extend(_CheckOwnerIsInAuthorsFile(input_api, output_api)) |
389 return results | 445 return results |
OLD | NEW |