| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| 3 # for details. All rights reserved. Use of this source code is governed by a | |
| 4 # BSD-style license that can be found in the LICENSE file. | |
| 5 """Used to merge and copy dart source files for deployment to AppEngine""" | |
| 6 | |
| 7 import fileinput | |
| 8 import sys | |
| 9 import shutil | |
| 10 import os | |
| 11 import re | |
| 12 from os.path import abspath, basename, dirname, exists, isabs, join | |
| 13 from glob import glob | |
| 14 | |
| 15 re_directive = re.compile( | |
| 16 r'^#(library|import|source|native|resource)\([\'"]([^\'"]*)[\'"](.*)\);$') | |
| 17 | |
| 18 class Library(object): | |
| 19 def __init__(self, name, imports, sources, natives, code): | |
| 20 self.name = name | |
| 21 self.imports = imports | |
| 22 self.sources = sources | |
| 23 self.natives = natives | |
| 24 self.code = code | |
| 25 | |
| 26 def parseLibrary(library): | |
| 27 """ Parses a .dart source file that is the root of a library, and returns | |
| 28 information about it: the name, the imports, included sources, and any | |
| 29 code in the file. | |
| 30 """ | |
| 31 libraryname = None | |
| 32 imports = [] | |
| 33 sources = [] | |
| 34 natives = [] | |
| 35 inlinecode = [] | |
| 36 if exists(library): | |
| 37 # TODO(sigmund): stop parsing when import/source | |
| 38 for line in fileinput.input(library): | |
| 39 match = re_directive.match(line) | |
| 40 if match: | |
| 41 directive = match.group(1) | |
| 42 if directive == 'library': | |
| 43 assert libraryname is None | |
| 44 libraryname = match.group(2) | |
| 45 elif directive == 'source': | |
| 46 sources.append(match.group(2)) | |
| 47 elif directive == 'import': | |
| 48 imports.append((match.group(2), match.group(3))) | |
| 49 elif directive == 'native': | |
| 50 natives.append(match.group(2)) | |
| 51 elif directive == 'resource': | |
| 52 # currently ignored | |
| 53 pass | |
| 54 else: | |
| 55 raise 'unknown directive %s' % directive | |
| 56 else: | |
| 57 inlinecode.append(line) | |
| 58 fileinput.close() | |
| 59 return Library(libraryname, imports, sources, natives, inlinecode) | |
| 60 | |
| 61 def normjoin(*args): | |
| 62 return os.path.normpath(os.path.join(*args)) | |
| 63 | |
| 64 def mergefiles(srcs, dstfile): | |
| 65 for src in srcs: | |
| 66 with open(src, 'r') as s: | |
| 67 dstfile.write(s.read()) | |
| 68 | |
| 69 def copyfile(src, dst): | |
| 70 if not exists(dirname(dst)): | |
| 71 os.makedirs(dirname(dst)) | |
| 72 with open(src, 'r') as s: | |
| 73 with open(dst, 'w') as d: | |
| 74 d.write(s.read()) | |
| 75 | |
| 76 def main(outdir = None, *inputs): | |
| 77 if not outdir or not inputs: | |
| 78 print "Usage: %s OUTDIR INPUTS" % args[0] | |
| 79 print " OUTDIR is the war directory to copy to" | |
| 80 print " INPUTS is a list of files or patterns used to specify the input" | |
| 81 print " .dart files" | |
| 82 print "This script should be run from the client root directory." | |
| 83 print "Files will be merged and copied to: OUTDIR/relative-path-of-file," | |
| 84 print "except for dart files with absolute paths, which will be copied to" | |
| 85 print " OUTDIR/absolute-path-as-directories" | |
| 86 return 1 | |
| 87 | |
| 88 entry_libraries = [] | |
| 89 for i in inputs: | |
| 90 entry_libraries.extend(glob(i)) | |
| 91 | |
| 92 for entrypoint in entry_libraries: | |
| 93 # Get the transitive set of dart files this entrypoint depends on, merging | |
| 94 # each library along the way. | |
| 95 worklist = [os.path.normpath(entrypoint)] | |
| 96 seen = set() | |
| 97 while len(worklist) > 0: | |
| 98 lib = worklist.pop() | |
| 99 if lib in seen: | |
| 100 continue | |
| 101 | |
| 102 seen.add(lib) | |
| 103 | |
| 104 if lib.startswith('dart:'): | |
| 105 continue | |
| 106 | |
| 107 if (dirname(dirname(lib)).endswith('dom/generated/src') | |
| 108 or dirname(lib).endswith('dom/src')): | |
| 109 continue | |
| 110 | |
| 111 if lib.endswith('json/json.dart'): | |
| 112 # TODO(jmesserly): Dartium interprets "json.dart" as "dart_json.dart", | |
| 113 # so we need that add dart_json.dart here. This is hacky. | |
| 114 lib = lib.replace('json.dart', 'dart_json.dart') | |
| 115 | |
| 116 library = parseLibrary(lib) | |
| 117 | |
| 118 # Ensure output directory exists | |
| 119 outpath = join(outdir, lib[1:] if isabs(lib) else lib) | |
| 120 dstpath = dirname(outpath) | |
| 121 if not exists(dstpath): | |
| 122 os.makedirs(dstpath) | |
| 123 | |
| 124 | |
| 125 # Create file containing all imports, and inlining all sources | |
| 126 with open(outpath, 'w') as f: | |
| 127 if library.name: | |
| 128 f.write("#library('%s');\n\n" % library.name) | |
| 129 else: | |
| 130 f.write("#library('%s');\n\n" % basename(lib)) | |
| 131 for (importfile, optional_prefix) in library.imports: | |
| 132 f.write("#import('%s'%s);\n" % (importfile, optional_prefix)) | |
| 133 for native in library.natives: | |
| 134 if isabs(native): | |
| 135 npath = native[1:] | |
| 136 else: | |
| 137 npath = native | |
| 138 f.write("#native('%s');\n" % npath) | |
| 139 copyfile(normjoin(dirname(lib), native), | |
| 140 join(dirname(outpath), npath)) | |
| 141 f.write('%s' % (''.join(library.code))) | |
| 142 mergefiles([normjoin(dirname(lib), s) for s in library.sources], f) | |
| 143 | |
| 144 for (i, prefix) in library.imports: | |
| 145 if not i.startswith('dart:'): | |
| 146 worklist.append(normjoin(dirname(lib), i)); | |
| 147 | |
| 148 return 0 | |
| 149 | |
| 150 if __name__ == '__main__': | |
| 151 sys.exit(main(*sys.argv[1:])) | |
| OLD | NEW |