| #!/usr/bin/env python |
| # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| # for details. All rights reserved. Use of this source code is governed by a |
| # BSD-style license that can be found in the LICENSE file. |
| """Used to merge and copy dart source files for deployment to AppEngine""" |
| |
| import fileinput |
| import sys |
| import os |
| import re |
| from os.path import basename, dirname, exists, isabs, join |
| from glob import glob |
| |
| re_directive = re.compile( |
| r'^(library|import|part|native|resource)\s+(.*);$') |
| re_comment = re.compile( |
| r'^(///|/\*| \*).*$') |
| |
| class Library(object): |
| def __init__(self, name, imports, sources, natives, code, comment): |
| self.name = name |
| self.imports = imports |
| self.sources = sources |
| self.natives = natives |
| self.code = code |
| self.comment = comment |
| |
| def parseLibrary(library): |
| """ Parses a .dart source file that is the root of a library, and returns |
| information about it: the name, the imports, included sources, and any |
| code in the file. |
| """ |
| libraryname = None |
| imports = [] |
| sources = [] |
| natives = [] |
| inlinecode = [] |
| librarycomment = [] |
| if exists(library): |
| # TODO(sigmund): stop parsing when import/source |
| for line in fileinput.input(library): |
| match = re_directive.match(line) |
| if match: |
| directive = match.group(1) |
| if directive == 'library': |
| assert libraryname is None |
| libraryname = match.group(2) |
| elif directive == 'part': |
| suffix = match.group(2) |
| if not suffix.startswith('of '): |
| sources.append(match.group(2).strip('"\'')) |
| elif directive == 'import': |
| imports.append(match.group(2)) |
| else: |
| raise Exception('unknown directive %s in %s' % (directive, line)) |
| else: |
| # Check for library comment. |
| if not libraryname and re_comment.match(line): |
| librarycomment.append(line) |
| else: |
| inlinecode.append(line) |
| fileinput.close() |
| return Library(libraryname, imports, sources, natives, inlinecode, |
| librarycomment) |
| |
| def normjoin(*args): |
| return os.path.normpath(os.path.join(*args)) |
| |
| def mergefiles(srcs, dstfile): |
| for src in srcs: |
| with open(src, 'r') as s: |
| for line in s: |
| if not line.startswith('part of '): |
| dstfile.write(line) |
| |
| def main(outdir = None, *inputs): |
| if not outdir or not inputs: |
| print "Usage: %s OUTDIR INPUTS" % sys.argv[0] |
| print " OUTDIR is the war directory to copy to" |
| print " INPUTS is a list of files or patterns used to specify the input" |
| print " .dart files" |
| print "This script should be run from the client root directory." |
| print "Files will be merged and copied to: OUTDIR/relative-path-of-file," |
| print "except for dart files with absolute paths, which will be copied to" |
| print " OUTDIR/absolute-path-as-directories" |
| return 1 |
| |
| entry_libraries = [] |
| for i in inputs: |
| entry_libraries.extend(glob(i)) |
| |
| for entrypoint in entry_libraries: |
| # Get the transitive set of dart files this entrypoint depends on, merging |
| # each library along the way. |
| worklist = [os.path.normpath(entrypoint)] |
| seen = set() |
| while len(worklist) > 0: |
| lib = worklist.pop() |
| if lib in seen: |
| continue |
| |
| seen.add(lib) |
| |
| if (dirname(dirname(lib)).endswith('dom/generated/src') |
| or dirname(lib).endswith('dom/src')): |
| continue |
| |
| library = parseLibrary(lib) |
| |
| # Ensure output directory exists |
| outpath = join(outdir, lib[1:] if isabs(lib) else lib) |
| dstpath = dirname(outpath) |
| if not exists(dstpath): |
| os.makedirs(dstpath) |
| |
| |
| # Create file containing all imports, and inlining all sources |
| with open(outpath, 'w') as f: |
| if library.name: |
| if library.comment: |
| f.write('%s' % (''.join(library.comment))) |
| f.write("library %s;\n\n" % library.name) |
| else: |
| f.write("library %s;\n\n" % basename(lib)) |
| for importfile in library.imports: |
| f.write("import %s;\n" % importfile) |
| f.write('%s' % (''.join(library.code))) |
| mergefiles([normjoin(dirname(lib), s) for s in library.sources], f) |
| |
| for suffix in library.imports: |
| m = re.match(r'[\'"]([^\'"]+)[\'"](\s+as\s+\w+)?.*$', suffix) |
| uri = m.group(1) |
| if not uri.startswith('dart:'): |
| worklist.append(normjoin(dirname(lib), uri)) |
| |
| return 0 |
| |
| if __name__ == '__main__': |
| sys.exit(main(*sys.argv[1:])) |