Thanks to visit codestin.com
Credit goes to webrtc.googlesource.com

blob: 8575dd656c0ca7a00920bf1a5e67e8cb9d165447 [file] [log] [blame]
[email protected]2442de12012-01-23 17:45:411# 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.
[email protected]da159d62011-05-30 11:51:348
kjellander7439f972016-12-06 06:47:469import json
[email protected]aefe61a2014-12-08 13:00:3010import os
[email protected]85759802013-10-22 16:47:4011import re
[email protected]3bd41562014-09-01 11:06:3712import sys
Mirko Bonadei4dc4e252017-09-19 11:49:1613from collections import defaultdict
Oleh Prypin2f33a562017-10-04 18:17:5414from contextlib import contextmanager
[email protected]85759802013-10-22 16:47:4015
16
oprypin2aa463f2017-03-23 10:17:0217# Files and directories that are *skipped* by cpplint in the presubmit script.
18CPPLINT_BLACKLIST = [
Mirko Bonadei92ea95e2017-09-15 04:47:3119 'api/video_codecs/video_decoder.h',
20 'common_types.cc',
21 'common_types.h',
22 'examples/objc',
Steve Antone78bcb92017-10-31 16:53:0823 'media/base/streamparams.h',
24 'media/base/videocommon.h',
25 'media/engine/fakewebrtcdeviceinfo.h',
26 'media/sctp/sctptransport.cc',
Mirko Bonadei92ea95e2017-09-15 04:47:3127 'modules/audio_coding',
Mirko Bonadei92ea95e2017-09-15 04:47:3128 'modules/audio_device',
29 'modules/audio_processing',
30 'modules/desktop_capture',
31 'modules/include/module_common_types.h',
Mirko Bonadei92ea95e2017-09-15 04:47:3132 'modules/utility',
33 'modules/video_capture',
Steve Anton6c38cc72017-11-29 18:25:5834 'p2p/base/pseudotcp.cc',
35 'p2p/base/pseudotcp.h',
Mirko Bonadei92ea95e2017-09-15 04:47:3136 'rtc_base',
37 'sdk/android/src/jni',
38 'sdk/objc',
39 'system_wrappers',
40 'test',
Henrik Kjellander90fd7d82017-05-09 06:30:1041 'tools_webrtc',
Mirko Bonadei92ea95e2017-09-15 04:47:3142 'voice_engine',
Artem Titova04d1402018-05-11 09:23:0043 'third_party',
[email protected]0fcaf992015-11-26 14:24:5244]
45
jbauchc4e3ead2016-02-19 08:25:5546# These filters will always be removed, even if the caller specifies a filter
47# set, as they are problematic or broken in some way.
48#
49# Justifications for each filter:
50# - build/c++11 : Rvalue ref checks are unreliable (false positives),
51# include file and feature blacklists are
52# google3-specific.
kjellandere5a87a52016-04-27 09:32:1253# - whitespace/operators: Same as above (doesn't seem sufficient to eliminate
54# all move-related errors).
jbauchc4e3ead2016-02-19 08:25:5555BLACKLIST_LINT_FILTERS = [
56 '-build/c++11',
kjellandere5a87a52016-04-27 09:32:1257 '-whitespace/operators',
jbauchc4e3ead2016-02-19 08:25:5558]
59
kjellanderfd595232015-12-04 10:44:0960# List of directories of "supported" native APIs. That means changes to headers
61# will be done in a compatible way following this scheme:
62# 1. Non-breaking changes are made.
63# 2. The old APIs as marked as deprecated (with comments).
64# 3. Deprecation is announced to [email protected] and
65# [email protected] (internal list).
66# 4. (later) The deprecated APIs are removed.
kjellander53047c92015-12-03 07:56:1467NATIVE_API_DIRS = (
Karl Wibergef52d8b82017-10-25 11:20:0368 'api', # All subdirectories of api/ are included as well.
Mirko Bonadeia4eeeff2018-01-11 12:16:5269 'media/base',
70 'media/engine',
Mirko Bonadei92ea95e2017-09-15 04:47:3171 'modules/audio_device/include',
72 'pc',
kjellanderdd705472016-06-09 18:17:2773)
Mirko Bonadei4dc4e252017-09-19 11:49:1674
kjellanderdd705472016-06-09 18:17:2775# These directories should not be used but are maintained only to avoid breaking
76# some legacy downstream code.
77LEGACY_API_DIRS = (
Mirko Bonadei92ea95e2017-09-15 04:47:3178 'common_audio/include',
79 'modules/audio_coding/include',
Mirko Bonadei92ea95e2017-09-15 04:47:3180 'modules/audio_processing/include',
81 'modules/bitrate_controller/include',
82 'modules/congestion_controller/include',
83 'modules/include',
84 'modules/remote_bitrate_estimator/include',
85 'modules/rtp_rtcp/include',
86 'modules/rtp_rtcp/source',
87 'modules/utility/include',
88 'modules/video_coding/codecs/h264/include',
89 'modules/video_coding/codecs/i420/include',
90 'modules/video_coding/codecs/vp8/include',
91 'modules/video_coding/codecs/vp9/include',
92 'modules/video_coding/include',
93 'rtc_base',
94 'system_wrappers/include',
kjellander53047c92015-12-03 07:56:1495)
Mirko Bonadei4dc4e252017-09-19 11:49:1696
Karl Wibergd4f01c12017-11-10 09:55:4597# NOTE: The set of directories in API_DIRS should be the same as those
98# listed in the table in native-api.md.
kjellanderdd705472016-06-09 18:17:2799API_DIRS = NATIVE_API_DIRS[:] + LEGACY_API_DIRS[:]
kjellander53047c92015-12-03 07:56:14100
Mirko Bonadei4dc4e252017-09-19 11:49:16101# TARGET_RE matches a GN target, and extracts the target name and the contents.
102TARGET_RE = re.compile(r'(?P<indent>\s*)\w+\("(?P<target_name>\w+)"\) {'
103 r'(?P<target_contents>.*?)'
104 r'(?P=indent)}',
105 re.MULTILINE | re.DOTALL)
106
107# SOURCES_RE matches a block of sources inside a GN target.
108SOURCES_RE = re.compile(r'sources \+?= \[(?P<sources>.*?)\]',
109 re.MULTILINE | re.DOTALL)
110
111# FILE_PATH_RE matchies a file path.
112FILE_PATH_RE = re.compile(r'"(?P<file_path>(\w|\/)+)(?P<extension>\.\w+)"')
113
kjellander53047c92015-12-03 07:56:14114
Oleh Prypin2f33a562017-10-04 18:17:54115@contextmanager
116def _AddToPath(*paths):
117 original_sys_path = sys.path
118 sys.path.extend(paths)
119 try:
120 yield
121 finally:
122 # Restore sys.path to what it was before.
123 sys.path = original_sys_path
ehmaldonado4fb97462017-01-30 13:27:22124
125
charujain9893e252017-09-14 11:33:22126def VerifyNativeApiHeadersListIsValid(input_api, output_api):
kjellander53047c92015-12-03 07:56:14127 """Ensures the list of native API header directories is up to date."""
128 non_existing_paths = []
129 native_api_full_paths = [
130 input_api.os_path.join(input_api.PresubmitLocalPath(),
kjellanderdd705472016-06-09 18:17:27131 *path.split('/')) for path in API_DIRS]
kjellander53047c92015-12-03 07:56:14132 for path in native_api_full_paths:
133 if not os.path.isdir(path):
134 non_existing_paths.append(path)
135 if non_existing_paths:
136 return [output_api.PresubmitError(
137 'Directories to native API headers have changed which has made the '
138 'list in PRESUBMIT.py outdated.\nPlease update it to the current '
139 'location of our native APIs.',
140 non_existing_paths)]
141 return []
142
kjellanderc88b5d52017-04-05 13:42:43143API_CHANGE_MSG = """
kwibergeb133022016-04-07 14:41:48144You seem to be changing native API header files. Please make sure that you:
oprypin375b9ac2017-02-13 12:13:23145 1. Make compatible changes that don't break existing clients. Usually
146 this is done by keeping the existing method signatures unchanged.
147 2. Mark the old stuff as deprecated (see RTC_DEPRECATED macro).
kwibergeb133022016-04-07 14:41:48148 3. Create a timeline and plan for when the deprecated stuff will be
149 removed. (The amount of time we give users to change their code
150 should be informed by how much work it is for them. If they just
151 need to replace one name with another or something equally
152 simple, 1-2 weeks might be good; if they need to do serious work,
153 up to 3 months may be called for.)
154 4. Update/inform existing downstream code owners to stop using the
155 deprecated stuff. (Send announcements to
156 [email protected] and [email protected].)
157 5. Remove the deprecated stuff, once the agreed-upon amount of time
158 has passed.
159Related files:
160"""
kjellander53047c92015-12-03 07:56:14161
charujain9893e252017-09-14 11:33:22162def CheckNativeApiHeaderChanges(input_api, output_api):
kjellander53047c92015-12-03 07:56:14163 """Checks to remind proper changing of native APIs."""
164 files = []
Karl Wiberg6bfac032017-10-27 13:14:20165 source_file_filter = lambda x: input_api.FilterSourceFile(
166 x, white_list=[r'.+\.(gn|gni|h)$'])
167 for f in input_api.AffectedSourceFiles(source_file_filter):
168 for path in API_DIRS:
169 dn = os.path.dirname(f.LocalPath())
170 if path == 'api':
171 # Special case: Subdirectories included.
172 if dn == 'api' or dn.startswith('api/'):
173 files.append(f)
174 else:
175 # Normal case: Subdirectories not included.
176 if dn == path:
177 files.append(f)
kjellander53047c92015-12-03 07:56:14178
179 if files:
kjellanderc88b5d52017-04-05 13:42:43180 return [output_api.PresubmitNotifyResult(API_CHANGE_MSG, files)]
kjellander53047c92015-12-03 07:56:14181 return []
182
[email protected]0fcaf992015-11-26 14:24:52183
Artem Titova04d1402018-05-11 09:23:00184def CheckNoIOStreamInHeaders(input_api, output_api,
185 source_file_filter):
[email protected]51198f12012-02-21 17:53:46186 """Checks to make sure no .h files include <iostream>."""
187 files = []
188 pattern = input_api.re.compile(r'^#include\s*<iostream>',
189 input_api.re.MULTILINE)
Artem Titova04d1402018-05-11 09:23:00190 file_filter = lambda x: (input_api.FilterSourceFile(x)
191 and source_file_filter(x))
192 for f in input_api.AffectedSourceFiles(file_filter):
[email protected]51198f12012-02-21 17:53:46193 if not f.LocalPath().endswith('.h'):
194 continue
195 contents = input_api.ReadFile(f)
196 if pattern.search(contents):
197 files.append(f)
198
199 if len(files):
Henrik Kjellander57e5fd22015-05-25 10:55:39200 return [output_api.PresubmitError(
[email protected]51198f12012-02-21 17:53:46201 'Do not #include <iostream> in header files, since it inserts static ' +
202 'initialization into every file including the header. Instead, ' +
203 '#include <ostream>. See http://crbug.com/94794',
Henrik Kjellander57e5fd22015-05-25 10:55:39204 files)]
[email protected]51198f12012-02-21 17:53:46205 return []
206
[email protected]e4158642014-08-06 09:11:18207
Artem Titova04d1402018-05-11 09:23:00208def CheckNoPragmaOnce(input_api, output_api,
209 source_file_filter):
kjellander6aeef742017-02-20 09:13:18210 """Make sure that banned functions are not used."""
211 files = []
212 pattern = input_api.re.compile(r'^#pragma\s+once',
213 input_api.re.MULTILINE)
Artem Titova04d1402018-05-11 09:23:00214 file_filter = lambda x: (input_api.FilterSourceFile(x)
215 and source_file_filter(x))
216 for f in input_api.AffectedSourceFiles(file_filter):
kjellander6aeef742017-02-20 09:13:18217 if not f.LocalPath().endswith('.h'):
218 continue
219 contents = input_api.ReadFile(f)
220 if pattern.search(contents):
221 files.append(f)
222
223 if files:
224 return [output_api.PresubmitError(
225 'Do not use #pragma once in header files.\n'
226 'See http://www.chromium.org/developers/coding-style#TOC-File-headers',
227 files)]
228 return []
229
230
Artem Titova04d1402018-05-11 09:23:00231def CheckNoFRIEND_TEST(input_api, output_api, # pylint: disable=invalid-name
232 source_file_filter):
[email protected]51198f12012-02-21 17:53:46233 """Make sure that gtest's FRIEND_TEST() macro is not used, the
234 FRIEND_TEST_ALL_PREFIXES() macro from testsupport/gtest_prod_util.h should be
235 used instead since that allows for FLAKY_, FAILS_ and DISABLED_ prefixes."""
236 problems = []
237
Artem Titova04d1402018-05-11 09:23:00238 file_filter = lambda f: (f.LocalPath().endswith(('.cc', '.h'))
239 and source_file_filter(f))
[email protected]51198f12012-02-21 17:53:46240 for f in input_api.AffectedFiles(file_filter=file_filter):
241 for line_num, line in f.ChangedContents():
242 if 'FRIEND_TEST(' in line:
243 problems.append(' %s:%d' % (f.LocalPath(), line_num))
244
245 if not problems:
246 return []
247 return [output_api.PresubmitPromptWarning('WebRTC\'s code should not use '
248 'gtest\'s FRIEND_TEST() macro. Include testsupport/gtest_prod_util.h and '
249 'use FRIEND_TEST_ALL_PREFIXES() instead.\n' + '\n'.join(problems))]
250
[email protected]e4158642014-08-06 09:11:18251
charujain9893e252017-09-14 11:33:22252def IsLintBlacklisted(blacklist_paths, file_path):
oprypin2aa463f2017-03-23 10:17:02253 """ Checks if a file is blacklisted for lint check."""
254 for path in blacklist_paths:
255 if file_path == path or os.path.dirname(file_path).startswith(path):
[email protected]0fcaf992015-11-26 14:24:52256 return True
257 return False
258
259
charujain9893e252017-09-14 11:33:22260def CheckApprovedFilesLintClean(input_api, output_api,
Artem Titova04d1402018-05-11 09:23:00261 source_file_filter=None):
oprypin2aa463f2017-03-23 10:17:02262 """Checks that all new or non-blacklisted .cc and .h files pass cpplint.py.
charujain9893e252017-09-14 11:33:22263 This check is based on CheckChangeLintsClean in
[email protected]51198f12012-02-21 17:53:46264 depot_tools/presubmit_canned_checks.py but has less filters and only checks
265 added files."""
266 result = []
267
268 # Initialize cpplint.
269 import cpplint
270 # Access to a protected member _XX of a client class
271 # pylint: disable=W0212
272 cpplint._cpplint_state.ResetErrorCounts()
273
jbauchc4e3ead2016-02-19 08:25:55274 lint_filters = cpplint._Filters()
275 lint_filters.extend(BLACKLIST_LINT_FILTERS)
276 cpplint._SetFilters(','.join(lint_filters))
277
oprypin2aa463f2017-03-23 10:17:02278 # Create a platform independent blacklist for cpplint.
279 blacklist_paths = [input_api.os_path.join(*path.split('/'))
280 for path in CPPLINT_BLACKLIST]
[email protected]0fcaf992015-11-26 14:24:52281
[email protected]51198f12012-02-21 17:53:46282 # Use the strictest verbosity level for cpplint.py (level 1) which is the
oprypin2aa463f2017-03-23 10:17:02283 # default when running cpplint.py from command line. To make it possible to
284 # work with not-yet-converted code, we're only applying it to new (or
285 # moved/renamed) files and files not listed in CPPLINT_BLACKLIST.
[email protected]51198f12012-02-21 17:53:46286 verbosity_level = 1
287 files = []
288 for f in input_api.AffectedSourceFiles(source_file_filter):
Henrik Kjellander57e5fd22015-05-25 10:55:39289 # Note that moved/renamed files also count as added.
charujain9893e252017-09-14 11:33:22290 if f.Action() == 'A' or not IsLintBlacklisted(blacklist_paths,
oprypin2aa463f2017-03-23 10:17:02291 f.LocalPath()):
[email protected]51198f12012-02-21 17:53:46292 files.append(f.AbsoluteLocalPath())
[email protected]2a452092012-07-01 05:55:23293
[email protected]51198f12012-02-21 17:53:46294 for file_name in files:
295 cpplint.ProcessFile(file_name, verbosity_level)
296
297 if cpplint._cpplint_state.error_count > 0:
298 if input_api.is_committing:
oprypin8e58d652017-03-21 14:52:41299 res_type = output_api.PresubmitError
[email protected]51198f12012-02-21 17:53:46300 else:
301 res_type = output_api.PresubmitPromptWarning
302 result = [res_type('Changelist failed cpplint.py check.')]
303
304 return result
305
charujain9893e252017-09-14 11:33:22306def CheckNoSourcesAbove(input_api, gn_files, output_api):
ehmaldonado5b1ba082016-09-02 12:51:08307 # Disallow referencing source files with paths above the GN file location.
308 source_pattern = input_api.re.compile(r' +sources \+?= \[(.*?)\]',
309 re.MULTILINE | re.DOTALL)
310 file_pattern = input_api.re.compile(r'"((\.\./.*?)|(//.*?))"')
311 violating_gn_files = set()
312 violating_source_entries = []
313 for gn_file in gn_files:
314 contents = input_api.ReadFile(gn_file)
315 for source_block_match in source_pattern.finditer(contents):
316 # Find all source list entries starting with ../ in the source block
317 # (exclude overrides entries).
318 for file_list_match in file_pattern.finditer(source_block_match.group(1)):
319 source_file = file_list_match.group(1)
320 if 'overrides/' not in source_file:
321 violating_source_entries.append(source_file)
322 violating_gn_files.add(gn_file)
323 if violating_gn_files:
324 return [output_api.PresubmitError(
325 'Referencing source files above the directory of the GN file is not '
Henrik Kjellanderb4af3d62016-11-16 19:11:29326 'allowed. Please introduce new GN targets in the proper location '
327 'instead.\n'
ehmaldonado5b1ba082016-09-02 12:51:08328 'Invalid source entries:\n'
329 '%s\n'
330 'Violating GN files:' % '\n'.join(violating_source_entries),
331 items=violating_gn_files)]
332 return []
333
Mirko Bonadei4dc4e252017-09-19 11:49:16334def CheckNoMixingSources(input_api, gn_files, output_api):
335 """Disallow mixing C, C++ and Obj-C/Obj-C++ in the same target.
336
337 See bugs.webrtc.org/7743 for more context.
338 """
339 def _MoreThanOneSourceUsed(*sources_lists):
340 sources_used = 0
341 for source_list in sources_lists:
342 if len(source_list):
343 sources_used += 1
344 return sources_used > 1
345
346 errors = defaultdict(lambda: [])
kjellander7439f972016-12-06 06:47:46347 for gn_file in gn_files:
Mirko Bonadei4dc4e252017-09-19 11:49:16348 gn_file_content = input_api.ReadFile(gn_file)
349 for target_match in TARGET_RE.finditer(gn_file_content):
350 # list_of_sources is a list of tuples of the form
351 # (c_files, cc_files, objc_files) that keeps track of all the sources
352 # defined in a target. A GN target can have more that on definition of
353 # sources (since it supports if/else statements).
354 # E.g.:
355 # rtc_static_library("foo") {
356 # if (is_win) {
357 # sources = [ "foo.cc" ]
358 # } else {
359 # sources = [ "foo.mm" ]
360 # }
361 # }
362 # This is allowed and the presubmit check should support this case.
363 list_of_sources = []
kjellander7439f972016-12-06 06:47:46364 c_files = []
365 cc_files = []
Mirko Bonadei4dc4e252017-09-19 11:49:16366 objc_files = []
367 target_name = target_match.group('target_name')
368 target_contents = target_match.group('target_contents')
369 for sources_match in SOURCES_RE.finditer(target_contents):
370 if '+=' not in sources_match.group(0):
371 if c_files or cc_files or objc_files:
372 list_of_sources.append((c_files, cc_files, objc_files))
373 c_files = []
374 cc_files = []
375 objc_files = []
376 for file_match in FILE_PATH_RE.finditer(sources_match.group(1)):
377 file_path = file_match.group('file_path')
378 extension = file_match.group('extension')
379 if extension == '.c':
380 c_files.append(file_path + extension)
381 if extension == '.cc':
382 cc_files.append(file_path + extension)
383 if extension in ['.m', '.mm']:
384 objc_files.append(file_path + extension)
385 list_of_sources.append((c_files, cc_files, objc_files))
386 for c_files_list, cc_files_list, objc_files_list in list_of_sources:
387 if _MoreThanOneSourceUsed(c_files_list, cc_files_list, objc_files_list):
388 all_sources = sorted(c_files_list + cc_files_list + objc_files_list)
389 errors[gn_file.LocalPath()].append((target_name, all_sources))
390 if errors:
kjellander7439f972016-12-06 06:47:46391 return [output_api.PresubmitError(
Mirko Bonadei4dc4e252017-09-19 11:49:16392 'GN targets cannot mix .c, .cc and .m (or .mm) source files.\n'
393 'Please create a separate target for each collection of sources.\n'
kjellander7439f972016-12-06 06:47:46394 'Mixed sources: \n'
395 '%s\n'
Mirko Bonadei4dc4e252017-09-19 11:49:16396 'Violating GN files:\n%s\n' % (json.dumps(errors, indent=2),
397 '\n'.join(errors.keys())))]
kjellander7439f972016-12-06 06:47:46398 return []
399
charujain9893e252017-09-14 11:33:22400def CheckNoPackageBoundaryViolations(input_api, gn_files, output_api):
ehmaldonado4fb97462017-01-30 13:27:22401 cwd = input_api.PresubmitLocalPath()
Oleh Prypin2f33a562017-10-04 18:17:54402 with _AddToPath(input_api.os_path.join(
403 cwd, 'tools_webrtc', 'presubmit_checks_lib')):
404 from check_package_boundaries import CheckPackageBoundaries
405 build_files = [os.path.join(cwd, gn_file.LocalPath()) for gn_file in gn_files]
406 errors = CheckPackageBoundaries(cwd, build_files)[:5]
407 if errors:
ehmaldonado4fb97462017-01-30 13:27:22408 return [output_api.PresubmitError(
Oleh Prypin2f33a562017-10-04 18:17:54409 'There are package boundary violations in the following GN files:',
410 long_text='\n\n'.join(str(err) for err in errors))]
ehmaldonado4fb97462017-01-30 13:27:22411 return []
412
Mirko Bonadeia51bbd82018-03-08 15:15:45413
414def _ReportErrorFileAndLineNumber(filename, line_num):
415 """Default error formatter for _FindNewViolationsOfRule."""
416 return '%s (line %s)' % (filename, line_num)
417
418
419def CheckNoStreamUsageIsAdded(input_api, output_api,
Artem Titov739351d2018-05-11 10:21:36420 source_file_filter,
421 error_formatter=_ReportErrorFileAndLineNumber):
Mirko Bonadeia51bbd82018-03-08 15:15:45422 """Make sure that no more dependencies on stringstream are added."""
423 error_msg = ('Usage of <sstream>, <istream> and <ostream> in WebRTC is '
424 'deprecated.\n'
425 'This includes the following types:\n'
426 'std::istringstream, std::ostringstream, std::wistringstream, '
427 'std::wostringstream,\n'
428 'std::wstringstream, std::ostream, std::wostream, std::istream,'
429 'std::wistream,\n'
430 'std::iostream, std::wiostream.\n'
431 'If you are not adding this code (e.g. you are just moving '
432 'existing code),\n'
433 'you can add a comment on the line that causes the problem:\n\n'
434 '#include <sstream> // no-presubmit-check TODO(webrtc:8982)\n'
435 'std::ostream& F() { // no-presubmit-check TODO(webrtc:8982)\n'
436 '\n'
Karl Wibergebd01e82018-03-14 14:08:39437 'If you are adding new code, consider using '
438 'rtc::SimpleStringBuilder\n'
439 '(in rtc_base/strings/string_builder.h).\n'
Mirko Bonadeia51bbd82018-03-08 15:15:45440 'Affected files:\n')
441 errors = [] # 2-element tuples with (file, line number)
442 include_re = input_api.re.compile(r'#include <(i|o|s)stream>')
443 usage_re = input_api.re.compile(r'std::(w|i|o|io|wi|wo|wio)(string)*stream')
444 no_presubmit_re = input_api.re.compile(
Jonas Olsson74395342018-04-03 10:22:07445 r'// no-presubmit-check TODO\(webrtc:8982\)')
Artem Titova04d1402018-05-11 09:23:00446 file_filter = lambda x: (input_api.FilterSourceFile(x)
447 and source_file_filter(x))
448 for f in input_api.AffectedSourceFiles(file_filter):
Mirko Bonadeid2c83322018-03-19 10:31:47449 if f.LocalPath() == 'PRESUBMIT.py':
450 continue
451 for line_num, line in f.ChangedContents():
452 if ((include_re.search(line) or usage_re.search(line))
453 and not no_presubmit_re.search(line)):
454 errors.append(error_formatter(f.LocalPath(), line_num))
Mirko Bonadeia51bbd82018-03-08 15:15:45455 if errors:
456 return [output_api.PresubmitError(error_msg, errors)]
457 return []
458
Mirko Bonadeia05d47e2018-05-09 09:03:38459def CheckPublicDepsIsNotUsed(gn_files, input_api, output_api):
460 """Checks that public_deps is not used without a good reason."""
Mirko Bonadei5c1ad592017-12-12 10:52:27461 result = []
Mirko Bonadeia05d47e2018-05-09 09:03:38462 no_presubmit_check_re = input_api.re.compile(
463 r'# no-presubmit-check TODO\(webrtc:8603\)')
464 error_msg = ('public_deps is not recommended in WebRTC BUILD.gn files '
465 'because it doesn\'t map well to downstream build systems.\n'
466 'Used in: %s (line %d).\n'
467 'If you are not adding this code (e.g. you are just moving '
468 'existing code) or you have a good reason, you can add a '
469 'comment on the line that causes the problem:\n\n'
470 'public_deps = [ # no-presubmit-check TODO(webrtc:8603)\n')
Mirko Bonadei5c1ad592017-12-12 10:52:27471 for affected_file in gn_files:
472 for (line_number, affected_line) in affected_file.ChangedContents():
Mirko Bonadeia05d47e2018-05-09 09:03:38473 if ('public_deps' in affected_line
474 and not no_presubmit_check_re.search(affected_line)):
Mirko Bonadei5c1ad592017-12-12 10:52:27475 result.append(
476 output_api.PresubmitError(error_msg % (affected_file.LocalPath(),
477 line_number)))
478 return result
479
Patrik Höglund6f491062018-01-11 11:04:23480def CheckCheckIncludesIsNotUsed(gn_files, output_api):
481 result = []
482 error_msg = ('check_includes overrides are not allowed since it can cause '
483 'incorrect dependencies to form. It effectively means that your '
484 'module can include any .h file without depending on its '
485 'corresponding target. There are some exceptional cases when '
486 'this is allowed: if so, get approval from a .gn owner in the'
487 'root OWNERS file.\n'
488 'Used in: %s (line %d).')
489 for affected_file in gn_files:
490 for (line_number, affected_line) in affected_file.ChangedContents():
491 if 'check_includes' in affected_line:
492 result.append(
493 output_api.PresubmitError(error_msg % (affected_file.LocalPath(),
494 line_number)))
495 return result
496
Artem Titova04d1402018-05-11 09:23:00497def CheckGnChanges(input_api, output_api, source_file_filter):
498 file_filter = lambda x: (input_api.FilterSourceFile(
Oleh Prypinafe01652017-10-04 13:56:08499 x, white_list=(r'.+\.(gn|gni)$',),
Mirko Bonadei5c1ad592017-12-12 10:52:27500 black_list=(r'.*/presubmit_checks_lib/testdata/.*',))
Artem Titova04d1402018-05-11 09:23:00501 and source_file_filter(x))
ehmaldonado5b1ba082016-09-02 12:51:08502
503 gn_files = []
Artem Titova04d1402018-05-11 09:23:00504 for f in input_api.AffectedSourceFiles(file_filter):
Mirko Bonadei92ea95e2017-09-15 04:47:31505 gn_files.append(f)
ehmaldonado5b1ba082016-09-02 12:51:08506
507 result = []
508 if gn_files:
charujain9893e252017-09-14 11:33:22509 result.extend(CheckNoSourcesAbove(input_api, gn_files, output_api))
Mirko Bonadei4dc4e252017-09-19 11:49:16510 result.extend(CheckNoMixingSources(input_api, gn_files, output_api))
511 result.extend(CheckNoPackageBoundaryViolations(input_api, gn_files,
512 output_api))
Mirko Bonadeia05d47e2018-05-09 09:03:38513 result.extend(CheckPublicDepsIsNotUsed(gn_files, input_api, output_api))
Patrik Höglund6f491062018-01-11 11:04:23514 result.extend(CheckCheckIncludesIsNotUsed(gn_files, output_api))
ehmaldonado5b1ba082016-09-02 12:51:08515 return result
516
Oleh Prypin920b6532017-10-05 09:28:51517def CheckGnGen(input_api, output_api):
518 """Runs `gn gen --check` with default args to detect mismatches between
519 #includes and dependencies in the BUILD.gn files, as well as general build
520 errors.
521 """
522 with _AddToPath(input_api.os_path.join(
523 input_api.PresubmitLocalPath(), 'tools_webrtc', 'presubmit_checks_lib')):
524 from gn_check import RunGnCheck
525 errors = RunGnCheck(input_api.PresubmitLocalPath())[:5]
526 if errors:
527 return [output_api.PresubmitPromptWarning(
528 'Some #includes do not match the build dependency graph. Please run:\n'
529 ' gn gen --check <out_dir>',
530 long_text='\n\n'.join(errors))]
531 return []
532
Artem Titova04d1402018-05-11 09:23:00533def CheckUnwantedDependencies(input_api, output_api, source_file_filter):
[email protected]3bd41562014-09-01 11:06:37534 """Runs checkdeps on #include statements added in this
535 change. Breaking - rules is an error, breaking ! rules is a
536 warning.
537 """
538 # Copied from Chromium's src/PRESUBMIT.py.
539
540 # We need to wait until we have an input_api object and use this
541 # roundabout construct to import checkdeps because this file is
542 # eval-ed and thus doesn't have __file__.
Oleh Prypin2f33a562017-10-04 18:17:54543 checkdeps_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
544 'buildtools', 'checkdeps')
545 if not os.path.exists(checkdeps_path):
546 return [output_api.PresubmitError(
547 'Cannot find checkdeps at %s\nHave you run "gclient sync" to '
548 'download all the DEPS entries?' % checkdeps_path)]
549 with _AddToPath(checkdeps_path):
[email protected]3bd41562014-09-01 11:06:37550 import checkdeps
551 from cpp_checker import CppChecker
552 from rules import Rule
[email protected]3bd41562014-09-01 11:06:37553
554 added_includes = []
Artem Titova04d1402018-05-11 09:23:00555 for f in input_api.AffectedFiles(file_filter=source_file_filter):
[email protected]3bd41562014-09-01 11:06:37556 if not CppChecker.IsCppFile(f.LocalPath()):
557 continue
558
Henrik Kjellander57e5fd22015-05-25 10:55:39559 changed_lines = [line for _, line in f.ChangedContents()]
[email protected]3bd41562014-09-01 11:06:37560 added_includes.append([f.LocalPath(), changed_lines])
561
562 deps_checker = checkdeps.DepsChecker(input_api.PresubmitLocalPath())
563
564 error_descriptions = []
565 warning_descriptions = []
566 for path, rule_type, rule_description in deps_checker.CheckAddedCppIncludes(
567 added_includes):
568 description_with_path = '%s\n %s' % (path, rule_description)
569 if rule_type == Rule.DISALLOW:
570 error_descriptions.append(description_with_path)
571 else:
572 warning_descriptions.append(description_with_path)
573
574 results = []
575 if error_descriptions:
576 results.append(output_api.PresubmitError(
kjellandera7066a32017-03-23 10:47:05577 'You added one or more #includes that violate checkdeps rules.\n'
578 'Check that the DEPS files in these locations contain valid rules.\n'
579 'See https://cs.chromium.org/chromium/src/buildtools/checkdeps/ for '
580 'more details about checkdeps.',
[email protected]3bd41562014-09-01 11:06:37581 error_descriptions))
582 if warning_descriptions:
583 results.append(output_api.PresubmitPromptOrNotify(
584 'You added one or more #includes of files that are temporarily\n'
585 'allowed but being removed. Can you avoid introducing the\n'
kjellandera7066a32017-03-23 10:47:05586 '#include? See relevant DEPS file(s) for details and contacts.\n'
587 'See https://cs.chromium.org/chromium/src/buildtools/checkdeps/ for '
588 'more details about checkdeps.',
[email protected]3bd41562014-09-01 11:06:37589 warning_descriptions))
590 return results
591
charujain9893e252017-09-14 11:33:22592def CheckCommitMessageBugEntry(input_api, output_api):
593 """Check that bug entries are well-formed in commit message."""
594 bogus_bug_msg = (
Mirko Bonadei61880182017-10-12 13:12:35595 'Bogus Bug entry: %s. Please specify the issue tracker prefix and the '
charujain9893e252017-09-14 11:33:22596 'issue number, separated by a colon, e.g. webrtc:123 or chromium:12345.')
597 results = []
Mirko Bonadei61880182017-10-12 13:12:35598 for bug in input_api.change.BugsFromDescription():
charujain9893e252017-09-14 11:33:22599 bug = bug.strip()
600 if bug.lower() == 'none':
601 continue
charujain81a58c72017-09-25 11:25:45602 if 'b/' not in bug and ':' not in bug:
charujain9893e252017-09-14 11:33:22603 try:
604 if int(bug) > 100000:
605 # Rough indicator for current chromium bugs.
606 prefix_guess = 'chromium'
607 else:
608 prefix_guess = 'webrtc'
Mirko Bonadei61880182017-10-12 13:12:35609 results.append('Bug entry requires issue tracker prefix, e.g. %s:%s' %
charujain9893e252017-09-14 11:33:22610 (prefix_guess, bug))
611 except ValueError:
612 results.append(bogus_bug_msg % bug)
charujain81a58c72017-09-25 11:25:45613 elif not (re.match(r'\w+:\d+', bug) or re.match(r'b/\d+', bug)):
charujain9893e252017-09-14 11:33:22614 results.append(bogus_bug_msg % bug)
615 return [output_api.PresubmitError(r) for r in results]
616
617def CheckChangeHasBugField(input_api, output_api):
Mirko Bonadei61880182017-10-12 13:12:35618 """Requires that the changelist is associated with a bug.
kjellanderd1e26a92016-09-19 15:11:16619
620 This check is stricter than the one in depot_tools/presubmit_canned_checks.py
Mirko Bonadei61880182017-10-12 13:12:35621 since it fails the presubmit if the bug field is missing or doesn't contain
kjellanderd1e26a92016-09-19 15:11:16622 a bug reference.
Mirko Bonadei61880182017-10-12 13:12:35623
624 This supports both 'BUG=' and 'Bug:' since we are in the process of migrating
625 to Gerrit and it encourages the usage of 'Bug:'.
kjellanderd1e26a92016-09-19 15:11:16626 """
Mirko Bonadei61880182017-10-12 13:12:35627 if input_api.change.BugsFromDescription():
kjellanderd1e26a92016-09-19 15:11:16628 return []
629 else:
630 return [output_api.PresubmitError(
Mirko Bonadei61880182017-10-12 13:12:35631 'The "Bug: [bug number]" footer is mandatory. Please create a bug and '
kjellanderd1e26a92016-09-19 15:11:16632 'reference it using either of:\n'
Mirko Bonadei61880182017-10-12 13:12:35633 ' * https://bugs.webrtc.org - reference it using Bug: webrtc:XXXX\n'
634 ' * https://crbug.com - reference it using Bug: chromium:XXXXXX')]
[email protected]e4158642014-08-06 09:11:18635
Artem Titova04d1402018-05-11 09:23:00636def CheckJSONParseErrors(input_api, output_api, source_file_filter):
kjellander569cf942016-02-11 13:02:59637 """Check that JSON files do not contain syntax errors."""
638
639 def FilterFile(affected_file):
Artem Titova04d1402018-05-11 09:23:00640 return (input_api.os_path.splitext(affected_file.LocalPath())[1] == '.json'
641 and source_file_filter(affected_file))
kjellander569cf942016-02-11 13:02:59642
643 def GetJSONParseError(input_api, filename):
644 try:
645 contents = input_api.ReadFile(filename)
646 input_api.json.loads(contents)
647 except ValueError as e:
648 return e
649 return None
650
651 results = []
652 for affected_file in input_api.AffectedFiles(
653 file_filter=FilterFile, include_deletes=False):
654 parse_error = GetJSONParseError(input_api,
655 affected_file.AbsoluteLocalPath())
656 if parse_error:
657 results.append(output_api.PresubmitError('%s could not be parsed: %s' %
658 (affected_file.LocalPath(), parse_error)))
659 return results
660
661
charujain9893e252017-09-14 11:33:22662def RunPythonTests(input_api, output_api):
kjellanderc88b5d52017-04-05 13:42:43663 def Join(*args):
Henrik Kjellander8d3ad822015-05-26 17:52:05664 return input_api.os_path.join(input_api.PresubmitLocalPath(), *args)
665
666 test_directories = [
Edward Lemur6d01f6d2017-09-14 15:02:01667 input_api.PresubmitLocalPath(),
Mirko Bonadei92ea95e2017-09-15 04:47:31668 Join('rtc_tools', 'py_event_log_analyzer'),
669 Join('rtc_tools'),
670 Join('audio', 'test', 'unittests'),
ehmaldonado4fb97462017-01-30 13:27:22671 ] + [
Henrik Kjellander90fd7d82017-05-09 06:30:10672 root for root, _, files in os.walk(Join('tools_webrtc'))
ehmaldonado4fb97462017-01-30 13:27:22673 if any(f.endswith('_test.py') for f in files)
Henrik Kjellander8d3ad822015-05-26 17:52:05674 ]
675
676 tests = []
677 for directory in test_directories:
678 tests.extend(
679 input_api.canned_checks.GetUnitTestsInDirectory(
680 input_api,
681 output_api,
682 directory,
683 whitelist=[r'.+_test\.py$']))
684 return input_api.RunTests(tests, parallel=True)
685
686
Artem Titova04d1402018-05-11 09:23:00687def CheckUsageOfGoogleProtobufNamespace(input_api, output_api,
688 source_file_filter):
mbonadei38415b22017-04-07 12:38:01689 """Checks that the namespace google::protobuf has not been used."""
690 files = []
691 pattern = input_api.re.compile(r'google::protobuf')
Mirko Bonadei92ea95e2017-09-15 04:47:31692 proto_utils_path = os.path.join('rtc_base', 'protobuf_utils.h')
Artem Titova04d1402018-05-11 09:23:00693 file_filter = lambda x: (input_api.FilterSourceFile(x)
694 and source_file_filter(x))
695 for f in input_api.AffectedSourceFiles(file_filter):
mbonadei38415b22017-04-07 12:38:01696 if f.LocalPath() in [proto_utils_path, 'PRESUBMIT.py']:
697 continue
698 contents = input_api.ReadFile(f)
699 if pattern.search(contents):
700 files.append(f)
701
702 if files:
703 return [output_api.PresubmitError(
704 'Please avoid to use namespace `google::protobuf` directly.\n'
705 'Add a using directive in `%s` and include that header instead.'
706 % proto_utils_path, files)]
707 return []
708
709
Mirko Bonadei92ea95e2017-09-15 04:47:31710def _LicenseHeader(input_api):
711 """Returns the license header regexp."""
712 # Accept any year number from 2003 to the current year
713 current_year = int(input_api.time.strftime('%Y'))
714 allowed_years = (str(s) for s in reversed(xrange(2003, current_year + 1)))
715 years_re = '(' + '|'.join(allowed_years) + ')'
716 license_header = (
717 r'.*? Copyright( \(c\))? %(year)s The WebRTC [Pp]roject [Aa]uthors\. '
718 r'All [Rr]ights [Rr]eserved\.\n'
719 r'.*?\n'
720 r'.*? Use of this source code is governed by a BSD-style license\n'
721 r'.*? that can be found in the LICENSE file in the root of the source\n'
722 r'.*? tree\. An additional intellectual property rights grant can be '
723 r'found\n'
724 r'.*? in the file PATENTS\. All contributing project authors may\n'
725 r'.*? be found in the AUTHORS file in the root of the source tree\.\n'
726 ) % {
727 'year': years_re,
728 }
729 return license_header
730
731
charujain9893e252017-09-14 11:33:22732def CommonChecks(input_api, output_api):
[email protected]53df1362012-01-26 21:24:23733 """Checks common to both upload and commit."""
[email protected]da159d62011-05-30 11:51:34734 results = []
tkchin42f580e2015-11-27 07:18:23735 # Filter out files that are in objc or ios dirs from being cpplint-ed since
736 # they do not follow C++ lint rules.
737 black_list = input_api.DEFAULT_BLACK_LIST + (
738 r".*\bobjc[\\\/].*",
Kári Tristan Helgason3fa35172016-09-09 08:55:05739 r".*objc\.[hcm]+$",
tkchin42f580e2015-11-27 07:18:23740 )
741 source_file_filter = lambda x: input_api.FilterSourceFile(x, None, black_list)
charujain9893e252017-09-14 11:33:22742 results.extend(CheckApprovedFilesLintClean(
tkchin42f580e2015-11-27 07:18:23743 input_api, output_api, source_file_filter))
Mirko Bonadei92ea95e2017-09-15 04:47:31744 results.extend(input_api.canned_checks.CheckLicense(
745 input_api, output_api, _LicenseHeader(input_api)))
[email protected]5d3713932013-03-07 09:59:43746 results.extend(input_api.canned_checks.RunPylint(input_api, output_api,
[email protected]177567c2016-12-22 09:40:28747 black_list=(r'^base[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 11:10:04748 r'^build[\\\/].*\.py$',
749 r'^buildtools[\\\/].*\.py$',
kjellander38c65c82017-04-13 05:43:38750 r'^infra[\\\/].*\.py$',
Henrik Kjellander0779e8f2016-12-22 11:01:17751 r'^ios[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 11:10:04752 r'^out.*[\\\/].*\.py$',
753 r'^testing[\\\/].*\.py$',
754 r'^third_party[\\\/].*\.py$',
[email protected]177567c2016-12-22 09:40:28755 r'^tools[\\\/].*\.py$',
kjellanderafd54942016-12-17 20:21:39756 # TODO(phoglund): should arguably be checked.
Henrik Kjellander90fd7d82017-05-09 06:30:10757 r'^tools_webrtc[\\\/]mb[\\\/].*\.py$',
758 r'^tools_webrtc[\\\/]valgrind[\\\/].*\.py$',
Henrik Kjellander14771ac2015-06-02 11:10:04759 r'^xcodebuild.*[\\\/].*\.py$',),
Henrik Kjellander57e5fd22015-05-25 10:55:39760 pylintrc='pylintrc'))
kjellander569cf942016-02-11 13:02:59761
nisse3d21e232016-09-02 10:07:06762 # TODO(nisse): talk/ is no more, so make below checks simpler?
Henrik Kjellander57e5fd22015-05-25 10:55:39763 # WebRTC can't use the presubmit_canned_checks.PanProjectChecks function since
764 # we need to have different license checks in talk/ and webrtc/ directories.
765 # Instead, hand-picked checks are included below.
Henrik Kjellander63224672015-09-08 06:03:56766
tkchin3cd9a302016-06-08 19:40:28767 # .m and .mm files are ObjC files. For simplicity we will consider .h files in
768 # ObjC subdirectories ObjC headers.
769 objc_filter_list = (r'.+\.m$', r'.+\.mm$', r'.+objc\/.+\.h$')
Henrik Kjellanderb4af3d62016-11-16 19:11:29770 # Skip long-lines check for DEPS and GN files.
771 build_file_filter_list = (r'.+\.gn$', r'.+\.gni$', 'DEPS')
Artem Titova04d1402018-05-11 09:23:00772 # Also we will skip most checks for third_party directory.
773 third_party_filter_list = (r'^third_party[\\\/].+',)
tkchin3cd9a302016-06-08 19:40:28774 eighty_char_sources = lambda x: input_api.FilterSourceFile(x,
Artem Titova04d1402018-05-11 09:23:00775 black_list=build_file_filter_list + objc_filter_list +
776 third_party_filter_list)
tkchin3cd9a302016-06-08 19:40:28777 hundred_char_sources = lambda x: input_api.FilterSourceFile(x,
778 white_list=objc_filter_list)
[email protected]2442de12012-01-23 17:45:41779 results.extend(input_api.canned_checks.CheckLongLines(
tkchin3cd9a302016-06-08 19:40:28780 input_api, output_api, maxlen=80, source_file_filter=eighty_char_sources))
781 results.extend(input_api.canned_checks.CheckLongLines(
782 input_api, output_api, maxlen=100,
783 source_file_filter=hundred_char_sources))
784
Artem Titova04d1402018-05-11 09:23:00785 non_third_party_sources = lambda x: input_api.FilterSourceFile(x,
786 black_list=third_party_filter_list)
[email protected]2442de12012-01-23 17:45:41787 results.extend(input_api.canned_checks.CheckChangeHasNoTabs(
Artem Titova04d1402018-05-11 09:23:00788 input_api, output_api, source_file_filter=non_third_party_sources))
[email protected]53df1362012-01-26 21:24:23789 results.extend(input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
Artem Titova04d1402018-05-11 09:23:00790 input_api, output_api, source_file_filter=non_third_party_sources))
kjellandere5dc62a2016-12-14 08:16:21791 results.extend(input_api.canned_checks.CheckAuthorizedAuthor(
792 input_api, output_api))
[email protected]53df1362012-01-26 21:24:23793 results.extend(input_api.canned_checks.CheckChangeTodoHasOwner(
Artem Titova04d1402018-05-11 09:23:00794 input_api, output_api, source_file_filter=non_third_party_sources))
charujain9893e252017-09-14 11:33:22795 results.extend(CheckNativeApiHeaderChanges(input_api, output_api))
Artem Titova04d1402018-05-11 09:23:00796 results.extend(CheckNoIOStreamInHeaders(
797 input_api, output_api, source_file_filter=non_third_party_sources))
798 results.extend(CheckNoPragmaOnce(
799 input_api, output_api, source_file_filter=non_third_party_sources))
800 results.extend(CheckNoFRIEND_TEST(
801 input_api, output_api, source_file_filter=non_third_party_sources))
802 results.extend(CheckGnChanges(
803 input_api, output_api, source_file_filter=non_third_party_sources))
804 results.extend(CheckUnwantedDependencies(
805 input_api, output_api, source_file_filter=non_third_party_sources))
806 results.extend(CheckJSONParseErrors(
807 input_api, output_api, source_file_filter=non_third_party_sources))
charujain9893e252017-09-14 11:33:22808 results.extend(RunPythonTests(input_api, output_api))
Artem Titova04d1402018-05-11 09:23:00809 results.extend(CheckUsageOfGoogleProtobufNamespace(
810 input_api, output_api, source_file_filter=non_third_party_sources))
811 results.extend(CheckOrphanHeaders(
812 input_api, output_api, source_file_filter=non_third_party_sources))
813 results.extend(CheckNewlineAtTheEndOfProtoFiles(
814 input_api, output_api, source_file_filter=non_third_party_sources))
815 results.extend(CheckNoStreamUsageIsAdded(
Artem Titov739351d2018-05-11 10:21:36816 input_api, output_api, non_third_party_sources))
[email protected]53df1362012-01-26 21:24:23817 return results
[email protected]2442de12012-01-23 17:45:41818
[email protected]e4158642014-08-06 09:11:18819
[email protected]53df1362012-01-26 21:24:23820def CheckChangeOnUpload(input_api, output_api):
821 results = []
charujain9893e252017-09-14 11:33:22822 results.extend(CommonChecks(input_api, output_api))
Oleh Prypin920b6532017-10-05 09:28:51823 results.extend(CheckGnGen(input_api, output_api))
Henrik Kjellander57e5fd22015-05-25 10:55:39824 results.extend(
825 input_api.canned_checks.CheckGNFormatted(input_api, output_api))
[email protected]da159d62011-05-30 11:51:34826 return results
827
[email protected]e4158642014-08-06 09:11:18828
[email protected]2442de12012-01-23 17:45:41829def CheckChangeOnCommit(input_api, output_api):
[email protected]1198db92011-06-09 07:07:24830 results = []
charujain9893e252017-09-14 11:33:22831 results.extend(CommonChecks(input_api, output_api))
832 results.extend(VerifyNativeApiHeadersListIsValid(input_api, output_api))
[email protected]1198db92011-06-09 07:07:24833 results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
[email protected]53df1362012-01-26 21:24:23834 results.extend(input_api.canned_checks.CheckChangeWasUploaded(
835 input_api, output_api))
836 results.extend(input_api.canned_checks.CheckChangeHasDescription(
837 input_api, output_api))
charujain9893e252017-09-14 11:33:22838 results.extend(CheckChangeHasBugField(input_api, output_api))
839 results.extend(CheckCommitMessageBugEntry(input_api, output_api))
[email protected]12cb88c2014-02-13 11:53:43840 results.extend(input_api.canned_checks.CheckTreeIsOpen(
841 input_api, output_api,
842 json_url='http://webrtc-status.appspot.com/current?format=json'))
[email protected]1198db92011-06-09 07:07:24843 return results
mbonadei74973ed2017-05-09 14:58:05844
845
Artem Titova04d1402018-05-11 09:23:00846def CheckOrphanHeaders(input_api, output_api, source_file_filter):
mbonadei74973ed2017-05-09 14:58:05847 # We need to wait until we have an input_api object and use this
848 # roundabout construct to import prebubmit_checks_lib because this file is
849 # eval-ed and thus doesn't have __file__.
Patrik Höglund2f3f7222017-12-19 10:08:56850 error_msg = """{} should be listed in {}."""
mbonadei74973ed2017-05-09 14:58:05851 results = []
Patrik Höglund7e60de22018-01-09 13:22:00852 orphan_blacklist = [
853 os.path.join('tools_webrtc', 'ios', 'SDK'),
854 ]
Oleh Prypin2f33a562017-10-04 18:17:54855 with _AddToPath(input_api.os_path.join(
856 input_api.PresubmitLocalPath(), 'tools_webrtc', 'presubmit_checks_lib')):
mbonadei74973ed2017-05-09 14:58:05857 from check_orphan_headers import GetBuildGnPathFromFilePath
858 from check_orphan_headers import IsHeaderInBuildGn
mbonadei74973ed2017-05-09 14:58:05859
Artem Titova04d1402018-05-11 09:23:00860 file_filter = lambda x: input_api.FilterSourceFile(
861 x, black_list=orphan_blacklist) and source_file_filter(x)
862 for f in input_api.AffectedSourceFiles(file_filter):
Patrik Höglund7e60de22018-01-09 13:22:00863 if f.LocalPath().endswith('.h'):
mbonadei74973ed2017-05-09 14:58:05864 file_path = os.path.abspath(f.LocalPath())
865 root_dir = os.getcwd()
866 gn_file_path = GetBuildGnPathFromFilePath(file_path, os.path.exists,
867 root_dir)
868 in_build_gn = IsHeaderInBuildGn(file_path, gn_file_path)
869 if not in_build_gn:
870 results.append(output_api.PresubmitError(error_msg.format(
Patrik Höglund2f3f7222017-12-19 10:08:56871 f.LocalPath(), os.path.relpath(gn_file_path))))
mbonadei74973ed2017-05-09 14:58:05872 return results
Mirko Bonadei960fd5b2017-06-29 12:59:36873
874
Artem Titova04d1402018-05-11 09:23:00875def CheckNewlineAtTheEndOfProtoFiles(input_api, output_api,
876 source_file_filter):
Mirko Bonadei960fd5b2017-06-29 12:59:36877 """Checks that all .proto files are terminated with a newline."""
878 error_msg = 'File {} must end with exactly one newline.'
879 results = []
Artem Titova04d1402018-05-11 09:23:00880 file_filter = lambda x: input_api.FilterSourceFile(
881 x, white_list=(r'.+\.proto$',)) and source_file_filter(x)
882 for f in input_api.AffectedSourceFiles(file_filter):
Mirko Bonadei960fd5b2017-06-29 12:59:36883 file_path = f.LocalPath()
884 with open(file_path) as f:
885 lines = f.readlines()
Mirko Bonadeia730c1c2017-09-18 09:33:13886 if len(lines) > 0 and not lines[-1].endswith('\n'):
Mirko Bonadei960fd5b2017-06-29 12:59:36887 results.append(output_api.PresubmitError(error_msg.format(file_path)))
888 return results