diff options
author | initial.commit@chromium.org <initial.commit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-02 02:14:31 +0000 |
---|---|---|
committer | initial.commit@chromium.org <initial.commit@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-02 02:14:31 +0000 |
commit | 5a7bdf208c28c210b39cff63d1cf91302b02821b (patch) | |
tree | 5ff484561562f78b29d2670168a9e3b40b48dcab /ceee/ceee_presubmit.py | |
parent | 26a54a5e0f4603c8fda2fe51789d331125993c9a (diff) | |
download | chromium_src-5a7bdf208c28c210b39cff63d1cf91302b02821b.zip chromium_src-5a7bdf208c28c210b39cff63d1cf91302b02821b.tar.gz chromium_src-5a7bdf208c28c210b39cff63d1cf91302b02821b.tar.bz2 |
Checking in the initial version of CEEE (Chrome Extensions Execution
Environment), an optional feature of Chrome Frame that acts as an
adapter layer for a subset of the Chrome Extension APIs. This enables
extensions that stick to the supported subset of APIs to work in the
context of Chrome Frame with minimal or sometimes no changes.
See http://www.chromium.org/developers/design-documents/ceee for an
overview of the design of CEEE.
TEST=unit tests (run ceee/smoke_tests.bat as an administrator on Windows)
BUG=none
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64712 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ceee/ceee_presubmit.py')
-rw-r--r-- | ceee/ceee_presubmit.py | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/ceee/ceee_presubmit.py b/ceee/ceee_presubmit.py new file mode 100644 index 0000000..8037fb5 --- /dev/null +++ b/ceee/ceee_presubmit.py @@ -0,0 +1,263 @@ +# Copyright (c) 2010 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import re +import subprocess +import os + +try: + from internal import internal_presubmit +except ImportError: + internal_presubmit = None + + +SOURCE_FILE_EXTENSIONS = [ + '.c', '.cc', '.cpp', '.h', '.m', '.mm', '.py', '.mk', '.am', '.json', + '.gyp', '.gypi' + ] + +EXCLUDED_PATHS = [] + +# Finds what seem to be definitions of DllRegisterServer. +DLL_REGISTER_SERVER_RE = re.compile('\s+DllRegisterServer\s*\(') + +# Matches a Tracker story URL +story_url_re = re.compile('https?://tracker.+/[0-9]+') + +# Matches filenames in which we allow tabs +tabs_ok_re = re.compile('.*\.(vcproj|vsprops|sln)$') + +# Matches filenames of source files +source_files_re = re.compile('.*\.(cc|h|py|js)$') + + +# The top-level source directory. +_SRC_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + + +def CheckChange(input_api, output_api, committing): + results = [] + + do_not_submit_errors = input_api.canned_checks.CheckDoNotSubmit(input_api, + output_api) + if committing: + results += do_not_submit_errors + elif do_not_submit_errors: + results += [output_api.PresubmitNotifyResult( + 'There is a DO-NOT-SUBMIT issue')] + + results += CheckChangeHasNoTabs(input_api, output_api) + results += CheckLongLines(input_api, output_api) + results += CheckHasStoryOrBug(input_api, output_api) + results += LocalChecks(input_api, output_api) + results += CheckNoDllRegisterServer(input_api, output_api) + results += CheckUnittestsRan(input_api, output_api, committing) + if internal_presubmit: + results += internal_presubmit.InternalChecks(input_api, output_api, + committing) + return results + + +def CheckHasStoryOrBug(input_api, output_api): + """We require either BUG= to be present and non-empty. For + a completely trivial change, use BUG=none. + """ + if not ('BUG' in input_api.change.tags): + return [output_api.PresubmitError('A BUG= tag is required. For trivial ' + 'changes you can use BUG=none.')] + if ('BUG' in input_api.change.tags and + len(input_api.change.tags['BUG']) == 0): + return [output_api.PresubmitError('A non-empty BUG= is required. For ' + 'trivial changes you can use BUG=none.')] + return [] + + +def CheckChangeHasNoTabs(input_api, output_api): + """Slightly modified version of the canned check with the same name. + + This version ignores certain file types in which we allow tabs. + """ + for f, line_num, line in input_api.RightHandSideLines(): + if tabs_ok_re.match(f.LocalPath()): + continue + if '\t' in line: + return [output_api.PresubmitError( + "Found a tab character in %s, line %s" % + (f.LocalPath(), line_num))] + return [] + + +def CheckLongLines(input_api, output_api, maxlen=80): + """Checks that there aren't any lines longer than maxlen characters in any of + the text files to be submitted. + """ + basename = input_api.basename + + bad = [] + for f, line_num, line in input_api.RightHandSideLines(): + if not source_files_re.match(f.LocalPath()): + continue + if line.find('http://') != -1: + # Exemption for long URLs + continue + if line.endswith('\n'): + line = line[:-1] + if len(line) > maxlen: + bad.append( + '%s, line %s, %s chars' % + (basename(f.LocalPath()), line_num, len(line))) + if len(bad) == 5: # Just show the first 5 errors. + break + + if bad: + msg = "Found lines longer than %s characters (first 5 shown)." % maxlen + return [output_api.PresubmitPromptWarning(msg, items=bad)] + else: + return [] + + +_UNITTEST_MESSAGE = '''\ +You must build and run the CEEE smoke tests before submitting. To clear this +error, run the script "smoke_test.bat" in the CEEE directory. +''' + +def CheckUnittestsRan(input_api, output_api, committing): + '''Checks that the unittests success file is newer than any modified file''' + # But only if there were IE files modified, since we only have unit tests + # for CEEE IE. + files = [] + for f in input_api.AffectedFiles(include_deletes = False): + path = f.LocalPath() + if path.startswith('ie\\') or path.startswith('common\\'): + files.append(f) + + if not files: + return [] + + def MakeResult(message, modified_files=[]): + if committing: + return output_api.PresubmitError(message, modified_files) + else: + return output_api.PresubmitNotifyResult(message, modified_files) + os_path = input_api.os_path + + success_files = [ + os_path.join(input_api.PresubmitLocalPath(), + '../chrome/Debug/ceee.success'), + os_path.join(input_api.PresubmitLocalPath(), + '../chrome/Release/ceee.success')] + + if (not os_path.exists(success_files[0]) or + not os_path.exists(success_files[1])): + return [MakeResult(_UNITTEST_MESSAGE)] + + success_time = min(os.stat(success_files[0]).st_mtime, + os.stat(success_files[1]).st_mtime) + modified_files = [] + for f in modified_files: + file_time = os.stat(f.AbsoluteLocalPath()).st_mtime + if file_time > success_time: + modified_files.append(f.LocalPath()) + + result = [] + if modified_files: + result.append(MakeResult('These files have been modified since Debug and/or' + ' Release unittests were built.', modified_files)) + + return result + + +def CheckNoDllRegisterServer(input_api, output_api): + for f, line_num, line in input_api.RightHandSideLines(): + if DLL_REGISTER_SERVER_RE.search(line): + file_name = os.path.basename(f.LocalPath()) + if file_name not in ['install_utils.h', 'install_utils_unittest.cc']: + return [output_api.PresubmitError( + '%s seems to contain a definition of DllRegisterServer.\n' + 'Please search for CEEE_DEFINE_DLL_REGISTER_SERVER.' % + f.LocalPath())] + return [] + + +def LocalChecks(input_api, output_api, max_cols=80): + """Reports an error if for any source file in SOURCE_FILE_EXTENSIONS: + - uses CR (or CRLF) + - contains a TAB + - has a line that ends with whitespace + - contains a line >|max_cols| cols unless |max_cols| is 0. + - File does not end in a newline, or ends in more than one. + + Note that the whole file is checked, not only the changes. + """ + C_SOURCE_FILE_EXTENSIONS = ('.c', '.cc', '.cpp', '.h', '.inl') + cr_files = [] + eof_files = [] + results = [] + excluded_paths = [input_api.re.compile(x) for x in EXCLUDED_PATHS] + files = input_api.AffectedFiles(include_deletes=False) + for f in files: + path = f.LocalPath() + root, ext = input_api.os_path.splitext(path) + # Look for unsupported extensions. + if not ext in SOURCE_FILE_EXTENSIONS: + continue + # Look for excluded paths. + found = False + for item in excluded_paths: + if item.match(path): + found = True + break + if found: + continue + + # Need to read the file ourselves since AffectedFile.NewContents() + # will normalize line endings. + contents = input_api.ReadFile(f, 'rb') + if '\r' in contents: + cr_files.append(path) + + # Check that the file ends in one and only one newline character. + if len(contents) > 0 and (contents[-1:] != "\n" or contents[-2:-1] == "\n"): + eof_files.append(path) + + local_errors = [] + # Remove end of line character. + lines = contents.splitlines() + line_num = 1 + for line in lines: + if line.endswith(' '): + local_errors.append(output_api.PresubmitError( + '%s, line %s ends with whitespaces.' % + (path, line_num))) + # Accept lines with http://, https:// and C #define/#pragma/#include to + # exceed the max_cols rule. + if (max_cols and + len(line) > max_cols and + not 'http://' in line and + not 'https://' in line and + not (line[0] == '#' and ext in C_SOURCE_FILE_EXTENSIONS)): + local_errors.append(output_api.PresubmitError( + '%s, line %s has %s chars, please reduce to %d chars.' % + (path, line_num, len(line), max_cols))) + if '\t' in line: + local_errors.append(output_api.PresubmitError( + "%s, line %s contains a tab character." % + (path, line_num))) + line_num += 1 + # Just show the first 5 errors. + if len(local_errors) == 6: + local_errors.pop() + local_errors.append(output_api.PresubmitError("... and more.")) + break + results.extend(local_errors) + + if cr_files: + results.append(output_api.PresubmitError( + 'Found CR (or CRLF) line ending in these files, please use only LF:', + items=cr_files)) + if eof_files: + results.append(output_api.PresubmitError( + 'These files should end in one (and only one) newline character:', + items=eof_files)) + return results |