| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2006-2009 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 """Enables directory-specific presubmit checks to run at upload and/or commit. | 6 """Enables directory-specific presubmit checks to run at upload and/or commit. |
| 7 """ | 7 """ |
| 8 | 8 |
| 9 __version__ = '1.1' | 9 __version__ = '1.1' |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 import gcl | 34 import gcl |
| 35 import gclient | 35 import gclient |
| 36 import presubmit_canned_checks | 36 import presubmit_canned_checks |
| 37 | 37 |
| 38 | 38 |
| 39 # Matches key/value (or "tag") lines in changelist descriptions. | 39 # Matches key/value (or "tag") lines in changelist descriptions. |
| 40 _tag_line_re = re.compile( | 40 _tag_line_re = re.compile( |
| 41 '^\s*(?P<key>[A-Z][A-Z_0-9]*)\s*=\s*(?P<value>.*?)\s*$') | 41 '^\s*(?P<key>[A-Z][A-Z_0-9]*)\s*=\s*(?P<value>.*?)\s*$') |
| 42 | 42 |
| 43 | 43 |
| 44 # Friendly names may be used for certain keys. All values for key-value pairs | |
| 45 # in change descriptions (like BUG=123) can be retrieved from a change object | |
| 46 # directly as if they were attributes, e.g. change.R (or equivalently because | |
| 47 # we have a friendly name for it, change.Reviewers), change.BUG (or | |
| 48 # change.BugIDs) and so forth. | |
| 49 # | |
| 50 # Add to this mapping as needed/desired. | |
| 51 SPECIAL_KEYS = { | |
| 52 'Reviewers' : 'R', | |
| 53 'BugIDs' : 'BUG', | |
| 54 'Tested': 'TESTED', | |
| 55 'Test': 'TEST' | |
| 56 } | |
| 57 | |
| 58 | |
| 59 class NotImplementedException(Exception): | 44 class NotImplementedException(Exception): |
| 60 """We're leaving placeholders in a bunch of places to remind us of the | 45 """We're leaving placeholders in a bunch of places to remind us of the |
| 61 design of the API, but we have not implemented all of it yet. Implement as | 46 design of the API, but we have not implemented all of it yet. Implement as |
| 62 the need arises. | 47 the need arises. |
| 63 """ | 48 """ |
| 64 pass | 49 pass |
| 65 | 50 |
| 66 | 51 |
| 67 def normpath(path): | 52 def normpath(path): |
| 68 '''Version of os.path.normpath that also changes backward slashes to | 53 '''Version of os.path.normpath that also changes backward slashes to |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 | 437 |
| 453 self.affected_files = [ | 438 self.affected_files = [ |
| 454 SvnAffectedFile(info[1], info[0].strip(), repository_root) | 439 SvnAffectedFile(info[1], info[0].strip(), repository_root) |
| 455 for info in change_info.files | 440 for info in change_info.files |
| 456 ] | 441 ] |
| 457 | 442 |
| 458 def Change(self): | 443 def Change(self): |
| 459 """Returns the change name.""" | 444 """Returns the change name.""" |
| 460 return self.name | 445 return self.name |
| 461 | 446 |
| 462 def Changelist(self): | |
| 463 """Synonym for Change().""" | |
| 464 return self.Change() | |
| 465 | |
| 466 def DescriptionText(self): | 447 def DescriptionText(self): |
| 467 """Returns the user-entered changelist description, minus tags. | 448 """Returns the user-entered changelist description, minus tags. |
| 468 | 449 |
| 469 Any line in the user-provided description starting with e.g. "FOO=" | 450 Any line in the user-provided description starting with e.g. "FOO=" |
| 470 (whitespace permitted before and around) is considered a tag line. Such | 451 (whitespace permitted before and around) is considered a tag line. Such |
| 471 lines are stripped out of the description this function returns. | 452 lines are stripped out of the description this function returns. |
| 472 """ | 453 """ |
| 473 return self.description_without_tags | 454 return self.description_without_tags |
| 474 | 455 |
| 475 def FullDescriptionText(self): | 456 def FullDescriptionText(self): |
| 476 """Returns the complete changelist description including tags.""" | 457 """Returns the complete changelist description including tags.""" |
| 477 return self.full_description | 458 return self.full_description |
| 478 | 459 |
| 479 def RepositoryRoot(self): | 460 def RepositoryRoot(self): |
| 480 """Returns the repository root for this change, as an absolute path.""" | 461 """Returns the repository root for this change, as an absolute path.""" |
| 481 return self.repository_root | 462 return self.repository_root |
| 482 | 463 |
| 483 def __getattr__(self, attr): | 464 def __getattr__(self, attr): |
| 484 """Return keys directly as attributes on the object. | 465 """Return keys directly as attributes on the object. |
| 485 | 466 |
| 486 You may use a friendly name (from SPECIAL_KEYS) or the actual name of | 467 You may use a friendly name (from SPECIAL_KEYS) or the actual name of |
| 487 the key. | 468 the key. |
| 488 """ | 469 """ |
| 489 if attr in SPECIAL_KEYS: | 470 return self.tags.get(attr) |
| 490 key = SPECIAL_KEYS[attr] | |
| 491 if key in self.tags: | |
| 492 return self.tags[key] | |
| 493 if attr in self.tags: | |
| 494 return self.tags[attr] | |
| 495 | 471 |
| 496 def AffectedFiles(self, include_dirs=False, include_deletes=True): | 472 def AffectedFiles(self, include_dirs=False, include_deletes=True): |
| 497 """Returns a list of AffectedFile instances for all files in the change. | 473 """Returns a list of AffectedFile instances for all files in the change. |
| 498 | 474 |
| 499 Args: | 475 Args: |
| 500 include_deletes: If false, deleted files will be filtered out. | 476 include_deletes: If false, deleted files will be filtered out. |
| 501 include_dirs: True to include directories in the list | 477 include_dirs: True to include directories in the list |
| 502 | 478 |
| 503 Returns: | 479 Returns: |
| 504 [AffectedFile(path, action), AffectedFile(path, action)] | 480 [AffectedFile(path, action), AffectedFile(path, action)] |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 744 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), | 720 return not DoPresubmitChecks(gcl.ChangeInfo(name='temp', files=files), |
| 745 options.commit, | 721 options.commit, |
| 746 options.verbose, | 722 options.verbose, |
| 747 sys.stdout, | 723 sys.stdout, |
| 748 sys.stdin, | 724 sys.stdin, |
| 749 default_presubmit=None) | 725 default_presubmit=None) |
| 750 | 726 |
| 751 | 727 |
| 752 if __name__ == '__main__': | 728 if __name__ == '__main__': |
| 753 sys.exit(Main(sys.argv)) | 729 sys.exit(Main(sys.argv)) |
| OLD | NEW |