Skip to content

Commit 0c56d22

Browse files
authored
Merge pull request broccolijs#474 from ef4/absolute-ignore
2 parents 81ec444 + 5fda57e commit 0c56d22

File tree

3 files changed

+57
-3
lines changed

3 files changed

+57
-3
lines changed

lib/watcher.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ interface WatcherOptions {
1111
debounce?: number;
1212
watcherAdapter?: WatcherAdapter;
1313
saneOptions?: sane.Options;
14+
15+
// list of absolute paths that we should not watch, even if they end up nested
16+
// beneath dirs that we are watching.
17+
ignored?: string[];
1418
}
1519

1620
// This Watcher handles all the Broccoli logic, such as debouncing. The
@@ -43,7 +47,8 @@ class Watcher extends EventEmitter {
4347
this._currentBuild = Promise.resolve();
4448
this.builder = builder;
4549
this.watcherAdapter =
46-
this.options.watcherAdapter || new WatcherAdapter(watchedNodes, this.options.saneOptions);
50+
this.options.watcherAdapter ||
51+
new WatcherAdapter(watchedNodes, this.options.saneOptions, this.options.ignored);
4752

4853
this._rebuildScheduled = false;
4954
this._ready = false;

lib/watcher_adapter.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@ import SourceNode from './wrappers/source-node';
44
import SourceNodeWrapper from './wrappers/source-node';
55
import bindFileEvent from './utils/bind-file-event';
66
import HeimdallLogger from 'heimdalljs-logger';
7+
import { isAbsolute, relative } from 'path';
78

89
const logger = new HeimdallLogger('broccoli:watcherAdapter');
910

1011
class WatcherAdapter extends EventEmitter {
1112
watchers: sane.Watcher[];
1213
watchedNodes: SourceNodeWrapper[];
1314
options: sane.Options;
15+
private ignored: string[] | undefined;
1416

15-
constructor(watchedNodes: SourceNodeWrapper[], options: sane.Options = {}) {
17+
constructor(
18+
watchedNodes: SourceNodeWrapper[],
19+
options: sane.Options = {},
20+
ignored: string[] | undefined = undefined
21+
) {
1622
super();
1723
if (!Array.isArray(watchedNodes)) {
1824
throw new TypeError(
@@ -29,13 +35,14 @@ class WatcherAdapter extends EventEmitter {
2935
}
3036
this.watchedNodes = watchedNodes;
3137
this.options = options;
38+
this.ignored = ignored;
3239
this.watchers = [];
3340
}
3441

3542
watch() {
3643
const watchers = this.watchedNodes.map((node: SourceNodeWrapper) => {
3744
const watchedPath = node.nodeInfo.sourceDirectory;
38-
const watcher = sane(watchedPath, this.options);
45+
const watcher = sane(watchedPath, this.optionsFor(watchedPath));
3946
this.watchers.push(watcher);
4047
bindFileEvent(this, watcher, node, 'change');
4148
bindFileEvent(this, watcher, node, 'add');
@@ -73,6 +80,26 @@ class WatcherAdapter extends EventEmitter {
7380
// eslint-disable-next-line @typescript-eslint/no-empty-function
7481
return Promise.all(closing).then(() => {});
7582
}
83+
84+
private optionsFor(watchedPath: string): sane.Options {
85+
let options = this.options;
86+
if (this.ignored) {
87+
// we need to convert any absolute ignored paths to local paths that sit
88+
// within the watchedPath
89+
const localIgnored = this.ignored
90+
.map(ignoredAbsPath => {
91+
const ignoredRelativePath = relative(watchedPath, ignoredAbsPath);
92+
if (!ignoredRelativePath.startsWith('..') && !isAbsolute(ignoredRelativePath)) {
93+
return ignoredRelativePath + '/**';
94+
}
95+
})
96+
.filter(Boolean) as string[];
97+
if (localIgnored.length > 0) {
98+
options = Object.assign({}, options, { ignored: localIgnored });
99+
}
100+
}
101+
return options;
102+
}
76103
}
77104

78105
export = WatcherAdapter;

test/watcher_adapter_test.js

+22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import TransformNodeWrapper from '../lib/wrappers/transform-node';
66
import SourceNodeWrapper from '../lib/wrappers/source-node';
77
import WatcherAdapter from '../lib/watcher_adapter';
88
import bindFileEvent from '../lib/utils/bind-file-event';
9+
import { join } from 'path';
910

1011
const expect = chai.expect;
1112
chai.use(sinonChai);
@@ -234,4 +235,25 @@ describe('WatcherAdapter', function() {
234235
});
235236
});
236237
});
238+
describe('optionsFor', function() {
239+
let adapter;
240+
beforeEach(function() {
241+
adapter = new WatcherAdapter([], {}, [join(__dirname, 'my-ignored-subdir')]);
242+
});
243+
afterEach(async function() {
244+
await adapter.quit();
245+
});
246+
it('generates a relative ignored path inside watchedDir', function() {
247+
const options = adapter.optionsFor(__dirname);
248+
expect(options.ignored).to.deep.eq(['my-ignored-subdir/**']);
249+
});
250+
it('generates no relative ignored paths when they are outside watchedDir', function() {
251+
const options = adapter.optionsFor('/somewhere/else');
252+
expect(options.ignored).to.eq(undefined);
253+
});
254+
it('is not fooled by name prefix matches', function() {
255+
const options = adapter.optionsFor(join(__dirname, 'my-ignored-subdir-just-kidding'));
256+
expect(options.ignored).to.eq(undefined);
257+
});
258+
});
237259
});

0 commit comments

Comments
 (0)