PRESUBMIT.py revision 5821806d5e7f356e8fa4b058a389a808ea183019
1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Presubmit script for changes affecting extensions. 6 7See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts 8for more details about the presubmit API built into gcl. 9""" 10import fnmatch 11import os 12import re 13 14EXTENSIONS_PATH = os.path.join('chrome', 'common', 'extensions') 15DOCS_PATH = os.path.join(EXTENSIONS_PATH, 'docs') 16SERVER2_PATH = os.path.join(DOCS_PATH, 'server2') 17API_PATH = os.path.join(EXTENSIONS_PATH, 'api') 18TEMPLATES_PATH = os.path.join(DOCS_PATH, 'templates') 19PRIVATE_TEMPLATES_PATH = os.path.join(TEMPLATES_PATH, 'private') 20PUBLIC_TEMPLATES_PATH = os.path.join(TEMPLATES_PATH, 'public') 21INTROS_PATH = os.path.join(TEMPLATES_PATH, 'intros') 22ARTICLES_PATH = os.path.join(TEMPLATES_PATH, 'articles') 23 24LOCAL_PUBLIC_TEMPLATES_PATH = os.path.join('docs', 25 'templates', 26 'public') 27 28def _ListFilesInPublic(): 29 all_files = [] 30 for path, dirs, files in os.walk(LOCAL_PUBLIC_TEMPLATES_PATH): 31 all_files.extend( 32 os.path.join(path, filename)[len(LOCAL_PUBLIC_TEMPLATES_PATH + os.sep):] 33 for filename in files) 34 return all_files 35 36def _UnixName(name): 37 name = os.path.splitext(name)[0] 38 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name) 39 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) 40 return s2.replace('.', '_').lower() 41 42def _FindMatchingTemplates(template_name, template_path_list): 43 matches = [] 44 unix_name = _UnixName(template_name) 45 for template in template_path_list: 46 if unix_name == _UnixName(template.split(os.sep)[-1]): 47 matches.append(template) 48 return matches 49 50def _SanitizeAPIName(name, api_path): 51 if not api_path.endswith(os.sep): 52 api_path += os.sep 53 filename = os.path.splitext(name)[0][len(api_path):].replace(os.sep, '_') 54 if 'experimental' in filename: 55 filename = 'experimental_' + filename.replace('experimental_', '') 56 return filename 57 58def _CreateIntegrationTestArgs(affected_files): 59 if (any(fnmatch.fnmatch(name, '%s*.py' % SERVER2_PATH) 60 for name in affected_files) or 61 any(fnmatch.fnmatch(name, '%s*' % PRIVATE_TEMPLATES_PATH) 62 for name in affected_files)): 63 return ['-a'] 64 args = [] 65 for name in affected_files: 66 if (fnmatch.fnmatch(name, '%s*' % PUBLIC_TEMPLATES_PATH) or 67 fnmatch.fnmatch(name, '%s*' % INTROS_PATH) or 68 fnmatch.fnmatch(name, '%s*' % ARTICLES_PATH)): 69 args.extend(_FindMatchingTemplates(name.split(os.sep)[-1], 70 _ListFilesInPublic())) 71 if fnmatch.fnmatch(name, '%s*' % API_PATH): 72 args.extend(_FindMatchingTemplates(_SanitizeAPIName(name, API_PATH), 73 _ListFilesInPublic())) 74 return args 75 76def _CheckHeadingIDs(input_api): 77 ids_re = re.compile('<h[23].*id=.*?>') 78 headings_re = re.compile('<h[23].*?>') 79 bad_files = [] 80 for name in input_api.AbsoluteLocalPaths(): 81 if (fnmatch.fnmatch(name, '*%s*' % INTROS_PATH) or 82 fnmatch.fnmatch(name, '*%s*' % ARTICLES_PATH)): 83 contents = input_api.ReadFile(name) 84 if (len(re.findall(headings_re, contents)) != 85 len(re.findall(ids_re, contents))): 86 bad_files.append(name) 87 return bad_files 88 89def _CheckVersions(input_api, output_api, results): 90 version = '_VERSION =' 91 for affected_file in input_api.AffectedFiles(): 92 local_path = affected_file.LocalPath() 93 if not fnmatch.fnmatch(local_path, '%s*' % SERVER2_PATH): 94 continue 95 if local_path.endswith('PRESUBMIT.py'): 96 continue 97 if any(version in line for line in affected_file.NewContents()): 98 found = False 99 for _, text in affected_file.ChangedContents(): 100 if version in text: 101 found = True 102 break 103 if not found: 104 results.append(output_api.PresubmitError( 105 '_VERSION of %s needs to be incremented.' % affected_file)) 106 107def _CheckChange(input_api, output_api): 108 results = [ 109 output_api.PresubmitError('File %s needs an id for each heading.' % name) 110 for name in _CheckHeadingIDs(input_api)] 111 try: 112 integration_test = [] 113 # From depot_tools/presubmit_canned_checks.py:529 114 if input_api.platform == 'win32': 115 integration_test = [input_api.python_executable] 116 integration_test.append( 117 os.path.join('docs', 'server2', 'integration_test.py')) 118 integration_test.extend(_CreateIntegrationTestArgs(input_api.LocalPaths())) 119 input_api.subprocess.check_call(integration_test, 120 cwd=input_api.PresubmitLocalPath()) 121 except input_api.subprocess.CalledProcessError: 122 results.append(output_api.PresubmitError('IntegrationTest failed!')) 123 _CheckVersions(input_api, output_api, results) 124 return results 125 126def CheckChangeOnUpload(input_api, output_api): 127 return _CheckChange(input_api, output_api) 128 129def CheckChangeOnCommit(input_api, output_api): 130 return _CheckChange(input_api, output_api) 131