OLD | NEW |
1 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2010 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 """Generic presubmit checks that can be reused by other presubmit checks.""" | 5 """Generic presubmit checks that can be reused by other presubmit checks.""" |
6 | 6 |
7 | 7 |
8 ### Description checks | 8 ### Description checks |
9 | 9 |
10 def CheckChangeHasTestField(input_api, output_api): | 10 def CheckChangeHasTestField(input_api, output_api): |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 | 754 |
755 | 755 |
756 def _RietveldOwnerAndApprovers(input_api, email_regexp): | 756 def _RietveldOwnerAndApprovers(input_api, email_regexp): |
757 """Return the owner and approvers of a change, if any.""" | 757 """Return the owner and approvers of a change, if any.""" |
758 # TODO(dpranke): Should figure out if input_api.host_url is supposed to | 758 # TODO(dpranke): Should figure out if input_api.host_url is supposed to |
759 # be a host or a scheme+host and normalize it there. | 759 # be a host or a scheme+host and normalize it there. |
760 host = input_api.host_url | 760 host = input_api.host_url |
761 if not host.startswith('http://') and not host.startswith('https://'): | 761 if not host.startswith('http://') and not host.startswith('https://'): |
762 host = 'http://' + host | 762 host = 'http://' + host |
763 url = '%s/api/%s?messages=true' % (host, input_api.change.issue) | 763 url = '%s/api/%s?messages=true' % (host, input_api.change.issue) |
| 764 issue_props = input_api.json.load(input_api.urllib2.urlopen(url)) |
| 765 owner_email = issue_props['owner_email'] |
764 | 766 |
765 f = input_api.urllib2.urlopen(url) | 767 def match_reviewer(r): |
766 issue_props = input_api.json.load(f) | 768 return email_regexp.match(r) and r != owner_email |
| 769 |
767 messages = issue_props.get('messages', []) | 770 messages = issue_props.get('messages', []) |
768 owner_email = issue_props['owner_email'] | 771 approvers = set( |
769 owner_regexp = input_api.re.compile(input_api.re.escape(owner_email)) | 772 m['sender'] for m in messages |
770 approvers = _GetApprovers(messages, email_regexp, owner_regexp) | 773 if m.get('approval') and match_reviewer(m['sender'])) |
771 | 774 |
772 return (owner_email, set(approvers)) | 775 return owner_email, approvers |
773 | |
774 | |
775 def _IsApprovingComment(text): | |
776 """Implements the logic for parsing a change comment for approval.""" | |
777 | |
778 # Any comment that contains a non-quoted line containing an 'lgtm' is an | |
779 # approval. | |
780 # | |
781 # TODO(dpranke): this differs from the logic used inside Google in a few | |
782 # ways. Inside Google, | |
783 # | |
784 # 1) the approving phrase must appear at the beginning of the first non | |
785 # quoted-line in the comment.' | |
786 # 2) "LG", "Looks Good", and "Looks Good to Me" are also acceptable. | |
787 # 3) Subsequent comments from the reviewer can rescind approval, unless | |
788 # the phrase "LGTM++" was used. | |
789 # We should consider implementing some or all of this here. | |
790 for l in text.splitlines(): | |
791 l = l.strip().lower() | |
792 if l.startswith('>'): | |
793 continue | |
794 | |
795 if 'lgtm' in l: | |
796 return True | |
797 return False | |
798 | |
799 | |
800 def _GetApprovers(messages, email_regexp, owner_regexp): | |
801 """Returns the set of approvers for a change given the owner and messages. | |
802 | |
803 Messages should be a list of dicts containing 'sender' and 'text' keys.""" | |
804 | |
805 # TODO(dpranke): This mimics the logic in | |
806 # /tools/commit-queue/verifiers/reviewer_lgtm.py | |
807 # We should share the code and/or remove the check there where it is | |
808 # redundant (since the commit queue also enforces the presubmit checks). | |
809 def match_reviewer(r): | |
810 return email_regexp.match(r) and not owner_regexp.match(r) | |
811 | |
812 approvers = [] | |
813 for m in messages: | |
814 sender = m['sender'] | |
815 if _IsApprovingComment(m['text']) and match_reviewer(sender): | |
816 approvers.append(sender) | |
817 return set(approvers) | |
818 | 776 |
819 | 777 |
820 def _CheckConstNSObject(input_api, output_api, source_file_filter): | 778 def _CheckConstNSObject(input_api, output_api, source_file_filter): |
821 """Checks to make sure no objective-c files have |const NSSomeClass*|.""" | 779 """Checks to make sure no objective-c files have |const NSSomeClass*|.""" |
822 pattern = input_api.re.compile( | 780 pattern = input_api.re.compile( |
823 r'const\s+NS(?!(Point|Range|Rect|Size)\s*\*)\w*\s*\*') | 781 r'const\s+NS(?!(Point|Range|Rect|Size)\s*\*)\w*\s*\*') |
824 | 782 |
825 def objective_c_filter(f): | 783 def objective_c_filter(f): |
826 return (source_file_filter(f) and | 784 return (source_file_filter(f) and |
827 input_api.os_path.splitext(f.LocalPath())[1] in ('.h', '.m', '.mm')) | 785 input_api.os_path.splitext(f.LocalPath())[1] in ('.h', '.m', '.mm')) |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 results.extend(input_api.canned_checks.CheckChangeSvnEolStyle( | 908 results.extend(input_api.canned_checks.CheckChangeSvnEolStyle( |
951 input_api, output_api, source_file_filter=text_files)) | 909 input_api, output_api, source_file_filter=text_files)) |
952 snapshot("checking svn mime types") | 910 snapshot("checking svn mime types") |
953 results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes( | 911 results.extend(input_api.canned_checks.CheckSvnForCommonMimeTypes( |
954 input_api, output_api)) | 912 input_api, output_api)) |
955 snapshot("checking license") | 913 snapshot("checking license") |
956 results.extend(input_api.canned_checks.CheckLicense( | 914 results.extend(input_api.canned_checks.CheckLicense( |
957 input_api, output_api, license_header, source_file_filter=sources)) | 915 input_api, output_api, license_header, source_file_filter=sources)) |
958 snapshot("done") | 916 snapshot("done") |
959 return results | 917 return results |
OLD | NEW |