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