Adding rmistry for emergency reverts.
[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 sys
14
15
16 SKIA_TREE_STATUS_URL = 'http://skia-tree-status.appspot.com'
17
18 PUBLIC_API_OWNERS = (
19     'reed@chromium.org',
20     'reed@google.com',
21     'bsalomon@chromium.org',
22     'bsalomon@google.com',
23     'rmistry@google.com',  # For emergency reverts only.
24 )
25
26
27 def _CheckChangeHasEol(input_api, output_api, source_file_filter=None):
28   """Checks that files end with atleast one \n (LF)."""
29   eof_files = []
30   for f in input_api.AffectedSourceFiles(source_file_filter):
31     contents = input_api.ReadFile(f, 'rb')
32     # Check that the file ends in atleast one newline character.
33     if len(contents) > 1 and contents[-1:] != '\n':
34       eof_files.append(f.LocalPath())
35
36   if eof_files:
37     return [output_api.PresubmitPromptWarning(
38       'These files should end in a newline character:',
39       items=eof_files)]
40   return []
41
42
43 def _CommonChecks(input_api, output_api):
44   """Presubmit checks common to upload and commit."""
45   results = []
46   sources = lambda x: (x.LocalPath().endswith('.h') or
47                        x.LocalPath().endswith('.gypi') or
48                        x.LocalPath().endswith('.gyp') or
49                        x.LocalPath().endswith('.py') or
50                        x.LocalPath().endswith('.sh') or
51                        x.LocalPath().endswith('.cpp'))
52   results.extend(
53       _CheckChangeHasEol(
54           input_api, output_api, source_file_filter=sources))
55   return results
56
57
58 def CheckChangeOnUpload(input_api, output_api):
59   """Presubmit checks for the change on upload.
60
61   The following are the presubmit checks:
62   * Check change has one and only one EOL.
63   """
64   results = []
65   results.extend(_CommonChecks(input_api, output_api))
66   return results
67
68
69 def _CheckTreeStatus(input_api, output_api, json_url):
70   """Check whether to allow commit.
71
72   Args:
73     input_api: input related apis.
74     output_api: output related apis.
75     json_url: url to download json style status.
76   """
77   tree_status_results = input_api.canned_checks.CheckTreeIsOpen(
78       input_api, output_api, json_url=json_url)
79   if not tree_status_results:
80     # Check for caution state only if tree is not closed.
81     connection = input_api.urllib2.urlopen(json_url)
82     status = input_api.json.loads(connection.read())
83     connection.close()
84     if ('caution' in status['message'].lower() and
85         os.isatty(sys.stdout.fileno())):
86       # Display a prompt only if we are in an interactive shell. Without this
87       # check the commit queue behaves incorrectly because it considers
88       # prompts to be failures.
89       short_text = 'Tree state is: ' + status['general_state']
90       long_text = status['message'] + '\n' + json_url
91       tree_status_results.append(
92           output_api.PresubmitPromptWarning(
93               message=short_text, long_text=long_text))
94   else:
95     # Tree status is closed. Put in message about contacting sheriff.
96     connection = input_api.urllib2.urlopen(
97         SKIA_TREE_STATUS_URL + '/current-sheriff')
98     sheriff_details = input_api.json.loads(connection.read())
99     if sheriff_details:
100       tree_status_results[0]._message += (
101           '\n\nPlease contact the current Skia sheriff (%s) if you are trying '
102           'to submit a build fix\nand do not know how to submit because the '
103           'tree is closed') % sheriff_details['username']
104   return tree_status_results
105
106
107 def _CheckLGTMsForPublicAPI(input_api, output_api):
108   """Check LGTMs for public API changes.
109
110   For public API files make sure there is an LGTM from the list of owners in
111   PUBLIC_API_OWNERS.
112   """
113   results = []
114   requires_owner_check = False
115   for affected_svn_file in input_api.AffectedFiles():
116     affected_file_path = affected_svn_file.AbsoluteLocalPath()
117     file_path, file_ext = os.path.splitext(affected_file_path)
118     # We only care about files that end in .h and are under the include dir.
119     if file_ext == '.h' and 'include' in file_path.split(os.path.sep):
120       requires_owner_check = True
121
122   if not requires_owner_check:
123     return results
124
125   lgtm_from_owner = False
126   issue = input_api.change.issue
127   if issue and input_api.rietveld:
128     issue_properties = input_api.rietveld.get_issue_properties(
129         issue=int(issue), messages=True)
130     if issue_properties['owner_email'] in PUBLIC_API_OWNERS:
131       # An owner created the CL that is an automatic LGTM.
132       lgtm_from_owner = True
133
134     messages = issue_properties.get('messages')
135     if messages:
136       for message in messages:
137         if (message['sender'] in PUBLIC_API_OWNERS and
138             'lgtm' in message['text'].lower()):
139           # Found an lgtm in a message from an owner.
140           lgtm_from_owner = True
141           break;
142        
143   if not lgtm_from_owner:
144     results.append(
145         output_api.PresubmitError(
146             'Since the CL is editing public API, you must have an LGTM from '
147             'one of: %s' % str(PUBLIC_API_OWNERS)))
148   return results
149
150
151 def CheckChangeOnCommit(input_api, output_api):
152   """Presubmit checks for the change on commit.
153
154   The following are the presubmit checks:
155   * Check change has one and only one EOL.
156   * Ensures that the Skia tree is open in
157     http://skia-tree-status.appspot.com/. Shows a warning if it is in 'Caution'
158     state and an error if it is in 'Closed' state.
159   """
160   results = []
161   results.extend(_CommonChecks(input_api, output_api))
162   results.extend(
163       _CheckTreeStatus(input_api, output_api, json_url=(
164           SKIA_TREE_STATUS_URL + '/banner-status?format=json')))
165   results.extend(_CheckLGTMsForPublicAPI(input_api, output_api))
166   return results