Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: chrome/common/extensions/PRESUBMIT.py

Issue 10885049: Extensions Docs Server: KILL BUILD.PY (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: better Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/common/extensions/PRESUBMIT_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 import os.path # for initializing constants
6
7 # Directories that we run presubmit checks on.
8 PRESUBMIT_PATH = os.path.normpath('chrome/common/extensions/PRESUBMIT.py')
9 API_DIR = os.path.normpath('chrome/common/extensions/api')
10 DOC_DIR = os.path.normpath('chrome/common/extensions/docs')
11 BUILD_DIR = os.path.join(DOC_DIR, 'build')
12 TEMPLATE_DIR = os.path.join(DOC_DIR, 'template')
13 JS_DIR = os.path.join(DOC_DIR, 'js')
14 CSS_DIR = os.path.join(DOC_DIR, 'css')
15 STATIC_DIR = os.path.join(DOC_DIR, 'static')
16 SAMPLES_DIR = os.path.join(DOC_DIR, 'examples')
17 APPS_DIR = os.path.join(DOC_DIR, 'apps')
18 EXTENSIONS_DIR = os.path.join(DOC_DIR, 'extensions')
19
20 EXCEPTIONS = ['README', 'README.txt', 'OWNERS']
21
22 # Presubmit messages.
23 README = os.path.join(DOC_DIR, 'README.txt')
24 REBUILD_WARNING = (
25 'This change modifies the extension docs but the generated docs have '
26 'not been updated properly. See %s for more info.' % README)
27 BUILD_SCRIPT = os.path.join(BUILD_DIR, 'build.py')
28 REBUILD_INSTRUCTIONS = (
29 'First build DumpRenderTree, then update the docs by running:\n %s'
30 ' --page-name=<apiName>' %
31 BUILD_SCRIPT)
32
33
34 def CheckChangeOnUpload(input_api, output_api):
35 return (CheckPresubmitChanges(input_api, output_api) +
36 CheckDocChanges(input_api, output_api))
37
38 def CheckChangeOnCommit(input_api, output_api):
39 return (CheckPresubmitChanges(input_api, output_api) +
40 CheckDocChanges(input_api, output_api, strict=False))
41
42 def CheckPresubmitChanges(input_api, output_api):
43 for PRESUBMIT_PATH in input_api.LocalPaths():
44 return input_api.canned_checks.RunUnitTests(input_api, output_api,
45 ['./PRESUBMIT_test.py'])
46 return []
47
48 def CheckDocChanges(input_api, output_api, strict=True):
49 warnings = []
50
51 for af in input_api.AffectedFiles():
52 path = af.LocalPath()
53 if IsSkippedFile(path, input_api):
54 continue
55
56 elif (IsApiFile(path, input_api) or
57 IsBuildFile(path, input_api) or
58 IsTemplateFile(path, input_api) or
59 IsJsFile(path, input_api) or
60 IsCssFile(path, input_api)):
61 # These files do not always cause changes to the generated docs
62 # so we can ignore them if not running strict checks.
63 if strict and not DocsGenerated(input_api):
64 warnings.append('Docs out of sync with %s changes.' % path)
65
66 elif IsStaticDoc(path, input_api):
67 if not StaticDocBuilt(af, input_api):
68 warnings.append('Changes to %s not reflected in generated doc.' % path)
69
70 elif IsSampleFile(path, input_api):
71 if not SampleZipped(af, input_api):
72 warnings.append('Changes to sample %s have not been re-zipped.' % path)
73
74 elif IsGeneratedDoc(path, input_api):
75 if not NonGeneratedFilesEdited(input_api):
76 warnings.append('Changes to generated doc %s not reflected in '
77 'non-generated files.' % path)
78
79 if warnings:
80 warnings.sort()
81 warnings = [' - %s\n' % w for w in warnings]
82 # Prompt user if they want to continue.
83 return [output_api.PresubmitPromptWarning(REBUILD_WARNING + '\n' +
84 ''.join(warnings) +
85 REBUILD_INSTRUCTIONS)]
86 return []
87
88 def IsSkippedFile(path, input_api):
89 return input_api.os_path.basename(path) in EXCEPTIONS
90
91 def IsApiFile(path, input_api):
92 return (input_api.os_path.dirname(path) == API_DIR and
93 (path.endswith('.json') or path.endswith('.idl')))
94
95 def IsBuildFile(path, input_api):
96 return input_api.os_path.dirname(path) == BUILD_DIR
97
98 def IsTemplateFile(path, input_api):
99 return input_api.os_path.dirname(path) == TEMPLATE_DIR
100
101 def IsJsFile(path, input_api):
102 return (input_api.os_path.dirname(path) == JS_DIR and
103 path.endswith('.js'))
104
105 def IsCssFile(path, input_api):
106 return (input_api.os_path.dirname(path) == CSS_DIR and
107 path.endswith('.css'))
108
109 def IsStaticDoc(path, input_api):
110 return (input_api.os_path.dirname(path) == STATIC_DIR and
111 path.endswith('.html'))
112
113 def IsSampleFile(path, input_api):
114 return input_api.os_path.dirname(path).startswith(SAMPLES_DIR)
115
116 def IsGeneratedDoc(path, input_api):
117 return (input_api.os_path.dirname(path) in [APPS_DIR, EXTENSIONS_DIR] and
118 path.endswith('.html'))
119
120 def DocsGenerated(input_api):
121 """Return True if there are any generated docs in this change.
122
123 Generated docs are the files that are the output of build.py. Typically
124 all docs changes will contain both generated docs and non-generated files.
125 """
126 return any(IsGeneratedDoc(path, input_api)
127 for path in input_api.LocalPaths())
128
129 def NonGeneratedFilesEdited(input_api):
130 """Return True if there are any non-generated files in this change.
131
132 Non-generated files are those that are the input to build.py. Typically
133 all docs changes will contain both non-generated files and generated docs.
134 """
135 return any(IsApiFile(path, input_api) or
136 IsBuildFile(path, input_api) or
137 IsTemplateFile(path, input_api) or
138 IsJsFile(path, input_api) or
139 IsCssFile(path, input_api) or
140 IsStaticDoc(path, input_api) or
141 IsSampleFile(path, input_api)
142 for path in input_api.LocalPaths())
143
144 def StaticDocBuilt(static_file, input_api):
145 """Return True if the generated doc that corresponds to the |static_file|
146 is also in this change. Both files must also contain matching changes.
147 """
148 for subdir in [APPS_DIR, EXTENSIONS_DIR]:
149 generated_file = _FindFileInAlternateDir(static_file, subdir, input_api)
150 if _ChangesMatch(generated_file, static_file):
151 return True
152 return False
153
154 def _FindFileInAlternateDir(affected_file, alt_dir, input_api):
155 """Return an AffectFile for the file in |alt_dir| that corresponds to
156 |affected_file|.
157
158 If the file does not exist in the is change, return None.
159 """
160 alt_path = _AlternateFilePath(affected_file.LocalPath(), alt_dir, input_api)
161 for f in input_api.AffectedFiles():
162 if f.LocalPath() == alt_path:
163 return f
164
165 def _AlternateFilePath(path, alt_dir, input_api):
166 """Return a path with the same basename as |path| but in |alt_dir| directory.
167
168 This is useful for finding corresponding static and generated docs.
169
170 Example:
171 _AlternateFilePath('/foo/bar', '/alt/dir', ...) == '/alt/dir/bar')
172 """
173 base_name = input_api.os_path.basename(path)
174 return input_api.os_path.join(alt_dir, base_name)
175
176 def _ChangesMatch(generated_file, static_file):
177 """Return True if the two files contain the same textual changes.
178
179 There may be extra generated lines and generated lines are still considered
180 to "match" static ones even if they have extra formatting/text at their
181 beginnings and ends.
182 Line numbers may differ but order may not.
183 """
184 if not generated_file and not static_file:
185 return True # Neither file affected.
186
187 if not generated_file or not static_file:
188 return False # One file missing.
189
190 generated_changes = generated_file.ChangedContents()
191 static_changes = static_file.ChangedContents()
192 # ChangedContents() is a list of (line number, text) for all new lines.
193 # Ignore the line number, but check that the text for each new line matches.
194
195 next_generated = 0
196 start_pos = 0
197 for next_static in range(len(static_changes)):
198 _, static_text = static_changes[next_static]
199
200 # Search generated changes for this static text.
201 found = False
202 while not found and next_generated < len(generated_changes):
203 _, generated_text = generated_changes[next_generated]
204 # Text need not be identical but the entire static line should be
205 # in the generated one (e.g. generated text might have extra formatting).
206 found_at = generated_text[start_pos:].find(static_text)
207 if found_at != -1:
208 # Next search starts on the same line, after the substring matched.
209 start_pos = found_at + len(static_text)
210 found = True
211 else:
212 next_generated += 1
213 start_pos = 0
214
215 if not found:
216 return False
217
218 return True
219
220 def SampleZipped(sample_file, input_api):
221 """Return True if the zipfile that should contain |sample_file| is in
222 this change.
223 """
224 sample_path = sample_file.LocalPath()
225 for af in input_api.AffectedFiles():
226 root, ext = input_api.os_path.splitext(af.LocalPath())
227 if ext == '.zip' and sample_path.startswith(root):
228 return True
229 return False
OLDNEW
« no previous file with comments | « no previous file | chrome/common/extensions/PRESUBMIT_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698