Do not enforce the public API presubmit check for Revert CLs.
[platform/upstream/libSkiaSharp.git] / PRESUBMIT.py
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.
4
5
6 """Top-level presubmit script for Skia.
7
8 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
9 for more details about the presubmit API built into gcl.
10 """
11
12 import os
13 import re
14 import sys
15
16
17 REVERT_CL_SUBJECT_PREFIX = 'Revert '
18
19 SKIA_TREE_STATUS_URL = 'http://skia-tree-status.appspot.com'
20
21 PUBLIC_API_OWNERS = (
22     'reed@chromium.org',
23     'reed@google.com',
24     'bsalomon@chromium.org',
25     'bsalomon@google.com',
26 )
27
28
29 def _CheckChangeHasEol(input_api, output_api, source_file_filter=None):
30   """Checks that files end with atleast one \n (LF)."""
31   eof_files = []
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())
37
38   if eof_files:
39     return [output_api.PresubmitPromptWarning(
40       'These files should end in a newline character:',
41       items=eof_files)]
42   return []
43
44
45 def _CommonChecks(input_api, output_api):
46   """Presubmit checks common to upload and commit."""
47   results = []
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'))
54   results.extend(
55       _CheckChangeHasEol(
56           input_api, output_api, source_file_filter=sources))
57   return results
58
59
60 def CheckChangeOnUpload(input_api, output_api):
61   """Presubmit checks for the change on upload.
62
63   The following are the presubmit checks:
64   * Check change has one and only one EOL.
65   """
66   results = []
67   results.extend(_CommonChecks(input_api, output_api))
68   return results
69
70
71 def _CheckTreeStatus(input_api, output_api, json_url):
72   """Check whether to allow commit.
73
74   Args:
75     input_api: input related apis.
76     output_api: output related apis.
77     json_url: url to download json style status.
78   """
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())
85     connection.close()
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))
96   else:
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())
101     if sheriff_details:
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
107
108
109 def _CheckLGTMsForPublicAPI(input_api, output_api):
110   """Check LGTMs for public API changes.
111
112   For public API files make sure there is an LGTM from the list of owners in
113   PUBLIC_API_OWNERS.
114   """
115   results = []
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
123
124   if not requires_owner_check:
125     return results
126
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.
134       return results
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
138
139     messages = issue_properties.get('messages')
140     if 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
146           break;
147
148   if not lgtm_from_owner:
149     results.append(
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)))
153   return results
154
155
156 def CheckChangeOnCommit(input_api, output_api):
157   """Presubmit checks for the change on commit.
158
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.
164   """
165   results = []
166   results.extend(_CommonChecks(input_api, output_api))
167   results.extend(
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))
171   return results