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
3 # found in the LICENSE file.
6 """Top-level presubmit script for Skia.
8 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
9 for more details about the presubmit API built into gcl.
17 REVERT_CL_SUBJECT_PREFIX = 'Revert '
19 SKIA_TREE_STATUS_URL = 'http://skia-tree-status.appspot.com'
24 'bsalomon@chromium.org',
25 'bsalomon@google.com',
29 def _CheckChangeHasEol(input_api, output_api, source_file_filter=None):
30 """Checks that files end with atleast one \n (LF)."""
32 for f in input_api.AffectedSourceFiles(source_file_filter):
33 contents = input_api.ReadFile(f, 'rb')
34 # Check that the file ends in atleast one newline character.
35 if len(contents) > 1 and contents[-1:] != '\n':
36 eof_files.append(f.LocalPath())
39 return [output_api.PresubmitPromptWarning(
40 'These files should end in a newline character:',
45 def _CommonChecks(input_api, output_api):
46 """Presubmit checks common to upload and commit."""
48 sources = lambda x: (x.LocalPath().endswith('.h') or
49 x.LocalPath().endswith('.gypi') or
50 x.LocalPath().endswith('.gyp') or
51 x.LocalPath().endswith('.py') or
52 x.LocalPath().endswith('.sh') or
53 x.LocalPath().endswith('.cpp'))
56 input_api, output_api, source_file_filter=sources))
60 def CheckChangeOnUpload(input_api, output_api):
61 """Presubmit checks for the change on upload.
63 The following are the presubmit checks:
64 * Check change has one and only one EOL.
67 results.extend(_CommonChecks(input_api, output_api))
71 def _CheckTreeStatus(input_api, output_api, json_url):
72 """Check whether to allow commit.
75 input_api: input related apis.
76 output_api: output related apis.
77 json_url: url to download json style status.
79 tree_status_results = input_api.canned_checks.CheckTreeIsOpen(
80 input_api, output_api, json_url=json_url)
81 if not tree_status_results:
82 # Check for caution state only if tree is not closed.
83 connection = input_api.urllib2.urlopen(json_url)
84 status = input_api.json.loads(connection.read())
86 if ('caution' in status['message'].lower() and
87 os.isatty(sys.stdout.fileno())):
88 # Display a prompt only if we are in an interactive shell. Without this
89 # check the commit queue behaves incorrectly because it considers
90 # prompts to be failures.
91 short_text = 'Tree state is: ' + status['general_state']
92 long_text = status['message'] + '\n' + json_url
93 tree_status_results.append(
94 output_api.PresubmitPromptWarning(
95 message=short_text, long_text=long_text))
97 # Tree status is closed. Put in message about contacting sheriff.
98 connection = input_api.urllib2.urlopen(
99 SKIA_TREE_STATUS_URL + '/current-sheriff')
100 sheriff_details = input_api.json.loads(connection.read())
102 tree_status_results[0]._message += (
103 '\n\nPlease contact the current Skia sheriff (%s) if you are trying '
104 'to submit a build fix\nand do not know how to submit because the '
105 'tree is closed') % sheriff_details['username']
106 return tree_status_results
109 def _CheckLGTMsForPublicAPI(input_api, output_api):
110 """Check LGTMs for public API changes.
112 For public API files make sure there is an LGTM from the list of owners in
116 requires_owner_check = False
117 for affected_svn_file in input_api.AffectedFiles():
118 affected_file_path = affected_svn_file.AbsoluteLocalPath()
119 file_path, file_ext = os.path.splitext(affected_file_path)
120 # We only care about files that end in .h and are under the include dir.
121 if file_ext == '.h' and 'include' in file_path.split(os.path.sep):
122 requires_owner_check = True
124 if not requires_owner_check:
127 lgtm_from_owner = False
128 issue = input_api.change.issue
129 if issue and input_api.rietveld:
130 issue_properties = input_api.rietveld.get_issue_properties(
131 issue=int(issue), messages=True)
132 if re.match(REVERT_CL_SUBJECT_PREFIX, issue_properties['subject'], re.I):
133 # It is a revert CL, ignore the public api owners check.
135 if issue_properties['owner_email'] in PUBLIC_API_OWNERS:
136 # An owner created the CL that is an automatic LGTM.
137 lgtm_from_owner = True
139 messages = issue_properties.get('messages')
141 for message in messages:
142 if (message['sender'] in PUBLIC_API_OWNERS and
143 'lgtm' in message['text'].lower()):
144 # Found an lgtm in a message from an owner.
145 lgtm_from_owner = True
148 if not lgtm_from_owner:
150 output_api.PresubmitError(
151 'Since the CL is editing public API, you must have an LGTM from '
152 'one of: %s' % str(PUBLIC_API_OWNERS)))
156 def CheckChangeOnCommit(input_api, output_api):
157 """Presubmit checks for the change on commit.
159 The following are the presubmit checks:
160 * Check change has one and only one EOL.
161 * Ensures that the Skia tree is open in
162 http://skia-tree-status.appspot.com/. Shows a warning if it is in 'Caution'
163 state and an error if it is in 'Closed' state.
166 results.extend(_CommonChecks(input_api, output_api))
168 _CheckTreeStatus(input_api, output_api, json_url=(
169 SKIA_TREE_STATUS_URL + '/banner-status?format=json')))
170 results.extend(_CheckLGTMsForPublicAPI(input_api, output_api))