OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 import os as _os | 7 import os as _os |
8 _HERE = _os.path.dirname(_os.path.abspath(__file__)) | 8 _HERE = _os.path.dirname(_os.path.abspath(__file__)) |
9 | 9 |
10 # Justifications for each filter: | 10 # Justifications for each filter: |
(...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 needed = 'LGTM from an OWNER' | 868 needed = 'LGTM from an OWNER' |
869 output = output_api.PresubmitError | 869 output = output_api.PresubmitError |
870 else: | 870 else: |
871 needed = 'OWNER reviewers' | 871 needed = 'OWNER reviewers' |
872 output = output_api.PresubmitNotifyResult | 872 output = output_api.PresubmitNotifyResult |
873 | 873 |
874 affected_files = set([f.LocalPath() for f in | 874 affected_files = set([f.LocalPath() for f in |
875 input_api.change.AffectedFiles(file_filter=source_file_filter)]) | 875 input_api.change.AffectedFiles(file_filter=source_file_filter)]) |
876 | 876 |
877 owners_db = input_api.owners_db | 877 owners_db = input_api.owners_db |
878 owner_email, reviewers = _CodereviewOwnersAndReviewers( | 878 owner_email, reviewers = GetCodereviewOwnerAndReviewers( |
879 input_api, | 879 input_api, |
880 owners_db.email_regexp, | 880 owners_db.email_regexp, |
881 approval_needed=input_api.is_committing) | 881 approval_needed=input_api.is_committing) |
882 | 882 |
883 owner_email = owner_email or input_api.change.author_email | 883 owner_email = owner_email or input_api.change.author_email |
884 | 884 |
885 if owner_email: | 885 if owner_email: |
886 reviewers_plus_owner = set([owner_email]).union(reviewers) | 886 reviewers_plus_owner = set([owner_email]).union(reviewers) |
887 missing_files = owners_db.files_not_covered_by(affected_files, | 887 missing_files = owners_db.files_not_covered_by(affected_files, |
888 reviewers_plus_owner) | 888 reviewers_plus_owner) |
889 else: | 889 else: |
890 missing_files = owners_db.files_not_covered_by(affected_files, reviewers) | 890 missing_files = owners_db.files_not_covered_by(affected_files, reviewers) |
891 | 891 |
892 if missing_files: | 892 if missing_files: |
893 output_list = [ | 893 output_list = [ |
894 output('Missing %s for these files:\n %s' % | 894 output('Missing %s for these files:\n %s' % |
895 (needed, '\n '.join(sorted(missing_files))))] | 895 (needed, '\n '.join(sorted(missing_files))))] |
896 if not input_api.is_committing: | 896 if not input_api.is_committing: |
897 suggested_owners = owners_db.reviewers_for(missing_files, owner_email) | 897 suggested_owners = owners_db.reviewers_for(missing_files, owner_email) |
898 output_list.append(output('Suggested OWNERS: ' + | 898 output_list.append(output('Suggested OWNERS: ' + |
899 '(Use "git-cl owners" to interactively select owners.)\n %s' % | 899 '(Use "git-cl owners" to interactively select owners.)\n %s' % |
900 ('\n '.join(suggested_owners or [])))) | 900 ('\n '.join(suggested_owners or [])))) |
901 return output_list | 901 return output_list |
902 | 902 |
903 if input_api.is_committing and not reviewers: | 903 if input_api.is_committing and not reviewers: |
904 return [output('Missing LGTM from someone other than %s' % owner_email)] | 904 return [output('Missing LGTM from someone other than %s' % owner_email)] |
905 return [] | 905 return [] |
906 | 906 |
907 def _CodereviewOwnersAndReviewers(input_api, email_regexp, approval_needed): | 907 def GetCodereviewOwnerAndReviewers(input_api, email_regexp, approval_needed): |
908 """Return the owner and reviewers of a change, if any. | 908 """Return the owner and reviewers of a change, if any. |
909 | 909 |
910 If approval_needed is True, only reviewers who have approved the change | 910 If approval_needed is True, only reviewers who have approved the change |
911 will be returned. | 911 will be returned. |
912 """ | 912 """ |
913 if input_api.change.issue: | 913 # Rietveld is default. |
914 if input_api.gerrit: | 914 func = _RietveldOwnerAndReviewers |
915 res = _GerritOwnerAndReviewers(input_api, email_regexp, approval_needed) | 915 if input_api.gerrit: |
916 else: | 916 func = _GerritOwnerAndReviewers |
917 # Rietveld is default. | 917 return func(input_api, email_regexp, approval_needed) |
918 res = _RietveldOwnerAndReviewers(input_api, email_regexp, approval_needed) | |
919 if res: | |
920 return res | |
921 | |
922 reviewers = set() | |
923 if not approval_needed: | |
924 reviewers = _ReviewersFromChange(input_api.change) | |
925 return None, reviewers | |
926 | 918 |
927 | 919 |
928 def _GetRietveldIssueProps(input_api, messages): | 920 def _GetRietveldIssueProps(input_api, messages): |
929 """Gets the issue properties from rietveld.""" | 921 """Gets the issue properties from rietveld.""" |
930 issue = input_api.change.issue | 922 issue = input_api.change.issue |
931 if issue and input_api.rietveld: | 923 if issue and input_api.rietveld: |
932 return input_api.rietveld.get_issue_properties( | 924 return input_api.rietveld.get_issue_properties( |
933 issue=int(issue), messages=messages) | 925 issue=int(issue), messages=messages) |
934 | 926 |
935 | 927 |
(...skipping 10 matching lines...) Expand all Loading... |
946 | 938 |
947 | 939 |
948 def _match_reviewer_email(r, owner_email, email_regexp): | 940 def _match_reviewer_email(r, owner_email, email_regexp): |
949 return email_regexp.match(r) and r != owner_email | 941 return email_regexp.match(r) and r != owner_email |
950 | 942 |
951 def _RietveldOwnerAndReviewers(input_api, email_regexp, approval_needed=False): | 943 def _RietveldOwnerAndReviewers(input_api, email_regexp, approval_needed=False): |
952 """Return the owner and reviewers of a change, if any. | 944 """Return the owner and reviewers of a change, if any. |
953 | 945 |
954 If approval_needed is True, only reviewers who have approved the change | 946 If approval_needed is True, only reviewers who have approved the change |
955 will be returned. | 947 will be returned. |
956 Returns None if can't fetch issue properties from codereview. | |
957 """ | 948 """ |
958 issue_props = _GetRietveldIssueProps(input_api, True) | 949 issue_props = _GetRietveldIssueProps(input_api, True) |
959 if not issue_props: | 950 if not issue_props: |
960 return None | 951 return None, (set() if approval_needed else |
| 952 _ReviewersFromChange(input_api.change)) |
961 | 953 |
962 if not approval_needed: | 954 if not approval_needed: |
963 return issue_props['owner_email'], set(issue_props['reviewers']) | 955 return issue_props['owner_email'], set(issue_props['reviewers']) |
964 | 956 |
965 owner_email = issue_props['owner_email'] | 957 owner_email = issue_props['owner_email'] |
966 | 958 |
967 messages = issue_props.get('messages', []) | 959 messages = issue_props.get('messages', []) |
968 approvers = set( | 960 approvers = set( |
969 m['sender'] for m in messages | 961 m['sender'] for m in messages |
970 if m.get('approval') and _match_reviewer_email(m['sender'], owner_email, | 962 if m.get('approval') and _match_reviewer_email(m['sender'], owner_email, |
971 email_regexp)) | 963 email_regexp)) |
972 return owner_email, approvers | 964 return owner_email, approvers |
973 | 965 |
974 | 966 |
975 def _GerritOwnerAndReviewers(input_api, email_regexp, approval_needed=False): | 967 def _GerritOwnerAndReviewers(input_api, email_regexp, approval_needed=False): |
976 """Return the owner and reviewers of a change, if any. | 968 """Return the owner and reviewers of a change, if any. |
977 | 969 |
978 If approval_needed is True, only reviewers who have approved the change | 970 If approval_needed is True, only reviewers who have approved the change |
979 will be returned. | 971 will be returned. |
980 Returns None if can't fetch issue properties from codereview. | |
981 """ | 972 """ |
982 issue = input_api.change.issue | 973 issue = input_api.change.issue |
983 if not issue: | 974 if not issue: |
984 return None | 975 return None, (set() if approval_needed else |
| 976 _ReviewersFromChange(input_api.change)) |
985 | 977 |
986 owner_email = input_api.gerrit.GetChangeOwner(issue) | 978 owner_email = input_api.gerrit.GetChangeOwner(issue) |
987 reviewers = set( | 979 reviewers = set( |
988 r for r in input_api.gerrit.GetChangeReviewers(issue, approval_needed) | 980 r for r in input_api.gerrit.GetChangeReviewers(issue, approval_needed) |
989 if _match_reviewer_email(r, owner_email, email_regexp)) | 981 if _match_reviewer_email(r, owner_email, email_regexp)) |
990 return owner_email, reviewers | 982 return owner_email, reviewers |
991 | 983 |
992 | 984 |
993 def _CheckConstNSObject(input_api, output_api, source_file_filter): | 985 def _CheckConstNSObject(input_api, output_api, source_file_filter): |
994 """Checks to make sure no objective-c files have |const NSSomeClass*|.""" | 986 """Checks to make sure no objective-c files have |const NSSomeClass*|.""" |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 for f in affected_files: | 1155 for f in affected_files: |
1164 cmd = ['gn', 'format', '--dry-run', f.AbsoluteLocalPath()] | 1156 cmd = ['gn', 'format', '--dry-run', f.AbsoluteLocalPath()] |
1165 rc = gn.main(cmd) | 1157 rc = gn.main(cmd) |
1166 if rc == 2: | 1158 if rc == 2: |
1167 warnings.append(output_api.PresubmitPromptWarning( | 1159 warnings.append(output_api.PresubmitPromptWarning( |
1168 '%s requires formatting. Please run `gn format --in-place %s`.' % ( | 1160 '%s requires formatting. Please run `gn format --in-place %s`.' % ( |
1169 f.AbsoluteLocalPath(), f.LocalPath()))) | 1161 f.AbsoluteLocalPath(), f.LocalPath()))) |
1170 # It's just a warning, so ignore other types of failures assuming they'll be | 1162 # It's just a warning, so ignore other types of failures assuming they'll be |
1171 # caught elsewhere. | 1163 # caught elsewhere. |
1172 return warnings | 1164 return warnings |
OLD | NEW |