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> {
|
||||
let args = ['-w'];
|
||||
treeDiff.changedPaths.forEach((changedFile) => {
|
||||
let sourcePath = path.join(this.inputPath, changedFile);
|
||||
let destPath = path.join(this.cachePath, changedFile);
|
||||
if (/\.dart$/.test(changedFile)) args.push(destPath);
|
||||
fse.copySync(sourcePath, destPath);
|
||||
});
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedFile) => {
|
||||
let sourcePath = path.join(this.inputPath, changedFile);
|
||||
let destPath = path.join(this.cachePath, changedFile);
|
||||
if (/\.dart$/.test(changedFile)) args.push(destPath);
|
||||
fse.copySync(sourcePath, destPath);
|
||||
});
|
||||
treeDiff.removedPaths.forEach((removedFile) => {
|
||||
let destPath = path.join(this.cachePath, removedFile);
|
||||
fse.removeSync(destPath);
|
||||
|
|
|
@ -15,13 +15,14 @@ class DestCopy implements DiffingBroccoliPlugin {
|
|||
|
||||
|
||||
rebuild(treeDiff: DiffResult) {
|
||||
treeDiff.changedPaths.forEach((changedFilePath) => {
|
||||
var destFilePath = path.join(this.outputRoot, changedFilePath);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedFilePath) => {
|
||||
var destFilePath = path.join(this.outputRoot, changedFilePath);
|
||||
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
fse.mkdirsSync(destDirPath);
|
||||
fse.copySync(path.join(this.inputPath, changedFilePath), destFilePath);
|
||||
});
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
fse.mkdirsSync(destDirPath);
|
||||
fse.copySync(path.join(this.inputPath, changedFilePath), destFilePath);
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((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']);
|
||||
});
|
||||
|
||||
|
||||
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 path = require('path');
|
||||
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 {
|
||||
constructor(private inputPath, private cachePath, private options) {}
|
||||
|
||||
|
||||
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 destFilePath = path.join(this.cachePath, path.basename(changedFilePath));
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
|
@ -21,9 +33,11 @@ export class DiffingFlatten implements DiffingBroccoliPlugin {
|
|||
fse.mkdirpSync(destDirPath);
|
||||
}
|
||||
|
||||
// TODO: once we have addedPaths support, we should throw dupes are found
|
||||
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);
|
||||
};
|
||||
|
||||
treeDiff.changedPaths.forEach(processFile);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths).forEach(processFile);
|
||||
treeDiff.removedPaths.forEach(removeFile);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ describe('MergeTrees', () => {
|
|||
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 = {
|
||||
'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)})},
|
||||
|
@ -54,15 +54,34 @@ describe('MergeTrees', () => {
|
|||
mockfs(testDir);
|
||||
let treeDiffer = MakeTreeDiffers(['tree1', 'tree2', 'tree3']);
|
||||
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'];
|
||||
delete testDir.tree3['foo.js'];
|
||||
testDir = {
|
||||
'tree1': {'foo.js': mockfs.file({content: 'tree1/foo.js content', mtime: new Date(1000)})},
|
||||
'tree2': {},
|
||||
'tree3': {}
|
||||
};
|
||||
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();
|
||||
|
||||
|
||||
testDir.tree2['foo.js'] = mockfs.file({content: 'tree2/foo.js content', mtime: new Date(1000)});
|
||||
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;
|
||||
import {wrapDiffingPlugin, DiffingBroccoliPlugin, DiffResult} from './diffing-broccoli-plugin';
|
||||
|
||||
var isWindows = process.platform === 'win32';
|
||||
|
||||
interface MergeTreesOptions {
|
||||
overwrite?: boolean;
|
||||
}
|
||||
|
@ -43,10 +45,12 @@ export class MergeTrees implements DiffingBroccoliPlugin {
|
|||
};
|
||||
|
||||
if (this.firstBuild) {
|
||||
this.firstBuild = false;
|
||||
|
||||
// Build initial cache
|
||||
treeDiffs.reverse().forEach((treeDiff: DiffResult, index) => {
|
||||
index = treeDiffs.length - 1 - index;
|
||||
treeDiff.changedPaths.forEach((changedPath) => {
|
||||
treeDiff.addedPaths.forEach((changedPath) => {
|
||||
let cache = this.pathCache[changedPath];
|
||||
if (cache === undefined) {
|
||||
this.pathCache[changedPath] = [index];
|
||||
|
@ -59,7 +63,7 @@ export class MergeTrees implements DiffingBroccoliPlugin {
|
|||
}
|
||||
});
|
||||
});
|
||||
this.firstBuild = false;
|
||||
|
||||
} else {
|
||||
// Update cache
|
||||
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];
|
||||
if (cache === undefined) {
|
||||
// File was added
|
||||
|
|
|
@ -17,32 +17,33 @@ class DiffingReplace implements DiffingBroccoliPlugin {
|
|||
var patterns = this.options.patterns;
|
||||
var files = this.options.files;
|
||||
|
||||
treeDiff.changedPaths.forEach((changedFilePath) => {
|
||||
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
||||
var destFilePath = path.join(this.cachePath, changedFilePath);
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedFilePath) => {
|
||||
var sourceFilePath = path.join(this.inputPath, changedFilePath);
|
||||
var destFilePath = path.join(this.cachePath, changedFilePath);
|
||||
var destDirPath = path.dirname(destFilePath);
|
||||
|
||||
if (!fs.existsSync(destDirPath)) {
|
||||
fse.mkdirpSync(destDirPath);
|
||||
}
|
||||
|
||||
var fileMatches = files.some((filePath) => minimatch(changedFilePath, filePath));
|
||||
if (fileMatches) {
|
||||
var content = fs.readFileSync(sourceFilePath, FILE_ENCODING);
|
||||
patterns.forEach((pattern) => {
|
||||
var replacement = pattern.replacement;
|
||||
if (typeof replacement === 'function') {
|
||||
replacement = function(content) {
|
||||
return pattern.replacement(content, changedFilePath);
|
||||
};
|
||||
if (!fs.existsSync(destDirPath)) {
|
||||
fse.mkdirpSync(destDirPath);
|
||||
}
|
||||
|
||||
var fileMatches = files.some((filePath) => minimatch(changedFilePath, filePath));
|
||||
if (fileMatches) {
|
||||
var content = fs.readFileSync(sourceFilePath, FILE_ENCODING);
|
||||
patterns.forEach((pattern) => {
|
||||
var replacement = pattern.replacement;
|
||||
if (typeof replacement === 'function') {
|
||||
replacement = function(content) {
|
||||
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) => {
|
||||
var destFilePath = path.join(this.cachePath, removedFilePath);
|
||||
|
|
|
@ -23,16 +23,17 @@ class TSToDartTranspiler implements DiffingBroccoliPlugin {
|
|||
rebuild(treeDiff: DiffResult) {
|
||||
let toEmit = [];
|
||||
let getDartFilePath = (path: string) => path.replace(/((\.js)|(\.ts))$/i, '.dart');
|
||||
treeDiff.changedPaths.forEach((changedPath) => {
|
||||
let inputFilePath = path.resolve(this.inputPath, changedPath);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedPath) => {
|
||||
let inputFilePath = path.resolve(this.inputPath, changedPath);
|
||||
|
||||
// Ignore files which don't need to be transpiled to Dart
|
||||
let dartInputFilePath = getDartFilePath(inputFilePath);
|
||||
if (fs.existsSync(dartInputFilePath)) return;
|
||||
// Ignore files which don't need to be transpiled to Dart
|
||||
let dartInputFilePath = getDartFilePath(inputFilePath);
|
||||
if (fs.existsSync(dartInputFilePath)) return;
|
||||
|
||||
// Prepare to rebuild
|
||||
toEmit.push(path.resolve(this.inputPath, changedPath));
|
||||
});
|
||||
// Prepare to rebuild
|
||||
toEmit.push(path.resolve(this.inputPath, changedPath));
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((removedPath) => {
|
||||
let absolutePath = path.resolve(this.inputPath, removedPath);
|
||||
|
|
|
@ -50,16 +50,17 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
|
|||
let pathsToEmit = [];
|
||||
let pathsWithErrors = [];
|
||||
|
||||
treeDiff.changedPaths.forEach((tsFilePath) => {
|
||||
if (!this.fileRegistry[tsFilePath]) {
|
||||
this.fileRegistry[tsFilePath] = {version: 0};
|
||||
this.rootFilePaths.push(tsFilePath);
|
||||
} else {
|
||||
this.fileRegistry[tsFilePath].version++;
|
||||
}
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((tsFilePath) => {
|
||||
if (!this.fileRegistry[tsFilePath]) {
|
||||
this.fileRegistry[tsFilePath] = {version: 0};
|
||||
this.rootFilePaths.push(tsFilePath);
|
||||
} else {
|
||||
this.fileRegistry[tsFilePath].version++;
|
||||
}
|
||||
|
||||
pathsToEmit.push(tsFilePath);
|
||||
});
|
||||
pathsToEmit.push(tsFilePath);
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((tsFilePath) => {
|
||||
console.log('removing outputs for', tsFilePath);
|
||||
|
|
|
@ -16,29 +16,31 @@ class DiffingTraceurCompiler implements DiffingBroccoliPlugin {
|
|||
static includeExtensions = ['.js', '.es6', '.cjs'];
|
||||
|
||||
rebuild(treeDiff: DiffResult) {
|
||||
treeDiff.changedPaths.forEach((changedFilePath) => {
|
||||
var traceurOpts = xtend({filename: changedFilePath}, this.options.traceurOptions);
|
||||
treeDiff.addedPaths.concat(treeDiff.changedPaths)
|
||||
.forEach((changedFilePath) => {
|
||||
var traceurOpts = xtend({filename: changedFilePath}, this.options.traceurOptions);
|
||||
|
||||
var fsOpts = {encoding: 'utf-8'};
|
||||
var absoluteInputFilePath = path.join(this.inputPath, changedFilePath);
|
||||
var sourcecode = fs.readFileSync(absoluteInputFilePath, fsOpts);
|
||||
var fsOpts = {encoding: 'utf-8'};
|
||||
var absoluteInputFilePath = path.join(this.inputPath, changedFilePath);
|
||||
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
|
||||
// (but we might switch to typescript first)
|
||||
var mapFilepath = changedFilePath.replace(/\.\w+$/, '') + this.options.destSourceMapExtension;
|
||||
result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(mapFilepath);
|
||||
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
|
||||
// (but we might switch to typescript first)
|
||||
var 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 destFile = path.join(this.cachePath, destFilepath);
|
||||
fse.mkdirsSync(path.dirname(destFile));
|
||||
fs.writeFileSync(destFile, result.js, fsOpts);
|
||||
var destFilepath = changedFilePath.replace(/\.\w+$/, this.options.destExtension);
|
||||
var destFile = path.join(this.cachePath, destFilepath);
|
||||
fse.mkdirsSync(path.dirname(destFile));
|
||||
fs.writeFileSync(destFile, result.js, fsOpts);
|
||||
|
||||
var destMap = path.join(this.cachePath, mapFilepath);
|
||||
result.sourceMap.file = destFilepath;
|
||||
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
||||
});
|
||||
var destMap = path.join(this.cachePath, mapFilepath);
|
||||
result.sourceMap.file = destFilepath;
|
||||
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
|
||||
});
|
||||
|
||||
treeDiff.removedPaths.forEach((removedFilePath) => {
|
||||
var destFilepath = removedFilePath.replace(/\.\w+$/, this.options.destExtension);
|
||||
|
|
|
@ -11,9 +11,9 @@ describe('TreeDiffer', () => {
|
|||
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 = {
|
||||
'dir1': {
|
||||
'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)}),
|
||||
|
@ -30,9 +30,10 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.changedPaths)
|
||||
expect(diffResult.addedPaths)
|
||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
||||
|
||||
expect(diffResult.changedPaths).toEqual([]);
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
});
|
||||
|
||||
|
@ -53,11 +54,13 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.changedPaths).not.toEqual([]);
|
||||
expect(diffResult.addedPaths).not.toEqual([]);
|
||||
expect(diffResult.changedPaths).toEqual([]);
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
|
||||
diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths).toEqual([]);
|
||||
expect(diffResult.changedPaths).toEqual([]);
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
});
|
||||
|
@ -80,7 +83,7 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.changedPaths)
|
||||
expect(diffResult.addedPaths)
|
||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
||||
|
||||
// change two files
|
||||
|
@ -126,7 +129,7 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.changedPaths)
|
||||
expect(diffResult.addedPaths)
|
||||
.toEqual(['file-1.txt', 'file-2.txt', 'subdir-1/file-1.1.txt']);
|
||||
|
||||
// change two files
|
||||
|
@ -138,8 +141,8 @@ describe('TreeDiffer', () => {
|
|||
|
||||
diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths).toEqual([]);
|
||||
expect(diffResult.changedPaths).toEqual(['file-1.txt', 'subdir-1/file-1.1.txt']);
|
||||
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
|
||||
// change one file
|
||||
|
@ -155,6 +158,7 @@ describe('TreeDiffer', () => {
|
|||
mockfs(testDir);
|
||||
|
||||
diffResult = differ.diffTree();
|
||||
expect(diffResult.addedPaths).toEqual([]);
|
||||
expect(diffResult.changedPaths).toEqual([]);
|
||||
expect(diffResult.removedPaths).toEqual(['file-1.txt']);
|
||||
|
||||
|
@ -171,7 +175,8 @@ describe('TreeDiffer', () => {
|
|||
mockfs(testDir);
|
||||
|
||||
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([]);
|
||||
});
|
||||
|
||||
|
@ -204,7 +209,9 @@ describe('TreeDiffer', () => {
|
|||
|
||||
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
|
||||
testDir['dir1']['file-1.js'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
|
||||
|
@ -216,8 +223,8 @@ describe('TreeDiffer', () => {
|
|||
|
||||
diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths).toEqual([]);
|
||||
expect(diffResult.changedPaths).toEqual(['file-1.js', 'file-3.coffee']);
|
||||
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
|
||||
// change one file
|
||||
|
@ -250,7 +257,7 @@ describe('TreeDiffer', () => {
|
|||
|
||||
let diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.changedPaths)
|
||||
expect(diffResult.addedPaths)
|
||||
.toEqual(['file-1.cs', 'file-1.ts', 'file-1d.cs', 'file-3.ts']);
|
||||
|
||||
// change two files
|
||||
|
@ -265,8 +272,8 @@ describe('TreeDiffer', () => {
|
|||
|
||||
diffResult = differ.diffTree();
|
||||
|
||||
expect(diffResult.addedPaths).toEqual([]);
|
||||
expect(diffResult.changedPaths).toEqual(['file-1.cs', 'file-1.ts', 'file-3.ts']);
|
||||
|
||||
expect(diffResult.removedPaths).toEqual([]);
|
||||
|
||||
// change one file
|
||||
|
@ -280,7 +287,7 @@ describe('TreeDiffer', () => {
|
|||
|
||||
describe('diff of new files', () => {
|
||||
|
||||
it('should detect file additions and report them as changed files', () => {
|
||||
it('should detect file additions', () => {
|
||||
let testDir = {
|
||||
'dir1':
|
||||
{'file-1.txt': mockfs.file({content: 'file-1.txt content', mtime: new Date(1000)})}
|
||||
|
@ -294,7 +301,9 @@ describe('TreeDiffer', () => {
|
|||
mockfs(testDir);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -66,8 +66,14 @@ export class TreeDiffer {
|
|||
if (!(this.include && !absolutePath.match(this.include)) &&
|
||||
!(this.exclude && absolutePath.match(this.exclude))) {
|
||||
result.filesChecked++;
|
||||
if (this.isFileDirty(absolutePath, pathStat)) {
|
||||
result.changedPaths.push(path.relative(this.rootPath, absolutePath));
|
||||
let relativeFilePath = 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 newFingerprint = `${stat.mtime.getTime()} # ${stat.size}`;
|
||||
|
||||
|
@ -88,11 +94,13 @@ export class TreeDiffer {
|
|||
|
||||
if (oldFingerprint === newFingerprint) {
|
||||
// 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 {
|
||||
addedPaths: string[];
|
||||
changedPaths: string[];
|
||||
removedPaths: string[];
|
||||
log(verbose: boolean): void;
|
||||
|
@ -124,6 +133,7 @@ export interface DiffResult {
|
|||
class DirtyCheckingDiffResult {
|
||||
public filesChecked: number = 0;
|
||||
public directoriesChecked: number = 0;
|
||||
public addedPaths: string[] = [];
|
||||
public changedPaths: string[] = [];
|
||||
public removedPaths: string[] = [];
|
||||
public startTime: number = Date.now();
|
||||
|
@ -133,13 +143,14 @@ class DirtyCheckingDiffResult {
|
|||
|
||||
toString() {
|
||||
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)})`;
|
||||
}
|
||||
|
||||
log(verbose) {
|
||||
let prefixedPaths =
|
||||
this.changedPaths.map((p) => `* ${p}`).concat(this.removedPaths.map((p) => `- ${p}`));
|
||||
let prefixedPaths = this.addedPaths.map(p => `+ ${p}`)
|
||||
.concat(this.changedPaths.map(p => `* ${p}`))
|
||||
.concat(this.removedPaths.map(p => `- ${p}`));
|
||||
console.log(`Tree diff: ${this}` + ((verbose && prefixedPaths.length) ?
|
||||
` [\n ${prefixedPaths.join('\n ')}\n]` :
|
||||
''));
|
||||
|
@ -153,3 +164,6 @@ function pad(value, length) {
|
|||
whitespaceLength = whitespaceLength + 1;
|
||||
return new Array(whitespaceLength).join(' ') + value;
|
||||
}
|
||||
|
||||
|
||||
enum FileStatus { ADDED, UNCHANGED, CHANGED }
|
||||
|
|
Loading…
Reference in New Issue