diff --git a/tools/broccoli/broccoli-flatten.spec.ts b/tools/broccoli/broccoli-flatten.spec.ts new file mode 100644 index 0000000000..5a975eafbd --- /dev/null +++ b/tools/broccoli/broccoli-flatten.spec.ts @@ -0,0 +1,55 @@ +/// +/// + +let mockfs = require('mock-fs'); +import fs = require('fs'); +import {TreeDiffer} from './tree-differ'; +import {DiffingFlatten} from './broccoli-flatten'; + +describe('Flatten', () => { + afterEach(() => mockfs.restore()); + + function flatten(inputPaths) { + return new DiffingFlatten(inputPaths, 'output', null); + } + + function read(path) { return fs.readFileSync(path, {encoding: "utf-8"}); } + function rm(path) { return fs.unlinkSync(path); } + function write(path, content) { fs.writeFileSync(path, content, {encoding: "utf-8"}); } + + + it('should flatten files and be incremental', () => { + let testDir = { + 'input': { + 'dir1': { + 'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)}), + 'file-2.txt': mockfs.file({content: 'file-2.txt content', mtime: new Date(1000)}), + 'subdir-1': { + 'file-1.1.txt': mockfs.file({content: 'file-1.1.txt content', mtime: new Date(1000)}) + }, + 'empty-dir': {} + }, + }, + 'output': {} + }; + mockfs(testDir); + + let differ = new TreeDiffer('testLabel', 'input'); + let flattenedTree = flatten('input'); + flattenedTree.rebuild(differ.diffTree()); + + expect(fs.readdirSync('output')).toEqual(['file-1.1.txt', 'file-1.txt', 'file-2.txt']); + // fails due to a mock-fs bug related to reading symlinks? + //expect(read('output/file-1.1.txt')).toBe('file-1.1.txt content'); + + + // delete a file + rm('input/dir1/file-1.txt'); + // add a new one + write('input/dir1/file-3.txt', 'file-3.txt content'); + + flattenedTree.rebuild(differ.diffTree()); + + expect(fs.readdirSync('output')).toEqual(['file-1.1.txt', 'file-2.txt', 'file-3.txt']); + }); +}); diff --git a/tools/broccoli/broccoli-flatten.ts b/tools/broccoli/broccoli-flatten.ts new file mode 100644 index 0000000000..fd99aa849d --- /dev/null +++ b/tools/broccoli/broccoli-flatten.ts @@ -0,0 +1,37 @@ +import fs = require('fs'); +import fse = require('fs-extra'); +import path = require('path'); +import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-broccoli-plugin'; + + +/** + * Intercepts each changed file and replaces its contents with + * the associated changes. + */ +export class DiffingFlatten implements DiffingBroccoliPlugin { + constructor(private inputPath, private cachePath, private options) {} + + rebuild(treeDiff: DiffResult) { + treeDiff.changedPaths.forEach((changedFilePath) => { + var sourceFilePath = path.join(this.inputPath, changedFilePath); + var destFilePath = path.join(this.cachePath, path.basename(changedFilePath)); + var destDirPath = path.dirname(destFilePath); + + if (!fs.existsSync(destDirPath)) { + fse.mkdirpSync(destDirPath); + } + + // TODO: once we have addedPaths support, we should throw dupes are found + if (!fs.existsSync(destFilePath)) { + fs.symlinkSync(sourceFilePath, destFilePath); + } + }); + + treeDiff.removedPaths.forEach((removedFilePath) => { + var destFilePath = path.join(this.cachePath, path.basename(removedFilePath)); + fs.unlinkSync(destFilePath); + }); + } +} + +export default wrapDiffingPlugin(DiffingFlatten); diff --git a/tools/broccoli/trees/browser_tree.ts b/tools/broccoli/trees/browser_tree.ts index bb16843254..18485d7b69 100644 --- a/tools/broccoli/trees/browser_tree.ts +++ b/tools/broccoli/trees/browser_tree.ts @@ -1,16 +1,16 @@ 'use strict'; var Funnel = require('broccoli-funnel'); -var flatten = require('broccoli-flatten'); var htmlReplace = require('../html-replace'); -import mergeTrees from '../broccoli-merge-trees'; var path = require('path'); var stew = require('broccoli-stew'); import compileWithTypescript from '../broccoli-typescript'; import destCopy from '../broccoli-dest-copy'; -import {default as transpileWithTraceur, TRACEUR_RUNTIME_PATH} from '../traceur/index'; +import flatten from '../broccoli-flatten'; +import mergeTrees from '../broccoli-merge-trees'; import replace from '../broccoli-replace'; +import {default as transpileWithTraceur, TRACEUR_RUNTIME_PATH} from '../traceur/index'; var projectRootDir = path.normalize(path.join(__dirname, '..', '..', '..', '..'));