presubmit.py revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#!/usr/bin/env python
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# Copyright 2008 the V8 project authors. All rights reserved.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# Redistribution and use in source and binary forms, with or without
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# modification, are permitted provided that the following conditions are
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# met:
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#     * Redistributions of source code must retain the above copyright
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#       notice, this list of conditions and the following disclaimer.
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#     * Redistributions in binary form must reproduce the above
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#       copyright notice, this list of conditions and the following
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#       disclaimer in the documentation and/or other materials provided
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#       with the distribution.
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#     * Neither the name of Google Inc. nor the names of its
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#       contributors may be used to endorse or promote products derived
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#       from this software without specific prior written permission.
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport optparse
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport os
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfrom os.path import abspath, join, dirname, basename, exists
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport re
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport sys
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockimport subprocess
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# Disabled LINT rules and reason.
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block# build/include_what_you_use: Started giving false positives for variables
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#  named "string" and "map" assuming that you needed to include STL headers.
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockENABLED_LINT_RULES = """
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbuild/class
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbuild/deprecated
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbuild/endif_comment
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbuild/forward_decl
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbuild/include_order
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbuild/printf_format
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbuild/storage_class
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocklegal/copyright
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/boost
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/braces
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/casting
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/check
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/constructors
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/fn_size
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/function
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/multiline_comment
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/multiline_string
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/streams
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/todo
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockreadability/utf8
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/arrays
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/casting
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/deprecated_fn
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/explicit
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/int
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/memset
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/mutex
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/nonconf
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/printf
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/printf_format
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/references
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/rtti
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/sizeof
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/string
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/virtual
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockruntime/vlog
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/blank_line
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/braces
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/comma
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/comments
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/end_of_line
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/ending_newline
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/indent
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/labels
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/line_length
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/newline
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/operators
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/parens
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/tab
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockwhitespace/todo
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block""".split()
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SourceFileProcessor(object):
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  """
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Utility class that can run through a directory structure, find all relevant
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  files and invoke a custom check on the files.
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  """
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def Run(self, path):
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    all_files = []
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for file in self.GetPathsToSearch():
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      all_files += self.FindFilesIn(join(path, file))
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if not self.ProcessFiles(all_files, path):
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return False
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return True
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def IgnoreDir(self, name):
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return name.startswith('.') or name == 'data'
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def IgnoreFile(self, name):
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return name.startswith('.')
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def FindFilesIn(self, path):
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = []
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (root, dirs, files) in os.walk(path):
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for ignored in [x for x in dirs if self.IgnoreDir(x)]:
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        dirs.remove(ignored)
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for file in files:
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if not self.IgnoreFile(file) and self.IsRelevant(file):
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          result.append(join(root, file))
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return result
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CppLintProcessor(SourceFileProcessor):
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  """
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Lint files to check that they follow the google code style.
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  """
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def IsRelevant(self, name):
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return name.endswith('.cc') or name.endswith('.h')
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def IgnoreDir(self, name):
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (super(CppLintProcessor, self).IgnoreDir(name)
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              or (name == 'third_party'))
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IGNORE_LINT = ['flag-definitions.h']
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def IgnoreFile(self, name):
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (super(CppLintProcessor, self).IgnoreFile(name)
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              or (name in CppLintProcessor.IGNORE_LINT))
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def GetPathsToSearch(self):
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ['src', 'public', 'samples', join('test', 'cctest')]
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def ProcessFiles(self, files, path):
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    filt = '-,' + ",".join(['+' + n for n in ENABLED_LINT_RULES])
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    command = ['cpplint.py', '--filter', filt] + join(files)
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    local_cpplint = join(path, "tools", "cpplint.py")
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if exists(local_cpplint):
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      command = ['python', local_cpplint, '--filter', filt] + join(files)
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    process = subprocess.Popen(command)
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return process.wait() == 0
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockCOPYRIGHT_HEADER_PATTERN = re.compile(
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    r'Copyright [\d-]*200[8-9] the V8 project authors. All rights reserved.')
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SourceProcessor(SourceFileProcessor):
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  """
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Check that all files include a copyright notice.
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  """
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RELEVANT_EXTENSIONS = ['.js', '.cc', '.h', '.py', '.c', 'SConscript',
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'SConstruct', '.status']
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def IsRelevant(self, name):
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for ext in SourceProcessor.RELEVANT_EXTENSIONS:
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if name.endswith(ext):
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return True
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return False
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def GetPathsToSearch(self):
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return ['.']
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def IgnoreDir(self, name):
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return (super(SourceProcessor, self).IgnoreDir(name)
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              or (name == 'third_party')
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              or (name == 'obj'))
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IGNORE_COPYRIGHTS = ['earley-boyer.js', 'raytrace.js', 'crypto.js',
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'libraries.cc', 'libraries-empty.cc', 'jsmin.py', 'regexp-pcre.js']
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IGNORE_TABS = IGNORE_COPYRIGHTS + ['unicode-test.js',
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      'html-comments.js']
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def ProcessContents(self, name, contents):
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    result = True
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    base = basename(name)
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if not base in SourceProcessor.IGNORE_TABS:
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if '\t' in contents:
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        print "%s contains tabs" % name
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        result = False
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if not base in SourceProcessor.IGNORE_COPYRIGHTS:
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if not COPYRIGHT_HEADER_PATTERN.search(contents):
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        print "%s is missing a correct copyright header." % name
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        result = False
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return result
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  def ProcessFiles(self, files, path):
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    success = True
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for file in files:
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      try:
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        handle = open(file)
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        contents = handle.read()
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        success = self.ProcessContents(file, contents) and success
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      finally:
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        handle.close()
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return success
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdef GetOptions():
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = optparse.OptionParser()
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result.add_option('--no-lint', help="Do not run cpplint", default=False,
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    action="store_true")
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdef Main():
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  workspace = abspath(join(dirname(sys.argv[0]), '..'))
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  parser = GetOptions()
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  (options, args) = parser.parse_args()
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  success = True
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if not options.no_lint:
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    success = CppLintProcessor().Run(workspace) and success
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  success = SourceProcessor().Run(workspace) and success
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if success:
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 0
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  else:
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 1
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif __name__ == '__main__':
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  sys.exit(Main())
235