def _calculate_deps(js_entrypoint_file_path): js_sources = set() source_files = set() logging.info("Scanning paths for Javascript files...") for js_path in loader.locate("*.js"): if not js_path.startswith(coverage.INSTRUMENTED_CODE_PATH): source_files.add(js_path) for js_path in source_files: js_sources.add(closurebuilder._PathSource(js_path)) logging.info("Done") logging.info("Building dependency tree..") tree = depstree.DepsTree(js_sources) # find the namespace of entrypoint entrypoint_source = closurebuilder._PathSource(js_entrypoint_file_path) if entrypoint_source.provides: namespace = entrypoint_source.provides else: namespace = entrypoint_source.requires # namespace = [closurebuilder._PathSource(js_entrypoint_file_path).provides.pop()] # The Closure Library base file must go first. base = closurebuilder._GetClosureBaseFile(js_sources) deps = [base] + tree.GetDependencies(namespace) logging.info("Done") return deps
def __init__(self, buildout, name, options): self.buildout = buildout self.name = name self.options = options self.dependency = options["dependency"] self.compiler_jar = options.get("jar", DEFAULT_COMPILER_JAR) self.compiler_flags = [ flag for flag in options.get("flags", "").split() if flag ] self.extra_js = [ js for js in self.options.get("extra_js", "").split() if js] self.outputdir = self.options["output"] path_to_source = self.buildout[self.dependency].recipe.path_to_source sources = path_to_source.values() tree = DepsTree(sources) base = closurebuilder._GetClosureBaseFile(sources) start_wd = os.getcwd() input_namespaces = set() for input_path in self.options.get("inputs", "").split(): if not input_path: continue js_input = [ source for source in sources if source.GetPath() == os.path.join(start_wd, input_path) ] if len(js_input) != 1: # logging.error('No source matched input %s', input_path) raise Exception("No source matched input %s" % input_path) input_namespaces.update(js_input[0].provides) input_namespaces.update( [namespace for namespace in self.options.get("namespaces", "").split() if namespace] ) if not input_namespaces: raise Exception( "No namespaces found. At least one namespace must be " "specified with the --namespace or --input flags.") deps = [base] + tree.GetDependencies(input_namespaces) deps_sources = self.extra_js + \ [js_source.GetSourcePath()[1] for js_source in deps] self.compiled_code = jscompiler.Compile( self.compiler_jar, deps_sources, self.compiler_flags) md5name = hashlib.md5() md5name.update(self.compiled_code) self.options["filename"] = self.filename = md5name.hexdigest() + ".js"
def build_minified(self): from distutils import log import closurebuilder import treescan import depstree log.info('Building minified script "%s", mode: %s', self.minified, self.output_mode) log.info('Scanning paths...') sources = set( (closurebuilder._PathSource(js_path) for path in (self.root, self.project,) for js_path in treescan.ScanTreeForJsFiles(path) )) log.info('%s sources scanned.', len(sources)) log.info('Building dependency tree..') tree = depstree.DepsTree(sources) input_namespaces = set(self.namespaces) for input_path in self.inputs: js_input = closurebuilder._GetInputByPath(input_path, sources) if not js_input: msg = 'No source matched input %s' % input_path log.error(msg) raise DistutilsError, msg input_namespaces.update(js_input.provides) if not input_namespaces: msg = ('No namespaces found. At least one namespace must be ' 'specified with the --namespaces or --inputs flags.') log.error(msg) raise DistutilsError, msg base = closurebuilder._GetClosureBaseFile(sources) deps = [base] + tree.GetDependencies(input_namespaces) if self.output_mode == 'list': log.info('Listing files:') log.info('\n'.join([js_source.GetPath() for js_source in deps])) log.info('Build successful!') return out = open(self.minified, 'w') if self.output_mode == 'script': out.writelines([js_source.GetSource() for js_source in deps]) out.close() log.info('Build successful!') return import jscompiler compiled_source = jscompiler.Compile( self.compiler_jar, [js_source.GetPath() for js_source in deps], self.compiler_flags) if compiled_source is None: msg = 'JavaScript compilation failed.' log.error(msg) raise DistutilsError, msg else: log.info('JavaScript compilation succeeded.') out.write(compiled_source) log.info('Build successful!') out.close()
def _generateModules(sources, modules, keepBaseSeparate=True): tree = depstree.DepsTree(sources) # list of tuples, (module_name, file_deps, module_deps_names) # + we force all modules to be dependent on the base goog module (could inject as a file deps also but this should work and is easier) baseDep = [] if keepBaseSeparate: baseDep = ['goog'] depLst = [ (mod[0], tree.GetDependencies(mod[1]), list(baseDep)) for mod in modules ] # subtract basedeps from "upper" deps # todo: what to do if a module becomes empty? (i.e a duplicate) for i in range(len(depLst)): for j in range(i+1, len(depLst)): bd = depLst[i] dp = depLst[j][1] for d in bd[1]: try: dp.remove(d) except: pass # create union of all provides/requires in the deps files per module global moduleProvides # modulename->set of all provides in module moduleProvides = {} global moduleRequires moduleRequires = {} # modulename->set of all requires in module for name, deps, moddeps in depLst: if len(deps) == 0: out.writelines('Warning - empty module: "' + name + '". Probably due to incorrect module ordering') moduleProvides[name] = set() moduleRequires[name] = set() for src in deps: for prov in src.provides: moduleProvides[name].add(prov) for req in src.requires: moduleRequires[name].add(req) # figure out module-module deps # todo: could/should also verify that all dependecies go "down" (the tree should have fixed this though) moduleModuleDeps = {} # moduleName->list of module deps for i in range(len(depLst)-1, -1, -1): # reverse td = depLst[i] for j in range(i-1, -1, -1): bd = depLst[j] if moduleRequires[td[0]] & moduleProvides[bd[0]]: # intersects? (todo: is there no isintersecting test? (more efficient since we don't actually need the complete intersection set) td[2].append(bd[0]) # print 'module:', td[0], 'depends on module:', bd[0] # force goog.base to be present in compilation (note that it will Not become part of any of the modules, only a dummy goog.js will be output) # (?! this wasn't necessary previously?) gbase = closurebuilder._GetClosureBaseFile(sources) # _must_ be present! if keepBaseSeparate: depLst.insert(0, ('goog', [gbase], [])) # could rename it to make it clearer it is a dummy/helper? ('__goog'?) moduleProvides['goog'] = set() moduleRequires['goog'] = set() else: depLst[0][1].insert(0, gbase) # inject goog into base module return depLst