Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 | 2 |
| 3 # Copyright 2014 The Chromium Authors. All rights reserved. | 3 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 '''Produces various output formats from a set of JavaScript files with | 7 '''Produces various output formats from a set of JavaScript files with |
| 8 closure style require/provide calls. | 8 closure style require/provide calls. |
| 9 | 9 |
| 10 Scans one or more directory trees for JavaScript files. Then, from a | 10 Scans one or more directory trees for JavaScript files. Then, from a |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 - compressed_bundle: A bundle where non-significant whitespace, including | 25 - compressed_bundle: A bundle where non-significant whitespace, including |
| 26 comments, has been stripped is output. | 26 comments, has been stripped is output. |
| 27 | 27 |
| 28 - copy: the files are copied, or hard linked if possible, to the destination | 28 - copy: the files are copied, or hard linked if possible, to the destination |
| 29 directory. In this case, no output is generated. | 29 directory. In this case, no output is generated. |
| 30 ''' | 30 ''' |
| 31 | 31 |
| 32 | 32 |
| 33 import optparse | 33 import optparse |
| 34 import os | 34 import os |
| 35 import re | |
| 35 import shutil | 36 import shutil |
| 36 import sys | 37 import sys |
| 37 | 38 |
| 38 _SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__)) | 39 _SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__)) |
| 39 _CHROME_SOURCE = os.path.realpath( | 40 _CHROME_SOURCE = os.path.realpath( |
| 40 os.path.join(_SCRIPT_DIR, *[os.path.pardir] * 6)) | 41 os.path.join(_SCRIPT_DIR, *[os.path.pardir] * 6)) |
| 41 sys.path.insert(0, os.path.join( | 42 sys.path.insert(0, os.path.join( |
| 42 _CHROME_SOURCE, 'third_party/WebKit/Source/build/scripts')) | 43 _CHROME_SOURCE, 'third_party/WebKit/Source/build/scripts')) |
| 43 sys.path.insert(0, os.path.join( | 44 sys.path.insert(0, os.path.join( |
| 44 _CHROME_SOURCE, ('chrome/third_party/chromevox/third_party/' + | 45 _CHROME_SOURCE, ('chrome/third_party/chromevox/third_party/' + |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 for path in source_files: | 165 for path in source_files: |
| 165 if need_source_text: | 166 if need_source_text: |
| 166 EnsureSourceLoaded(path, sources) | 167 EnsureSourceLoaded(path, sources) |
| 167 else: | 168 else: |
| 168 # Just add an empty representation of the source. | 169 # Just add an empty representation of the source. |
| 169 sources[path] = SourceWithPaths( | 170 sources[path] = SourceWithPaths( |
| 170 '', path, path_rewriter.RewritePath(path)) | 171 '', path, path_rewriter.RewritePath(path)) |
| 171 return sources | 172 return sources |
| 172 | 173 |
| 173 | 174 |
| 175 def _GetBase(sources): | |
| 176 '''Gets the closure base.js file if present among the sources. | |
| 177 | |
| 178 Args: | |
| 179 sources, dict: Dictionary with SourceWithPath objects as values. | |
| 180 Returns: | |
|
David Tseng
2014/06/12 20:23:29
'sources, dict' looks like a pair so perhaps remov
| |
| 181 SourceWithPath: The source file providing the goog namespace. | |
| 182 ''' | |
| 183 for source in sources.itervalues(): | |
| 184 if (os.path.basename(source.GetInPath()) == 'base.js' and | |
| 185 'goog' in source.provides): | |
| 186 return source | |
| 187 Die('goog.base not provided by any file.') | |
| 188 | |
| 189 | |
| 174 def CalcDeps(bundle, sources, top_level): | 190 def CalcDeps(bundle, sources, top_level): |
| 175 '''Calculates dependencies for a set of top-level files. | 191 '''Calculates dependencies for a set of top-level files. |
| 176 | 192 |
| 177 Args: | 193 Args: |
| 178 bundle: Bundle to add the sources to. | 194 bundle: Bundle to add the sources to. |
| 179 sources, dict: Mapping from input path to SourceWithPaths objects. | 195 sources, dict: Mapping from input path to SourceWithPaths objects. |
| 180 top_level, list: List of top-level input paths to calculate dependencies | 196 top_level, list: List of top-level input paths to calculate dependencies |
| 181 for. | 197 for. |
| 182 ''' | 198 ''' |
| 183 def GetBase(sources): | |
| 184 for source in sources.itervalues(): | |
| 185 if (os.path.basename(source.GetInPath()) == 'base.js' and | |
| 186 'goog' in source.provides): | |
| 187 return source | |
| 188 Die('goog.base not provided by any file') | |
| 189 | |
| 190 providers = [s for s in sources.itervalues() if len(s.provides) > 0] | 199 providers = [s for s in sources.itervalues() if len(s.provides) > 0] |
| 191 deps = depstree.DepsTree(providers) | 200 deps = depstree.DepsTree(providers) |
| 192 namespaces = [] | 201 namespaces = [] |
| 193 for path in top_level: | 202 for path in top_level: |
| 194 namespaces.extend(sources[path].requires) | 203 namespaces.extend(sources[path].requires) |
| 195 # base.js is an implicit dependency that always goes first. | 204 # base.js is an implicit dependency that always goes first. |
| 196 bundle.Add(GetBase(sources)) | 205 bundle.Add(_GetBase(sources)) |
| 197 bundle.Add(deps.GetDependencies(namespaces)) | 206 bundle.Add(deps.GetDependencies(namespaces)) |
| 198 | 207 |
| 199 | 208 |
| 209 def _MarkAsCompiled(sources): | |
| 210 '''Sets COMPILED to true in the Closure base.js source.''' | |
|
David Tseng
2014/06/12 20:23:29
nit: Args?
| |
| 211 base = _GetBase(sources) | |
| 212 new_content, count = re.subn('^var COMPILED = false;$', | |
| 213 'var COMPILED = true;', | |
| 214 base.GetSource(), | |
| 215 count=1, | |
| 216 flags=re.MULTILINE) | |
| 217 if count != 1: | |
| 218 Die('COMPILED var assignment not found in %s' % base.GetInPath()) | |
|
David Tseng
2014/06/12 20:23:29
Print the count since technically it could be > 1
| |
| 219 sources[base.GetInPath()] = SourceWithPaths( | |
| 220 new_content, | |
| 221 base.GetInPath(), | |
| 222 base.GetOutPath()) | |
| 223 | |
| 200 def LinkOrCopyFiles(sources, dest_dir): | 224 def LinkOrCopyFiles(sources, dest_dir): |
| 201 '''Copies a list of sources to a destination directory.''' | 225 '''Copies a list of sources to a destination directory.''' |
| 202 | 226 |
| 203 def LinkOrCopyOneFile(src, dst): | 227 def LinkOrCopyOneFile(src, dst): |
| 204 if not os.path.exists(os.path.dirname(dst)): | 228 if not os.path.exists(os.path.dirname(dst)): |
| 205 os.makedirs(os.path.dirname(dst)) | 229 os.makedirs(os.path.dirname(dst)) |
| 206 if os.path.exists(dst): | 230 if os.path.exists(dst): |
| 207 # Avoid clobbering the inode if source and destination refer to the | 231 # Avoid clobbering the inode if source and destination refer to the |
| 208 # same file already. | 232 # same file already. |
| 209 if os.path.samefile(src, dst): | 233 if os.path.samefile(src, dst): |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 271 default='list', metavar='MODE', | 295 default='list', metavar='MODE', |
| 272 help=("Otput mode. One of 'list', 'html', 'bundle', " + | 296 help=("Otput mode. One of 'list', 'html', 'bundle', " + |
| 273 "'compressed_bundle' or 'copy'.")) | 297 "'compressed_bundle' or 'copy'.")) |
| 274 return parser | 298 return parser |
| 275 | 299 |
| 276 | 300 |
| 277 def main(): | 301 def main(): |
| 278 options, args = CreateOptionParser().parse_args() | 302 options, args = CreateOptionParser().parse_args() |
| 279 if len(args) < 1: | 303 if len(args) < 1: |
| 280 Die('At least one top-level source file must be specified.') | 304 Die('At least one top-level source file must be specified.') |
| 305 output_bundle = options.mode in ('bundle', 'compressed_bundle') | |
| 281 path_rewriter = PathRewriter(options.prefix_map) | 306 path_rewriter = PathRewriter(options.prefix_map) |
|
David Tseng
2014/06/12 20:23:29
Maybe call this need_source_text?
| |
| 282 sources = ReadSources(options.roots, | 307 sources = ReadSources(options.roots, args, output_bundle, path_rewriter) |
| 283 args, | 308 if output_bundle: |
| 284 options.mode in ('bundle', 'compressed_bundle'), | 309 _MarkAsCompiled(sources) |
| 285 path_rewriter) | |
| 286 bundle = Bundle() | 310 bundle = Bundle() |
| 287 if len(options.roots) > 0: | 311 if len(options.roots) > 0: |
| 288 CalcDeps(bundle, sources, args) | 312 CalcDeps(bundle, sources, args) |
| 289 bundle.Add((sources[name] for name in args)) | 313 bundle.Add((sources[name] for name in args)) |
| 290 if options.mode == 'copy': | 314 if options.mode == 'copy': |
| 291 if options.dest_dir is None: | 315 if options.dest_dir is None: |
| 292 Die('Must specify --dest_dir when copying.') | 316 Die('Must specify --dest_dir when copying.') |
| 293 LinkOrCopyFiles(bundle.GetSources(), options.dest_dir) | 317 LinkOrCopyFiles(bundle.GetSources(), options.dest_dir) |
| 294 else: | 318 else: |
| 295 if options.output_file: | 319 if options.output_file: |
| 296 out_file = open(options.output_file, 'w') | 320 out_file = open(options.output_file, 'w') |
| 297 else: | 321 else: |
| 298 out_file = sys.stdout | 322 out_file = sys.stdout |
| 299 try: | 323 try: |
| 300 WriteOutput(bundle, options.mode, out_file, options.dest_dir) | 324 WriteOutput(bundle, options.mode, out_file, options.dest_dir) |
| 301 finally: | 325 finally: |
| 302 if options.output_file: | 326 if options.output_file: |
| 303 out_file.close() | 327 out_file.close() |
| 304 | 328 |
| 305 | 329 |
| 306 if __name__ == '__main__': | 330 if __name__ == '__main__': |
| 307 main() | 331 main() |
| OLD | NEW |