blob: 04de7c8def9392b87b16347e19f00ca00a85aeb1 [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
kjellander986ee082015-06-16 04:32:13 -07009import json
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +000010import os
kjellander986ee082015-06-16 04:32:13 -070011import platform
kjellander@webrtc.org85759802013-10-22 16:47:40 +000012import re
kjellander986ee082015-06-16 04:32:13 -070013import subprocess
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +000014import sys
kjellander@webrtc.org85759802013-10-22 16:47:40 +000015
16
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010017# Directories that will be scanned by cpplint by the presubmit script.
18CPPLINT_DIRS = [
Fredrik Solenbergea073732015-12-01 11:26:34 +010019 'webrtc/audio',
20 'webrtc/call',
jbauch0f2e9392015-12-10 03:11:42 -080021 'webrtc/common_video',
jbauch70625e52015-12-09 14:18:14 -080022 'webrtc/examples',
aleloidf9e4d92016-08-08 10:26:09 -070023 'webrtc/modules/audio_mixer',
jbauchf91e6d02016-01-24 23:05:21 -080024 'webrtc/modules/bitrate_controller',
Stefan Holmer80e12072016-02-23 13:30:42 +010025 'webrtc/modules/congestion_controller',
jbauchd2a22962016-02-08 23:18:25 -080026 'webrtc/modules/pacing',
terelius8f09f172015-12-15 00:51:54 -080027 'webrtc/modules/remote_bitrate_estimator',
danilchap377b5e62015-12-15 04:33:44 -080028 'webrtc/modules/rtp_rtcp',
philipel5908c712015-12-21 08:23:20 -080029 'webrtc/modules/video_coding',
mflodman88eeac42015-12-08 09:21:28 +010030 'webrtc/modules/video_processing',
jbauch0f2e9392015-12-10 03:11:42 -080031 'webrtc/tools',
mflodmand1590b22015-12-09 07:07:59 -080032 'webrtc/video',
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010033]
34
jbauchc4e3ead2016-02-19 00:25:55 -080035# These filters will always be removed, even if the caller specifies a filter
36# set, as they are problematic or broken in some way.
37#
38# Justifications for each filter:
39# - build/c++11 : Rvalue ref checks are unreliable (false positives),
40# include file and feature blacklists are
41# google3-specific.
kjellandere5a87a52016-04-27 02:32:12 -070042# - whitespace/operators: Same as above (doesn't seem sufficient to eliminate
43# all move-related errors).
jbauchc4e3ead2016-02-19 00:25:55 -080044BLACKLIST_LINT_FILTERS = [
45 '-build/c++11',
kjellandere5a87a52016-04-27 02:32:12 -070046 '-whitespace/operators',
jbauchc4e3ead2016-02-19 00:25:55 -080047]
48
kjellanderfd595232015-12-04 02:44:09 -080049# List of directories of "supported" native APIs. That means changes to headers
50# will be done in a compatible way following this scheme:
51# 1. Non-breaking changes are made.
52# 2. The old APIs as marked as deprecated (with comments).
53# 3. Deprecation is announced to discuss-webrtc@googlegroups.com and
54# webrtc-users@google.com (internal list).
55# 4. (later) The deprecated APIs are removed.
kjellander53047c92015-12-02 23:56:14 -080056NATIVE_API_DIRS = (
kjellander53047c92015-12-02 23:56:14 -080057 'webrtc',
kjellanderdd705472016-06-09 11:17:27 -070058 'webrtc/api',
59 'webrtc/media',
kjellander53047c92015-12-02 23:56:14 -080060 'webrtc/modules/audio_device/include',
kjellanderdd705472016-06-09 11:17:27 -070061 'webrtc/pc',
62)
63# These directories should not be used but are maintained only to avoid breaking
64# some legacy downstream code.
65LEGACY_API_DIRS = (
kjellanderdd705472016-06-09 11:17:27 -070066 'webrtc/base',
67 'webrtc/common_audio/include',
68 'webrtc/modules/audio_coding/include',
69 'webrtc/modules/audio_conference_mixer/include',
kjellander53047c92015-12-02 23:56:14 -080070 'webrtc/modules/audio_processing/include',
71 'webrtc/modules/bitrate_controller/include',
Stefan Holmer80e12072016-02-23 13:30:42 +010072 'webrtc/modules/congestion_controller/include',
kjellander53047c92015-12-02 23:56:14 -080073 'webrtc/modules/include',
74 'webrtc/modules/remote_bitrate_estimator/include',
75 'webrtc/modules/rtp_rtcp/include',
kjellanderdd705472016-06-09 11:17:27 -070076 'webrtc/modules/rtp_rtcp/source',
kjellander53047c92015-12-02 23:56:14 -080077 'webrtc/modules/utility/include',
78 'webrtc/modules/video_coding/codecs/h264/include',
79 'webrtc/modules/video_coding/codecs/i420/include',
80 'webrtc/modules/video_coding/codecs/vp8/include',
81 'webrtc/modules/video_coding/codecs/vp9/include',
82 'webrtc/modules/video_coding/include',
kjellanderdd705472016-06-09 11:17:27 -070083 'webrtc/system_wrappers/include',
kjellander53047c92015-12-02 23:56:14 -080084 'webrtc/voice_engine/include',
85)
kjellanderdd705472016-06-09 11:17:27 -070086API_DIRS = NATIVE_API_DIRS[:] + LEGACY_API_DIRS[:]
kjellander53047c92015-12-02 23:56:14 -080087
88
89def _VerifyNativeApiHeadersListIsValid(input_api, output_api):
90 """Ensures the list of native API header directories is up to date."""
91 non_existing_paths = []
92 native_api_full_paths = [
93 input_api.os_path.join(input_api.PresubmitLocalPath(),
kjellanderdd705472016-06-09 11:17:27 -070094 *path.split('/')) for path in API_DIRS]
kjellander53047c92015-12-02 23:56:14 -080095 for path in native_api_full_paths:
96 if not os.path.isdir(path):
97 non_existing_paths.append(path)
98 if non_existing_paths:
99 return [output_api.PresubmitError(
100 'Directories to native API headers have changed which has made the '
101 'list in PRESUBMIT.py outdated.\nPlease update it to the current '
102 'location of our native APIs.',
103 non_existing_paths)]
104 return []
105
kwibergeb133022016-04-07 07:41:48 -0700106api_change_msg = """
107You seem to be changing native API header files. Please make sure that you:
108 1. Make compatible changes that don't break existing clients.
109 2. Mark the old stuff as deprecated.
110 3. Create a timeline and plan for when the deprecated stuff will be
111 removed. (The amount of time we give users to change their code
112 should be informed by how much work it is for them. If they just
113 need to replace one name with another or something equally
114 simple, 1-2 weeks might be good; if they need to do serious work,
115 up to 3 months may be called for.)
116 4. Update/inform existing downstream code owners to stop using the
117 deprecated stuff. (Send announcements to
118 discuss-webrtc@googlegroups.com and webrtc-users@google.com.)
119 5. Remove the deprecated stuff, once the agreed-upon amount of time
120 has passed.
121Related files:
122"""
kjellander53047c92015-12-02 23:56:14 -0800123
124def _CheckNativeApiHeaderChanges(input_api, output_api):
125 """Checks to remind proper changing of native APIs."""
126 files = []
127 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
128 if f.LocalPath().endswith('.h'):
kjellanderdd705472016-06-09 11:17:27 -0700129 for path in API_DIRS:
kjellander53047c92015-12-02 23:56:14 -0800130 if os.path.dirname(f.LocalPath()) == path:
131 files.append(f)
132
133 if files:
kwibergeb133022016-04-07 07:41:48 -0700134 return [output_api.PresubmitNotifyResult(api_change_msg, files)]
kjellander53047c92015-12-02 23:56:14 -0800135 return []
136
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100137
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000138def _CheckNoIOStreamInHeaders(input_api, output_api):
139 """Checks to make sure no .h files include <iostream>."""
140 files = []
141 pattern = input_api.re.compile(r'^#include\s*<iostream>',
142 input_api.re.MULTILINE)
143 for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
144 if not f.LocalPath().endswith('.h'):
145 continue
146 contents = input_api.ReadFile(f)
147 if pattern.search(contents):
148 files.append(f)
149
150 if len(files):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200151 return [output_api.PresubmitError(
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000152 'Do not #include <iostream> in header files, since it inserts static ' +
153 'initialization into every file including the header. Instead, ' +
154 '#include <ostream>. See http://crbug.com/94794',
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200155 files)]
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000156 return []
157
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000158
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000159def _CheckNoFRIEND_TEST(input_api, output_api):
160 """Make sure that gtest's FRIEND_TEST() macro is not used, the
161 FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
162 used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
163 problems = []
164
165 file_filter = lambda f: f.LocalPath().endswith(('.cc', '.h'))
166 for f in input_api.AffectedFiles(file_filter=file_filter):
167 for line_num, line in f.ChangedContents():
168 if 'FRIEND_TEST(' in line:
169 problems.append(' %s:%d' % (f.LocalPath(), line_num))
170
171 if not problems:
172 return []
173 return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
174 'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
175 'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
176
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000177
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100178def _IsLintWhitelisted(whitelist_dirs, file_path):
179 """ Checks if a file is whitelisted for lint check."""
180 for path in whitelist_dirs:
181 if os.path.dirname(file_path).startswith(path):
182 return True
183 return False
184
185
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000186def _CheckApprovedFilesLintClean(input_api, output_api,
187 source_file_filter=None):
188 """Checks that all new or whitelisted .cc and .h files pass cpplint.py.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000189 This check is based on _CheckChangeLintsClean in
190 depot_tools/presubmit_canned_checks.py but has less filters and only checks
191 added files."""
192 result = []
193
194 # Initialize cpplint.
195 import cpplint
196 # Access to a protected member _XX of a client class
197 # pylint: disable=W0212
198 cpplint._cpplint_state.ResetErrorCounts()
199
jbauchc4e3ead2016-02-19 00:25:55 -0800200 lint_filters = cpplint._Filters()
201 lint_filters.extend(BLACKLIST_LINT_FILTERS)
202 cpplint._SetFilters(','.join(lint_filters))
203
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100204 # Create a platform independent whitelist for the CPPLINT_DIRS.
205 whitelist_dirs = [input_api.os_path.join(*path.split('/'))
206 for path in CPPLINT_DIRS]
207
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000208 # Use the strictest verbosity level for cpplint.py (level 1) which is the
209 # default when running cpplint.py from command line.
210 # To make it possible to work with not-yet-converted code, we're only applying
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000211 # it to new (or moved/renamed) files and files listed in LINT_FOLDERS.
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000212 verbosity_level = 1
213 files = []
214 for f in input_api.AffectedSourceFiles(source_file_filter):
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200215 # Note that moved/renamed files also count as added.
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +0100216 if f.Action() == 'A' or _IsLintWhitelisted(whitelist_dirs, f.LocalPath()):
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000217 files.append(f.AbsoluteLocalPath())
mflodman@webrtc.org2a452092012-07-01 05:55:23 +0000218
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000219 for file_name in files:
220 cpplint.ProcessFile(file_name, verbosity_level)
221
222 if cpplint._cpplint_state.error_count > 0:
223 if input_api.is_committing:
224 # TODO(kjellander): Change back to PresubmitError below when we're
225 # confident with the lint settings.
226 res_type = output_api.PresubmitPromptWarning
227 else:
228 res_type = output_api.PresubmitPromptWarning
229 result = [res_type('Changelist failed cpplint.py check.')]
230
231 return result
232
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000233def _CheckNoRtcBaseDeps(input_api, gyp_files, output_api):
234 pattern = input_api.re.compile(r"base.gyp:rtc_base\s*'")
235 violating_files = []
236 for f in gyp_files:
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000237 gyp_exceptions = (
238 'base_tests.gyp',
239 'desktop_capture.gypi',
kjellander@webrtc.orge7237282015-02-26 11:12:17 +0000240 'p2p.gyp',
tkchin9eeb6242016-04-27 01:54:20 -0700241 'sdk.gyp',
henrike@webrtc.org36b0c1a2014-10-01 14:40:58 +0000242 'webrtc_test_common.gyp',
243 'webrtc_tests.gypi',
244 )
245 if f.LocalPath().endswith(gyp_exceptions):
246 continue
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000247 contents = input_api.ReadFile(f)
248 if pattern.search(contents):
249 violating_files.append(f)
250 if violating_files:
251 return [output_api.PresubmitError(
252 'Depending on rtc_base is not allowed. Change your dependency to '
253 'rtc_base_approved and possibly sanitize and move the desired source '
254 'file(s) to rtc_base_approved.\nChanged GYP files:',
255 items=violating_files)]
256 return []
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000257
ehmaldonado5b1ba082016-09-02 05:51:08 -0700258def _CheckNoRtcBaseDepsGn(input_api, gn_files, output_api):
259 pattern = input_api.re.compile(r'base:rtc_base\s*"')
260 violating_files = []
261 for f in gn_files:
262 gn_exceptions = (
263 os.path.join('base_tests', 'BUILD.gn'),
264 os.path.join('desktop_capture', 'BUILD.gn'),
265 os.path.join('p2p', 'BUILD.gn'),
266 os.path.join('sdk', 'BUILD.gn'),
267 os.path.join('webrtc_test_common', 'BUILD.gn'),
268 os.path.join('webrtc_tests', 'BUILD.gn'),
269
270 # TODO(ehmaldonado): Clean up references to rtc_base in these files.
271 # See https://bugs.chromium.org/p/webrtc/issues/detail?id=3806
272 os.path.join('webrtc', 'BUILD.gn'),
273 os.path.join('xmllite', 'BUILD.gn'),
274 os.path.join('xmpp', 'BUILD.gn'),
275 os.path.join('modules', 'BUILD.gn'),
276 os.path.join('audio_device', 'BUILD.gn'),
277 os.path.join('pc', 'BUILD.gn'),
278 )
279 if f.LocalPath().endswith(gn_exceptions):
280 continue
281 contents = input_api.ReadFile(f)
282 if pattern.search(contents):
283 violating_files.append(f)
284 if violating_files:
285 return [output_api.PresubmitError(
286 'Depending on rtc_base is not allowed. Change your dependency to '
287 'rtc_base_approved and possibly sanitize and move the desired source '
288 'file(s) to rtc_base_approved.\nChanged GN files:',
289 items=violating_files)]
290 return []
291
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000292def _CheckNoSourcesAboveGyp(input_api, gyp_files, output_api):
293 # Disallow referencing source files with paths above the GYP file location.
kjellander@webrtc.org74290b92016-06-15 17:19:06 +0200294 source_pattern = input_api.re.compile(r'\'sources\'.*?\[(.*?)\]',
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000295 re.MULTILINE | re.DOTALL)
kjellander@webrtc.orga33f05e2015-01-29 14:29:45 +0000296 file_pattern = input_api.re.compile(r"'((\.\./.*?)|(<\(webrtc_root\).*?))'")
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000297 violating_gyp_files = set()
298 violating_source_entries = []
299 for gyp_file in gyp_files:
kjellanderc61635c2016-02-02 02:30:07 -0800300 if 'supplement.gypi' in gyp_file.LocalPath():
301 # Exclude supplement.gypi from this check, as the LSan and TSan
302 # suppression files are located in a different location.
303 continue
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000304 contents = input_api.ReadFile(gyp_file)
305 for source_block_match in source_pattern.finditer(contents):
kjellander@webrtc.orgc98f6f32015-03-04 07:08:11 +0000306 # Find all source list entries starting with ../ in the source block
307 # (exclude overrides entries).
kjellander@webrtc.org74290b92016-06-15 17:19:06 +0200308 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
309 source_file = file_list_match.group(1)
kjellander@webrtc.orgc98f6f32015-03-04 07:08:11 +0000310 if 'overrides/' not in source_file:
311 violating_source_entries.append(source_file)
312 violating_gyp_files.add(gyp_file)
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000313 if violating_gyp_files:
314 return [output_api.PresubmitError(
315 'Referencing source files above the directory of the GYP file is not '
316 'allowed. Please introduce new GYP targets and/or GYP files in the '
317 'proper location instead.\n'
318 'Invalid source entries:\n'
319 '%s\n'
320 'Violating GYP files:' % '\n'.join(violating_source_entries),
321 items=violating_gyp_files)]
322 return []
323
ehmaldonado5b1ba082016-09-02 05:51:08 -0700324def _CheckNoSourcesAboveGn(input_api, gn_files, output_api):
325 # Disallow referencing source files with paths above the GN file location.
326 source_pattern = input_api.re.compile(r' +sources \+?= \[(.*?)\]',
327 re.MULTILINE | re.DOTALL)
328 file_pattern = input_api.re.compile(r'"((\.\./.*?)|(//.*?))"')
329 violating_gn_files = set()
330 violating_source_entries = []
331 for gn_file in gn_files:
332 contents = input_api.ReadFile(gn_file)
333 for source_block_match in source_pattern.finditer(contents):
334 # Find all source list entries starting with ../ in the source block
335 # (exclude overrides entries).
336 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
337 source_file = file_list_match.group(1)
338 if 'overrides/' not in source_file:
339 violating_source_entries.append(source_file)
340 violating_gn_files.add(gn_file)
341 if violating_gn_files:
342 return [output_api.PresubmitError(
343 'Referencing source files above the directory of the GN file is not '
344 'allowed. Please introduce new GYP targets and/or GN files in the '
345 'proper location instead.\n'
346 'Invalid source entries:\n'
347 '%s\n'
348 'Violating GN files:' % '\n'.join(violating_source_entries),
349 items=violating_gn_files)]
350 return []
351
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000352def _CheckGypChanges(input_api, output_api):
353 source_file_filter = lambda x: input_api.FilterSourceFile(
354 x, white_list=(r'.+\.(gyp|gypi)$',))
355
356 gyp_files = []
357 for f in input_api.AffectedSourceFiles(source_file_filter):
kjellander@webrtc.org3398a4a2014-11-24 10:05:37 +0000358 if f.LocalPath().startswith('webrtc'):
359 gyp_files.append(f)
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000360
361 result = []
362 if gyp_files:
363 result.append(output_api.PresubmitNotifyResult(
364 'As you\'re changing GYP files: please make sure corresponding '
365 'BUILD.gn files are also updated.\nChanged GYP files:',
366 items=gyp_files))
henrike@webrtc.org83fe69d2014-09-30 21:54:26 +0000367 result.extend(_CheckNoRtcBaseDeps(input_api, gyp_files, output_api))
kjellander@webrtc.orgf68ffca2015-01-27 13:13:24 +0000368 result.extend(_CheckNoSourcesAboveGyp(input_api, gyp_files, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000369 return result
370
ehmaldonado5b1ba082016-09-02 05:51:08 -0700371def _CheckGnChanges(input_api, output_api):
372 source_file_filter = lambda x: input_api.FilterSourceFile(
373 x, white_list=(r'.+\.(gn|gni)$',))
374
375 gn_files = []
376 for f in input_api.AffectedSourceFiles(source_file_filter):
377 if f.LocalPath().startswith('webrtc'):
378 gn_files.append(f)
379
380 result = []
381 if gn_files:
382 result.append(output_api.PresubmitNotifyResult(
383 'As you\'re changing GN files: please make sure corresponding GYP'
384 'files are also updated.\nChanged GN files:',
385 items=gn_files))
386 result.extend(_CheckNoRtcBaseDepsGn(input_api, gn_files, output_api))
387 result.extend(_CheckNoSourcesAboveGn(input_api, gn_files, output_api))
388 return result
389
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000390def _CheckUnwantedDependencies(input_api, output_api):
391 """Runs checkdeps on #include statements added in this
392 change. Breaking - rules is an error, breaking ! rules is a
393 warning.
394 """
395 # Copied from Chromium's src/PRESUBMIT.py.
396
397 # We need to wait until we have an input_api object and use this
398 # roundabout construct to import checkdeps because this file is
399 # eval-ed and thus doesn't have __file__.
400 original_sys_path = sys.path
401 try:
kjellander@webrtc.orgaefe61a2014-12-08 13:00:30 +0000402 checkdeps_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
403 'buildtools', 'checkdeps')
404 if not os.path.exists(checkdeps_path):
405 return [output_api.PresubmitError(
406 'Cannot find checkdeps at %s\nHave you run "gclient sync" to '
407 'download Chromium and setup the symlinks?' % checkdeps_path)]
408 sys.path.append(checkdeps_path)
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000409 import checkdeps
410 from cpp_checker import CppChecker
411 from rules import Rule
412 finally:
413 # Restore sys.path to what it was before.
414 sys.path = original_sys_path
415
416 added_includes = []
417 for f in input_api.AffectedFiles():
418 if not CppChecker.IsCppFile(f.LocalPath()):
419 continue
420
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200421 changed_lines = [line for _, line in f.ChangedContents()]
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000422 added_includes.append([f.LocalPath(), changed_lines])
423
424 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
425
426 error_descriptions = []
427 warning_descriptions = []
428 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
429 added_includes):
430 description_with_path = '%s\n %s' % (path, rule_description)
431 if rule_type == Rule.DISALLOW:
432 error_descriptions.append(description_with_path)
433 else:
434 warning_descriptions.append(description_with_path)
435
436 results = []
437 if error_descriptions:
438 results.append(output_api.PresubmitError(
439 'You added one or more #includes that violate checkdeps rules.',
440 error_descriptions))
441 if warning_descriptions:
442 results.append(output_api.PresubmitPromptOrNotify(
443 'You added one or more #includes of files that are temporarily\n'
444 'allowed but being removed. Can you avoid introducing the\n'
445 '#include? See relevant DEPS file(s) for details and contacts.',
446 warning_descriptions))
447 return results
448
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000449
kjellander569cf942016-02-11 05:02:59 -0800450def _CheckJSONParseErrors(input_api, output_api):
451 """Check that JSON files do not contain syntax errors."""
452
453 def FilterFile(affected_file):
454 return input_api.os_path.splitext(affected_file.LocalPath())[1] == '.json'
455
456 def GetJSONParseError(input_api, filename):
457 try:
458 contents = input_api.ReadFile(filename)
459 input_api.json.loads(contents)
460 except ValueError as e:
461 return e
462 return None
463
464 results = []
465 for affected_file in input_api.AffectedFiles(
466 file_filter=FilterFile, include_deletes=False):
467 parse_error = GetJSONParseError(input_api,
468 affected_file.AbsoluteLocalPath())
469 if parse_error:
470 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
471 (affected_file.LocalPath(), parse_error)))
472 return results
473
474
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200475def _RunPythonTests(input_api, output_api):
476 def join(*args):
477 return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
478
479 test_directories = [
480 join('tools', 'autoroller', 'unittests'),
aleloi7ebbf902016-06-20 07:39:15 -0700481 join('webrtc', 'tools', 'py_event_log_analyzer'),
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200482 ]
483
484 tests = []
485 for directory in test_directories:
486 tests.extend(
487 input_api.canned_checks.GetUnitTestsInDirectory(
488 input_api,
489 output_api,
490 directory,
491 whitelist=[r'.+_test\.py$']))
492 return input_api.RunTests(tests, parallel=True)
493
494
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000495def _CommonChecks(input_api, output_api):
496 """Checks common to both upload and commit."""
niklase@google.comda159d62011-05-30 11:51:34 +0000497 results = []
tkchin42f580e2015-11-26 23:18:23 -0800498 # Filter out files that are in objc or ios dirs from being cpplint-ed since
499 # they do not follow C++ lint rules.
500 black_list = input_api.DEFAULT_BLACK_LIST + (
501 r".*\bobjc[\\\/].*",
hjon65ae2d82016-08-02 23:55:44 -0700502 r"webrtc\/build\/ios\/SDK\/.*",
tkchin42f580e2015-11-26 23:18:23 -0800503 )
504 source_file_filter = lambda x: input_api.FilterSourceFile(x, None, black_list)
505 results.extend(_CheckApprovedFilesLintClean(
506 input_api, output_api, source_file_filter))
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000507 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
508 black_list=(r'^.*gviz_api\.py$',
509 r'^.*gaeunit\.py$',
fischman@webrtc.org33584f92013-07-25 16:43:30 +0000510 # Embedded shell-script fakes out pylint.
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200511 r'^build[\\\/].*\.py$',
512 r'^buildtools[\\\/].*\.py$',
513 r'^chromium[\\\/].*\.py$',
kjellanderd620f822016-04-04 06:07:08 -0700514 r'^mojo.*[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200515 r'^out.*[\\\/].*\.py$',
516 r'^testing[\\\/].*\.py$',
517 r'^third_party[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200518 r'^tools[\\\/]clang[\\\/].*\.py$',
519 r'^tools[\\\/]generate_library_loader[\\\/].*\.py$',
kjellanderd620f822016-04-04 06:07:08 -0700520 r'^tools[\\\/]generate_stubs[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200521 r'^tools[\\\/]gn[\\\/].*\.py$',
522 r'^tools[\\\/]gyp[\\\/].*\.py$',
Henrik Kjellanderd6d27e72015-09-25 22:19:11 +0200523 r'^tools[\\\/]isolate_driver.py$',
kjellanderd620f822016-04-04 06:07:08 -0700524 r'^tools[\\\/]mb[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200525 r'^tools[\\\/]protoc_wrapper[\\\/].*\.py$',
526 r'^tools[\\\/]python[\\\/].*\.py$',
527 r'^tools[\\\/]python_charts[\\\/]data[\\\/].*\.py$',
528 r'^tools[\\\/]refactoring[\\\/].*\.py$',
529 r'^tools[\\\/]swarming_client[\\\/].*\.py$',
530 r'^tools[\\\/]vim[\\\/].*\.py$',
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000531 # TODO(phoglund): should arguably be checked.
Henrik Kjellander14771ac2015-06-02 13:10:04 +0200532 r'^tools[\\\/]valgrind-webrtc[\\\/].*\.py$',
533 r'^tools[\\\/]valgrind[\\\/].*\.py$',
534 r'^tools[\\\/]win[\\\/].*\.py$',
535 r'^xcodebuild.*[\\\/].*\.py$',),
phoglund@webrtc.org5d3713932013-03-07 09:59:43 +0000536 disabled_warnings=['F0401', # Failed to import x
537 'E0611', # No package y in x
538 'W0232', # Class has no __init__ method
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200539 ],
540 pylintrc='pylintrc'))
kjellander569cf942016-02-11 05:02:59 -0800541
nisse3d21e232016-09-02 03:07:06 -0700542 # TODO(nisse): talk/ is no more, so make below checks simpler?
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200543 # WebRTC can't use the presubmit_canned_checks.PanProjectChecks function since
544 # we need to have different license checks in talk/ and webrtc/ directories.
545 # Instead, hand-picked checks are included below.
Henrik Kjellander63224672015-09-08 08:03:56 +0200546
tkchin3cd9a302016-06-08 12:40:28 -0700547 # .m and .mm files are ObjC files. For simplicity we will consider .h files in
548 # ObjC subdirectories ObjC headers.
549 objc_filter_list = (r'.+\.m$', r'.+\.mm$', r'.+objc\/.+\.h$')
Henrik Kjellander63224672015-09-08 08:03:56 +0200550 # Skip long-lines check for DEPS, GN and GYP files.
tkchin3cd9a302016-06-08 12:40:28 -0700551 build_file_filter_list = (r'.+\.gyp$', r'.+\.gypi$', r'.+\.gn$', r'.+\.gni$',
552 'DEPS')
553 eighty_char_sources = lambda x: input_api.FilterSourceFile(x,
554 black_list=build_file_filter_list + objc_filter_list)
555 hundred_char_sources = lambda x: input_api.FilterSourceFile(x,
556 white_list=objc_filter_list)
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000557 results.extend(input_api.canned_checks.CheckLongLines(
tkchin3cd9a302016-06-08 12:40:28 -0700558 input_api, output_api, maxlen=80, source_file_filter=eighty_char_sources))
559 results.extend(input_api.canned_checks.CheckLongLines(
560 input_api, output_api, maxlen=100,
561 source_file_filter=hundred_char_sources))
562
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000563 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
564 input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000565 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
566 input_api, output_api))
567 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
568 input_api, output_api))
kjellander53047c92015-12-02 23:56:14 -0800569 results.extend(_CheckNativeApiHeaderChanges(input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000570 results.extend(_CheckNoIOStreamInHeaders(input_api, output_api))
571 results.extend(_CheckNoFRIEND_TEST(input_api, output_api))
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000572 results.extend(_CheckGypChanges(input_api, output_api))
ehmaldonado5b1ba082016-09-02 05:51:08 -0700573 results.extend(_CheckGnChanges(input_api, output_api))
kjellander@webrtc.org3bd41562014-09-01 11:06:37 +0000574 results.extend(_CheckUnwantedDependencies(input_api, output_api))
kjellander569cf942016-02-11 05:02:59 -0800575 results.extend(_CheckJSONParseErrors(input_api, output_api))
Henrik Kjellander8d3ad822015-05-26 19:52:05 +0200576 results.extend(_RunPythonTests(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000577 return results
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000578
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000579
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000580def CheckChangeOnUpload(input_api, output_api):
581 results = []
582 results.extend(_CommonChecks(input_api, output_api))
Henrik Kjellander57e5fd22015-05-25 12:55:39 +0200583 results.extend(
584 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
niklase@google.comda159d62011-05-30 11:51:34 +0000585 return results
586
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000587
andrew@webrtc.org2442de12012-01-23 17:45:41 +0000588def CheckChangeOnCommit(input_api, output_api):
niklase@google.com1198db92011-06-09 07:07:24 +0000589 results = []
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000590 results.extend(_CommonChecks(input_api, output_api))
kjellander53047c92015-12-02 23:56:14 -0800591 results.extend(_VerifyNativeApiHeadersListIsValid(input_api, output_api))
niklase@google.com1198db92011-06-09 07:07:24 +0000592 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
andrew@webrtc.org53df1362012-01-26 21:24:23 +0000593 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
594 input_api, output_api))
595 results.extend(input_api.canned_checks.CheckChangeHasDescription(
596 input_api, output_api))
kjellander@webrtc.org51198f12012-02-21 17:53:46 +0000597 results.extend(input_api.canned_checks.CheckChangeHasBugField(
598 input_api, output_api))
599 results.extend(input_api.canned_checks.CheckChangeHasTestField(
600 input_api, output_api))
kjellander@webrtc.org12cb88c2014-02-13 11:53:43 +0000601 results.extend(input_api.canned_checks.CheckTreeIsOpen(
602 input_api, output_api,
603 json_url='http://webrtc-status.appspot.com/current?format=json'))
niklase@google.com1198db92011-06-09 07:07:24 +0000604 return results
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000605
kjellander@webrtc.orge4158642014-08-06 09:11:18 +0000606
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000607# pylint: disable=W0613
kjellander@webrtc.orgc7b8b2f2014-04-03 20:19:36 +0000608def GetPreferredTryMasters(project, change):
kjellander986ee082015-06-16 04:32:13 -0700609 cq_config_path = os.path.join(
tandrii04465d22015-06-20 04:00:49 -0700610 change.RepositoryRoot(), 'infra', 'config', 'cq.cfg')
kjellander986ee082015-06-16 04:32:13 -0700611 # commit_queue.py below is a script in depot_tools directory, which has a
612 # 'builders' command to retrieve a list of CQ builders from the CQ config.
613 is_win = platform.system() == 'Windows'
614 masters = json.loads(subprocess.check_output(
615 ['commit_queue', 'builders', cq_config_path], shell=is_win))
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000616
kjellander986ee082015-06-16 04:32:13 -0700617 try_config = {}
618 for master in masters:
619 try_config.setdefault(master, {})
620 for builder in masters[master]:
621 if 'presubmit' in builder:
622 # Do not trigger presubmit builders, since they're likely to fail
623 # (e.g. OWNERS checks before finished code review), and we're running
624 # local presubmit anyway.
625 pass
626 else:
627 try_config[master][builder] = ['defaulttests']
kjellander@webrtc.org85759802013-10-22 16:47:40 +0000628
kjellander986ee082015-06-16 04:32:13 -0700629 return try_config