| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  | /// <reference path="broccoli.d.ts" />
 | 
					
						
							|  |  |  | /// <reference path="../typings/fs-extra/fs-extra.d.ts" />
 | 
					
						
							|  |  |  | /// <reference path="../typings/node/node.d.ts" />
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import fs = require('fs'); | 
					
						
							|  |  |  | import fse = require('fs-extra'); | 
					
						
							|  |  |  | import path = require('path'); | 
					
						
							|  |  |  | import {TreeDiffer, DiffResult} from './tree-differ'; | 
					
						
							|  |  |  | let symlinkOrCopy = require('symlink-or-copy'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export {DiffResult} from './tree-differ'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Makes writing diffing plugins easy. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Factory method that takes a class that implements the DiffingBroccoliPlugin interface and returns | 
					
						
							|  |  |  |  * an instance of BroccoliTree. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param pluginClass | 
					
						
							|  |  |  |  * @returns {DiffingPlugin} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export function wrapDiffingPlugin(pluginClass): DiffingPluginWrapperFactory { | 
					
						
							|  |  |  |   return function() { return new DiffingPluginWrapper(pluginClass, arguments); }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export interface DiffingBroccoliPlugin { | 
					
						
							|  |  |  |   rebuild(diff: DiffResult): (Promise<any>| void); | 
					
						
							|  |  |  |   cleanup ? () : void; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type DiffingPluginWrapperFactory = (inputTrees: (BroccoliTree | BroccoliTree[]), options?) => | 
					
						
							|  |  |  |     BroccoliTree; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DiffingPluginWrapper implements BroccoliTree { | 
					
						
							|  |  |  |   treeDiffer: TreeDiffer; | 
					
						
							|  |  |  |   initialized = false; | 
					
						
							|  |  |  |   wrappedPlugin: DiffingBroccoliPlugin = null; | 
					
						
							|  |  |  |   inputTree = null; | 
					
						
							|  |  |  |   inputTrees = null; | 
					
						
							|  |  |  |   description = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // props monkey-patched by broccoli builder:
 | 
					
						
							|  |  |  |   inputPath = null; | 
					
						
							|  |  |  |   cachePath = null; | 
					
						
							|  |  |  |   outputPath = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   constructor(private pluginClass, private wrappedPluginArguments) { | 
					
						
							|  |  |  |     if (Array.isArray(wrappedPluginArguments[0])) { | 
					
						
							|  |  |  |       this.inputTrees = wrappedPluginArguments[0]; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       this.inputTree = wrappedPluginArguments[0]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this.description = this.pluginClass.name; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   rebuild() { | 
					
						
							| 
									
										
										
										
											2015-05-04 08:27:14 -07:00
										 |  |  |     try { | 
					
						
							|  |  |  |       let firstRun = !this.initialized; | 
					
						
							|  |  |  |       this.init(); | 
					
						
							| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-04 08:27:14 -07:00
										 |  |  |       let diffResult = this.treeDiffer.diffTree(); | 
					
						
							|  |  |  |       diffResult.log(!firstRun); | 
					
						
							| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-04 08:27:14 -07:00
										 |  |  |       var rebuildPromise = this.wrappedPlugin.rebuild(diffResult); | 
					
						
							| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-04 08:27:14 -07:00
										 |  |  |       if (rebuildPromise) { | 
					
						
							|  |  |  |         return (<Promise<any>>rebuildPromise).then(this.relinkOutputAndCachePaths.bind(this)); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-04 08:27:14 -07:00
										 |  |  |       this.relinkOutputAndCachePaths(); | 
					
						
							|  |  |  |     } catch (e) { | 
					
						
							|  |  |  |       e.message = `[${this.description}]: ${e.message}`; | 
					
						
							|  |  |  |       throw e; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private relinkOutputAndCachePaths() { | 
					
						
							|  |  |  |     // just symlink the cache and output tree
 | 
					
						
							|  |  |  |     fs.rmdirSync(this.outputPath); | 
					
						
							|  |  |  |     symlinkOrCopy.sync(this.cachePath, this.outputPath); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   private init() { | 
					
						
							|  |  |  |     if (!this.initialized) { | 
					
						
							| 
									
										
										
										
											2015-05-06 19:24:10 -04:00
										 |  |  |       let includeExtensions = this.pluginClass.includeExtensions || []; | 
					
						
							|  |  |  |       let excludeExtensions = this.pluginClass.excludeExtensions || []; | 
					
						
							| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  |       this.initialized = true; | 
					
						
							| 
									
										
										
										
											2015-05-06 19:24:10 -04:00
										 |  |  |       this.treeDiffer = new TreeDiffer(this.inputPath, includeExtensions, excludeExtensions); | 
					
						
							| 
									
										
										
										
											2015-05-04 08:19:25 -07:00
										 |  |  |       this.wrappedPlugin = | 
					
						
							|  |  |  |           new this.pluginClass(this.inputPath, this.cachePath, this.wrappedPluginArguments[1]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   cleanup() { | 
					
						
							|  |  |  |     if (this.wrappedPlugin.cleanup) { | 
					
						
							|  |  |  |       this.wrappedPlugin.cleanup(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |