|  | #!/usr/bin/env python3 | 
|  | # 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 | 
|  | OUTDIR is the war directory to copy to | 
|  | INPUTS is a list of files or patterns used to specify the input | 
|  | .dart files | 
|  | This script should be run from the client root directory. | 
|  | Files will be merged and copied to: OUTDIR/relative-path-of-file, | 
|  | except for dart files with absolute paths, which will be copied to | 
|  | OUTDIR/absolute-path-as-directories""" % sys.argv[0]) | 
|  | 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: | 
|  | prefix = os.environ.get('DART_HTML_PREFIX') | 
|  | if prefix: | 
|  | f.write(prefix + '\n') | 
|  | 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:])) |