build(broccoli): add support for DiffResult#addedPaths
Some plugins want to explicitly know of new paths, so we need to distinguish them from changed paths.
This commit is contained in:
parent
efab03274f
commit
dc45559c17
|
@ -30,12 +30,13 @@ class DartFormatter implements DiffingBroccoliPlugin {
|
||||||
|
|
||||||
rebuild(treeDiff: DiffResult): Promise<any> {
|
rebuild(treeDiff: DiffResult): Promise<any> {
|
||||||
let args = ['-w'];
|
let args = ['-w'];
|
||||||
treeDiff.changedPaths.forEach((changedFile) => {
|
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||||
let sourcePath = path.join(this.inputPath, changedFile);
|
.forEach((changedFile) => {
|
||||||
let destPath = path.join(this.cachePath, changedFile);
|
let sourcePath = path.join(this.inputPath, changedFile);
|
||||||
if (/\.dart$/.test(changedFile)) args.push(destPath);
|
let destPath = path.join(this.cachePath, changedFile);
|
||||||
fse.copySync(sourcePath, destPath);
|
if (/\.dart$/.test(changedFile)) args.push(destPath);
|
||||||
});
|
fse.copySync(sourcePath, destPath);
|
||||||
|
});
|
||||||
treeDiff.removedPaths.forEach((removedFile) => {
|
treeDiff.removedPaths.forEach((removedFile) => {
|
||||||
let destPath = path.join(this.cachePath, removedFile);
|
let destPath = path.join(this.cachePath, removedFile);
|
||||||
fse.removeSync(destPath);
|
fse.removeSync(destPath);
|
||||||
|
|
|
@ -15,13 +15,14 @@ class DestCopy implements DiffingBroccoliPlugin {
|
||||||
|
|
||||||
|
|
||||||
rebuild(treeDiff: DiffResult) {
|
rebuild(treeDiff: DiffResult) {
|
||||||
treeDiff.changedPaths.forEach((changedFilePath) => {
|
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||||
var destFilePath = path.join(this.outputRoot, changedFilePath);
|
.forEach((changedFilePath) => {
|
||||||
|
var destFilePath = path.join(this.outputRoot, changedFilePath);
|
||||||
|
|
||||||
var destDirPath = path.dirname(destFilePath);
|
var destDirPath = path.dirname(destFilePath);
|
||||||
fse.mkdirsSync(destDirPath);
|
fse.mkdirsSync(destDirPath);
|
||||||
fse.copySync(path.join(this.inputPath, changedFilePath), destFilePath);
|
fse.copySync(path.join(this.inputPath, changedFilePath), destFilePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
treeDiff.removedPaths.forEach((removedFilePath) => {
|
treeDiff.removedPaths.forEach((removedFilePath) => {
|
||||||
var destFilePath = path.join(this.outputRoot, removedFilePath);
|
var destFilePath = path.join(this.outputRoot, removedFilePath);
|
||||||
|
|
|
@ -52,4 +52,26 @@ describe('Flatten', () => {
|
||||||
|
|
||||||
expect(fs.readdirSync('output')).toEqual(['file-1.1.txt', 'file-2.txt', 'file-3.txt']);
|
expect(fs.readdirSync('output')).toEqual(['file-1.1.txt', 'file-2.txt', 'file-3.txt']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should throw an exception if duplicates are found', () => {
|
||||||
|
let testDir = {
|
||||||
|
'input': {
|
||||||
|
'dir1': {
|
||||||
|
'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)}),
|
||||||
|
'subdir-1': {
|
||||||
|
'file-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');
|
||||||
|
expect(() => flattenedTree.rebuild(differ.diffTree())).
|
||||||
|
toThrowError("Duplicate file 'file-1.txt' found in path 'dir1/subdir-1/file-1.txt'");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,6 +2,9 @@ import fs = require('fs');
|
||||||
import fse = require('fs-extra');
|
import fse = require('fs-extra');
|
||||||
import path = require('path');
|
import path = require('path');
|
||||||
import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-broccoli-plugin';
|
import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-broccoli-plugin';
|
||||||
|
var symlinkOrCopy = require('symlink-or-copy').sync;
|
||||||
|
|
||||||
|
var isWindows = process.platform === 'win32';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,8 +14,17 @@ import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-br
|
||||||
export class DiffingFlatten implements DiffingBroccoliPlugin {
|
export class DiffingFlatten implements DiffingBroccoliPlugin {
|
||||||
constructor(private inputPath, private cachePath, private options) {}
|
constructor(private inputPath, private cachePath, private options) {}
|
||||||
|
|
||||||
|
|
||||||
rebuild(treeDiff: DiffResult) {
|
rebuild(treeDiff: DiffResult) {
|
||||||
treeDiff.changedPaths.forEach((changedFilePath) => {
|
let pathsToUpdate = treeDiff.addedPaths;
|
||||||
|
|
||||||
|
// since we need to run on Windows as well we can't rely on symlinks being available,
|
||||||
|
// which means that we need to respond to both added and changed paths
|
||||||
|
if (isWindows) {
|
||||||
|
pathsToUpdate = pathsToUpdate.concat(treeDiff.changedPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
pathsToUpdate.forEach((changedFilePath) => {
|
||||||
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
||||||
var destFilePath = path.join(this.cachePath, path.basename(changedFilePath));
|
var destFilePath = path.join(this.cachePath, path.basename(changedFilePath));
|
||||||
var destDirPath = path.dirname(destFilePath);
|
var destDirPath = path.dirname(destFilePath);
|
||||||
|
@ -21,9 +33,11 @@ export class DiffingFlatten implements DiffingBroccoliPlugin {
|
||||||
fse.mkdirpSync(destDirPath);
|
fse.mkdirpSync(destDirPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: once we have addedPaths support, we should throw dupes are found
|
|
||||||
if (!fs.existsSync(destFilePath)) {
|
if (!fs.existsSync(destFilePath)) {
|
||||||
fs.symlinkSync(sourceFilePath, destFilePath);
|
symlinkOrCopy(sourceFilePath, destFilePath);
|
||||||
|
} else {
|
||||||
|
throw new Error(`Duplicate file '${path.basename(changedFilePath)}' ` +
|
||||||
|
`found in path '${changedFilePath}'`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ export class LodashRenderer implements DiffingBroccoliPlugin {
|
||||||
fs.unlinkSync(destFilePath);
|
fs.unlinkSync(destFilePath);
|
||||||
};
|
};
|
||||||
|
|
||||||
treeDiff.changedPaths.forEach(processFile);
|
treeDiff.addedPaths.concat(treeDiff.changedPaths).forEach(processFile);
|
||||||
treeDiff.removedPaths.forEach(removeFile);
|
treeDiff.removedPaths.forEach(removeFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ describe('MergeTrees', () => {
|
||||||
expect(read('dest/foo.js')).toBe('tree2/foo.js content');
|
expect(read('dest/foo.js')).toBe('tree2/foo.js content');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if duplicates are used by default', () => {
|
it('should throw if duplicates are found during the initial build', () => {
|
||||||
let testDir: any = {
|
let testDir: any = {
|
||||||
'tree1': {'foo.js': mockfs.file({content: 'tree1/foo.js content', mtime: new Date(1000)})},
|
'tree1': {'foo.js': mockfs.file({content: 'tree1/foo.js content', mtime: new Date(1000)})},
|
||||||
'tree2': {'foo.js': mockfs.file({content: 'tree2/foo.js content', mtime: new Date(1000)})},
|
'tree2': {'foo.js': mockfs.file({content: 'tree2/foo.js content', mtime: new Date(1000)})},
|
||||||
|
@ -54,15 +54,34 @@ describe('MergeTrees', () => {
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
let treeDiffer = MakeTreeDiffers(['tree1', 'tree2', 'tree3']);
|
let treeDiffer = MakeTreeDiffers(['tree1', 'tree2', 'tree3']);
|
||||||
let treeMerger = mergeTrees(['tree1', 'tree2', 'tree3'], 'dest', {});
|
let treeMerger = mergeTrees(['tree1', 'tree2', 'tree3'], 'dest', {});
|
||||||
expect(() => treeMerger.rebuild(treeDiffer.diffTrees())).toThrow();
|
expect(() => treeMerger.rebuild(treeDiffer.diffTrees())).
|
||||||
|
toThrowError("`overwrite` option is required for handling duplicates.");
|
||||||
|
|
||||||
delete testDir.tree2['foo.js'];
|
testDir = {
|
||||||
delete testDir.tree3['foo.js'];
|
'tree1': {'foo.js': mockfs.file({content: 'tree1/foo.js content', mtime: new Date(1000)})},
|
||||||
|
'tree2': {},
|
||||||
|
'tree3': {}
|
||||||
|
};
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should throw if duplicates are found during rebuild', () => {
|
||||||
|
let testDir = {
|
||||||
|
'tree1': {'foo.js': mockfs.file({content: 'tree1/foo.js content', mtime: new Date(1000)})},
|
||||||
|
'tree2': {},
|
||||||
|
'tree3': {}
|
||||||
|
};
|
||||||
|
mockfs(testDir);
|
||||||
|
|
||||||
|
let treeDiffer = MakeTreeDiffers(['tree1', 'tree2', 'tree3']);
|
||||||
|
let treeMerger = mergeTrees(['tree1', 'tree2', 'tree3'], 'dest', {});
|
||||||
expect(() => treeMerger.rebuild(treeDiffer.diffTrees())).not.toThrow();
|
expect(() => treeMerger.rebuild(treeDiffer.diffTrees())).not.toThrow();
|
||||||
|
|
||||||
|
|
||||||
testDir.tree2['foo.js'] = mockfs.file({content: 'tree2/foo.js content', mtime: new Date(1000)});
|
testDir.tree2['foo.js'] = mockfs.file({content: 'tree2/foo.js content', mtime: new Date(1000)});
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
expect(() => treeMerger.rebuild(treeDiffer.diffTrees())).toThrow();
|
expect(() => treeMerger.rebuild(treeDiffer.diffTrees())).
|
||||||
|
toThrowError("`overwrite` option is required for handling duplicates.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,8 @@ import path = require('path');
|
||||||
var symlinkOrCopySync = require('symlink-or-copy').sync;
|
var symlinkOrCopySync = require('symlink-or-copy').sync;
|
||||||
import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-broccoli-plugin';
|
import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-broccoli-plugin';
|
||||||
|
|
||||||
|
var isWindows = process.platform === 'win32';
|
||||||
|
|
||||||
interface MergeTreesOptions {
|
interface MergeTreesOptions {
|
||||||
overwrite?: boolean;
|
overwrite?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -43,10 +45,12 @@ export class MergeTrees implements DiffingBroccoliPlugin {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.firstBuild) {
|
if (this.firstBuild) {
|
||||||
|
this.firstBuild = false;
|
||||||
|
|
||||||
// Build initial cache
|
// Build initial cache
|
||||||
treeDiffs.reverse().forEach((treeDiff: DiffResult, index) => {
|
treeDiffs.reverse().forEach((treeDiff: DiffResult, index) => {
|
||||||
index = treeDiffs.length - 1 - index;
|
index = treeDiffs.length - 1 - index;
|
||||||
treeDiff.changedPaths.forEach((changedPath) => {
|
treeDiff.addedPaths.forEach((changedPath) => {
|
||||||
let cache = this.pathCache[changedPath];
|
let cache = this.pathCache[changedPath];
|
||||||
if (cache === undefined) {
|
if (cache === undefined) {
|
||||||
this.pathCache[changedPath] = [index];
|
this.pathCache[changedPath] = [index];
|
||||||
|
@ -59,7 +63,7 @@ export class MergeTrees implements DiffingBroccoliPlugin {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.firstBuild = false;
|
|
||||||
} else {
|
} else {
|
||||||
// Update cache
|
// Update cache
|
||||||
treeDiffs.reverse().forEach((treeDiff: DiffResult, index) => {
|
treeDiffs.reverse().forEach((treeDiff: DiffResult, index) => {
|
||||||
|
@ -81,7 +85,14 @@ export class MergeTrees implements DiffingBroccoliPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
treeDiff.changedPaths.forEach((changedPath) => {
|
|
||||||
|
let pathsToUpdate = treeDiff.addedPaths;
|
||||||
|
|
||||||
|
if (isWindows) {
|
||||||
|
pathsToUpdate = pathsToUpdate.concat(treeDiff.changedPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
pathsToUpdate.forEach((changedPath) => {
|
||||||
let cache = this.pathCache[changedPath];
|
let cache = this.pathCache[changedPath];
|
||||||
if (cache === undefined) {
|
if (cache === undefined) {
|
||||||
// File was added
|
// File was added
|
||||||
|
|
|
@ -17,32 +17,33 @@ class DiffingReplace implements DiffingBroccoliPlugin {
|
||||||
var patterns = this.options.patterns;
|
var patterns = this.options.patterns;
|
||||||
var files = this.options.files;
|
var files = this.options.files;
|
||||||
|
|
||||||
treeDiff.changedPaths.forEach((changedFilePath) => {
|
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||||
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
.forEach((changedFilePath) => {
|
||||||
var destFilePath = path.join(this.cachePath, changedFilePath);
|
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
||||||
var destDirPath = path.dirname(destFilePath);
|
var destFilePath = path.join(this.cachePath, changedFilePath);
|
||||||
|
var destDirPath = path.dirname(destFilePath);
|
||||||
|
|
||||||
if (!fs.existsSync(destDirPath)) {
|
if (!fs.existsSync(destDirPath)) {
|
||||||
fse.mkdirpSync(destDirPath);
|
fse.mkdirpSync(destDirPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileMatches = files.some((filePath) => minimatch(changedFilePath, filePath));
|
var fileMatches = files.some((filePath) => minimatch(changedFilePath, filePath));
|
||||||
if (fileMatches) {
|
if (fileMatches) {
|
||||||
var content = fs.readFileSync(sourceFilePath, FILE_ENCODING);
|
var content = fs.readFileSync(sourceFilePath, FILE_ENCODING);
|
||||||
patterns.forEach((pattern) => {
|
patterns.forEach((pattern) => {
|
||||||
var replacement = pattern.replacement;
|
var replacement = pattern.replacement;
|
||||||
if (typeof replacement === 'function') {
|
if (typeof replacement === 'function') {
|
||||||
replacement = function(content) {
|
replacement = function(content) {
|
||||||
return pattern.replacement(content, changedFilePath);
|
return pattern.replacement(content, changedFilePath);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
content = content.replace(pattern.match, replacement);
|
||||||
|
});
|
||||||
|
fs.writeFileSync(destFilePath, content, FILE_ENCODING);
|
||||||
|
} else if (!fs.existsSync(destFilePath)) {
|
||||||
|
fs.symlinkSync(sourceFilePath, destFilePath);
|
||||||
}
|
}
|
||||||
content = content.replace(pattern.match, replacement);
|
|
||||||
});
|
});
|
||||||
fs.writeFileSync(destFilePath, content, FILE_ENCODING);
|
|
||||||
} else if (!fs.existsSync(destFilePath)) {
|
|
||||||
fs.symlinkSync(sourceFilePath, destFilePath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
treeDiff.removedPaths.forEach((removedFilePath) => {
|
treeDiff.removedPaths.forEach((removedFilePath) => {
|
||||||
var destFilePath = path.join(this.cachePath, removedFilePath);
|
var destFilePath = path.join(this.cachePath, removedFilePath);
|
||||||
|
|
|
@ -23,16 +23,17 @@ class TSToDartTranspiler implements DiffingBroccoliPlugin {
|
||||||
rebuild(treeDiff: DiffResult) {
|
rebuild(treeDiff: DiffResult) {
|
||||||
let toEmit = [];
|
let toEmit = [];
|
||||||
let getDartFilePath = (path: string) => path.replace(/((\.js)|(\.ts))$/i, '.dart');
|
let getDartFilePath = (path: string) => path.replace(/((\.js)|(\.ts))$/i, '.dart');
|
||||||
treeDiff.changedPaths.forEach((changedPath) => {
|
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||||
let inputFilePath = path.resolve(this.inputPath, changedPath);
|
.forEach((changedPath) => {
|
||||||
|
let inputFilePath = path.resolve(this.inputPath, changedPath);
|
||||||
|
|
||||||
// Ignore files which don't need to be transpiled to Dart
|
// Ignore files which don't need to be transpiled to Dart
|
||||||
let dartInputFilePath = getDartFilePath(inputFilePath);
|
let dartInputFilePath = getDartFilePath(inputFilePath);
|
||||||
if (fs.existsSync(dartInputFilePath)) return;
|
if (fs.existsSync(dartInputFilePath)) return;
|
||||||
|
|
||||||
// Prepare to rebuild
|
// Prepare to rebuild
|
||||||
toEmit.push(path.resolve(this.inputPath, changedPath));
|
toEmit.push(path.resolve(this.inputPath, changedPath));
|
||||||
});
|
});
|
||||||
|
|
||||||
treeDiff.removedPaths.forEach((removedPath) => {
|
treeDiff.removedPaths.forEach((removedPath) => {
|
||||||
let absolutePath = path.resolve(this.inputPath, removedPath);
|
let absolutePath = path.resolve(this.inputPath, removedPath);
|
||||||
|
|
|
@ -50,16 +50,17 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
||||||
let pathsToEmit = [];
|
let pathsToEmit = [];
|
||||||
let pathsWithErrors = [];
|
let pathsWithErrors = [];
|
||||||
|
|
||||||
treeDiff.changedPaths.forEach((tsFilePath) => {
|
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||||
if (!this.fileRegistry[tsFilePath]) {
|
.forEach((tsFilePath) => {
|
||||||
this.fileRegistry[tsFilePath] = {version: 0};
|
if (!this.fileRegistry[tsFilePath]) {
|
||||||
this.rootFilePaths.push(tsFilePath);
|
this.fileRegistry[tsFilePath] = {version: 0};
|
||||||
} else {
|
this.rootFilePaths.push(tsFilePath);
|
||||||
this.fileRegistry[tsFilePath].version++;
|
} else {
|
||||||
}
|
this.fileRegistry[tsFilePath].version++;
|
||||||
|
}
|
||||||
|
|
||||||
pathsToEmit.push(tsFilePath);
|
pathsToEmit.push(tsFilePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
treeDiff.removedPaths.forEach((tsFilePath) => {
|
treeDiff.removedPaths.forEach((tsFilePath) => {
|
||||||
console.log('removing outputs for', tsFilePath);
|
console.log('removing outputs for', tsFilePath);
|
||||||
|
|
|
@ -16,29 +16,31 @@ class DiffingTraceurCompiler implements DiffingBroccoliPlugin {
|
||||||
static includeExtensions = ['.js', '.es6', '.cjs'];
|
static includeExtensions = ['.js', '.es6', '.cjs'];
|
||||||
|
|
||||||
rebuild(treeDiff: DiffResult) {
|
rebuild(treeDiff: DiffResult) {
|
||||||
treeDiff.changedPaths.forEach((changedFilePath) => {
|
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||||
var traceurOpts = xtend({filename: changedFilePath}, this.options.traceurOptions);
|
.forEach((changedFilePath) => {
|
||||||
|
var traceurOpts = xtend({filename: changedFilePath}, this.options.traceurOptions);
|
||||||
|
|
||||||
var fsOpts = {encoding: 'utf-8'};
|
var fsOpts = {encoding: 'utf-8'};
|
||||||
var absoluteInputFilePath = path.join(this.inputPath, changedFilePath);
|
var absoluteInputFilePath = path.join(this.inputPath, changedFilePath);
|
||||||
var sourcecode = fs.readFileSync(absoluteInputFilePath, fsOpts);
|
var sourcecode = fs.readFileSync(absoluteInputFilePath, fsOpts);
|
||||||
|
|
||||||
var result = traceur.compile(traceurOpts, changedFilePath, sourcecode);
|
var result = traceur.compile(traceurOpts, changedFilePath, sourcecode);
|
||||||
|
|
||||||
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
|
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
|
||||||
// (but we might switch to typescript first)
|
// (but we might switch to typescript first)
|
||||||
var mapFilepath = changedFilePath.replace(/\.\w+$/, '') + this.options.destSourceMapExtension;
|
var mapFilepath =
|
||||||
result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(mapFilepath);
|
changedFilePath.replace(/\.\w+$/, '') + this.options.destSourceMapExtension;
|
||||||
|
result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(mapFilepath);
|
||||||
|
|
||||||
var destFilepath = changedFilePath.replace(/\.\w+$/, this.options.destExtension);
|
var destFilepath = changedFilePath.replace(/\.\w+$/, this.options.destExtension);
|
||||||
var destFile = path.join(this.cachePath, destFilepath);
|
var destFile = path.join(this.cachePath, destFilepath);
|
||||||
fse.mkdirsSync(path.dirname(destFile));
|
fse.mkdirsSync(path.dirname(destFile));
|
||||||
fs.writeFileSync(destFile, result.js, fsOpts);
|
fs.writeFileSync(destFile, result.js, fsOpts);
|
||||||
|
|
||||||
var destMap = path.join(this.cachePath, mapFilepath);
|
var destMap = path.join(this.cachePath, mapFilepath);
|
||||||
result.sourceMap.file = destFilepath;
|
result.sourceMap.file = destFilepath;
|
||||||
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
||||||
});
|
});
|
||||||
|
|
||||||
treeDiff.removedPaths.forEach((removedFilePath) => {
|
treeDiff.removedPaths.forEach((removedFilePath) => {
|
||||||
var destFilepath = removedFilePath.replace(/\.\w+$/, this.options.destExtension);
|
var destFilepath = removedFilePath.replace(/\.\w+$/, this.options.destExtension);
|
||||||
|
|
|
@ -11,9 +11,9 @@ describe('TreeDiffer', () => {
|
||||||
afterEach(() => mockfs.restore());
|
afterEach(() => mockfs.restore());
|
||||||
|
|
||||||
|
|
||||||
describe('diff of changed files', () => {
|
describe('diff of added and changed files', () => {
|
||||||
|
|
||||||
it('should list all files but no directories during the first diff', () => {
|
it('should list all files (but no directories) during the first diff', () => {
|
||||||
let testDir = {
|
let testDir = {
|
||||||
'dir1': {
|
'dir1': {
|
||||||
'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)}),
|
'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)}),
|
||||||
|
@ -30,9 +30,10 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
|
|
||||||
expect(diffResult.changedPaths)
|
expect(diffResult.addedPaths)
|
||||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
||||||
|
|
||||||
|
expect(diffResult.changedPaths).toEqual([]);
|
||||||
expect(diffResult.removedPaths).toEqual([]);
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -53,11 +54,13 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
|
|
||||||
expect(diffResult.changedPaths).not.toEqual([]);
|
expect(diffResult.addedPaths).not.toEqual([]);
|
||||||
|
expect(diffResult.changedPaths).toEqual([]);
|
||||||
expect(diffResult.removedPaths).toEqual([]);
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
|
|
||||||
diffResult = differ.diffTree();
|
diffResult = differ.diffTree();
|
||||||
|
|
||||||
|
expect(diffResult.addedPaths).toEqual([]);
|
||||||
expect(diffResult.changedPaths).toEqual([]);
|
expect(diffResult.changedPaths).toEqual([]);
|
||||||
expect(diffResult.removedPaths).toEqual([]);
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
});
|
});
|
||||||
|
@ -80,7 +83,7 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
|
|
||||||
expect(diffResult.changedPaths)
|
expect(diffResult.addedPaths)
|
||||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
||||||
|
|
||||||
// change two files
|
// change two files
|
||||||
|
@ -126,7 +129,7 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
|
|
||||||
expect(diffResult.changedPaths)
|
expect(diffResult.addedPaths)
|
||||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
||||||
|
|
||||||
// change two files
|
// change two files
|
||||||
|
@ -138,8 +141,8 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
diffResult = differ.diffTree();
|
diffResult = differ.diffTree();
|
||||||
|
|
||||||
|
expect(diffResult.addedPaths).toEqual([]);
|
||||||
expect(diffResult.changedPaths).toEqual(['file-1.txt', 'subdir-1/file-1.1.txt']);
|
expect(diffResult.changedPaths).toEqual(['file-1.txt', 'subdir-1/file-1.1.txt']);
|
||||||
|
|
||||||
expect(diffResult.removedPaths).toEqual([]);
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
|
|
||||||
// change one file
|
// change one file
|
||||||
|
@ -155,6 +158,7 @@ describe('TreeDiffer', () => {
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
|
|
||||||
diffResult = differ.diffTree();
|
diffResult = differ.diffTree();
|
||||||
|
expect(diffResult.addedPaths).toEqual([]);
|
||||||
expect(diffResult.changedPaths).toEqual([]);
|
expect(diffResult.changedPaths).toEqual([]);
|
||||||
expect(diffResult.removedPaths).toEqual(['file-1.txt']);
|
expect(diffResult.removedPaths).toEqual(['file-1.txt']);
|
||||||
|
|
||||||
|
@ -171,7 +175,8 @@ describe('TreeDiffer', () => {
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
|
|
||||||
diffResult = differ.diffTree();
|
diffResult = differ.diffTree();
|
||||||
expect(diffResult.changedPaths).toEqual(['file-1.txt']);
|
expect(diffResult.addedPaths).toEqual(['file-1.txt']);
|
||||||
|
expect(diffResult.changedPaths).toEqual([]);
|
||||||
expect(diffResult.removedPaths).toEqual([]);
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -204,7 +209,9 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
|
|
||||||
expect(diffResult.changedPaths).toEqual(['file-1.js', 'file-3.coffee']);
|
expect(diffResult.addedPaths).toEqual(['file-1.js', 'file-3.coffee']);
|
||||||
|
expect(diffResult.changedPaths).toEqual([]);
|
||||||
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
|
|
||||||
// change two files
|
// change two files
|
||||||
testDir['dir1']['file-1.js'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
|
testDir['dir1']['file-1.js'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
|
||||||
|
@ -216,8 +223,8 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
diffResult = differ.diffTree();
|
diffResult = differ.diffTree();
|
||||||
|
|
||||||
|
expect(diffResult.addedPaths).toEqual([]);
|
||||||
expect(diffResult.changedPaths).toEqual(['file-1.js', 'file-3.coffee']);
|
expect(diffResult.changedPaths).toEqual(['file-1.js', 'file-3.coffee']);
|
||||||
|
|
||||||
expect(diffResult.removedPaths).toEqual([]);
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
|
|
||||||
// change one file
|
// change one file
|
||||||
|
@ -250,7 +257,7 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
|
|
||||||
expect(diffResult.changedPaths)
|
expect(diffResult.addedPaths)
|
||||||
.toEqual(['file-1.cs', 'file-1.ts', 'file-1d.cs', 'file-3.ts']);
|
.toEqual(['file-1.cs', 'file-1.ts', 'file-1d.cs', 'file-3.ts']);
|
||||||
|
|
||||||
// change two files
|
// change two files
|
||||||
|
@ -265,8 +272,8 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
diffResult = differ.diffTree();
|
diffResult = differ.diffTree();
|
||||||
|
|
||||||
|
expect(diffResult.addedPaths).toEqual([]);
|
||||||
expect(diffResult.changedPaths).toEqual(['file-1.cs', 'file-1.ts', 'file-3.ts']);
|
expect(diffResult.changedPaths).toEqual(['file-1.cs', 'file-1.ts', 'file-3.ts']);
|
||||||
|
|
||||||
expect(diffResult.removedPaths).toEqual([]);
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
|
|
||||||
// change one file
|
// change one file
|
||||||
|
@ -280,7 +287,7 @@ describe('TreeDiffer', () => {
|
||||||
|
|
||||||
describe('diff of new files', () => {
|
describe('diff of new files', () => {
|
||||||
|
|
||||||
it('should detect file additions and report them as changed files', () => {
|
it('should detect file additions', () => {
|
||||||
let testDir = {
|
let testDir = {
|
||||||
'dir1':
|
'dir1':
|
||||||
{'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)})}
|
{'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)})}
|
||||||
|
@ -294,7 +301,9 @@ describe('TreeDiffer', () => {
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
expect(diffResult.changedPaths).toEqual(['file-2.txt']);
|
expect(diffResult.addedPaths).toEqual(['file-2.txt']);
|
||||||
|
expect(diffResult.changedPaths).toEqual([]);
|
||||||
|
expect(diffResult.removedPaths).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -313,7 +322,8 @@ describe('TreeDiffer', () => {
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
expect(diffResult.changedPaths).toEqual(['file-1.txt', 'file-2.txt']);
|
expect(diffResult.addedPaths).toEqual(['file-2.txt']);
|
||||||
|
expect(diffResult.changedPaths).toEqual(['file-1.txt']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -358,7 +368,8 @@ describe('TreeDiffer', () => {
|
||||||
mockfs(testDir);
|
mockfs(testDir);
|
||||||
|
|
||||||
let diffResult = differ.diffTree();
|
let diffResult = differ.diffTree();
|
||||||
expect(diffResult.changedPaths).toEqual(['file-1.txt', 'file-3.txt']);
|
expect(diffResult.addedPaths).toEqual(['file-3.txt']);
|
||||||
|
expect(diffResult.changedPaths).toEqual(['file-1.txt']);
|
||||||
expect(diffResult.removedPaths).toEqual(['file-2.txt']);
|
expect(diffResult.removedPaths).toEqual(['file-2.txt']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -66,8 +66,14 @@ export class TreeDiffer {
|
||||||
if (!(this.include && !absolutePath.match(this.include)) &&
|
if (!(this.include && !absolutePath.match(this.include)) &&
|
||||||
!(this.exclude && absolutePath.match(this.exclude))) {
|
!(this.exclude && absolutePath.match(this.exclude))) {
|
||||||
result.filesChecked++;
|
result.filesChecked++;
|
||||||
if (this.isFileDirty(absolutePath, pathStat)) {
|
let relativeFilePath = path.relative(this.rootPath, absolutePath);
|
||||||
result.changedPaths.push(path.relative(this.rootPath, absolutePath));
|
|
||||||
|
switch (this.isFileDirty(absolutePath, pathStat)) {
|
||||||
|
case FileStatus.ADDED:
|
||||||
|
result.addedPaths.push(relativeFilePath);
|
||||||
|
break;
|
||||||
|
case FileStatus.CHANGED:
|
||||||
|
result.changedPaths.push(relativeFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +83,7 @@ export class TreeDiffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private isFileDirty(path: string, stat: fs.Stats): boolean {
|
private isFileDirty(path: string, stat: fs.Stats): FileStatus {
|
||||||
let oldFingerprint = this.fingerprints[path];
|
let oldFingerprint = this.fingerprints[path];
|
||||||
let newFingerprint = `${stat.mtime.getTime()} # ${stat.size}`;
|
let newFingerprint = `${stat.mtime.getTime()} # ${stat.size}`;
|
||||||
|
|
||||||
|
@ -88,11 +94,13 @@ export class TreeDiffer {
|
||||||
|
|
||||||
if (oldFingerprint === newFingerprint) {
|
if (oldFingerprint === newFingerprint) {
|
||||||
// nothing changed
|
// nothing changed
|
||||||
return false;
|
return FileStatus.UNCHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return FileStatus.CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return FileStatus.ADDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,6 +122,7 @@ export class TreeDiffer {
|
||||||
|
|
||||||
|
|
||||||
export interface DiffResult {
|
export interface DiffResult {
|
||||||
|
addedPaths: string[];
|
||||||
changedPaths: string[];
|
changedPaths: string[];
|
||||||
removedPaths: string[];
|
removedPaths: string[];
|
||||||
log(verbose: boolean): void;
|
log(verbose: boolean): void;
|
||||||
|
@ -124,6 +133,7 @@ export interface DiffResult {
|
||||||
class DirtyCheckingDiffResult {
|
class DirtyCheckingDiffResult {
|
||||||
public filesChecked: number = 0;
|
public filesChecked: number = 0;
|
||||||
public directoriesChecked: number = 0;
|
public directoriesChecked: number = 0;
|
||||||
|
public addedPaths: string[] = [];
|
||||||
public changedPaths: string[] = [];
|
public changedPaths: string[] = [];
|
||||||
public removedPaths: string[] = [];
|
public removedPaths: string[] = [];
|
||||||
public startTime: number = Date.now();
|
public startTime: number = Date.now();
|
||||||
|
@ -133,13 +143,14 @@ class DirtyCheckingDiffResult {
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return `${pad(this.label, 30)}, ${pad(this.endTime - this.startTime, 5)}ms, ` +
|
return `${pad(this.label, 30)}, ${pad(this.endTime - this.startTime, 5)}ms, ` +
|
||||||
`${pad(this.changedPaths.length + this.removedPaths.length, 5)} changes ` +
|
`${pad(this.addedPaths.length + this.changedPaths.length + this.removedPaths.length, 5)} changes ` +
|
||||||
`(files: ${pad(this.filesChecked, 5)}, dirs: ${pad(this.directoriesChecked, 4)})`;
|
`(files: ${pad(this.filesChecked, 5)}, dirs: ${pad(this.directoriesChecked, 4)})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
log(verbose) {
|
log(verbose) {
|
||||||
let prefixedPaths =
|
let prefixedPaths = this.addedPaths.map(p => `+ ${p}`)
|
||||||
this.changedPaths.map((p) => `* ${p}`).concat(this.removedPaths.map((p) => `- ${p}`));
|
.concat(this.changedPaths.map(p => `* ${p}`))
|
||||||
|
.concat(this.removedPaths.map(p => `- ${p}`));
|
||||||
console.log(`Tree diff: ${this}` + ((verbose && prefixedPaths.length) ?
|
console.log(`Tree diff: ${this}` + ((verbose && prefixedPaths.length) ?
|
||||||
` [\n ${prefixedPaths.join('\n ')}\n]` :
|
` [\n ${prefixedPaths.join('\n ')}\n]` :
|
||||||
''));
|
''));
|
||||||
|
@ -153,3 +164,6 @@ function pad(value, length) {
|
||||||
whitespaceLength = whitespaceLength + 1;
|
whitespaceLength = whitespaceLength + 1;
|
||||||
return new Array(whitespaceLength).join(' ') + value;
|
return new Array(whitespaceLength).join(' ') + value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum FileStatus { ADDED, UNCHANGED, CHANGED }
|
||||||
|
|
Loading…
Reference in New Issue