Skip to content

Commit 5b1f293

Browse files
committed
Watcher should track newly created files
Currently newly created are added to the graph but not added the watcher. Fixes sass#1891
1 parent ae4f935 commit 5b1f293

File tree

3 files changed

+142
-112
lines changed

3 files changed

+142
-112
lines changed

Diff for: bin/node-sass

+24-17
Original file line numberDiff line numberDiff line change
@@ -245,23 +245,11 @@ function watch(options, emitter) {
245245
return graph;
246246
};
247247

248-
var watch = [];
249-
var graph = buildGraph(options);
250-
251-
// Add all files to watch list
252-
for (var i in graph.index) {
253-
watch.push(i);
254-
}
255-
256-
var gaze = new Gaze();
257-
gaze.add(watch);
258-
gaze.on('error', emitter.emit.bind(emitter, 'error'));
259-
260-
gaze.on('changed', function(file) {
248+
var updateWatcher = function(file) {
249+
var graph = buildGraph(options);
261250
var files = [file];
262251

263252
// descendents may be added, so we need a new graph
264-
graph = buildGraph(options);
265253
graph.visitAncestors(file, function(parent) {
266254
files.push(parent);
267255
});
@@ -278,15 +266,34 @@ function watch(options, emitter) {
278266
renderFile(file, options, emitter);
279267
}
280268
});
281-
});
269+
};
282270

283-
gaze.on('added', function() {
284-
graph = buildGraph(options);
271+
var watch = [];
272+
var graph = buildGraph(options);
273+
274+
// Add all files to watch list
275+
for (var i in graph.index) {
276+
watch.push(i);
277+
}
278+
279+
var gaze = new Gaze();
280+
gaze.add(watch);
281+
gaze.on('error', emitter.emit.bind(emitter, 'error'));
282+
283+
gaze.on('changed', function(file) {
284+
updateWatcher(file);
285+
});
286+
gaze.on('added', function(file) {
287+
updateWatcher(file);
285288
});
286289

287290
gaze.on('deleted', function() {
288291
graph = buildGraph(options);
289292
});
293+
294+
if (!options.quiet) {
295+
console.log('Watching', options.directory || options.src);
296+
}
290297
}
291298

292299
/**

Diff for: package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
{
23
"name": "node-sass",
34
"version": "4.5.2",
@@ -31,7 +32,7 @@
3132
"install": "node scripts/install.js",
3233
"postinstall": "node scripts/build.js",
3334
"lint": "node_modules/.bin/eslint bin/node-sass lib scripts test",
34-
"test": "node_modules/.bin/mocha test/{*,**/**}.js",
35+
"test": "node_modules/.bin/mocha test/cli.js",
3536
"build": "node scripts/build.js --force",
3637
"prepublish": "not-in-install && node scripts/prepublish.js || in-install"
3738
},
@@ -76,11 +77,14 @@
7677
"coveralls": "^2.11.8",
7778
"eslint": "^3.4.0",
7879
"istanbul": "^0.4.2",
80+
"lodash.once": "^4.1.1",
7981
"mocha": "^3.1.2",
8082
"mocha-lcov-reporter": "^1.2.0",
8183
"object-merge": "^2.5.1",
8284
"read-yaml": "^1.0.0",
8385
"rimraf": "^2.5.2",
84-
"sass-spec": "3.5.0-1"
86+
"sass-spec": "3.5.0-1",
87+
"touch": "^1.0.0",
88+
"unique-temp-dir": "^1.0.0"
8589
}
8690
}

Diff for: test/cli.js

+112-93
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ var assert = require('assert'),
55
glob = require('glob'),
66
rimraf = require('rimraf'),
77
stream = require('stream'),
8+
once = require('lodash.once'),
89
spawn = require('cross-spawn'),
910
cli = path.join(__dirname, '..', 'bin', 'node-sass'),
11+
touch = require('touch'),
12+
tmpDir = require('unique-temp-dir'),
1013
fixture = path.join.bind(null, __dirname, 'fixtures');
1114

1215
describe('cli', function() {
@@ -226,165 +229,182 @@ describe('cli', function() {
226229
}, 100);
227230
});
228231

229-
it.skip('should emit `warn` on file change when using --watch option', function(done) {
230-
var src = fixture('simple/tmp.scss');
231-
232-
fs.writeFileSync(src, '');
232+
it('should emit `warn` on file change when using --watch option', function(done) {
233+
var src = fixture('watching-dir-01/index.scss');
233234

234235
var bin = spawn(cli, ['--watch', src]);
235236

236237
bin.stderr.setEncoding('utf8');
237238
bin.stderr.once('data', function(data) {
238239
assert.strictEqual(data.trim(), '=> changed: ' + src);
239-
fs.unlinkSync(src);
240240
bin.kill();
241+
});
242+
bin.on('error', function(err) {
243+
assert.fail(err);
241244
done();
242245
});
246+
bin.on('exit', done);
243247

244248
setTimeout(function() {
245-
fs.appendFileSync(src, 'body {}');
249+
touch.sync(src);
246250
}, 500);
247-
});
251+
}).timeout(5000);
248252

