mirror of
https://github.com/SrIzan10/nodemon.git
synced 2026-05-01 10:55:09 +00:00
@@ -4,6 +4,7 @@ WIP - but here's the TL;DR
|
||||
|
||||
## Issues
|
||||
|
||||
- Please include the output from `nodemon --dump` for diagnosis
|
||||
- If there's a script that nodemon is having trouble with or is causing nodemon to throw exceptions, please include it in your filed issue to allow me to replicate the issue.
|
||||
|
||||
## Sending pull requests
|
||||
|
||||
@@ -73,12 +73,14 @@ A config file can take any of the command line arguments as JSON key values, for
|
||||
|
||||
The above `nodemon.json` file might be my global config so that I have support for ruby files and processing files, and I can simply run `nodemon demo.pde` and nodemon will automatically know how to run the script even though out of the box support for processing scripts.
|
||||
|
||||
Note that `ignore` and `watch` values are *merged* with your CLI arguments, rather than overwritten.
|
||||
|
||||
A further example of options can be seen in [sample-nodemon.md]()
|
||||
|
||||
*This section needs better documentation, but for now you can also see `nodemon --help config` ([also here]())*.
|
||||
|
||||
## Using nodemon as a module
|
||||
|
||||
Please see [doc/requireable.md](doc/requireable.md)
|
||||
|
||||
## Running non-node scripts
|
||||
|
||||
nodemon can also be used to execute and monitor other programs. nodemon will read the file extension of the script being run and monitor that extension instead of .js if there's no .nodemonignore:
|
||||
|
||||
@@ -12,6 +12,5 @@ if (notifier.update) {
|
||||
}
|
||||
|
||||
var options = cli.parse(process.argv);
|
||||
options.restartable = 'rs';
|
||||
|
||||
nodemon(options);
|
||||
3
doc/cli/usage.txt
Normal file
3
doc/cli/usage.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
Usage: nodemon [nodemon options] [script.js] [args]
|
||||
|
||||
See "nodemon --help" for more.
|
||||
34
doc/rules.md
Normal file
34
doc/rules.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Rules
|
||||
|
||||
Given a nodemon.json file that contains:
|
||||
|
||||
```json
|
||||
{
|
||||
"ignore": ["*.coffee"],
|
||||
"watch": ["server/*.coffee", "test/"]
|
||||
}
|
||||
```
|
||||
|
||||
Then nodemon detects changes, but what causes nodemon to restart? The ignored files or the watched files? Which wins?
|
||||
|
||||
```js
|
||||
var files = ['server/foo.coffee', 'server/app.js'];
|
||||
|
||||
// afterIgnore = ['server/app.js'] now since foo.coffee matches *.coffee
|
||||
var afterIgnore = files.filter(applyIgnore);
|
||||
|
||||
// watch = ['server/foo.coffee'] as it's under the watch
|
||||
var watched = files.filter(applyWatch);
|
||||
```
|
||||
|
||||
What about:
|
||||
|
||||
```js
|
||||
var files = ['test/app.js', 'test/app.coffee'];
|
||||
|
||||
// afterIgnore = ['test/app.js'] now since test/app.coffee matches *.coffee
|
||||
var afterIgnore = files.filter(applyIgnore);
|
||||
|
||||
// watch.length = 2 as watch implies test/*.*
|
||||
var watched = files.filter(applyWatch);
|
||||
```
|
||||
@@ -1,5 +1,6 @@
|
||||
// default options for config.options
|
||||
module.exports = {
|
||||
restartable: 'rs',
|
||||
execMap: {
|
||||
py: 'python',
|
||||
rb: 'ruby'
|
||||
@@ -7,8 +8,8 @@ module.exports = {
|
||||
// compatible with linux, mac and windows, or make the default.js dynamically
|
||||
// append the `.cmd` for node based utilities
|
||||
},
|
||||
watch: [],
|
||||
ignore: [],
|
||||
ignore: ['.git/', 'node_modules/**/node_modules/'],
|
||||
watch: ['*.*'],
|
||||
stdin: true,
|
||||
verbose: false
|
||||
};
|
||||
@@ -22,11 +22,16 @@ function exec(nodemonOptions, execMap) {
|
||||
var options = utils.clone(nodemonOptions || {}),
|
||||
script = path.basename(options.script || ''),
|
||||
scriptExt = path.extname(script),
|
||||
extension = options.ext || scriptExt || '.js';
|
||||
extension = options.ext || scriptExt || 'js';
|
||||
|
||||
// strip any leading periods int he extension
|
||||
if (extension.indexOf('.') === 0) {
|
||||
extension = extension.slice(1);
|
||||
}
|
||||
|
||||
// allows the user to simplify cli usage: https://github.com/remy/nodemon/issues/195
|
||||
if (execMap[extension.slice(1)] !== undefined) {
|
||||
options.exec = execMap[extension.slice(1)];
|
||||
if (execMap[extension] !== undefined) {
|
||||
options.exec = execMap[extension];
|
||||
}
|
||||
|
||||
if (options.exec === undefined) {
|
||||
@@ -71,7 +76,7 @@ function exec(nodemonOptions, execMap) {
|
||||
if (options.exec === 'coffee') {
|
||||
// don't override user specified extension tracking
|
||||
if (!options.ext) {
|
||||
extension = '.coffee|.litcoffee|.js';
|
||||
extension = 'coffee litcoffee js';
|
||||
}
|
||||
|
||||
// because windows can't find 'coffee', it needs the real file 'coffee.cmd'
|
||||
@@ -94,13 +99,13 @@ function exec(nodemonOptions, execMap) {
|
||||
.replace(/,/g, '|') // convert commas to pipes
|
||||
.split('|') // split on those pipes
|
||||
.map(function (item) {
|
||||
return '.' + item.replace(/^[\*\.]+/, ''); // remove "*."
|
||||
}).join('$|'); // return regexp string like: .js$|.jade$
|
||||
return item.replace(/^[\*\.]+/, ''); // remove "*."
|
||||
}).join(','); // return regexp string like: .js$|.jade$
|
||||
}
|
||||
|
||||
// this final part ensures both multiple extension and
|
||||
// single extensions work
|
||||
extension += '$';
|
||||
// extension += '$';
|
||||
|
||||
options.ext = extension;
|
||||
|
||||
|
||||
@@ -6,22 +6,30 @@
|
||||
* This is *not* the user's config.
|
||||
*/
|
||||
var load = require('./load'),
|
||||
bus = require('../utils/bus'),
|
||||
rules = require('../rules'),
|
||||
utils = require('../utils'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
existsSync = fs.existsSync || path.existsSync,
|
||||
bus = utils.bus,
|
||||
checkWatchSupport = require('./checkWatchSupport');
|
||||
|
||||
function reset() {
|
||||
rules.reset();
|
||||
|
||||
config.dirs = [];
|
||||
config.options = { ignore: [], watch: [] };
|
||||
config.lastStarted = 0;
|
||||
config.loaded = [];
|
||||
}
|
||||
|
||||
var config = {
|
||||
run: false,
|
||||
system: {
|
||||
// TODO decide whether we need both of these
|
||||
noWatch: false,
|
||||
watchWorks: false,
|
||||
},
|
||||
required: false,
|
||||
dirs: [],
|
||||
ignoring: [],
|
||||
timeout: 1000,
|
||||
options: {}
|
||||
};
|
||||
@@ -36,26 +44,64 @@ var config = {
|
||||
* @param {Function} ready callback fired once the config is loaded
|
||||
*/
|
||||
config.load = function (settings, ready) {
|
||||
reset();
|
||||
var config = this;
|
||||
load(settings, config.options, config, function (options) {
|
||||
config.options = options;
|
||||
|
||||
if (options.execOptions.ext) {
|
||||
rules.watch.add(new RegExp(options.execOptions.ext));
|
||||
if (options.watch && options.watch.length) {
|
||||
options.monitor = utils.clone(options.watch);
|
||||
}
|
||||
|
||||
// read directories to monitor
|
||||
options.watch.forEach(function (dir) {
|
||||
dir = path.resolve(dir);
|
||||
if (existsSync(config.dir)) {
|
||||
config.dirs.push(path.resolve(config.dir));
|
||||
}
|
||||
});
|
||||
if (options.ignore) {
|
||||
[].push.apply(options.monitor, (options.ignore || []).map(function (rule) {
|
||||
return '!' + rule;
|
||||
}));
|
||||
}
|
||||
|
||||
// if (options.execOptions.ext) {
|
||||
// options.execOptions.ext.split(',').forEach(function (ext) {
|
||||
// options.monitor.push(ext);
|
||||
// });
|
||||
// }
|
||||
|
||||
// delete options.watch;
|
||||
// delete options.ignore;
|
||||
|
||||
var cwd = process.cwd();
|
||||
|
||||
if (config.dirs.length === 0) {
|
||||
config.dirs.unshift(process.cwd());
|
||||
config.dirs.unshift(cwd);
|
||||
}
|
||||
|
||||
// next check if the monitored paths are actual directories
|
||||
// or just patterns - and expand the rule to include *.*
|
||||
options.monitor = options.monitor.map(function (rule) {
|
||||
var not = rule.slice(0, 1) === '!';
|
||||
|
||||
if (rule.slice(-1) === '/') {
|
||||
// just slap on a * anyway
|
||||
return rule + '*';
|
||||
}
|
||||
|
||||
if (not) {
|
||||
rule = rule.slice(1);
|
||||
}
|
||||
|
||||
var dir = path.resolve(cwd, rule);
|
||||
|
||||
try {
|
||||
var stat = fs.statSync(dir);
|
||||
if (stat.isDirectory()) {
|
||||
if (rule.slice(-1) !== '/') {
|
||||
rule += '/';
|
||||
}
|
||||
rule += '*';
|
||||
}
|
||||
} catch (e) {}
|
||||
return (not ? '!' : '') + rule;
|
||||
});
|
||||
|
||||
// now run automatic checks on system adding to the config object
|
||||
checkWatchSupport(config, function (config) {
|
||||
bus.emit('config:update', config);
|
||||
@@ -64,5 +110,7 @@ config.load = function (settings, ready) {
|
||||
});
|
||||
};
|
||||
|
||||
config.reset = reset;
|
||||
|
||||
module.exports = config;
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ function load(settings, options, config, callback) {
|
||||
|
||||
// if we didn't pick up a nodemon.json file & there's no cli ignores
|
||||
// then try loading an old style .nodemonignore file
|
||||
if (config.loaded.length === 0 && options.ignore.length === 0) {
|
||||
if (config.loaded.length === 0) {
|
||||
// TODO decide whether this is just confusing...
|
||||
var legacy = loadLegacyIgnore.bind(null, options, ready);
|
||||
|
||||
@@ -129,6 +129,10 @@ function loadFile(options, config, dir, ready) {
|
||||
ready = function () {};
|
||||
}
|
||||
|
||||
if (!dir) {
|
||||
return callback({});
|
||||
}
|
||||
|
||||
var callback = function (settings) {
|
||||
// prefer the local nodemon.json and fill in missing items using
|
||||
// the global options
|
||||
|
||||
77
lib/monitor/match.js
Normal file
77
lib/monitor/match.js
Normal file
@@ -0,0 +1,77 @@
|
||||
'use strict';
|
||||
|
||||
var minimatch = require('minimatch'),
|
||||
path = require('path'),
|
||||
utils = require('../utils');
|
||||
|
||||
module.exports = match;
|
||||
|
||||
function match(files, monitor, ext) {
|
||||
// sort the rules by highest specificity (based on number of slashes)
|
||||
// TODO actually check separator rules work on windows
|
||||
var rules = monitor.sort(function (a, b) {
|
||||
var r = b.split(path.sep).length - a.split(path.sep).length;
|
||||
|
||||
if (r === 0) {
|
||||
return b.length - a.length;
|
||||
}
|
||||
return r;
|
||||
}).map(function (s) {
|
||||
var prefix = s.slice(0, 1),
|
||||
sep = path.sep;
|
||||
|
||||
if (prefix === '!') {
|
||||
return '!**' + (s.slice(0, 1) !== '/' ? '/' : '') + s.slice(1);
|
||||
}
|
||||
return '**' + (s.slice(0, 1) !== '/' ? '/' : '') + s;
|
||||
});
|
||||
|
||||
var good = [],
|
||||
ignored = 0,
|
||||
watched = 0;
|
||||
|
||||
files.forEach(function (file) {
|
||||
var matched = false;
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
if (rules[i].slice(0, 1) === '!') {
|
||||
if (!minimatch(file, rules[i])) {
|
||||
ignored++;
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (minimatch(file, rules[i])) {
|
||||
watched++;
|
||||
utils.log.detail('matched rule: ' + rules[i]);
|
||||
good.push(file);
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
ignored++;
|
||||
}
|
||||
});
|
||||
|
||||
// finally check the good files against the extensions that we're monitoring
|
||||
if (ext) {
|
||||
if (ext.indexOf(',') === -1) {
|
||||
ext = '**/*.' + ext;
|
||||
} else {
|
||||
ext = '**/*.{' + ext + '}';
|
||||
}
|
||||
|
||||
// console.log('before', good, ext);
|
||||
good = good.filter(function(file) {
|
||||
return minimatch(file, ext);
|
||||
});
|
||||
} // else assume *.*
|
||||
|
||||
return {
|
||||
result: good,
|
||||
ignored: ignored,
|
||||
watched: watched,
|
||||
total: files.length
|
||||
};
|
||||
}
|
||||
@@ -162,12 +162,23 @@ bus.on('quit', function () {
|
||||
}
|
||||
};
|
||||
|
||||
// if we're not running already, don't bother with trying to kill
|
||||
if (config.run === false) {
|
||||
return exit();
|
||||
}
|
||||
|
||||
// immediately try to stop any polling
|
||||
config.run = false;
|
||||
|
||||
if (child) {
|
||||
child.removeAllListeners('exit');
|
||||
child.on('exit', exit);
|
||||
child.kill('SIGINT');
|
||||
// give up waiting for the kids after 10 seconds
|
||||
setTimeout(exit, 10 * 1000);
|
||||
} else {
|
||||
exit();
|
||||
}
|
||||
setTimeout(exit, 10 * 1000); // give up waiting for the kids after 10 seconds
|
||||
});
|
||||
|
||||
bus.on('restart', function () {
|
||||
|
||||
@@ -4,6 +4,7 @@ var fs = require('fs'),
|
||||
changedSince = require('./changed-since'),
|
||||
utils = require('../utils'),
|
||||
bus = utils.bus,
|
||||
match = require('./match'),
|
||||
config = require('../config'),
|
||||
childProcess = require('child_process'),
|
||||
exec = childProcess.exec,
|
||||
@@ -102,7 +103,7 @@ bus.on('config:update', function () {
|
||||
|
||||
// filter ignored files
|
||||
function ignoredFilter(file) {
|
||||
if (config.options.ignore.length) {
|
||||
if (config.options.ignore.length && config.options.ignore.re) {
|
||||
// If we are in a Windows machine
|
||||
if (utils.isWindows) {
|
||||
// Break up the file by slashes
|
||||
@@ -122,35 +123,29 @@ function ignoredFilter(file) {
|
||||
}
|
||||
|
||||
function filterAndRestart(files) {
|
||||
var data = {};
|
||||
if (files.length) {
|
||||
data.all = files.length;
|
||||
utils.log.detail('files trigggering change check: ' + files.join('\n'));
|
||||
var cwd = process.cwd();
|
||||
utils.log.detail('files triggering change check: ' + files.map(function (file) {
|
||||
return path.relative(cwd, file);
|
||||
}).join(', '));
|
||||
|
||||
files = files.filter(ignoredFilter);
|
||||
|
||||
data.ignore = files.length;
|
||||
|
||||
if (config.options.watch.length) {
|
||||
files = files.filter(function (file) {
|
||||
return config.options.watch.re.test(file);
|
||||
});
|
||||
if (!config.options.execOptions) {
|
||||
console.log(config);
|
||||
}
|
||||
var matched = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
data.watch = files.length;
|
||||
|
||||
utils.log.detail('changes after filters (pre/ignored/valid): ' + [data.all, data.ignore, data.watch].join('/'));
|
||||
utils.log.detail('changes after filters (before/after): ' + [files.length, matched.result.length].join('/'));
|
||||
|
||||
// reset the last check so we're only looking at recently modified files
|
||||
config.lastStarted = Date.now();
|
||||
|
||||
if (files.length) {
|
||||
if (matched.result.length) {
|
||||
if (restartTimer !== null) {
|
||||
clearTimeout(restartTimer);
|
||||
}
|
||||
restartTimer = setTimeout(function () {
|
||||
utils.log.status('restarting due to changes...');
|
||||
files.forEach(function (file) {
|
||||
matched.result.forEach(function (file) {
|
||||
utils.log.detail(path.relative(process.cwd(), file));
|
||||
});
|
||||
if (config.options.verbose) {
|
||||
@@ -165,22 +160,28 @@ function filterAndRestart(files) {
|
||||
}
|
||||
|
||||
if (config.system.noWatch || config.options.forceLegacyWatch) {
|
||||
setTimeout(monitor, config.timeout);
|
||||
if (config.run) {
|
||||
setTimeout(watch, config.timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var monitor = module.exports = function () {
|
||||
var watch = module.exports = function () {
|
||||
// if we have noWatch or watchWorks (i.e. not using `find`)
|
||||
// then called `changeFunction` which is local to this script
|
||||
if ((config.system.noWatch || config.system.watchWorks) && !config.options.forceLegacyWatch) {
|
||||
changeFunction(config.lastStarted, function (files) {
|
||||
filterAndRestart(files);
|
||||
if (config.run) {
|
||||
filterAndRestart(files);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Fallback for when both find and fs.watch don't work
|
||||
// using the `changedSince` which is external
|
||||
changedSince(config.lastStarted, function (files) {
|
||||
filterAndRestart(files);
|
||||
if (config.run) {
|
||||
filterAndRestart(files);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -4,6 +4,7 @@ var monitor = require('./monitor'),
|
||||
version = require('./version'),
|
||||
util = require('util'),
|
||||
utils = require('./utils'),
|
||||
rules = require('./rules'),
|
||||
bus = utils.bus,
|
||||
help = require('./help'),
|
||||
config = require('./config'),
|
||||
@@ -14,21 +15,15 @@ var monitor = require('./monitor'),
|
||||
config.required = utils.isRequired;
|
||||
|
||||
function nodemon(settings) {
|
||||
nodemon.removeAllListners();
|
||||
utils.reset();
|
||||
|
||||
// set the debug flag as early as possible to get all the detailed logging
|
||||
if (settings.verbose) {
|
||||
utils.debug = true;
|
||||
}
|
||||
nodemon.reset();
|
||||
|
||||
if (typeof settings === 'string') {
|
||||
settings = cli.parse(settings);
|
||||
}
|
||||
|
||||
// by default, ignore .git and node_modules
|
||||
if (!settings.ignore) {
|
||||
settings.ignore = ['.git', 'node_modules/**/node_modules'];
|
||||
// set the debug flag as early as possible to get all the detailed logging
|
||||
if (settings.verbose) {
|
||||
utils.debug = true;
|
||||
}
|
||||
|
||||
if (settings.help) {
|
||||
@@ -45,10 +40,18 @@ function nodemon(settings) {
|
||||
}
|
||||
}
|
||||
|
||||
// always echo out the current version
|
||||
utils.log.info(version);
|
||||
|
||||
config.load(settings, function (config) {
|
||||
if (!config.options.script) {
|
||||
if (!config.required) {
|
||||
console.log(help('usage'));
|
||||
process.exit();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// always echo out the current version
|
||||
utils.log.info(version);
|
||||
|
||||
// echo out notices about running state
|
||||
if (config.options.restartable) {
|
||||
// allow nodemon to restart when the use types 'rs\n'
|
||||
@@ -93,15 +96,20 @@ function nodemon(settings) {
|
||||
utils.log.info('to restart at any time, enter `' + config.options.restartable + '`');
|
||||
}
|
||||
|
||||
config.dirs.forEach(function (dir) {
|
||||
utils.log.info('watching: ' + dir);
|
||||
});
|
||||
var none = function (v) {
|
||||
return v;
|
||||
};
|
||||
|
||||
utils.log.detail('ignoring: ' + config.options.monitor.map(function (rule) {
|
||||
return rule.slice(0, 1) === '!' ? rule.slice(1) : false;
|
||||
}).filter(none).join(' '));
|
||||
|
||||
utils.log.info('watching: ' + config.options.monitor.map(function (rule) {
|
||||
return rule.slice(0, 1) !== '!' ? rule : false;
|
||||
}).filter(none).join(' '));
|
||||
|
||||
utils.log.detail('watching extensions: ' + config.options.ext);
|
||||
|
||||
config.options.ignore.forEach(function (pattern) {
|
||||
utils.log.detail('ignoring: ' + pattern);
|
||||
});
|
||||
|
||||
if (config.options.dump) {
|
||||
utils.log._log('log', '--------------');
|
||||
@@ -118,6 +126,7 @@ function nodemon(settings) {
|
||||
}
|
||||
}
|
||||
|
||||
config.run = true;
|
||||
monitor.run(config.options);
|
||||
});
|
||||
|
||||
@@ -141,7 +150,7 @@ nodemon.once = function (event, handler) {
|
||||
if (!eventHandlers[event]) { eventHandlers[event] = []; }
|
||||
eventHandlers[event].push(handler);
|
||||
bus.once(event, function () {
|
||||
eventHandlers[event].splice(eventHandlers[event].indexOf(handler), 0);
|
||||
eventHandlers[event].splice(eventHandlers[event].indexOf(handler), 1);
|
||||
handler.apply(this, arguments);
|
||||
});
|
||||
return nodemon;
|
||||
@@ -159,7 +168,7 @@ nodemon.removeAllListners = function (event) {
|
||||
}).forEach(function (event) {
|
||||
eventHandlers[event].forEach(function (handler) {
|
||||
bus.removeListener(event, handler);
|
||||
eventHandlers[event].splice(eventHandlers[event].indexOf(handler), 0);
|
||||
eventHandlers[event].splice(eventHandlers[event].indexOf(handler), 1);
|
||||
});
|
||||
// delete eventHandlers[event];
|
||||
});
|
||||
@@ -167,21 +176,30 @@ nodemon.removeAllListners = function (event) {
|
||||
return nodemon;
|
||||
};
|
||||
|
||||
nodemon.reset = function () {
|
||||
// console.trace();
|
||||
nodemon.removeAllListners();
|
||||
utils.reset();
|
||||
rules.reset();
|
||||
config.run = false;
|
||||
};
|
||||
|
||||
// expose the full config
|
||||
nodemon.config = config;
|
||||
|
||||
|
||||
// on exception *inside* nodemon, shutdown wrapped node app
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.error('exception in nodemon killing node');
|
||||
console.error(err.stack);
|
||||
console.error();
|
||||
console.error('If appropriate, please file an error: http://github.com/remy/nodemon/issues/new\n');
|
||||
if (!config.required) {
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
if (!config.required) {
|
||||
process.on('uncaughtException', function (err) {
|
||||
console.error('exception in nodemon killing node');
|
||||
console.error(err.stack);
|
||||
console.error();
|
||||
console.error('If appropriate, please file an error: http://github.com/remy/nodemon/issues/new\n');
|
||||
if (!config.required) {
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = nodemon;
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
var utils = require('../utils');
|
||||
|
||||
// internal
|
||||
var reEscComments = /\\#/g,
|
||||
reUnescapeComments = /\^\^/g, // note that '^^' is used in place of escaped comments
|
||||
@@ -39,7 +43,9 @@ function add(rules, which, rule) {
|
||||
// support the rule being a RegExp, but reformat it to
|
||||
// the custom :<regexp> format that we're working with.
|
||||
if (rule instanceof RegExp) {
|
||||
rule = ':' + rule.toString().replace(/^\/(.*?)\/$/g, '$1');
|
||||
// rule = ':' + rule.toString().replace(/^\/(.*?)\/$/g, '$1');
|
||||
utils.log.error('RegExp format no longer supported, but globs are.');
|
||||
return;
|
||||
}
|
||||
|
||||
// remove comments and trim lines
|
||||
@@ -54,6 +60,7 @@ function add(rules, which, rule) {
|
||||
|
||||
if (typeof rule === 'string' && rule.substring(0, 1) === ':') {
|
||||
rule = rule.substring(1);
|
||||
utils.log.error('RegExp no longer supported: ' + rule);
|
||||
regexp = true;
|
||||
} else if (rule.length === 0) {
|
||||
// blank line (or it was a comment)
|
||||
@@ -61,14 +68,19 @@ function add(rules, which, rule) {
|
||||
}
|
||||
|
||||
if (regexp) {
|
||||
rules[which].push(rule);
|
||||
// rules[which].push(rule);
|
||||
} else {
|
||||
rule = rule.replace(reEscapeChars, '\\$&')
|
||||
.replace(reAsterisk, '.*');
|
||||
// rule = rule.replace(reEscapeChars, '\\$&')
|
||||
// .replace(reAsterisk, '.*');
|
||||
|
||||
rules[which].push(rule);
|
||||
}
|
||||
// compile a regexp of all the rules for this ignore or watch
|
||||
var re = rules[which].map(function (rule) {
|
||||
return rule.replace(reEscapeChars, '\\$&')
|
||||
.replace(reAsterisk, '.*');
|
||||
}).join('|');
|
||||
|
||||
// compile a regexp of all the rules for this ignore or watch
|
||||
rules[which].re = new RegExp(rules[which].join('|'));
|
||||
// used for the directory matching
|
||||
rules[which].re = new RegExp(re);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,8 @@ function load(filename, callback) {
|
||||
module.exports = {
|
||||
reset: function () { // just used for testing
|
||||
rules.ignore.length = rules.watch.length = 0;
|
||||
delete rules.ignore.re;
|
||||
delete rules.watch.re;
|
||||
},
|
||||
load: load,
|
||||
ignore: {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use strict';
|
||||
var events = require('events'),
|
||||
util = require('util');
|
||||
|
||||
|
||||
@@ -22,17 +22,20 @@ var utils = module.exports = {
|
||||
// nukes the logging
|
||||
if (!this.debug) {
|
||||
Object.keys(this.log).forEach(function (method) {
|
||||
// this.log[method] = noop;
|
||||
this.log[method] = noop;
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
reset: function () {
|
||||
if (!this.debug) {
|
||||
Object.keys(this.log).forEach(function (method) {
|
||||
// delete this.log[method];
|
||||
delete this.log[method];
|
||||
}.bind(this));
|
||||
}
|
||||
this.debug = false;
|
||||
},
|
||||
regexpToText: function (t) {
|
||||
return t.replace(/\.\*\\./g, '*.').replace(/\\{2}/g, '^^').replace(/\\/g, '').replace(/\^\^/g, '\\');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ Logger.prototype.required = function (val) {
|
||||
Logger.prototype.debug = false;
|
||||
Logger.prototype._log = function (type, msg) {
|
||||
if (required) {
|
||||
bus.emit('log', { type: type, message: msg, colour: msg });
|
||||
bus.emit('log', { type: type, message: msg || '', colour: msg || '' });
|
||||
} else if (type === 'error') {
|
||||
util.error(msg);
|
||||
} else {
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
],
|
||||
"main": "./lib/nodemon",
|
||||
"scripts": {
|
||||
"coverage": "istanbul cover _mocha -- --timeout 15000 --ui bdd --reporter list test/**/*.test.js",
|
||||
"test": "node_modules/mocha/bin/_mocha --timeout 15000 --ui bdd --reporter list test/**/*.test.js",
|
||||
"coverage": "istanbul cover _mocha -- --timeout 20000 --ui bdd --reporter list test/**/*.test.js",
|
||||
"test": "node_modules/mocha/bin/_mocha --timeout 20000 --ui bdd test/**/*.test.js",
|
||||
"web": "node web"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -43,6 +43,7 @@
|
||||
"touch": "0.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"update-notifier": "~0.1.7"
|
||||
"update-notifier": "~0.1.7",
|
||||
"minimatch": "~0.2.14"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,16 @@ var exec = require('../../lib/config/exec'),
|
||||
describe('nodemon exec', function () {
|
||||
it('should default to node', function () {
|
||||
var options = exec({ script: 'index.js' });
|
||||
assert(options.exec === 'node');
|
||||
assert(options.ext === '.js$');
|
||||
assert(options.exec === 'node', 'exec is node');
|
||||
assert(options.ext === 'js');
|
||||
});
|
||||
|
||||
it('should support --debug', function () {
|
||||
var options = exec({ script: 'app.js', nodeArgs: [ '--debug' ]});
|
||||
|
||||
assert(options.exec === 'node');
|
||||
assert(options.execArgs.indexOf('--debug') !== -1);
|
||||
assert(options.ext.indexOf('.js') !== -1);
|
||||
assert(options.exec === 'node', 'exec is node');
|
||||
assert(options.execArgs.indexOf('--debug') !== -1, '--debug is in the execArgs');
|
||||
assert(options.ext.indexOf('js') !== -1, 'extension watched is .js');
|
||||
});
|
||||
|
||||
it('should support --debug=XXXX', function () {
|
||||
@@ -24,7 +24,7 @@ describe('nodemon exec', function () {
|
||||
|
||||
assert(options.exec === 'node');
|
||||
assert(options.execArgs.indexOf('--debug=9999') !== -1);
|
||||
assert(options.ext.indexOf('.js') !== -1);
|
||||
assert(options.ext.indexOf('js') !== -1);
|
||||
});
|
||||
|
||||
it('should support multiple extensions', function () {
|
||||
@@ -58,7 +58,7 @@ describe('nodemon exec', function () {
|
||||
it('should use coffeescript on .coffee', function () {
|
||||
var options = exec({ script: 'index.coffee' });
|
||||
assert(options.exec.indexOf('coffee') === 0, 'using coffeescript to execute');
|
||||
assert(options.ext.indexOf('.coffee') !== -1);
|
||||
assert(options.ext.indexOf('coffee') !== -1);
|
||||
});
|
||||
|
||||
it('should support coffeescript in debug mode', function () {
|
||||
@@ -66,14 +66,14 @@ describe('nodemon exec', function () {
|
||||
|
||||
assert(options.exec.indexOf('coffee') === 0, 'using coffeescript to execute');
|
||||
assert(options.execArgs.indexOf('--debug') !== -1);
|
||||
assert(options.ext.indexOf('.coffee') !== -1);
|
||||
assert(options.ext.indexOf('coffee') !== -1);
|
||||
});
|
||||
|
||||
it('should support custom execs', function () {
|
||||
var options = exec({ script: 'app.py', exec: 'python'});
|
||||
|
||||
assert(options.exec === 'python');
|
||||
assert(options.ext.indexOf('.py') !== -1);
|
||||
assert(options.ext.indexOf('py') !== -1);
|
||||
});
|
||||
|
||||
it('should support custom executables with arguments', function () {
|
||||
@@ -81,7 +81,7 @@ describe('nodemon exec', function () {
|
||||
|
||||
assert(options.exec === 'python');
|
||||
assert(options.execArgs.indexOf('--debug') !== -1);
|
||||
assert(options.ext.indexOf('.py') !== -1);
|
||||
assert(options.ext.indexOf('py') !== -1);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,10 +1,12 @@
|
||||
'use strict';
|
||||
/*global describe:true, it: true, afterEach: true, beforeEach: true */
|
||||
/*global describe:true, it: true, afterEach: true, beforeEach: true, after:true */
|
||||
var load = require('../../lib/config/load'),
|
||||
path = require('path'),
|
||||
testUtils = require('../utils'),
|
||||
utils = require('../../lib/utils'),
|
||||
rules = require('../../lib/rules'),
|
||||
exec = require('../../lib/config/exec'),
|
||||
nodemon = require('../../lib/nodemon'),
|
||||
assert = require('assert');
|
||||
|
||||
describe('config load', function () {
|
||||
@@ -16,13 +18,19 @@ describe('config load', function () {
|
||||
utils.home = oldhome;
|
||||
});
|
||||
|
||||
after(function (done) {
|
||||
// clean up just in case.
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
});
|
||||
|
||||
function removeRegExp(options) {
|
||||
delete options.watch.re;
|
||||
delete options.ignore.re;
|
||||
}
|
||||
|
||||
utils.quiet();
|
||||
|
||||
beforeEach(function () {
|
||||
// move to the fixtures directory to allow for config loading
|
||||
process.chdir(path.resolve(pwd, 'test/fixtures'));
|
||||
@@ -31,6 +39,30 @@ describe('config load', function () {
|
||||
rules.reset();
|
||||
});
|
||||
|
||||
it('should remove ignore defaults if user provides their own', function (done) {
|
||||
|
||||
nodemon({
|
||||
script: testUtils.appjs,
|
||||
verbose: true
|
||||
}).on('log', function (event) {
|
||||
// console.log(event.colour);
|
||||
}).on('start', function () {
|
||||
assert.ok(nodemon.config.options.ignore.indexOf('one') !== -1, 'Contains "one" path');
|
||||
assert.ok(nodemon.config.options.ignore.indexOf('three') !== -1, 'Contains "three" path');
|
||||
// note: we use the escaped format: \\.git
|
||||
assert.ok(nodemon.config.options.ignore.indexOf('\\.git') === -1, 'nodemon is not ignoring (default) .git');
|
||||
|
||||
nodemon.on('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
nodemon.emit('quit');
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
it('should support old .nodemonignore', function (done) {
|
||||
// prevents our test from finding the nodemon.json files
|
||||
process.chdir(path.resolve(pwd, 'test/fixtures/legacy'));
|
||||
@@ -41,8 +73,7 @@ describe('config load', function () {
|
||||
options = {};
|
||||
|
||||
load(settings, options, config, function (config) {
|
||||
removeRegExp(config);
|
||||
assert(config.ignore.length > 0, 'no ignore rules found');
|
||||
assert(config.ignore.length === 5, '5 rules found: ' + config.ignore);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -53,8 +84,7 @@ describe('config load', function () {
|
||||
settings = { quiet: true },
|
||||
options = {};
|
||||
load(settings, options, config, function (config) {
|
||||
removeRegExp(config);
|
||||
assert(config.verbose);
|
||||
assert(config.verbose, 'we are verbose');
|
||||
|
||||
// ensure global mapping works too
|
||||
var options = exec({ script: 'template.jade' }, config.execMap);
|
||||
@@ -71,8 +101,9 @@ describe('config load', function () {
|
||||
options = {};
|
||||
load(settings, options, config, function (config) {
|
||||
removeRegExp(config);
|
||||
assert.deepEqual(config.ignore, ['one', 'three']);
|
||||
assert.deepEqual(config.watch, ['four']);
|
||||
assert.ok(config.ignore.indexOf('one') !== -1, 'ignore contains "one": ' + config.ignore);
|
||||
assert.ok(config.ignore.indexOf('three') !== -1, 'ignore contains "three": ' + config.ignore);
|
||||
assert.deepEqual(config.watch, ['four'], 'watch is "four": ' + config.watch);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -83,8 +114,8 @@ describe('config load', function () {
|
||||
options = {};
|
||||
load(settings, options, config, function (config) {
|
||||
removeRegExp(config);
|
||||
assert.deepEqual(config.ignore, ['one']);
|
||||
assert.deepEqual(config.watch, ['one']);
|
||||
assert.deepEqual(config.ignore, ['one'], 'ignore is "one": ' + config.ignore);
|
||||
assert.deepEqual(config.watch, ['one'], 'watch is "one": ' + config.watch);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
3
test/fixtures/legacy/.nodemonignore
vendored
3
test/fixtures/legacy/.nodemonignore
vendored
@@ -4,4 +4,5 @@
|
||||
/public/* # static files
|
||||
./README.md # a specific file
|
||||
*.css # ignore any CSS files too
|
||||
:(\d)*\.js # monitor javascript files with only digits in their name
|
||||
:(\d)*\.js # ignore javascript files with only digits in their name
|
||||
app.json # any app.json file
|
||||
@@ -10,7 +10,7 @@ var utils = require('../utils'),
|
||||
cleanup = utils.cleanup,
|
||||
run = utils.run;
|
||||
|
||||
describe('nodemon simply running', function () {
|
||||
describe('nodemon fork simply running', function () {
|
||||
it('should start', function (done) {
|
||||
var p = run(appjs, {
|
||||
output: function (data) {
|
||||
@@ -28,7 +28,7 @@ describe('nodemon simply running', function () {
|
||||
|
||||
});
|
||||
|
||||
describe('nodemon monitor', function () {
|
||||
describe('nodemon fork monitor', function () {
|
||||
var complete = function (p, done, err) {
|
||||
p.once('exit', function () {
|
||||
done(err);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
/*global describe:true, it: true, after: true */
|
||||
var nodemon = require('../../lib/'),
|
||||
assert = require('assert'),
|
||||
var assert = require('assert'),
|
||||
fs = require('fs'),
|
||||
utils = require('../utils'),
|
||||
colour = require('../../lib/utils/colour'),
|
||||
@@ -20,9 +19,6 @@ describe('nodemon fork child restart', function () {
|
||||
after(function () {
|
||||
fs.unlink(tmpjs);
|
||||
fs.unlink(tmpmd);
|
||||
// clean up just in case.
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
});
|
||||
|
||||
it('should happen when monitoring a single extension', function (done) {
|
||||
@@ -42,8 +38,6 @@ describe('nodemon fork child restart', function () {
|
||||
}, 1000);
|
||||
} else if (event.type === 'restart') {
|
||||
assert(true, 'nodemon restarted');
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
cleanup(p, done);
|
||||
}
|
||||
});
|
||||
@@ -64,8 +58,6 @@ describe('nodemon fork child restart', function () {
|
||||
var changes = msg.slice(-5).split('/');
|
||||
var restartedOn = changes.pop();
|
||||
assert(restartedOn === '1', 'nodemon restarted on a single file change');
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
cleanup(p, done);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ var nodemon = require('../../lib/'),
|
||||
appjs = path.resolve(__dirname, '..', 'fixtures', 'app.js');
|
||||
|
||||
describe('require-able', function () {
|
||||
afterEach(function (){
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
afterEach(function (done) {
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
});
|
||||
|
||||
it('should know nodemon has been required', function () {
|
||||
@@ -28,7 +30,7 @@ describe('require-able', function () {
|
||||
nodemon.emit('quit');
|
||||
}).on('quit', function () {
|
||||
assert(restarted, 'nodemon restarted and quit properly');
|
||||
nodemon.removeAllListners();
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).on('log', function (event) {
|
||||
// console.log(event.message);
|
||||
@@ -47,8 +49,8 @@ describe('require-able', function () {
|
||||
nodemon.emit('quit');
|
||||
}).on('quit', function () {
|
||||
assert(restarted);
|
||||
nodemon.reset();
|
||||
// unbind events for testing again
|
||||
nodemon.removeAllListners();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
152
test/monitor/match.test.js
Normal file
152
test/monitor/match.test.js
Normal file
@@ -0,0 +1,152 @@
|
||||
'use strict';
|
||||
/*global describe:true, it: true */
|
||||
var assert = require('assert'),
|
||||
match = require('../../lib/monitor/match'),
|
||||
config = require('../../lib/config'),
|
||||
path = require('path'),
|
||||
nodemonUtils = require('../../lib/utils'),
|
||||
utils = require('../utils');
|
||||
|
||||
describe('match', function () {
|
||||
var monitor = [
|
||||
'!.git',
|
||||
'!node_modules/*',
|
||||
'!public/*',
|
||||
'!npm-debug.log',
|
||||
'!node_modules/*',
|
||||
'views/server/*.coffee',
|
||||
'!*.coffee',
|
||||
];
|
||||
|
||||
it('should return based on number of slashes in monitor rules', function () {
|
||||
var files = [ 'views/server/remy.coffee', 'random.coffee', '/User/remy/app/server/foo.coffee' ];
|
||||
|
||||
var results = match(files, monitor); // ignoring extension support
|
||||
assert(results.result.length === 1, 'expecting 1 file in good');
|
||||
});
|
||||
|
||||
it('should apply *.js to any js file', function () {
|
||||
var files = [utils.appjs];
|
||||
|
||||
var result = match(files, ['*.*'], 'js');
|
||||
|
||||
assert.deepEqual(result.result, files, 'file returned from match, matches');
|
||||
assert(result.ignored === 0, 'no files were ignored');
|
||||
assert(result.watched === files.length, 'a single file was matched');
|
||||
});
|
||||
|
||||
it('should ignore .coffee if watching *.js', function () {
|
||||
var files = [utils.appcoffee];
|
||||
|
||||
var result = match(files, ['*.*'], 'js');
|
||||
|
||||
assert.deepEqual(result.result, [], 'no results returned');
|
||||
});
|
||||
|
||||
it('should match .coffee if watching *.js & *.coffee', function (done) {
|
||||
config.load({
|
||||
ext: 'js coffee'
|
||||
}, function (config) {
|
||||
var files = [utils.appcoffee];
|
||||
|
||||
var result = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
assert.deepEqual(result.result, files, 'coffee file matched');
|
||||
assert(result.ignored === 0, '0 files ignored');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should ignore nodemon default rules', function (done) {
|
||||
config.load({ ext: '*.js' }, function (config) {
|
||||
|
||||
var files = [utils.appjs, path.join(__dirname, '/.git/foo.js')];
|
||||
|
||||
var result = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
assert.deepEqual(result.result, files.slice(0, 1), 'first file matched');
|
||||
assert(result.ignored === 1, '.git file was ignored');
|
||||
assert(result.watched === 1, 'a single file was matched');
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should ignore directories', function (done) {
|
||||
config.load({
|
||||
ext: 'js',
|
||||
ignore: 'test/fixtures'
|
||||
}, function (config) {
|
||||
var files = [utils.appjs];
|
||||
|
||||
var result = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
assert.deepEqual(result.result, [], 'should be no files matched');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should check all directories by default', function (done) {
|
||||
config.load({
|
||||
ext: 'js'
|
||||
}, function (config) {
|
||||
var files = [utils.appjs];
|
||||
var result = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
assert.deepEqual(result.result, files, 'results should match');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should support old .nodemonignore', function (done) {
|
||||
// prevents our test from finding the nodemon.json files
|
||||
var pwd = process.cwd(),
|
||||
old = nodemonUtils.home;
|
||||
|
||||
process.chdir(path.resolve(pwd, 'test/fixtures/legacy'));
|
||||
nodemonUtils.home = path.resolve(pwd, 'test/fixtures/legacy');
|
||||
|
||||
// will load the legacy file format
|
||||
config.load({ script: utils.appjs, ext: 'js json' }, function (config) {
|
||||
var files = [utils.appjs];
|
||||
var result = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
assert.deepEqual(result.result, files, 'allows app.js: ' + result.result);
|
||||
|
||||
files = [path.resolve(pwd, 'test/fixtures/app.json')];
|
||||
result = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
assert.deepEqual(result.result, [], 'nothing matched' + result.result);
|
||||
|
||||
process.chdir(pwd);
|
||||
nodemonUtils.home = old;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
it('should be specific about directories', function (done) {
|
||||
config.load({
|
||||
ext: 'js md jade',
|
||||
watch: ['lib']
|
||||
}, function (config) {
|
||||
var files = [utils.appjs];
|
||||
var result = match(files, config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
assert.deepEqual(result.result, [], 'no results');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not match coffee when monitoring just js', function (done) {
|
||||
config.load({
|
||||
script: utils.appjs
|
||||
}, function (config) {
|
||||
var result = match([utils.appcoffee], config.options.monitor, config.options.execOptions.ext);
|
||||
|
||||
assert.deepEqual(result.result, [], 'no results');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -10,11 +10,13 @@ var nodemon = require('../../lib/'),
|
||||
describe('when nodemon runs', function () {
|
||||
var tmp = path.resolve('test/fixtures/test' + crypto.randomBytes(16).toString('hex') + '.js');
|
||||
|
||||
after(function () {
|
||||
after(function (done) {
|
||||
fs.unlink(tmp);
|
||||
// clean up just in case.
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
});
|
||||
|
||||
it('should wait when the script crashes', function (done) {
|
||||
@@ -28,9 +30,10 @@ describe('when nodemon runs', function () {
|
||||
}, 1000);
|
||||
}).on('restart', function () {
|
||||
assert(true, 'nodemon restarted');
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
done();
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,9 +50,10 @@ describe('when nodemon runs', function () {
|
||||
}, 500);
|
||||
}).on('restart', function () {
|
||||
assert(true, 'nodemon restarted');
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
done();
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -71,8 +75,7 @@ describe('when nodemon runs', function () {
|
||||
assert(false, 'detected crashed state');
|
||||
}).on('exit', function () {
|
||||
assert(true, 'quit correctly');
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
nodemon.reset();
|
||||
done();
|
||||
|
||||
setTimeout(function () {
|
||||
@@ -82,4 +85,4 @@ describe('when nodemon runs', function () {
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,38 +10,48 @@ var nodemon = require('../../lib/'),
|
||||
crypto = require('crypto'),
|
||||
baseFilename = 'test/fixtures/test' + crypto.randomBytes(16).toString('hex');
|
||||
|
||||
describe('nodemon child restart', function () {
|
||||
describe('nodemon monitor child restart', function () {
|
||||
var tmpjs = path.resolve(baseFilename + '.js'),
|
||||
tmpmd = path.resolve(baseFilename + '.md');
|
||||
|
||||
function write(both) {
|
||||
fs.writeFileSync(tmpjs, 'true;');
|
||||
if (both) {
|
||||
fs.writeFileSync(tmpmd, '# true');
|
||||
}
|
||||
}
|
||||
|
||||
after(function (done) {
|
||||
fs.unlink(tmpjs);
|
||||
fs.unlink(tmpmd);
|
||||
// clean up just in case.
|
||||
bus.once('exit', done);
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
});
|
||||
|
||||
it('should happen when monitoring a single extension', function (done) {
|
||||
fs.writeFileSync(tmpjs, 'true;');
|
||||
write();
|
||||
|
||||
nodemon({ script: tmpjs, verbose: true, ext: 'js' }).on('start', function () {
|
||||
setTimeout(function () {
|
||||
touch.sync(tmpjs);
|
||||
}, 1000);
|
||||
}).on('restart', function () {
|
||||
assert(true, 'nodemon restarted');
|
||||
bus.once('exit', done);
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
});
|
||||
setTimeout(function () {
|
||||
nodemon({ script: tmpjs, verbose: true, ext: 'js' }).on('start', function () {
|
||||
setTimeout(function () {
|
||||
touch.sync(tmpjs);
|
||||
}, 1500);
|
||||
}).on('restart', function () {
|
||||
assert(true, 'nodemon restarted');
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
it('should happen when monitoring multiple extensions', function (done) {
|
||||
write(true);
|
||||
setTimeout(function () {
|
||||
fs.writeFileSync(tmpjs, 'true;');
|
||||
fs.writeFileSync(tmpmd, '# true');
|
||||
|
||||
nodemon({
|
||||
script: tmpjs,
|
||||
@@ -50,7 +60,7 @@ describe('nodemon child restart', function () {
|
||||
}).on('start', function () {
|
||||
setTimeout(function () {
|
||||
touch.sync(tmpmd);
|
||||
}, 1000);
|
||||
}, 1500);
|
||||
}).on('log', function (event) {
|
||||
// console.log(event.message);
|
||||
var msg = event.message;
|
||||
@@ -58,11 +68,41 @@ describe('nodemon child restart', function () {
|
||||
var changes = msg.trim().slice(-5).split('/');
|
||||
var restartedOn = changes.pop();
|
||||
assert(restartedOn === '1', 'nodemon restarted on a single file change');
|
||||
bus.once('exit', done);
|
||||
nodemon.emit('quit');
|
||||
nodemon.removeAllListners();
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
}
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
it('should restart when watching directory', function (done) {
|
||||
write(true);
|
||||
|
||||
setTimeout(function () {
|
||||
nodemon({
|
||||
script: tmpjs,
|
||||
verbose: true,
|
||||
ext: 'js md',
|
||||
watch: ['test/fixtures/']
|
||||
}).on('start', function () {
|
||||
setTimeout(function () {
|
||||
touch.sync(tmpmd);
|
||||
}, 1000);
|
||||
}).on('log', function (event) {
|
||||
var msg = event.message;
|
||||
if (utils.match(msg, 'changes after filters')) {
|
||||
var changes = msg.trim().slice(-5).split('/');
|
||||
var restartedOn = changes.pop();
|
||||
assert(restartedOn === '1', 'nodemon restarted when watched directory');
|
||||
nodemon.once('exit', function () {
|
||||
nodemon.reset();
|
||||
done();
|
||||
}).emit('quit');
|
||||
}
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
/*global describe:true, it: true, beforeEach: true */
|
||||
var fs = require('fs'),
|
||||
nodemon = require('../../lib/nodemon'),
|
||||
rules = require('../../lib/rules'),
|
||||
assert = require('assert');
|
||||
|
||||
@@ -22,12 +23,26 @@ describe('nodemon rules', function () {
|
||||
};
|
||||
|
||||
beforeEach(function () {
|
||||
rules.reset();
|
||||
nodemon.reset();
|
||||
});
|
||||
|
||||
it('should be resetable', function (done) {
|
||||
nodemon.reset();
|
||||
rules.load('./test/fixtures/simple.json', function () {
|
||||
nodemon.reset();
|
||||
|
||||
rules.load('./test/fixtures/comments', function (error, rules) {
|
||||
assert.deepEqual(rules, { watch: [], ignore: [] }, 'rules are empty: ' + JSON.stringify(rules));
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should read json', function (done) {
|
||||
rules.load('./test/fixtures/simple.json', function (error, rules) {
|
||||
assert(rules.ignore.re.test('/public/anything'), 'ignores public directory');
|
||||
assert(typeof rules === 'object', 'rules file is parsed');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -48,9 +63,9 @@ describe('nodemon rules', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should read regular expressions', function (done) {
|
||||
it('should ignore regular expressions', function (done) {
|
||||
rules.load(fixtures.regexp.path, function (error, rules) {
|
||||
assert.equal(rules.ignore.re.test('nodemon.js'), true);
|
||||
assert.deepEqual(rules, { 'watch': [], 'ignore': [] }, 'rules are empty');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -28,22 +28,22 @@ describe('logger', function () {
|
||||
});
|
||||
});
|
||||
|
||||
it('should not log detail if debug is off', function (done) {
|
||||
logger.debug = false;
|
||||
// it('should not log detail if debug is off', function (done) {
|
||||
// logger.debug = false;
|
||||
|
||||
function handler() {
|
||||
assert(false, 'logged a message when we should not have done');
|
||||
bus.removeListener('log', handler);
|
||||
done();
|
||||
}
|
||||
// function handler() {
|
||||
// assert(false, 'logged a message when we should not have done');
|
||||
// bus.removeListener('log', handler);
|
||||
// done();
|
||||
// }
|
||||
|
||||
bus.addListener('log', handler);
|
||||
// bus.addListener('log', handler);
|
||||
|
||||
logger.detail('detail');
|
||||
// logger.detail('detail');
|
||||
|
||||
setTimeout(function () {
|
||||
bus.removeListener('log', handler);
|
||||
done();
|
||||
}, 500);
|
||||
});
|
||||
// setTimeout(function () {
|
||||
// bus.removeListener('log', handler);
|
||||
// done();
|
||||
// }, 500);
|
||||
// });
|
||||
});
|
||||
Reference in New Issue
Block a user