diff --git a/tools/broccoli/diffing-broccoli-plugin.ts b/tools/broccoli/diffing-broccoli-plugin.ts index ff2b69ae47..4548c1415c 100644 --- a/tools/broccoli/diffing-broccoli-plugin.ts +++ b/tools/broccoli/diffing-broccoli-plugin.ts @@ -28,7 +28,7 @@ export function wrapDiffingPlugin(pluginClass): DiffingPluginWrapperFactory { export interface DiffingBroccoliPlugin { - rebuild(diff: (DiffResult | DiffResult[])): (Promise| void); + rebuild(diff: (DiffResult | DiffResult[])): (Promise| DiffResult | void); cleanup ? () : void; } @@ -52,6 +52,8 @@ class DiffingPluginWrapper implements BroccoliTree { cachePath = null; outputPath = null; + private diffResult: DiffResult = null; + constructor(private pluginClass, private wrappedPluginArguments) { if (Array.isArray(wrappedPluginArguments[0])) { this.inputTrees = this.stabilizeTrees(wrappedPluginArguments[0]); @@ -62,33 +64,59 @@ class DiffingPluginWrapper implements BroccoliTree { this.description = this.pluginClass.name; } - private calculateDiff(firstRun: boolean): (DiffResult | DiffResult[]) { - // TODO(caitp): optionally log trees based on environment variable or - // command line option. It may be worth logging for trees where elapsed - // time exceeds some threshold, like 10ms. - if (this.treeDiffer) { - return this.treeDiffer.diffTree(); - } else if (this.treeDiffers) { - return this.treeDiffers.map((treeDiffer) => treeDiffer.diffTree()); + private getDiffResult(): (DiffResult | DiffResult[]) { + let returnOrCalculateDiffResult = (tree, index) => { + // returnOrCalculateDiffResult will do one of two things: + // + // If `this.diffResult` is null, calculate a DiffResult using TreeDiffer + // for the input tree. + // + // Otherwise, `this.diffResult` was produced from the output of the + // inputTree's rebuild() method, and can be used without being checked. + // Set `this.diffResult` to null and return the previously stored value. + if (!tree.diffResult) { + let differ = index === false ? this.treeDiffer : this.treeDiffers[index]; + return differ.diffTree(); + } + let diffResult = tree.diffResult; + tree.diffResult = null; + return diffResult; + }; + + if (this.inputTrees) { + return this.inputTrees.map(returnOrCalculateDiffResult); + } else if (this.inputTree) { + return returnOrCalculateDiffResult(this.inputTree, false); } else { throw new Error("Missing TreeDiffer"); } } + private maybeStoreDiffResult(value: (DiffResult | void)) { + this.diffResult = value ? (value) : null; + } rebuild() { try { let firstRun = !this.initialized; this.init(); - let diffResult = this.calculateDiff(firstRun); + let diffResult = this.getDiffResult(); - var rebuildPromise = this.wrappedPlugin.rebuild(diffResult); + let result = this.wrappedPlugin.rebuild(diffResult); - if (rebuildPromise) { - return (>rebuildPromise).then(this.relinkOutputAndCachePaths.bind(this)); + if (result) { + let resultPromise = >(result); + if (resultPromise.then) { + // rebuild() -> Promise<> + return resultPromise.then((result: (DiffResult | void)) => { + this.maybeStoreDiffResult(result); + this.relinkOutputAndCachePaths(); + }); + } } + this.maybeStoreDiffResult(<(DiffResult | void)>(result)); this.relinkOutputAndCachePaths(); } catch (e) { e.message = `[${this.description}]: ${e.message}`; diff --git a/tools/broccoli/tree-differ.ts b/tools/broccoli/tree-differ.ts index 7439d03e5b..29e4dad0ef 100644 --- a/tools/broccoli/tree-differ.ts +++ b/tools/broccoli/tree-differ.ts @@ -121,25 +121,28 @@ export class TreeDiffer { } -export interface DiffResult { - addedPaths: string[]; - changedPaths: string[]; - removedPaths: string[]; - log(verbose: boolean): void; - toString(): string; -} - - -class DirtyCheckingDiffResult { - public filesChecked: number = 0; - public directoriesChecked: number = 0; +export class DiffResult { public addedPaths: string[] = []; public changedPaths: string[] = []; public removedPaths: string[] = []; + + constructor(public label: string = '') {} + + log(verbose: boolean): void {} + + toString(): string { + // TODO(@caitp): more meaningful logging + return ''; + } +} + +class DirtyCheckingDiffResult extends DiffResult { + public filesChecked: number = 0; + public directoriesChecked: number = 0; public startTime: number = Date.now(); public endTime: number = null; - constructor(public label: string, public directoryName: string) {} + constructor(label: string, public directoryName: string) { super(label); } toString() { return `${pad(this.label, 30)}, ${pad(this.endTime - this.startTime, 5)}ms, ` +