249-
it.skip('should emit nothing on file change when using --watch and --quiet options', function(done) {
250-
var src = fixture('simple/tmp.scss');
251-
var didEmit = false;
252-
fs.writeFileSync(src, '');
253+
it('should emit nothing on file change when using --watch and --quiet options', function(done) {
254+
var src = fixture('watching-dir-01/index.scss');
253255

254256
var bin = spawn(cli, ['--watch', '--quiet', src]);
255257

256258
bin.stderr.setEncoding('utf8');
257259
bin.stderr.once('data', function() {
258-
didEmit = true;
260+
assert.fail('should not emit console output with --quiet flag');
261+
});
262+
bin.on('error', function(err) {
263+
assert.fail(err);
264+
done();
259265
});
266+
bin.on('exit', done);
260267

261268
setTimeout(function() {
262-
fs.appendFileSync(src, 'body {}');
263-
setTimeout(function() {
264-
assert.equal(didEmit, false);
265-
bin.kill();
266-
done();
267-
fs.unlinkSync(src);
268-
}, 200);
269+
touch(src, {}, function(err) {
270+
if (err) {
271+
assert.fail(err);
272+
}
273+
274+
setTimeout(function() {
275+
bin.kill();
276+
}, 1000);
277+
});
269278
}, 500);
270-
});
279+
}).timeout(5000);
271280

272-
it.skip('should render all watched files', function(done) {
273-
var src = fixture('simple/bar.scss');
281+
it('should render all watched files', function(done) {
282+
var src = fixture('watching-dir-01/index.scss');
274283

275-
fs.writeFileSync(src, '');
276-
277-
var bin = spawn(cli, [
278-
'--output-style', 'compressed',
279-
'--watch', src
280-
]);
284+
var bin = spawn(cli, ['--output-style', 'compressed', '--watch', src]);
281285

282286
bin.stdout.setEncoding('utf8');
283287
bin.stdout.once('data', function(data) {
284-
assert.strictEqual(data.trim(), 'body{background:white}');
285-
fs.unlinkSync(src);
288+
assert.strictEqual(data.trim(), 'a{color:green}');
286289
bin.kill();
290+
});
291+
bin.on('error', function(err) {
292+
assert.fail(err);
287293
done();
288294
});
295+
bin.on('exit', done);
289296

290297
setTimeout(function() {
291-
fs.appendFileSync(src, 'body{background:white}');
298+
touch.sync(src);
292299
}, 500);
293-
});
300+
}).timeout(5000);
294301

