1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#!/usr/bin/python 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# Copyright (c) 2009 The Chromium Authors. All rights reserved. 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# Use of this source code is governed by a BSD-style license that can be 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# found in the LICENSE file. 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott"""Top-level presubmit script for googleurl. 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSee http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdetails on the presubmit API built into gcl. 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott""" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# Files with these extensions will be considered source files 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSOURCE_FILE_EXTENSIONS = [ 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott '.c', '.cc', '.cpp', '.h', '.m', '.mm', '.py', '.mk', '.am', '.json', 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott] 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEXCLUDED_PATHS = [ 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott r".*third_party[\\\/].*", 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott] 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdef ReadFile(path): 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott """Given a path, returns the full contents of the file. 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Reads files in binary format. 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott """ 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fo = open(path, 'rb') 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott try: 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott contents = fo.read() 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott finally: 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fo.close() 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return contents 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdef CheckChangeOnUpload(input_api, output_api): 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # TODO(brettw) Enforce 80 cols. 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return LocalChecks(input_api, output_api, max_cols=0) 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdef CheckChangeOnCommit(input_api, output_api): 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # TODO(brettw) Enforce 80 cols. 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (LocalChecks(input_api, output_api, max_cols=0) + 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott input_api.canned_checks.CheckDoNotSubmit(input_api, output_api)) 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottdef LocalChecks(input_api, output_api, max_cols=80): 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott """Reports an error if for any source file in SOURCE_FILE_EXTENSIONS: 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott - uses CR (or CRLF) 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott - contains a TAB 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott - has a line that ends with whitespace 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott - contains a line >|max_cols| cols unless |max_cols| is 0. 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Note that the whole file is checked, not only the changes. 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott """ 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cr_files = [] 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott results = [] 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott excluded_paths = [input_api.re.compile(x) for x in EXCLUDED_PATHS] 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott files = input_api.AffectedFiles() 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for f in files: 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott path = f.LocalPath() 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott root, ext = input_api.os_path.splitext(path) 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # Look for unsupported extensions. 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if not ext in SOURCE_FILE_EXTENSIONS: 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # Look for excluded paths. 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott found = False 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for item in excluded_paths: 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if item.match(path): 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott found = True 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if found: 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # Need to read the file ourselves since AffectedFile.NewContents() 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # will normalize line endings. 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott contents = ReadFile(path) 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if '\r' in contents: 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cr_files.append(path) 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott local_errors = [] 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # Remove EOL character. 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lines = contents.splitlines() 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott line_num = 1 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for line in lines: 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if line.endswith(' '): 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott local_errors.append(output_api.PresubmitError( 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott '%s, line %s ends with whitespaces.' % 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (path, line_num))) 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # Accept lines with http:// to exceed the max_cols rule. 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if max_cols and len(line) > max_cols and not 'http://' in line: 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott local_errors.append(output_api.PresubmitError( 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott '%s, line %s has %s chars, please reduce to %d chars.' % 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (path, line_num, len(line), max_cols))) 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if '\t' in line: 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott local_errors.append(output_api.PresubmitError( 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "%s, line %s contains a tab character." % 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (path, line_num))) 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott line_num += 1 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott # Just show the first 5 errors. 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if len(local_errors) == 6: 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott local_errors.pop() 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott local_errors.append(output_api.PresubmitError("... and more.")) 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott results.extend(local_errors) 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if cr_files: 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott results.append(output_api.PresubmitError( 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 'Found CR (or CRLF) line ending in these files, please use only LF:', 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott items=cr_files)) 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return results 109