blob: 1f3f3f5d6e93800b9bcdc99e8450603c21baab6d [file] [log] [blame]
andrew@webrtc.org2442de12012-01-23 17:45:41 +00001# Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
2#
3# Use of this source code is governed by a BSD-style license
4# that can be found in the LICENSE file in the root of the source
5# tree. An additional intellectual property rights grant can be found
6# in the file PATENTS. All contributing project authors may
7# be found in the AUTHORS file in the root of the source tree.
niklase@google.comda159d62011-05-30 11:51:34 +00008
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +00009import os
kjellander@webrtc.org85759802013-10-22 16:47:40 +000010import re
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +000011import sys
kjellander@webrtc.org85759802013-10-22 16:47:40 +000012
13
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010014# Directories that will be scanned by cpplint by the presubmit script.
15CPPLINT_DIRS = [
Fredrik Solenbergea073732015-12-01 11:26:34 +010016 'webrtc/audio',
17 'webrtc/call',
jbauch0f2e9392015-12-10 03:11:42 -080018 'webrtc/common_video',
jbauch70625e52015-12-09 14:18:14 -080019 'webrtc/examples',
aleloidf9e4d92016-08-08 10:26:09 -070020 'webrtc/modules/audio_mixer',
jbauchf91e6d02016-01-24 23:05:21 -080021 'webrtc/modules/bitrate_controller',
Stefan Holmer80e12072016-02-23 13:30:42 +010022 'webrtc/modules/congestion_controller',
jbauchd2a22962016-02-08 23:18:25 -080023 'webrtc/modules/pacing',
terelius8f09f172015-12-15 00:51:54 -080024 'webrtc/modules/remote_bitrate_estimator',
danilchap377b5e62015-12-15 04:33:44 -080025 'webrtc/modules/rtp_rtcp',
philipel5908c712015-12-21 08:23:20 -080026 'webrtc/modules/video_coding',
mflodman88eeac42015-12-08 09:21:28 +010027 'webrtc/modules/video_processing',
jbauch0f2e9392015-12-10 03:11:42 -080028 'webrtc/tools',
mflodmand1590b22015-12-09 07:07:59 -080029 'webrtc/video',
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010030]
31
jbauchc4e3ead2016-02-19 00:25:55 -080032# These filters will always be removed, even if the caller specifies a filter
33# set, as they are problematic or broken in some way.
34#
35# Justifications for each filter:
36# - build/c++11 : Rvalue ref checks are unreliable (false positives),
37# include file and feature blacklists are
38# google3-specific.
kjellandere5a87a52016-04-27 02:32:12 -070039# - whitespace/operators: Same as above (doesn't seem sufficient to eliminate
40# all move-related errors).
jbauchc4e3ead2016-02-19 00:25:55 -080041BLACKLIST_LINT_FILTERS = [
42 '-build/c++11',
kjellandere5a87a52016-04-27 02:32:12 -070043 '-whitespace/operators',
jbauchc4e3ead2016-02-19 00:25:55 -080044]
45
kjellanderfd595232015-12-04 02:44:09 -080046# List of directories of "supported" native APIs. That means changes to headers
47# will be done in a compatible way following this scheme:
48# 1. Non-breaking changes are made.
49# 2. The old APIs as marked as deprecated (with comments).
50# 3. Deprecation is announced to discuss-webrtc@googlegroups.com and
51# webrtc-users@google.com (internal list).
52# 4. (later) The deprecated APIs are removed.
kjellander53047c92015-12-02 23:56:14 -080053NATIVE_API_DIRS = (
kjellander53047c92015-12-02 23:56:14 -080054 'webrtc',
kjellanderdd705472016-06-09 11:17:27 -070055 'webrtc/api',
56 'webrtc/media',
kjellander53047c92015-12-02 23:56:14 -080057 'webrtc/modules/audio_device/include',
kjellanderdd705472016-06-09 11:17:27 -070058 'webrtc/pc',
59)
60# These directories should not be used but are maintained only to avoid breaking
61# some legacy downstream code.
62LEGACY_API_DIRS = (
kjellanderdd705472016-06-09 11:17:27 -070063 'webrtc/base',
64 'webrtc/common_audio/include',
65 'webrtc/modules/audio_coding/include',
66 'webrtc/modules/audio_conference_mixer/include',
kjellander53047c92015-12-02 23:56:14 -080067 'webrtc/modules/audio_processing/include',
68 'webrtc/modules/bitrate_controller/include',
Stefan Holmer80e12072016-02-23 13:30:42 +010069 'webrtc/modules/congestion_controller/include',
kjellander53047c92015-12-02 23:56:14 -080070 'webrtc/modules/include',
71 'webrtc/modules/remote_bitrate_estimator/include',
72 'webrtc/modules/rtp_rtcp/include',
kjellanderdd705472016-06-09 11:17:27 -070073 'webrtc/modules/rtp_rtcp/source',
kjellander53047c92015-12-02 23:56:14 -080074 'webrtc/modules/utility/include',
75 'webrtc/modules/video_coding/codecs/h264/include',
76 'webrtc/modules/video_coding/codecs/i420/include',
77 'webrtc/modules/video_coding/codecs/vp8/include',
78 'webrtc/modules/video_coding/codecs/vp9/include',
79 'webrtc/modules/video_coding/include',
kjellanderdd705472016-06-09 11:17:27 -070080 'webrtc/system_wrappers/include',
kjellander53047c92015-12-02 23:56:14 -080081 'webrtc/voice_engine/include',
82)
kjellanderdd705472016-06-09 11:17:27 -070083API_DIRS = NATIVE_API_DIRS[:] + LEGACY_API_DIRS[:]
kjellander53047c92015-12-02 23:56:14 -080084
85
86def _VerifyNativeApiHeadersListIsValid(input_api, output_api):
87 """Ensures the list of native API header directories is up to date."""
88 non_existing_paths = []
89 native_api_full_paths = [
90 input_api.os_path.join(input_api.PresubmitLocalPath(),
kjellanderdd705472016-06-09 11:17:27 -070091 *path.split('/')) for path in API_DIRS]
kjellander53047c92015-12-02 23:56:14 -080092 for path in native_api_full_paths:
93 if not os.path.isdir(path):
94 non_existing_paths.append(path)
95 if non_existing_paths:
96 return [output_api.PresubmitError(
97 'Directories to native API headers have changed which has made the '
98 'list in PRESUBMIT.py outdated.\nPlease update it to the current '
99 'location of our native APIs.',
100 non_existing_paths)]
101 return []
102
kwibergeb133022016-04-07 07:41:48 -0700103api_change_msg = """
104You seem to be changing native API header files. Please make sure that you:
105 1. Make compatible changes that don't break existing clients.
106 2. Mark the old stuff as deprecated.
107 3. Create a timeline and plan for when the deprecated stuff will be
108 removed. (The amount of time we give users to change their code
109 should be informed by how much work it is for them. If they just
110 need to replace one name with another or something equally
111 simple, 1-2 weeks might be good; if they need to do serious work,
112 up to 3 months may be called for.)
113 4. Update/inform existing downstream code owners to stop using the
114 deprecated stuff. (Send announcements to
115 discuss-webrtc@googlegroups.com and webrtc-users@google.com.)
116 5. Remove the deprecated stuff, once the agreed-upon amount of time
117 has passed.
118Related files:
119"""
kjellander53047c92015-12-02 23:56:14 -0800120
121def _CheckNativeApiHeaderChanges(input_api, output_api):
122 """Checks to remind proper changing of native APIs."""
123 files = []
124 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
125 if f.LocalPath().endswith('.h'):
kjellanderdd705472016-06-09 11:17:27 -0700126 for path in API_DIRS:
kjellander53047c92015-12-02 23:56:14 -0800127 if os.path.dirname(f.LocalPath()) == path:
128 files.append(f)
129
130 if files:
kwibergeb133022016-04-07 07:41:48 -0700131 return [output_api.PresubmitNotifyResult(api_change_msg, files)]
kjellander53047c92015-12-02 23:56:14 -0800132 return []
133
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100134
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000135def _CheckNoIOStreamInHeaders(input_api, output_api):
136 """Checks to make sure no .h files include <iostream>."""
137 files = []
138 pattern = input_api.re.compile(r'^#include\s*<iostream>',
139 input_api.re.MULTILINE)
140 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
141 if not f.LocalPath().endswith('.h'):
142 continue
143 contents = input_api.ReadFile(f)
144 if pattern.search(contents):
145 files.append(f)
146
147 if len(files):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200148 return [output_api.PresubmitError(
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000149 'Do not #include <iostream> in header files, since it inserts static ' +
150 'initialization into every file including the header. Instead, ' +
151 '#include <ostream>. See http://crbug.com/94794',
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200152 files)]
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000153 return []
154
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000155
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000156def _CheckNoFRIEND_TEST(input_api, output_api):
157 """Make sure that gtest's FRIEND_TEST() macro is not used, the
158 FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
159 used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
160 problems = []
161
162 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.h'))
163 for f in input_api.AffectedFiles(file_filter=file_filter):
164 for line_num, line in f.ChangedContents():
165 if 'FRIEND_TEST(' in line:
166 problems.append(' %s:%d' % (f.LocalPath(), line_num))
167
168 if not problems:
169 return []
170 return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
171 'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
172 'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
173
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000174
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100175def _IsLintWhitelisted(whitelist_dirs, file_path):
176 """ Checks if a file is whitelisted for lint check."""
177 for path in whitelist_dirs:
178 if os.path.dirname(file_path).startswith(path):
179 return True
180 return False
181
182
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000183def _CheckApprovedFilesLintClean(input_api, output_api,
184 source_file_filter=None):
185 """Checks that all new or whitelisted .cc and .h files pass cpplint.py.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000186 This check is based on _CheckChangeLintsClean in
187 depot_tools/presubmit_canned_checks.py but has less filters and only checks
188 added files."""
189 result = []
190
191 # Initialize cpplint.
192 import cpplint
193 # Access to a protected member _XX of a client class
194 # pylint: disable=W0212
195 cpplint._cpplint_state.ResetErrorCounts()
196
jbauchc4e3ead2016-02-19 00:25:55 -0800197 lint_filters = cpplint._Filters()
198 lint_filters.extend(BLACKLIST_LINT_FILTERS)
199 cpplint._SetFilters(','.join(lint_filters))
200
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100201 # Create a platform independent whitelist for the CPPLINT_DIRS.
202 whitelist_dirs = [input_api.os_path.join(*path.split('/'))
203 for path in CPPLINT_DIRS]
204
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000205 # Use the strictest verbosity level for cpplint.py (level 1) which is the
206 # default when running cpplint.py from command line.
207 # To make it possible to work with not-yet-converted code, we're only applying
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000208 # it to new (or moved/renamed) files and files listed in LINT_FOLDERS.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000209 verbosity_level = 1
210 files = []
211 for f in input_api.AffectedSourceFiles(source_file_filter):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200212 # Note that moved/renamed files also count as added.
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100213 if f.Action() == 'A' or _IsLintWhitelisted(whitelist_dirs, f.LocalPath()):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000214 files.append(f.AbsoluteLocalPath())
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000215
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000216 for file_name in files:
217 cpplint.ProcessFile(file_name, verbosity_level)
218
219 if cpplint._cpplint_state.error_count > 0:
220 if input_api.is_committing:
221 # TODO(kjellander): Change back to PresubmitError below when we're
222 # confident with the lint settings.
223 res_type = output_api.PresubmitPromptWarning
224 else:
225 res_type = output_api.PresubmitPromptWarning
226 result = [res_type('Changelist failed cpplint.py check.')]
227
228 return result
229
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000230def _CheckNoRtcBaseDeps(input_api, gyp_files, output_api):
231 pattern = input_api.re.compile(r"base.gyp:rtc_base\s*'")
232 violating_files = []
233 for f in gyp_files:
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000234 gyp_exceptions = (
maxmorinec623742016-09-15 05:11:55 -0700235 'audio_device.gypi',
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000236 'base_tests.gyp',
237 'desktop_capture.gypi',
kjellander@webrtc.orge7237282015-02-26 11:12:17 +0000238 'p2p.gyp',
tkchin9eeb6242016-04-27 01:54:20 -0700239 'sdk.gyp',
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000240 'webrtc_test_common.gyp',
241 'webrtc_tests.gypi',
242 )
243 if f.LocalPath().endswith(gyp_exceptions):
244 continue
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000245 contents = input_api.ReadFile(f)
246 if pattern.search(contents):
247 violating_files.append(f)
248 if violating_files:
249 return [output_api.PresubmitError(
250 'Depending on rtc_base is not allowed. Change your dependency to '
251 'rtc_base_approved and possibly sanitize and move the desired source '
252 'file(s) to rtc_base_approved.\nChanged GYP files:',
253 items=violating_files)]
254 return []
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000255
ehmaldonado5b1ba082016-09-02 05:51:08 -0700256def _CheckNoRtcBaseDepsGn(input_api, gn_files, output_api):
257 pattern = input_api.re.compile(r'base:rtc_base\s*"')
258 violating_files = []
259 for f in gn_files:
260 gn_exceptions = (
maxmorinec623742016-09-15 05:11:55 -0700261 os.path.join('audio_device', 'BUILD.gn'),
ehmaldonado5b1ba082016-09-02 05:51:08 -0700262 os.path.join('base_tests', 'BUILD.gn'),
263 os.path.join('desktop_capture', 'BUILD.gn'),
264 os.path.join('p2p', 'BUILD.gn'),
265 os.path.join('sdk', 'BUILD.gn'),
266 os.path.join('webrtc_test_common', 'BUILD.gn'),
267 os.path.join('webrtc_tests', 'BUILD.gn'),
268
269 # TODO(ehmaldonado): Clean up references to rtc_base in these files.
270 # See https://bugs.chromium.org/p/webrtc/issues/detail?id=3806
271 os.path.join('webrtc', 'BUILD.gn'),
272 os.path.join('xmllite', 'BUILD.gn'),
273 os.path.join('xmpp', 'BUILD.gn'),
274 os.path.join('modules', 'BUILD.gn'),
275 os.path.join('audio_device', 'BUILD.gn'),
276 os.path.join('pc', 'BUILD.gn'),
277 )
278 if f.LocalPath().endswith(gn_exceptions):
279 continue
280 contents = input_api.ReadFile(f)
281 if pattern.search(contents):
282 violating_files.append(f)
283 if violating_files:
284 return [output_api.PresubmitError(
285 'Depending on rtc_base is not allowed. Change your dependency to '
286 'rtc_base_approved and possibly sanitize and move the desired source '
287 'file(s) to rtc_base_approved.\nChanged GN files:',
288 items=violating_files)]
289 return []
290
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000291def _CheckNoSourcesAboveGyp(input_api, gyp_files, output_api):
292 # Disallow referencing source files with paths above the GYP file location.
kjellander@webrtc.org74290b92016-06-15 17:19:06 +0200293 source_pattern = input_api.re.compile(r'\'sources\'.*?\[(.*?)\]',
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000294 re.MULTILINE | re.DOTALL)
kjellander@webrtc.orga33f05e2015-01-29 14:29:45 +0000295 file_pattern = input_api.re.compile(r"'((\.\./.*?)|(<\(webrtc_root\).*?))'")
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000296 violating_gyp_files = set()
297 violating_source_entries = []
298 for gyp_file in gyp_files:
kjellanderc61635c2016-02-02 02:30:07 -0800299 if 'supplement.gypi' in gyp_file.LocalPath():
300 # Exclude supplement.gypi from this check, as the LSan and TSan
301 # suppression files are located in a different location.
302 continue
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000303 contents = input_api.ReadFile(gyp_file)
304 for source_block_match in source_pattern.finditer(contents):
kjellander@webrtc.orgc98f6f32015-03-04 07:08:11 +0000305 # Find all source list entries starting with ../ in the source block
306 # (exclude overrides entries).
kjellander@webrtc.org74290b92016-06-15 17:19:06 +0200307 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
308 source_file = file_list_match.group(1)
kjellander@webrtc.orgc98f6f32015-03-04 07:08:11 +0000309 if 'overrides/' not in source_file:
310 violating_source_entries.append(source_file)
311 violating_gyp_files.add(gyp_file)
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000312 if violating_gyp_files:
313 return [output_api.PresubmitError(
314 'Referencing source files above the directory of the GYP file is not '
315 'allowed. Please introduce new GYP targets and/or GYP files in the '
316 'proper location instead.\n'
317 'Invalid source entries:\n'
318 '%s\n'
319 'Violating GYP files:' % '\n'.join(violating_source_entries),
320 items=violating_gyp_files)]
321 return []
322
ehmaldonado5b1ba082016-09-02 05:51:08 -0700323def _CheckNoSourcesAboveGn(input_api, gn_files, output_api):
324 # Disallow referencing source files with paths above the GN file location.
325 source_pattern = input_api.re.compile(r' +sources \+?= \[(.*?)\]',
326 re.MULTILINE | re.DOTALL)
327 file_pattern = input_api.re.compile(r'"((\.\./.*?)|(//.*?))"')
328 violating_gn_files = set()
329 violating_source_entries = []
330 for gn_file in gn_files:
331 contents = input_api.ReadFile(gn_file)
332 for source_block_match in source_pattern.finditer(contents):
333 # Find all source list entries starting with ../ in the source block
334 # (exclude overrides entries).
335 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
336 source_file = file_list_match.group(1)
337 if 'overrides/' not in source_file:
338 violating_source_entries.append(source_file)
339 violating_gn_files.add(gn_file)
340 if violating_gn_files:
341 return [output_api.PresubmitError(
342 'Referencing source files above the directory of the GN file is not '
343 'allowed. Please introduce new GYP targets and/or GN files in the '
344 'proper location instead.\n'
345 'Invalid source entries:\n'
346 '%s\n'
347 'Violating GN files:' % '\n'.join(violating_source_entries),
348 items=violating_gn_files)]
349 return []
350
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000351def _CheckGypChanges(input_api, output_api):
352 source_file_filter = lambda x: input_api.FilterSourceFile(
353 x, white_list=(r'.+\.(gyp|gypi)$',))
354
355 gyp_files = []
356 for f in input_api.AffectedSourceFiles(source_file_filter):
kjellander@webrtc.org3398a4a2014-11-24 10:05:37 +0000357 if f.LocalPath().startswith('webrtc'):
358 gyp_files.append(f)
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000359
360 result = []
361 if gyp_files:
362 result.append(output_api.PresubmitNotifyResult(
363 'As you\'re changing GYP files: please make sure corresponding '
364 'BUILD.gn files are also updated.\nChanged GYP files:',
365 items=gyp_files))
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000366 result.extend(_CheckNoRtcBaseDeps(input_api, gyp_files, output_api))
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000367 result.extend(_CheckNoSourcesAboveGyp(input_api, gyp_files, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000368 return result
369
ehmaldonado5b1ba082016-09-02 05:51:08 -0700370def _CheckGnChanges(input_api, output_api):
371 source_file_filter = lambda x: input_api.FilterSourceFile(
372 x, white_list=(r'.+\.(gn|gni)$',))
373
374 gn_files = []
375 for f in input_api.AffectedSourceFiles(source_file_filter):
376 if f.LocalPath().startswith('webrtc'):
377 gn_files.append(f)
378
379 result = []
380 if gn_files:
381 result.append(output_api.PresubmitNotifyResult(
382 'As you\'re changing GN files: please make sure corresponding GYP'
383 'files are also updated.\nChanged GN files:',
384 items=gn_files))
385 result.extend(_CheckNoRtcBaseDepsGn(input_api, gn_files, output_api))
386 result.extend(_CheckNoSourcesAboveGn(input_api, gn_files, output_api))
387 return result
388
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000389def _CheckUnwantedDependencies(input_api, output_api):
390 """Runs checkdeps on #include statements added in this
391 change. Breaking - rules is an error, breaking ! rules is a
392 warning.
393 """
394 # Copied from Chromium's src/PRESUBMIT.py.
395
396 # We need to wait until we have an input_api object and use this
397 # roundabout construct to import checkdeps because this file is
398 # eval-ed and thus doesn't have __file__.
399 original_sys_path = sys.path
400 try:
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +0000401 checkdeps_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
402 'buildtools', 'checkdeps')
403 if not os.path.exists(checkdeps_path):
404 return [output_api.PresubmitError(
405 'Cannot find checkdeps at %s\nHave you run "gclient sync" to '
406 'download Chromium and setup the symlinks?' % checkdeps_path)]
407 sys.path.append(checkdeps_path)
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000408 import checkdeps
409 from cpp_checker import CppChecker
410 from rules import Rule
411 finally:
412 # Restore sys.path to what it was before.
413 sys.path = original_sys_path
414
415 added_includes = []
416 for f in input_api.AffectedFiles():
417 if not CppChecker.IsCppFile(f.LocalPath()):
418 continue
419
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200420 changed_lines = [line for _, line in f.ChangedContents()]
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000421 added_includes.append([f.LocalPath(), changed_lines])
422
423 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
424
425 error_descriptions = []
426 warning_descriptions = []
427 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
428 added_includes):
429 description_with_path = '%s\n %s' % (path, rule_description)
430 if rule_type == Rule.DISALLOW:
431 error_descriptions.append(description_with_path)
432 else:
433 warning_descriptions.append(description_with_path)
434
435 results = []
436 if error_descriptions:
437 results.append(output_api.PresubmitError(
438 'You added one or more #includes that violate checkdeps rules.',
439 error_descriptions))
440 if warning_descriptions:
441 results.append(output_api.PresubmitPromptOrNotify(
442 'You added one or more #includes of files that are temporarily\n'
443 'allowed but being removed. Can you avoid introducing the\n'
444 '#include? See relevant DEPS file(s) for details and contacts.',
445 warning_descriptions))
446 return results
447
kjellanderd1e26a92016-09-19 08:11:16 -0700448def _CheckChangeHasBugField(input_api, output_api):
449 """Requires that the changelist have a BUG= field.
450
451 This check is stricter than the one in depot_tools/presubmit_canned_checks.py
452 since it fails the presubmit if the BUG= field is missing or doesn't contain
453 a bug reference.
454 """
455 if input_api.change.BUG:
456 return []
457 else:
458 return [output_api.PresubmitError(
459 'The BUG=[bug number] field is mandatory. Please create a bug and '
460 'reference it using either of:\n'
461 ' * https://bugs.webrtc.org - reference it using BUG=webrtc:XXXX\n'
462 ' * https://crbug.com - reference it using BUG=chromium:XXXXXX')]
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000463
kjellander569cf942016-02-11 05:02:59 -0800464def _CheckJSONParseErrors(input_api, output_api):
465 """Check that JSON files do not contain syntax errors."""
466
467 def FilterFile(affected_file):
468 return input_api.os_path.splitext(affected_file.LocalPath())[1] == '.json'
469
470 def GetJSONParseError(input_api, filename):
471 try:
472 contents = input_api.ReadFile(filename)
473 input_api.json.loads(contents)
474 except ValueError as e:
475 return e
476 return None
477
478 results = []
479 for affected_file in input_api.AffectedFiles(
480 file_filter=FilterFile, include_deletes=False):
481 parse_error = GetJSONParseError(input_api,
482 affected_file.AbsoluteLocalPath())
483 if parse_error:
484 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
485 (affected_file.LocalPath(), parse_error)))
486 return results
487
488
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200489def _RunPythonTests(input_api, output_api):
490 def join(*args):
491 return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
492
493 test_directories = [
494 join('tools', 'autoroller', 'unittests'),
aleloi7ebbf902016-06-20 07:39:15 -0700495 join('webrtc', 'tools', 'py_event_log_analyzer'),
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200496 ]
497
498 tests = []
499 for directory in test_directories:
500 tests.extend(
501 input_api.canned_checks.GetUnitTestsInDirectory(
502 input_api,
503 output_api,
504 directory,
505 whitelist=[r'.+_test\.py$']))
506 return input_api.RunTests(tests, parallel=True)
507
508
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000509def _CommonChecks(input_api, output_api):
510 """Checks common to both upload and commit."""
niklase@google.comda159d62011-05-30 11:51:34 +0000511 results = []
tkchin42f580e2015-11-26 23:18:23 -0800512 # Filter out files that are in objc or ios dirs from being cpplint-ed since
513 # they do not follow C++ lint rules.
514 black_list = input_api.DEFAULT_BLACK_LIST + (
515 r".*\bobjc[\\\/].*",
Kári Tristan Helgason3fa35172016-09-09 08:55:05 +0000516 r".*objc\.[hcm]+$",
hjon65ae2d82016-08-02 23:55:44 -0700517 r"webrtc\/build\/ios\/SDK\/.*",
tkchin42f580e2015-11-26 23:18:23 -0800518 )
519 source_file_filter = lambda x: input_api.FilterSourceFile(x, None, black_list)
520 results.extend(_CheckApprovedFilesLintClean(
521 input_api, output_api, source_file_filter))
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000522 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
523 black_list=(r'^.*gviz_api\.py$',
524 r'^.*gaeunit\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000525 # Embedded shell-script fakes out pylint.
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200526 r'^build[\\\/].*\.py$',
527 r'^buildtools[\\\/].*\.py$',
528 r'^chromium[\\\/].*\.py$',
kjellanderd620f822016-04-04 06:07:08 -0700529 r'^mojo.*[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200530 r'^out.*[\\\/].*\.py$',
531 r'^testing[\\\/].*\.py$',
532 r'^third_party[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200533 r'^tools[\\\/]clang[\\\/].*\.py$',
534 r'^tools[\\\/]generate_library_loader[\\\/].*\.py$',
kjellanderd620f822016-04-04 06:07:08 -0700535 r'^tools[\\\/]generate_stubs[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200536 r'^tools[\\\/]gn[\\\/].*\.py$',
537 r'^tools[\\\/]gyp[\\\/].*\.py$',
Henrik Kjellanderd6d27e72015-09-25 22:19:11 +0200538 r'^tools[\\\/]isolate_driver.py$',
kjellanderd620f822016-04-04 06:07:08 -0700539 r'^tools[\\\/]mb[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200540 r'^tools[\\\/]protoc_wrapper[\\\/].*\.py$',
541 r'^tools[\\\/]python[\\\/].*\.py$',
542 r'^tools[\\\/]python_charts[\\\/]data[\\\/].*\.py$',
543 r'^tools[\\\/]refactoring[\\\/].*\.py$',
544 r'^tools[\\\/]swarming_client[\\\/].*\.py$',
545 r'^tools[\\\/]vim[\\\/].*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000546 # TODO(phoglund): should arguably be checked.
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200547 r'^tools[\\\/]valgrind-webrtc[\\\/].*\.py$',
548 r'^tools[\\\/]valgrind[\\\/].*\.py$',
549 r'^tools[\\\/]win[\\\/].*\.py$',
550 r'^xcodebuild.*[\\\/].*\.py$',),
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000551 disabled_warnings=['F0401', # Failed to import x
552 'E0611', # No package y in x
553 'W0232', # Class has no __init__ method
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200554 ],
555 pylintrc='pylintrc'))
kjellander569cf942016-02-11 05:02:59 -0800556
nisse3d21e232016-09-02 03:07:06 -0700557 # TODO(nisse): talk/ is no more, so make below checks simpler?
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200558 # WebRTC can't use the presubmit_canned_checks.PanProjectChecks function since
559 # we need to have different license checks in talk/ and webrtc/ directories.
560 # Instead, hand-picked checks are included below.
Henrik Kjellander63224672015-09-08 08:03:56 +0200561
tkchin3cd9a302016-06-08 12:40:28 -0700562 # .m and .mm files are ObjC files. For simplicity we will consider .h files in
563 # ObjC subdirectories ObjC headers.
564 objc_filter_list = (r'.+\.m$', r'.+\.mm$', r'.+objc\/.+\.h$')
Henrik Kjellander63224672015-09-08 08:03:56 +0200565 # Skip long-lines check for DEPS, GN and GYP files.
tkchin3cd9a302016-06-08 12:40:28 -0700566 build_file_filter_list = (r'.+\.gyp$', r'.+\.gypi$', r'.+\.gn$', r'.+\.gni$',
567 'DEPS')
568 eighty_char_sources = lambda x: input_api.FilterSourceFile(x,
569 black_list=build_file_filter_list + objc_filter_list)
570 hundred_char_sources = lambda x: input_api.FilterSourceFile(x,
571 white_list=objc_filter_list)
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000572 results.extend(input_api.canned_checks.CheckLongLines(
tkchin3cd9a302016-06-08 12:40:28 -0700573 input_api, output_api, maxlen=80, source_file_filter=eighty_char_sources))
574 results.extend(input_api.canned_checks.CheckLongLines(
575 input_api, output_api, maxlen=100,
576 source_file_filter=hundred_char_sources))
577
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000578 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
579 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000580 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
581 input_api, output_api))
582 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
583 input_api, output_api))
kjellander53047c92015-12-02 23:56:14 -0800584 results.extend(_CheckNativeApiHeaderChanges(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000585 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
586 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000587 results.extend(_CheckGypChanges(input_api, output_api))
ehmaldonado5b1ba082016-09-02 05:51:08 -0700588 results.extend(_CheckGnChanges(input_api, output_api))
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000589 results.extend(_CheckUnwantedDependencies(input_api, output_api))
kjellander569cf942016-02-11 05:02:59 -0800590 results.extend(_CheckJSONParseErrors(input_api, output_api))
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200591 results.extend(_RunPythonTests(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000592 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000593
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000594
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000595def CheckChangeOnUpload(input_api, output_api):
596 results = []
597 results.extend(_CommonChecks(input_api, output_api))
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200598 results.extend(
599 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000600 return results
601
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000602
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000603def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000604 results = []
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000605 results.extend(_CommonChecks(input_api, output_api))
kjellander53047c92015-12-02 23:56:14 -0800606 results.extend(_VerifyNativeApiHeadersListIsValid(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000607 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000608 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
609 input_api, output_api))
610 results.extend(input_api.canned_checks.CheckChangeHasDescription(
611 input_api, output_api))
kjellanderd1e26a92016-09-19 08:11:16 -0700612 results.extend(_CheckChangeHasBugField(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000613 results.extend(input_api.canned_checks.CheckChangeHasTestField(
614 input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000615 results.extend(input_api.canned_checks.CheckTreeIsOpen(
616 input_api, output_api,
617 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000618 return results