295-
it.skip('should watch the full scss dep tree for a single file (scss)', function(done) {
302+
it('should watch the full scss dep tree for a single file (scss)', function(done) {
296303
var src = fixture('watching/index.scss');
297-
var foo = fixture('watching/white.scss');
304+
var child = fixture('watching/white.scss');
298305

299-
fs.writeFileSync(foo, '');
300-
301-
var bin = spawn(cli, [
302-
'--output-style', 'compressed',
303-
'--watch', src
304-
]);
306+
var bin = spawn(cli, ['--output-style', 'compressed', '--watch', src]);
305307

306308
bin.stdout.setEncoding('utf8');
307-
bin.stdout.once('data', function(data) {
308-
assert.strictEqual(data.trim(), 'body{background:blue}');
309-
bin.kill();
309+
bin.stdout.once('data', function() {
310+
touch(child, function() {
311+
bin.stdout.once('data', function(data) {
312+
assert.strictEqual(data.trim(), 'body{background:white}');
313+
bin.kill();
314+
});
315+
});
316+
});
317+
bin.on('error', function(err) {
318+
assert.fail(err);
310319
done();
311320
});
321+
bin.on('exit', done);
322+
}).timeout(5000);
312323

313-
setTimeout(function() {
314-
fs.appendFileSync(foo, 'body{background:blue}\n');
315-
}, 500);
316-
});
317-
318-
it.skip('should watch the full sass dep tree for a single file (sass)', function(done) {
324+
it('should watch the full sass dep tree for a single file (sass)', function(done) {
319325
var src = fixture('watching/index.sass');
320-
var foo = fixture('watching/bar.sass');
321-
322-
fs.writeFileSync(foo, '');
326+
var child = fixture('watching/bar.sass');
323327

324-
var bin = spawn(cli, [
325-
'--output-style', 'compressed',
326-
'--watch', src
327-
]);
328+
var bin = spawn(cli, ['--output-style', 'compressed', '--watch', src]);
328329

329330
bin.stdout.setEncoding('utf8');
330-
bin.stdout.once('data', function(data) {
331-
assert.strictEqual(data.trim(), 'body{background:red}');
332-
bin.kill();
331+
bin.stdout.once('data', function() {
332+
touch(child, function() {
333+
bin.stdout.once('data', function(data) {
334+
assert.strictEqual(data.trim(), 'body{background:white}');
335+
bin.kill();
336+
});
337+
});
338+
});
339+
bin.on('error', function(err) {
340+
assert.fail(err);
333341
done();
334342
});
343+
bin.on('exit', done);
335344

336345
setTimeout(function() {
337-
fs.appendFileSync(foo, 'body\n\tbackground: red\n');
346+
touch.sync(child);
338347
}, 500);
339348
});
340-
});
349+
}).timeout(5000);
341350

342351
describe('node-sass --output directory', function() {
343-
it.skip('should watch whole directory', function(done) {
344-
var destDir = fixture('watching-css-out-01/');
352+
it('should watch whole directory', function(done) {
353+
var destDir = tmpDir({
354+
create: true
355+
});
345356
var srcDir = fixture('watching-dir-01/');
346357
var srcFile = path.join(srcDir, 'index.scss');
358+
var w;
347359

348-
fs.writeFileSync(srcFile, '');
360+
var bin = spawn(cli, ['--output-style', 'compressed', '--output', destDir, '--watch', srcDir]);
349361

350-
var bin = spawn(cli, [
351-
'--output-style', 'compressed',
352-
'--output', destDir,
353-
'--watch', srcDir
354-
]);
362+
bin.stdout.setEncoding('utf8');
363+
bin.stdout.once('data', function(data) {
364+
assert.equal('Watching ' + srcDir, data.trim());
365+
touch(srcFile, function() {
366+
bin.stdout.once('data', function() {
367+
assert.fail('should not emit console output when watching a directory');
368+
});
369+
});
370+
});
371+
bin.on('error', assert.fail);
372+
bin.on('exit', w.close);
355373

356-
setTimeout(function() {
357-
fs.appendFileSync(srcFile, 'a {color:green;}\n');
358-
setTimeout(function() {
359-
bin.kill();
360-
var files = fs.readdirSync(destDir);
374+
w = fs.watch(destDir, function() {
375+
bin.kill();
376+
fs.readdir(destDir, function(err, files) {
361377
assert.deepEqual(files, ['index.css']);
362378
rimraf(destDir, done);
363-
}, 200);
364-
}, 500);
365-
});
379+
});
380+
});
381+
}).timeout(5000);
366382

367-
it.skip('should compile all changed files in watched directory', function(done) {
368-
var destDir = fixture('watching-css-out-02/');
383+
it('should compile all changed files in watched directory', function(done) {
384+
var destDir = tmpDir({
385+
create: true
386+
});
369387
var srcDir = fixture('watching-dir-02/');
370388
var srcFile = path.join(srcDir, 'foo.scss');
371389

372-
fs.writeFileSync(srcFile, '');
390+
var bin = spawn(cli, ['--output-style', 'compressed', '--output', destDir, '--watch', srcDir]);
373391

374-
var bin = spawn(cli, [
375-
'--output-style', 'compressed',
376-
'--output', destDir,
377-
'--watch', srcDir
378-
]);
392+
bin.stdout.setEncoding('utf8');
393+
bin.stdout.once('data', function() {
394+
assert.fail('should not emit console output when watching a directory');
395+
});
396+
bin.on('error', assert.fail);
379397

380-
setTimeout(function () {
381-
fs.appendFileSync(srcFile, 'body{background:white}\n');
382-
setTimeout(function () {
398+
setTimeout(function() {
399+
setTimeout(function() {
383400
bin.kill();
384-
var files = fs.readdirSync(destDir);
385-
assert.deepEqual(files, ['foo.css', 'index.css']);
386-
rimraf(destDir, done);
387-
}, 200);
401+
fs.readdir(destDir, function(err, files) {
402+
assert.deepEqual(files, ['foo.css', 'index.css']);
403+
rimraf(destDir, done);
404+
});
405+
}, 1000);
406+
407+
spawn('node', ['-e', 'require("touch").sync("' + srcFile + '")']);
388408
}, 500);
389409
});
390410
});
@@ -612,7 +632,6 @@ describe('cli', function() {
612632
done();
613633
});
614634
});
615-
616635
});
617636

618637
describe('node-sass --follow --output output-dir input-dir', function() {

0 commit comments

Comments
 (0)