public BuildStatus build(final Collection<Module> modules, final Flags flags) { boolean incremental = flags.incremental(); final List<ModuleChunk> chunks = myProjectBuilder.getChunks(flags.tests()).getChunkList(); for (final ModuleChunk c : chunks) { final Set<Module> chunkModules = c.getElements(); if (!DefaultGroovyMethods.intersect(modules, chunkModules).isEmpty()) { final Set<String> removedSources = new HashSet<String>(); if (incremental) { final Set<String> chunkSources = new HashSet<String>(); final Set<String> outdatedSources = new HashSet<String>(); for (Module m : chunkModules) { final ModuleWrapper mw = getModule(m.getName()); outdatedSources.addAll(mw.getOutdatedFiles(flags.tests())); chunkSources.addAll(mw.getSources(flags.tests())); removedSources.addAll(mw.getRemovedFiles(flags.tests())); } final BuildStatus result = iterativeCompile(c, chunkSources, outdatedSources, removedSources, flags); incremental = result == BuildStatus.INCREMENTAL; if (result == BuildStatus.FAILURE) { return result; } } else { new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Compiling chunk " + c.getName() + " non-incrementally."); } }.log(); for (Module m : chunkModules) { final ModuleWrapper mw = getModule(m.getName()); removedSources.addAll(flags.tests() ? mw.getRemovedTests() : mw.getRemovedSources()); } final Set<Module> toClean = new HashSet<Module>(); for (Module m : chunkModules) { if (!cleared.contains(m)) { toClean.add(m); } } if (!toClean.isEmpty() && !flags.tests()) { builder.clearChunk(new ModuleChunk(toClean), null, ProjectWrapper.this); cleared.addAll(toClean); } final Mappings delta = dependencyMapping.createDelta(); final Callbacks.Backend deltaCallback = delta.getCallback(); try { builder.buildChunk(c, flags.tests(), null, deltaCallback, ProjectWrapper.this); } catch (Exception e) { e.printStackTrace(); return BuildStatus.FAILURE; } final Set<String> allFiles = new HashSet<String>(); for (Module m : c.getElements()) { final ModuleWrapper module = getModule(m.getName()); affectedFiles.removeAll(module.getSources(flags.tests())); allFiles.addAll(module.getSources(flags.tests())); } final Collection<File> files = new HashSet<File>(); for (String f : allFiles) { files.add(new File(f)); } dependencyMapping.integrate(delta, files, removedSources); for (Module m : chunkModules) { Reporter.reportBuildSuccess(m, flags.tests()); } } } } return BuildStatus.INCREMENTAL; }
public void makeModules(final Collection<Module> initial, final Flags flags) { if (myHistory == null && !flags.tests()) { clean(); } new Logger(flags) { @Override public void log(final PrintStream stream) { stream.println("Request to make modules:"); logMany(stream, initial); stream.println("End of request"); } }.log(); final ClasspathKind kind = ClasspathKind.compile(flags.tests()); final Set<Module> modules = new HashSet<Module>(); final Set<String> marked = new HashSet<String>(); final Map<String, Boolean> visited = new HashMap<String, Boolean>(); final Set<String> frontier = new HashSet<String>(); final Map<String, Set<String>> reversedDependencies = new HashMap<String, Set<String>>(); final DotPrinter printer = new DotPrinter(flags.logStream()); printer.header(); for (Module m : myProject.getModules().values()) { final String mName = m.getName(); printer.node(mName); for (ClasspathItem cpi : m.getClasspath(kind)) { if (cpi instanceof Module) { final String name = ((Module) cpi).getName(); printer.edge(name, mName); Set<String> sm = reversedDependencies.get(name); if (sm == null) { sm = new HashSet<String>(); reversedDependencies.put(name, sm); } sm.add(mName); } } } printer.footer(); // Building "upper" subgraph printer.header(); new Object() { public void run(final Collection<Module> initial) { if (initial == null) return; for (Module module : initial) { final String mName = module.getName(); if (marked.contains(mName)) continue; printer.node(mName); final List<Module> dep = new ArrayList<Module>(); for (ClasspathItem cpi : module.getClasspath(kind)) { if (cpi instanceof Module && !marked.contains(((Module) cpi).getName())) { printer.edge(((Module) cpi).getName(), mName); dep.add((Module) cpi); } } if (dep.size() == 0) { frontier.add(mName); } marked.add(mName); run(dep); } } }.run(initial); printer.footer(); // Traversing "upper" subgraph and collecting outdated modules and their descendants new Object() { public void run(final Collection<String> initial, final boolean force) { if (initial == null) return; for (String moduleName : initial) { if (!marked.contains(moduleName)) continue; final Boolean property = visited.get(moduleName); if (property == null || !property && force) { final boolean outdated = getModule(moduleName).isOutdated(flags.tests(), myHistory); if (force || outdated) { visited.put(moduleName, true); modules.add(myProject.getModules().get(moduleName)); run(reversedDependencies.get(moduleName), true); } else { if (property == null) { visited.put(moduleName, false); } run(reversedDependencies.get(moduleName), false); } } } } }.run(frontier, flags.force()); new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Propagated modules:"); logMany(stream, modules); stream.println("End of propagated"); } }.log(); if (modules.size() == 0 && !flags.force()) { System.out.println("All requested modules are up-to-date."); return; } final BusyBeaver beaver = new BusyBeaver(myProjectBuilder); myProjectBuilder.buildStart(); if (flags.tests()) { beaver.build( modules, new Flags() { public boolean tests() { return false; } public boolean incremental() { return flags.incremental(); } public boolean force() { return flags.force(); } public PrintStream logStream() { return flags.logStream(); } }); } beaver.build(modules, flags); myProjectBuilder.buildStop(); for (Module mod : modules) { getModule(mod.getName()).updateOutputStatus(); } }
BuildStatus iterativeCompile( final ModuleChunk chunk, final Set<String> sources, final Set<String> outdated, final Set<String> removed, final Flags flags) { final Collection<String> filesToCompile = DefaultGroovyMethods.intersect(affectedFiles, sources); if (outdated != null) { for (String s : outdated) { assert (s != null); } filesToCompile.addAll(outdated); } filesToCompile.removeAll(compiledFiles); if (!filesToCompile.isEmpty() || removed != null) { final Set<String> outputFiles = new HashSet<String>(); for (String f : filesToCompile) { final Set<ClassRepr> classes = dependencyMapping.getClasses(f); if (classes != null) { for (ClassRepr cr : classes) { outputFiles.add(cr.getFileName()); } } } if (removed != null) { for (String f : removed) { final Set<ClassRepr> classes = dependencyMapping.getClasses(f); if (classes != null) { for (ClassRepr cr : classes) { outputFiles.add(cr.getFileName()); } } } } if (!outputFiles.isEmpty()) { new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Cleaning output files:"); logFilePaths(stream, outputFiles); stream.println("End of files"); } }.log(); builder.clearChunk(chunk, outputFiles, ProjectWrapper.this); } final Mappings delta = dependencyMapping.createDelta(); final Callbacks.Backend deltaBackend = delta.getCallback(); new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Compiling files:"); logFilePaths(stream, filesToCompile); stream.println("End of files"); } }.log(); boolean buildException = false; try { builder.buildChunk( chunk, flags.tests(), filesToCompile, deltaBackend, ProjectWrapper.this); } catch (Exception e) { e.printStackTrace(); buildException = true; } if (!buildException) { compiledFiles.addAll(filesToCompile); affectedFiles.removeAll(filesToCompile); final Collection<File> files = new HashSet<File>(); final Collection<File> compiled = new HashSet<File>(); for (String f : filesToCompile) { files.add(new File(f)); } for (String f : compiledFiles) { compiled.add(new File(f)); } final Collection<File> affected = new HashSet<File>(); final boolean incremental = dependencyMapping.differentiate(delta, removed, files, compiled, affected); for (File a : affected) { affectedFiles.add(FileUtil.toSystemIndependentName(a.getAbsolutePath())); } dependencyMapping.integrate(delta, files, removed); if (!incremental) { affectedFiles.addAll(sources); affectedFiles.removeAll(compiledFiles); final BuildStatus result = iterativeCompile(chunk, sources, null, null, flags); if (result == BuildStatus.FAILURE) { return result; } return BuildStatus.CONSERVATIVE; } return iterativeCompile(chunk, sources, null, null, flags); } else { return BuildStatus.FAILURE; } } else { for (Module m : chunk.getElements()) { Reporter.reportBuildSuccess(m, flags.tests()); } } return BuildStatus.INCREMENTAL; }