Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / chrome / common / extensions / PRESUBMIT.py
blobbcfba68e3f109b9859cfaaa594bf67bc11477505
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.
5 """Presubmit script for changes affecting extensions.
7 See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
8 for more details about the presubmit API built into depot_tools.
9 """
10 import fnmatch
11 import os
12 import re
14 EXTENSIONS_PATH = os.path.join('chrome', 'common', 'extensions')
15 DOCS_PATH = os.path.join(EXTENSIONS_PATH, 'docs')
16 SERVER2_PATH = os.path.join(DOCS_PATH, 'server2')
17 API_PATH = os.path.join(EXTENSIONS_PATH, 'api')
18 TEMPLATES_PATH = os.path.join(DOCS_PATH, 'templates')
19 PRIVATE_TEMPLATES_PATH = os.path.join(TEMPLATES_PATH, 'private')
20 PUBLIC_TEMPLATES_PATH = os.path.join(TEMPLATES_PATH, 'public')
21 INTROS_PATH = os.path.join(TEMPLATES_PATH, 'intros')
22 ARTICLES_PATH = os.path.join(TEMPLATES_PATH, 'articles')
24 LOCAL_PUBLIC_TEMPLATES_PATH = os.path.join('docs',
25 'templates',
26 'public')
28 EXTENSIONS_TO_REMOVE_FOR_CLEAN_URLS = ('.md', '.html')
30 def _ReadFile(filename):
31 with open(filename) as f:
32 return f.read()
34 def _ListFilesInPublic():
35 all_files = []
36 for path, dirs, files in os.walk(LOCAL_PUBLIC_TEMPLATES_PATH):
37 all_files.extend(
38 os.path.join(path, filename)[len(LOCAL_PUBLIC_TEMPLATES_PATH + os.sep):]
39 for filename in files)
40 return all_files
42 def _UnixName(name):
43 name = os.path.splitext(name)[0]
44 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name)
45 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1)
46 return s2.replace('.', '_').lower()
48 def _FindMatchingTemplates(template_name, template_path_list):
49 matches = []
50 unix_name = _UnixName(template_name)
51 for template in template_path_list:
52 if unix_name == _UnixName(template.split(os.sep)[-1]):
53 basename, ext = os.path.splitext(template)
54 # The docserver expects clean (extensionless) template URLs, so we
55 # strip some extensions here when generating the list of matches.
56 if ext in EXTENSIONS_TO_REMOVE_FOR_CLEAN_URLS:
57 matches.append(basename)
58 else:
59 matches.append(template)
60 return matches
62 def _SanitizeAPIName(name, api_path):
63 if not api_path.endswith(os.sep):
64 api_path += os.sep
65 filename = os.path.splitext(name)[0][len(api_path):].replace(os.sep, '_')
66 if 'experimental' in filename:
67 filename = 'experimental_' + filename.replace('experimental_', '')
68 return filename
70 def _CreateIntegrationTestArgs(affected_files):
71 if (any(fnmatch.fnmatch(name, '%s*.py' % SERVER2_PATH)
72 for name in affected_files) or
73 any(fnmatch.fnmatch(name, '%s*' % PRIVATE_TEMPLATES_PATH)
74 for name in affected_files)):
75 return ['-a']
76 args = []
77 for name in affected_files:
78 if (fnmatch.fnmatch(name, '%s*' % PUBLIC_TEMPLATES_PATH) or
79 fnmatch.fnmatch(name, '%s*' % INTROS_PATH) or
80 fnmatch.fnmatch(name, '%s*' % ARTICLES_PATH)):
81 args.extend(_FindMatchingTemplates(name.split(os.sep)[-1],
82 _ListFilesInPublic()))
83 if fnmatch.fnmatch(name, '%s*' % API_PATH):
84 args.extend(_FindMatchingTemplates(_SanitizeAPIName(name, API_PATH),
85 _ListFilesInPublic()))
86 return args
88 def _CheckHeadingIDs(input_api):
89 ids_re = re.compile('<h[23].*id=.*?>')
90 headings_re = re.compile('<h[23].*?>')
91 bad_files = []
92 for name in input_api.AbsoluteLocalPaths():
93 if not os.path.exists(name):
94 continue
95 if (fnmatch.fnmatch(name, '*%s*' % INTROS_PATH) or
96 fnmatch.fnmatch(name, '*%s*' % ARTICLES_PATH)):
97 contents = input_api.ReadFile(name)
98 if (len(re.findall(headings_re, contents)) !=
99 len(re.findall(ids_re, contents))):
100 bad_files.append(name)
101 return bad_files
103 def _CheckLinks(input_api, output_api, results):
104 for affected_file in input_api.AffectedFiles():
105 name = affected_file.LocalPath()
106 absolute_path = affected_file.AbsoluteLocalPath()
107 if not os.path.exists(absolute_path):
108 continue
109 if (fnmatch.fnmatch(name, '%s*' % PUBLIC_TEMPLATES_PATH) or
110 fnmatch.fnmatch(name, '%s*' % INTROS_PATH) or
111 fnmatch.fnmatch(name, '%s*' % ARTICLES_PATH) or
112 fnmatch.fnmatch(name, '%s*' % API_PATH)):
113 contents = _ReadFile(absolute_path)
114 args = []
115 if input_api.platform == 'win32':
116 args = [input_api.python_executable]
117 args.extend([os.path.join('docs', 'server2', 'link_converter.py'),
118 '-o',
119 '-f',
120 absolute_path])
121 output = input_api.subprocess.check_output(
122 args,
123 cwd=input_api.PresubmitLocalPath(),
124 universal_newlines=True)
125 if output != contents:
126 changes = ''
127 for i, (line1, line2) in enumerate(
128 zip(contents.split('\n'), output.split('\n'))):
129 if line1 != line2:
130 changes = ('%s\nLine %d:\n-%s\n+%s\n' %
131 (changes, i + 1, line1, line2))
132 if changes:
133 results.append(output_api.PresubmitPromptWarning(
134 'File %s may have an old-style <a> link to an API page. Please '
135 'run docs/server2/link_converter.py to convert the link[s], or '
136 'convert them manually.\n\nSuggested changes are: %s' %
137 (name, changes)))
139 def _CheckChange(input_api, output_api):
140 results = [
141 output_api.PresubmitError('File %s needs an id for each heading.' % name)
142 for name in _CheckHeadingIDs(input_api)]
143 try:
144 integration_test = []
145 # From depot_tools/presubmit_canned_checks.py:529
146 if input_api.platform == 'win32':
147 integration_test = [input_api.python_executable]
148 integration_test.append(
149 os.path.join('docs', 'server2', 'integration_test.py'))
150 integration_test.extend(_CreateIntegrationTestArgs(input_api.LocalPaths()))
151 input_api.subprocess.check_call(integration_test,
152 cwd=input_api.PresubmitLocalPath())
153 except input_api.subprocess.CalledProcessError:
154 results.append(output_api.PresubmitError('IntegrationTest failed!'))
156 # TODO(kalman): Re-enable this check, or decide to delete it forever. Now
157 # that we have multiple directories it no longer works.
158 # See http://crbug.com/297178.
159 #_CheckLinks(input_api, output_api, results)
161 return results
163 def CheckChangeOnUpload(input_api, output_api):
164 results = []
165 results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
166 results += _CheckChange(input_api, output_api)
167 return results
169 def CheckChangeOnCommit(input_api, output_api):
170 return _CheckChange(input_api, output_api)