Skip to content

Commit aaf3edd

Browse files
committed
build(brocolli): move filename filtering into DiffingPluginWrapper
Closes angular#1719
1 parent 6bba289 commit aaf3edd

File tree

5 files changed

+154
-48
lines changed

5 files changed

+154
-48
lines changed

tools/broccoli/broccoli-typescript.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
3030
private tsServiceHost: ts.LanguageServiceHost;
3131
private tsService: ts.LanguageService;
3232

33+
static includeExtensions = ['.ts'];
34+
static excludeExtensions = ['.d.ts'];
3335

3436
constructor(public inputPath: string, public cachePath: string, public options) {
3537
this.tsOpts = Object.create(options);
@@ -46,8 +48,7 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
4648
let pathsToEmit = [];
4749
let pathsWithErrors = [];
4850

49-
treeDiff.changedPaths.filter((changedPath) =>
50-
changedPath.match(/\.ts/) && !changedPath.match(/\.d\.ts/))
51+
treeDiff.changedPaths
5152
.forEach((tsFilePath) => {
5253
if (!this.fileRegistry[tsFilePath]) {
5354
this.fileRegistry[tsFilePath] = {version: 0};
@@ -59,8 +60,7 @@ class DiffingTSCompiler implements DiffingBroccoliPlugin {
5960
pathsToEmit.push(tsFilePath);
6061
});
6162

62-
treeDiff.removedPaths.filter((changedPath) =>
63-
changedPath.match(/\.ts/) && !changedPath.match(/\.d\.ts/))
63+
treeDiff.removedPaths
6464
.forEach((tsFilePath) => {
6565
console.log('removing outputs for', tsFilePath);
6666

tools/broccoli/diffing-broccoli-plugin.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ class DiffingPluginWrapper implements BroccoliTree {
4949
cachePath = null;
5050
outputPath = null;
5151

52-
5352
constructor(private pluginClass, private wrappedPluginArguments) {
5453
if (Array.isArray(wrappedPluginArguments[0])) {
5554
this.inputTrees = wrappedPluginArguments[0];
@@ -92,8 +91,10 @@ class DiffingPluginWrapper implements BroccoliTree {
9291

9392
private init() {
9493
if (!this.initialized) {
94+
let includeExtensions = this.pluginClass.includeExtensions || [];
95+
let excludeExtensions = this.pluginClass.excludeExtensions || [];
9596
this.initialized = true;
96-
this.treeDiffer = new TreeDiffer(this.inputPath);
97+
this.treeDiffer = new TreeDiffer(this.inputPath, includeExtensions, excludeExtensions);
9798
this.wrappedPlugin =
9899
new this.pluginClass(this.inputPath, this.cachePath, this.wrappedPluginArguments[1]);
99100
}

tools/broccoli/traceur/index.ts

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,37 @@ let xtend = require('xtend');
1313
class DiffingTraceurCompiler implements DiffingBroccoliPlugin {
1414
constructor(public inputPath: string, public cachePath: string, public options) {}
1515

16+
static includeExtensions = ['.js', '.es6', '.cjs'];
1617

1718
rebuild(treeDiff: DiffResult) {
1819
treeDiff.changedPaths.forEach((changedFilePath) => {
19-
var extension = path.extname(changedFilePath).toLowerCase();
20-
if (extension === '.js' || extension === '.es6' || extension === '.cjs') {
21-
var traceurOpts = xtend({filename: changedFilePath}, this.options.traceurOptions);
22-
23-
var fsOpts = {encoding: 'utf-8'};
24-
var absoluteInputFilePath = path.join(this.inputPath, changedFilePath);
25-
var sourcecode = fs.readFileSync(absoluteInputFilePath, fsOpts);
26-
27-
var result = traceur.compile(traceurOpts, changedFilePath, sourcecode);
28-
29-
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
30-
// (but we might switch to typescript first)
31-
var mapFilepath =
32-
changedFilePath.replace(/\.\w+$/, '') + this.options.destSourceMapExtension;
33-
result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(mapFilepath);
34-
35-
var destFilepath = changedFilePath.replace(/\.\w+$/, this.options.destExtension);
36-
var destFile = path.join(this.cachePath, destFilepath);
37-
fse.mkdirsSync(path.dirname(destFile));
38-
fs.writeFileSync(destFile, result.js, fsOpts);
39-
40-
var destMap = path.join(this.cachePath, mapFilepath);
41-
result.sourceMap.file = destFilepath;
42-
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
43-
}
20+
var traceurOpts = xtend({filename: changedFilePath}, this.options.traceurOptions);
21+
22+
var fsOpts = {encoding: 'utf-8'};
23+
var absoluteInputFilePath = path.join(this.inputPath, changedFilePath);
24+
var sourcecode = fs.readFileSync(absoluteInputFilePath, fsOpts);
25+
26+
var result = traceur.compile(traceurOpts, changedFilePath, sourcecode);
27+
28+
// TODO: we should fix the sourceMappingURL written by Traceur instead of overriding
29+
// (but we might switch to typescript first)
30+
var mapFilepath = changedFilePath.replace(/\.\w+$/, '') + this.options.destSourceMapExtension;
31+
result.js = result.js + '\n//# sourceMappingURL=./' + path.basename(mapFilepath);
32+
33+
var destFilepath = changedFilePath.replace(/\.\w+$/, this.options.destExtension);
34+
var destFile = path.join(this.cachePath, destFilepath);
35+
fse.mkdirsSync(path.dirname(destFile));
36+
fs.writeFileSync(destFile, result.js, fsOpts);
37+
38+
var destMap = path.join(this.cachePath, mapFilepath);
39+
result.sourceMap.file = destFilepath;
40+
fs.writeFileSync(destMap, JSON.stringify(result.sourceMap), fsOpts);
4441
});
4542

4643
treeDiff.removedPaths.forEach((removedFilePath) => {
47-
var extension = path.extname(removedFilePath).toLowerCase();
48-
if (extension === '.js' || extension === '.es6' || extension === '.cjs') {
49-
var destFilepath = removedFilePath.replace(/\.\w+$/, this.options.destExtension);
50-
var absoluteOuputFilePath = path.join(this.cachePath, destFilepath);
51-
fs.unlinkSync(absoluteOuputFilePath);
52-
}
44+
var destFilepath = removedFilePath.replace(/\.\w+$/, this.options.destExtension);
45+
var absoluteOuputFilePath = path.join(this.cachePath, destFilepath);
46+
fs.unlinkSync(absoluteOuputFilePath);
5347
});
5448
}
5549
}

tools/broccoli/tree-differ.spec.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,95 @@ describe('TreeDiffer', () => {
102102
diffResult = differ.diffTree();
103103
expect(diffResult.changedPaths).toEqual(['file-1.txt']);
104104
});
105+
106+
107+
it('should ignore files with extensions not listed in includeExtensions', () => {
108+
let testDir = {
109+
'dir1': {
110+
'file-1.js': mockfs.file({content: 'file-1.js content', mtime: new Date(1000)}),
111+
'file-2.md': mockfs.file({content: 'file-2.md content', mtime: new Date(1000)}),
112+
'file-3.coffee': mockfs.file({content: 'file-3.coffee content', mtime: new Date(1000)}),
113+
'subdir-1': {
114+
'file-1.1.cc': mockfs.file({content: 'file-1.1.cc content', mtime: new Date(1000)})
115+
}
116+
}
117+
};
118+
mockfs(testDir);
119+
120+
let differ = new TreeDiffer('dir1', ['.js', '.coffee']);
121+
122+
let diffResult = differ.diffTree();
123+
124+
expect(diffResult.changedPaths).toEqual(['file-1.js', 'file-3.coffee']);
125+
126+
// change two files
127+
testDir['dir1']['file-1.js'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
128+
testDir['dir1']['file-3.coffee'] =
129+
mockfs.file({content: 'new content', mtime: new Date(1000)});
130+
testDir['dir1']['subdir-1']['file-1.1.cc'] =
131+
mockfs.file({content: 'file-1.1.cc content', mtime: new Date(9999)});
132+
mockfs(testDir);
133+
134+
diffResult = differ.diffTree();
135+
136+
expect(diffResult.changedPaths).toEqual(['file-1.js', 'file-3.coffee']);
137+
138+
expect(diffResult.removedPaths).toEqual([]);
139+
140+
// change one file
141+
testDir['dir1']['file-1.js'] = mockfs.file({content: 'super new', mtime: new Date(1000)});
142+
mockfs(testDir);
143+
144+
diffResult = differ.diffTree();
145+
expect(diffResult.changedPaths).toEqual(['file-1.js']);
146+
});
147+
148+
149+
it('should ignore files with extensions listed in excludeExtensions', () => {
150+
let testDir = {
151+
'dir1': {
152+
'file-1.ts': mockfs.file({content: 'file-1.ts content', mtime: new Date(1000)}),
153+
'file-1.cs': mockfs.file({content: 'file-1.cs content', mtime: new Date(1000)}),
154+
'file-1.d.cs': mockfs.file({content: 'file-1.d.cs content', mtime: new Date(1000)}),
155+
'file-2.md': mockfs.file({content: 'file-2.md content', mtime: new Date(1000)}),
156+
'file-3.ts': mockfs.file({content: 'file-3.ts content', mtime: new Date(1000)}),
157+
'file-4.d.ts': mockfs.file({content: 'file-4.d.ts content', mtime: new Date(1000)}),
158+
'subdir-1': {
159+
'file-1.1.cc': mockfs.file({content: 'file-1.1.cc content', mtime: new Date(1000)})
160+
}
161+
}
162+
};
163+
mockfs(testDir);
164+
165+
let differ = new TreeDiffer('dir1', ['.ts', '.cs'], ['.d.ts', '.d.cs']);
166+
167+
let diffResult = differ.diffTree();
168+
169+
expect(diffResult.changedPaths).toEqual(['file-1.cs', 'file-1.ts', 'file-3.ts']);
170+
171+
// change two files
172+
testDir['dir1']['file-1.ts'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
173+
testDir['dir1']['file-1.cs'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
174+
testDir['dir1']['file-1.d.cs'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
175+
testDir['dir1']['file-3.ts'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
176+
testDir['dir1']['file-4.d.ts'] = mockfs.file({content: 'new content', mtime: new Date(1000)});
177+
testDir['dir1']['subdir-1']['file-1.1.cc'] =
178+
mockfs.file({content: 'file-1.1.cc content', mtime: new Date(9999)});
179+
mockfs(testDir);
180+
181+
diffResult = differ.diffTree();
182+
183+
expect(diffResult.changedPaths).toEqual(['file-1.cs', 'file-1.ts', 'file-3.ts']);
184+
185+
expect(diffResult.removedPaths).toEqual([]);
186+
187+
// change one file
188+
testDir['dir1']['file-4.d.ts'] = mockfs.file({content: 'super new', mtime: new Date(1000)});
189+
mockfs(testDir);
190+
191+
diffResult = differ.diffTree();
192+
expect(diffResult.changedPaths).toEqual([]);
193+
});
105194
});
106195

107196
describe('diff of new files', () => {

tools/broccoli/tree-differ.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,24 @@ export class TreeDiffer {
88
private fingerprints: {[key: string]: string} = Object.create(null);
99
private nextFingerprints: {[key: string]: string} = Object.create(null);
1010
private rootDirName: string;
11+
private include: RegExp = null;
12+
private exclude: RegExp = null;
1113

12-
constructor(private rootPath: string) { this.rootDirName = path.basename(rootPath); }
14+
constructor(private rootPath: string, includeExtensions?: string[],
15+
excludeExtensions?: string[]) {
16+
this.rootDirName = path.basename(rootPath);
17+
18+
let buildRegexp = (arr) => new RegExp(`(${arr.reduce(combine, "")})$`, "i");
19+
20+
this.include = (includeExtensions || []).length ? buildRegexp(includeExtensions) : null;
21+
this.exclude = (excludeExtensions || []).length ? buildRegexp(excludeExtensions) : null;
22+
23+
function combine(prev, curr) {
24+
if (curr.charAt(0) !== ".") throw new TypeError("Extension must begin with '.'");
25+
curr = '(' + curr + ')';
26+
return prev ? (prev + '|' + curr) : curr;
27+
}
28+
}
1329

1430

1531
public diffTree(): DiffResult {
@@ -30,9 +46,12 @@ export class TreeDiffer {
3046
result.directoriesChecked++;
3147
this.dirtyCheckPath(absolutePath, result);
3248
} else {
33-
result.filesChecked++;
34-
if (this.isFileDirty(absolutePath, pathStat)) {
35-
result.changedPaths.push(path.relative(this.rootPath, absolutePath));
49+
if (!(this.include && !absolutePath.match(this.include)) &&
50+
!(this.exclude && absolutePath.match(this.exclude))) {
51+
result.filesChecked++;
52+
if (this.isFileDirty(absolutePath, pathStat)) {
53+
result.changedPaths.push(path.relative(this.rootPath, absolutePath));
54+
}
3655
}
3756
}
3857
});
@@ -62,9 +81,12 @@ export class TreeDiffer {
6281

6382
private detectDeletionsAndUpdateFingerprints(result: DiffResult) {
6483
for (let absolutePath in this.fingerprints) {
65-
if (this.fingerprints[absolutePath] !== null) {
66-
let relativePath = path.relative(this.rootPath, absolutePath);
67-
result.removedPaths.push(relativePath);
84+
if (!(this.include && !absolutePath.match(this.include)) &&
85+
!(this.exclude && absolutePath.match(this.exclude))) {
86+
if (this.fingerprints[absolutePath] !== null) {
87+
let relativePath = path.relative(this.rootPath, absolutePath);
88+
result.removedPaths.push(relativePath);
89+
}
6890
}
6991
}
7092

@@ -93,17 +115,17 @@ class DirtyCheckingDiffResult {
93115
constructor(public name: string) {}
94116

95117
toString() {
96-
return `${pad(this.name, 40)}, ` +
97-
`duration: ${pad(this.endTime - this.startTime, 5)}ms, ` +
118+
return `${pad(this.name, 40)}, duration: ${pad(this.endTime - this.startTime, 5)}ms, ` +
98119
`${pad(this.changedPaths.length + this.removedPaths.length, 5)} changes detected ` +
99120
`(files: ${pad(this.filesChecked, 5)}, directories: ${pad(this.directoriesChecked, 4)})`;
100121
}
101122

102123
log(verbose) {
103124
let prefixedPaths =
104125
this.changedPaths.map((p) => `* ${p}`).concat(this.removedPaths.map((p) => `- ${p}`));
105-
console.log(`Tree diff: ${this}` +
106-
((verbose && prefixedPaths.length) ? ` [\n ${prefixedPaths.join('\n ')}\n]` : ''));
126+
console.log(`Tree diff: ${this}` + ((verbose && prefixedPaths.length) ?
127+
` [\n ${prefixedPaths.join('\n ')}\n]` :
128+
''));
107129
}
108130
}
109131

0 commit comments

Comments
 (0)