summaryrefslogtreecommitdiffstats
path: root/node_modules/chokidar/lib
diff options
context:
space:
mode:
authorGravatar Piotr Russ <mail@pruss.it> 2020-11-18 23:26:45 +0100
committerGravatar Piotr Russ <mail@pruss.it> 2020-11-18 23:26:45 +0100
commit81ddf9b700bc48a1f8e472209f080f9c1d9a9b09 (patch)
tree8b959d50c5a614cbf9fcb346ed556140374d4b6d /node_modules/chokidar/lib
parent1870f3fdf43707a15fda0f609a021f516f45eb63 (diff)
downloadwebsite_creator-81ddf9b700bc48a1f8e472209f080f9c1d9a9b09.tar.gz
website_creator-81ddf9b700bc48a1f8e472209f080f9c1d9a9b09.tar.bz2
website_creator-81ddf9b700bc48a1f8e472209f080f9c1d9a9b09.zip
rm node_modules
Diffstat (limited to 'node_modules/chokidar/lib')
-rw-r--r--node_modules/chokidar/lib/fsevents-handler.js412
-rw-r--r--node_modules/chokidar/lib/nodefs-handler.js506
2 files changed, 0 insertions, 918 deletions
diff --git a/node_modules/chokidar/lib/fsevents-handler.js b/node_modules/chokidar/lib/fsevents-handler.js
deleted file mode 100644
index c85ba60..0000000
--- a/node_modules/chokidar/lib/fsevents-handler.js
+++ /dev/null
@@ -1,412 +0,0 @@
-'use strict';
-
-var fs = require('fs');
-var sysPath = require('path');
-var readdirp = require('readdirp');
-var fsevents;
-try { fsevents = require('fsevents'); } catch (error) {
- if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error)
-}
-
-// fsevents instance helper functions
-
-// object to hold per-process fsevents instances
-// (may be shared across chokidar FSWatcher instances)
-var FSEventsWatchers = Object.create(null);
-
-// Threshold of duplicate path prefixes at which to start
-// consolidating going forward
-var consolidateThreshhold = 10;
-
-// Private function: Instantiates the fsevents interface
-
-// * path - string, path to be watched
-// * callback - function, called when fsevents is bound and ready
-
-// Returns new fsevents instance
-function createFSEventsInstance(path, callback) {
- return (new fsevents(path)).on('fsevent', callback).start();
-}
-
-// Private function: Instantiates the fsevents interface or binds listeners
-// to an existing one covering the same file tree
-
-// * path - string, path to be watched
-// * realPath - string, real path (in case of symlinks)
-// * listener - function, called when fsevents emits events
-// * rawEmitter - function, passes data to listeners of the 'raw' event
-
-// Returns close function
-function setFSEventsListener(path, realPath, listener, rawEmitter) {
- var watchPath = sysPath.extname(path) ? sysPath.dirname(path) : path;
- var watchContainer;
- var parentPath = sysPath.dirname(watchPath);
-
- // If we've accumulated a substantial number of paths that
- // could have been consolidated by watching one directory
- // above the current one, create a watcher on the parent
- // path instead, so that we do consolidate going forward.
- if (couldConsolidate(parentPath)) {
- watchPath = parentPath;
- }
-
- var resolvedPath = sysPath.resolve(path);
- var hasSymlink = resolvedPath !== realPath;
- function filteredListener(fullPath, flags, info) {
- if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath);
- if (
- fullPath === resolvedPath ||
- !fullPath.indexOf(resolvedPath + sysPath.sep)
- ) listener(fullPath, flags, info);
- }
-
- // check if there is already a watcher on a parent path
- // modifies `watchPath` to the parent path when it finds a match
- function watchedParent() {
- return Object.keys(FSEventsWatchers).some(function(watchedPath) {
- // condition is met when indexOf returns 0
- if (!realPath.indexOf(sysPath.resolve(watchedPath) + sysPath.sep)) {
- watchPath = watchedPath;
- return true;
- }
- });
- }
-
- if (watchPath in FSEventsWatchers || watchedParent()) {
- watchContainer = FSEventsWatchers[watchPath];
- watchContainer.listeners.push(filteredListener);
- } else {
- watchContainer = FSEventsWatchers[watchPath] = {
- listeners: [filteredListener],
- rawEmitters: [rawEmitter],
- watcher: createFSEventsInstance(watchPath, function(fullPath, flags) {
- var info = fsevents.getInfo(fullPath, flags);
- watchContainer.listeners.forEach(function(listener) {
- listener(fullPath, flags, info);
- });
- watchContainer.rawEmitters.forEach(function(emitter) {
- emitter(info.event, fullPath, info);
- });
- })
- };
- }
- var listenerIndex = watchContainer.listeners.length - 1;
-
- // removes this instance's listeners and closes the underlying fsevents
- // instance if there are no more listeners left
- return function close() {
- delete watchContainer.listeners[listenerIndex];
- delete watchContainer.rawEmitters[listenerIndex];
- if (!Object.keys(watchContainer.listeners).length) {
- watchContainer.watcher.stop();
- delete FSEventsWatchers[watchPath];
- }
- };
-}
-
-// Decide whether or not we should start a new higher-level
-// parent watcher
-function couldConsolidate(path) {
- var keys = Object.keys(FSEventsWatchers);
- var count = 0;
-
- for (var i = 0, len = keys.length; i < len; ++i) {
- var watchPath = keys[i];
- if (watchPath.indexOf(path) === 0) {
- count++;
- if (count >= consolidateThreshhold) {
- return true;
- }
- }
- }
-
- return false;
-}
-
-function isConstructor(obj) {
- return obj.prototype !== undefined && obj.prototype.constructor !== undefined;
-}
-
-// returns boolean indicating whether fsevents can be used
-function canUse() {
- return fsevents && Object.keys(FSEventsWatchers).length < 128 && isConstructor(fsevents);
-}
-
-// determines subdirectory traversal levels from root to path
-function depth(path, root) {
- var i = 0;
- while (!path.indexOf(root) && (path = sysPath.dirname(path)) !== root) i++;
- return i;
-}
-
-// fake constructor for attaching fsevents-specific prototype methods that
-// will be copied to FSWatcher's prototype
-function FsEventsHandler() {}
-
-// Private method: Handle symlinks encountered during directory scan
-
-// * watchPath - string, file/dir path to be watched with fsevents
-// * realPath - string, real path (in case of symlinks)
-// * transform - function, path transformer
-// * globFilter - function, path filter in case a glob pattern was provided
-
-// Returns close function for the watcher instance
-FsEventsHandler.prototype._watchWithFsEvents =
-function(watchPath, realPath, transform, globFilter) {
- if (this._isIgnored(watchPath)) return;
- var watchCallback = function(fullPath, flags, info) {
- if (
- this.options.depth !== undefined &&
- depth(fullPath, realPath) > this.options.depth
- ) return;
- var path = transform(sysPath.join(
- watchPath, sysPath.relative(watchPath, fullPath)
- ));
- if (globFilter && !globFilter(path)) return;
- // ensure directories are tracked
- var parent = sysPath.dirname(path);
- var item = sysPath.basename(path);
- var watchedDir = this._getWatchedDir(
- info.type === 'directory' ? path : parent
- );
- var checkIgnored = function(stats) {
- if (this._isIgnored(path, stats)) {
- this._ignoredPaths[path] = true;
- if (stats && stats.isDirectory()) {
- this._ignoredPaths[path + '/**/*'] = true;
- }
- return true;
- } else {
- delete this._ignoredPaths[path];
- delete this._ignoredPaths[path + '/**/*'];
- }
- }.bind(this);
-
- var handleEvent = function(event) {
- if (checkIgnored()) return;
-
- if (event === 'unlink') {
- // suppress unlink events on never before seen files
- if (info.type === 'directory' || watchedDir.has(item)) {
- this._remove(parent, item);
- }
- } else {
- if (event === 'add') {
- // track new directories
- if (info.type === 'directory') this._getWatchedDir(path);
-
- if (info.type === 'symlink' && this.options.followSymlinks) {
- // push symlinks back to the top of the stack to get handled
- var curDepth = this.options.depth === undefined ?
- undefined : depth(fullPath, realPath) + 1;
- return this._addToFsEvents(path, false, true, curDepth);
- } else {
- // track new paths
- // (other than symlinks being followed, which will be tracked soon)
- this._getWatchedDir(parent).add(item);
- }
- }
- var eventName = info.type === 'directory' ? event + 'Dir' : event;
- this._emit(eventName, path);
- if (eventName === 'addDir') this._addToFsEvents(path, false, true);
- }
- }.bind(this);
-
- function addOrChange() {
- handleEvent(watchedDir.has(item) ? 'change' : 'add');
- }
- function checkFd() {
- fs.open(path, 'r', function(error, fd) {
- if (error) {
- error.code !== 'EACCES' ?
- handleEvent('unlink') : addOrChange();
- } else {
- fs.close(fd, function(err) {
- err && err.code !== 'EACCES' ?
- handleEvent('unlink') : addOrChange();
- });
- }
- });
- }
- // correct for wrong events emitted
- var wrongEventFlags = [
- 69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912
- ];
- if (wrongEventFlags.indexOf(flags) !== -1 || info.event === 'unknown') {
- if (typeof this.options.ignored === 'function') {
- fs.stat(path, function(error, stats) {
- if (checkIgnored(stats)) return;
- stats ? addOrChange() : handleEvent('unlink');
- });
- } else {
- checkFd();
- }
- } else {
- switch (info.event) {
- case 'created':
- case 'modified':
- return addOrChange();
- case 'deleted':
- case 'moved':
- return checkFd();
- }
- }
- }.bind(this);
-
- var closer = setFSEventsListener(
- watchPath,
- realPath,
- watchCallback,
- this.emit.bind(this, 'raw')
- );
-
- this._emitReady();
- return closer;
-};
-
-// Private method: Handle symlinks encountered during directory scan
-
-// * linkPath - string, path to symlink
-// * fullPath - string, absolute path to the symlink
-// * transform - function, pre-existing path transformer
-// * curDepth - int, level of subdirectories traversed to where symlink is
-
-// Returns nothing
-FsEventsHandler.prototype._handleFsEventsSymlink =
-function(linkPath, fullPath, transform, curDepth) {
- // don't follow the same symlink more than once
- if (this._symlinkPaths[fullPath]) return;
- else this._symlinkPaths[fullPath] = true;
-
- this._readyCount++;
-
- fs.realpath(linkPath, function(error, linkTarget) {
- if (this._handleError(error) || this._isIgnored(linkTarget)) {
- return this._emitReady();
- }
-
- this._readyCount++;
-
- // add the linkTarget for watching with a wrapper for transform
- // that causes emitted paths to incorporate the link's path
- this._addToFsEvents(linkTarget || linkPath, function(path) {
- var dotSlash = '.' + sysPath.sep;
- var aliasedPath = linkPath;
- if (linkTarget && linkTarget !== dotSlash) {
- aliasedPath = path.replace(linkTarget, linkPath);
- } else if (path !== dotSlash) {
- aliasedPath = sysPath.join(linkPath, path);
- }
- return transform(aliasedPath);
- }, false, curDepth);
- }.bind(this));
-};
-
-// Private method: Handle added path with fsevents
-
-// * path - string, file/directory path or glob pattern
-// * transform - function, converts working path to what the user expects
-// * forceAdd - boolean, ensure add is emitted
-// * priorDepth - int, level of subdirectories already traversed
-
-// Returns nothing
-FsEventsHandler.prototype._addToFsEvents =
-function(path, transform, forceAdd, priorDepth) {
-
- // applies transform if provided, otherwise returns same value
- var processPath = typeof transform === 'function' ?
- transform : function(val) { return val; };
-
- var emitAdd = function(newPath, stats) {
- var pp = processPath(newPath);
- var isDir = stats.isDirectory();
- var dirObj = this._getWatchedDir(sysPath.dirname(pp));
- var base = sysPath.basename(pp);
-
- // ensure empty dirs get tracked
- if (isDir) this._getWatchedDir(pp);
-
- if (dirObj.has(base)) return;
- dirObj.add(base);
-
- if (!this.options.ignoreInitial || forceAdd === true) {
- this._emit(isDir ? 'addDir' : 'add', pp, stats);
- }
- }.bind(this);
-
- var wh = this._getWatchHelpers(path);
-
- // evaluate what is at the path we're being asked to watch
- fs[wh.statMethod](wh.watchPath, function(error, stats) {
- if (this._handleError(error) || this._isIgnored(wh.watchPath, stats)) {
- this._emitReady();
- return this._emitReady();
- }
-
- if (stats.isDirectory()) {
- // emit addDir unless this is a glob parent
- if (!wh.globFilter) emitAdd(processPath(path), stats);
-
- // don't recurse further if it would exceed depth setting
- if (priorDepth && priorDepth > this.options.depth) return;
-
- // scan the contents of the dir
- readdirp({
- root: wh.watchPath,
- entryType: 'all',
- fileFilter: wh.filterPath,
- directoryFilter: wh.filterDir,
- lstat: true,
- depth: this.options.depth - (priorDepth || 0)
- }).on('data', function(entry) {
- // need to check filterPath on dirs b/c filterDir is less restrictive
- if (entry.stat.isDirectory() && !wh.filterPath(entry)) return;
-
- var joinedPath = sysPath.join(wh.watchPath, entry.path);
- var fullPath = entry.fullPath;
-
- if (wh.followSymlinks && entry.stat.isSymbolicLink()) {
- // preserve the current depth here since it can't be derived from
- // real paths past the symlink
- var curDepth = this.options.depth === undefined ?
- undefined : depth(joinedPath, sysPath.resolve(wh.watchPath)) + 1;
-
- this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth);
- } else {
- emitAdd(joinedPath, entry.stat);
- }
- }.bind(this)).on('error', function() {
- // Ignore readdirp errors
- }).on('end', this._emitReady);
- } else {
- emitAdd(wh.watchPath, stats);
- this._emitReady();
- }
- }.bind(this));
-
- if (this.options.persistent && forceAdd !== true) {
- var initWatch = function(error, realPath) {
- if (this.closed) return;
- var closer = this._watchWithFsEvents(
- wh.watchPath,
- sysPath.resolve(realPath || wh.watchPath),
- processPath,
- wh.globFilter
- );
- if (closer) {
- this._closers[path] = this._closers[path] || [];
- this._closers[path].push(closer);
- }
- }.bind(this);
-
- if (typeof transform === 'function') {
- // realpath has already been resolved
- initWatch();
- } else {
- fs.realpath(wh.watchPath, initWatch);
- }
- }
-};
-
-module.exports = FsEventsHandler;
-module.exports.canUse = canUse;
diff --git a/node_modules/chokidar/lib/nodefs-handler.js b/node_modules/chokidar/lib/nodefs-handler.js
deleted file mode 100644
index 4f49ac2..0000000
--- a/node_modules/chokidar/lib/nodefs-handler.js
+++ /dev/null
@@ -1,506 +0,0 @@
-'use strict';
-
-var fs = require('fs');
-var sysPath = require('path');
-var readdirp = require('readdirp');
-var isBinaryPath = require('is-binary-path');
-
-// fs.watch helpers
-
-// object to hold per-process fs.watch instances
-// (may be shared across chokidar FSWatcher instances)
-var FsWatchInstances = Object.create(null);
-
-
-// Private function: Instantiates the fs.watch interface
-
-// * path - string, path to be watched
-// * options - object, options to be passed to fs.watch
-// * listener - function, main event handler
-// * errHandler - function, handler which emits info about errors
-// * emitRaw - function, handler which emits raw event data
-
-// Returns new fsevents instance
-function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
- var handleEvent = function(rawEvent, evPath) {
- listener(path);
- emitRaw(rawEvent, evPath, {watchedPath: path});
-
- // emit based on events occurring for files from a directory's watcher in
- // case the file's watcher misses it (and rely on throttling to de-dupe)
- if (evPath && path !== evPath) {
- fsWatchBroadcast(
- sysPath.resolve(path, evPath), 'listeners', sysPath.join(path, evPath)
- );
- }
- };
- try {
- return fs.watch(path, options, handleEvent);
- } catch (error) {
- errHandler(error);
- }
-}
-
-// Private function: Helper for passing fs.watch event data to a
-// collection of listeners
-
-// * fullPath - string, absolute path bound to the fs.watch instance
-// * type - string, listener type
-// * val[1..3] - arguments to be passed to listeners
-
-// Returns nothing
-function fsWatchBroadcast(fullPath, type, val1, val2, val3) {
- if (!FsWatchInstances[fullPath]) return;
- FsWatchInstances[fullPath][type].forEach(function(listener) {
- listener(val1, val2, val3);
- });
-}
-
-// Private function: Instantiates the fs.watch interface or binds listeners
-// to an existing one covering the same file system entry
-
-// * path - string, path to be watched
-// * fullPath - string, absolute path
-// * options - object, options to be passed to fs.watch
-// * handlers - object, container for event listener functions
-
-// Returns close function
-function setFsWatchListener(path, fullPath, options, handlers) {
- var listener = handlers.listener;
- var errHandler = handlers.errHandler;
- var rawEmitter = handlers.rawEmitter;
- var container = FsWatchInstances[fullPath];
- var watcher;
- if (!options.persistent) {
- watcher = createFsWatchInstance(
- path, options, listener, errHandler, rawEmitter
- );
- return watcher.close.bind(watcher);
- }
- if (!container) {
- watcher = createFsWatchInstance(
- path,
- options,
- fsWatchBroadcast.bind(null, fullPath, 'listeners'),
- errHandler, // no need to use broadcast here
- fsWatchBroadcast.bind(null, fullPath, 'rawEmitters')
- );
- if (!watcher) return;
- var broadcastErr = fsWatchBroadcast.bind(null, fullPath, 'errHandlers');
- watcher.on('error', function(error) {
- container.watcherUnusable = true; // documented since Node 10.4.1
- // Workaround for https://github.com/joyent/node/issues/4337
- if (process.platform === 'win32' && error.code === 'EPERM') {
- fs.open(path, 'r', function(err, fd) {
- if (!err) fs.close(fd, function(err) {
- if (!err) broadcastErr(error);
- });
- });
- } else {
- broadcastErr(error);
- }
- });
- container = FsWatchInstances[fullPath] = {
- listeners: [listener],
- errHandlers: [errHandler],
- rawEmitters: [rawEmitter],
- watcher: watcher
- };
- } else {
- container.listeners.push(listener);
- container.errHandlers.push(errHandler);
- container.rawEmitters.push(rawEmitter);
- }
- var listenerIndex = container.listeners.length - 1;
-
- // removes this instance's listeners and closes the underlying fs.watch
- // instance if there are no more listeners left
- return function close() {
- delete container.listeners[listenerIndex];
- delete container.errHandlers[listenerIndex];
- delete container.rawEmitters[listenerIndex];
- if (!Object.keys(container.listeners).length) {
- if (!container.watcherUnusable) { // check to protect against issue #730
- container.watcher.close();
- }
- delete FsWatchInstances[fullPath];
- }
- };
-}
-
-// fs.watchFile helpers
-
-// object to hold per-process fs.watchFile instances
-// (may be shared across chokidar FSWatcher instances)
-var FsWatchFileInstances = Object.create(null);
-
-// Private function: Instantiates the fs.watchFile interface or binds listeners
-// to an existing one covering the same file system entry
-
-// * path - string, path to be watched
-// * fullPath - string, absolute path
-// * options - object, options to be passed to fs.watchFile
-// * handlers - object, container for event listener functions
-
-// Returns close function
-function setFsWatchFileListener(path, fullPath, options, handlers) {
- var listener = handlers.listener;
- var rawEmitter = handlers.rawEmitter;
- var container = FsWatchFileInstances[fullPath];
- var listeners = [];
- var rawEmitters = [];
- if (
- container && (
- container.options.persistent < options.persistent ||
- container.options.interval > options.interval
- )
- ) {
- // "Upgrade" the watcher to persistence or a quicker interval.
- // This creates some unlikely edge case issues if the user mixes
- // settings in a very weird way, but solving for those cases
- // doesn't seem worthwhile for the added complexity.
- listeners = container.listeners;
- rawEmitters = container.rawEmitters;
- fs.unwatchFile(fullPath);
- container = false;
- }
- if (!container) {
- listeners.push(listener);
- rawEmitters.push(rawEmitter);
- container = FsWatchFileInstances[fullPath] = {
- listeners: listeners,
- rawEmitters: rawEmitters,
- options: options,
- watcher: fs.watchFile(fullPath, options, function(curr, prev) {
- container.rawEmitters.forEach(function(rawEmitter) {
- rawEmitter('change', fullPath, {curr: curr, prev: prev});
- });
- var currmtime = curr.mtime.getTime();
- if (curr.size !== prev.size || currmtime > prev.mtime.getTime() || currmtime === 0) {
- container.listeners.forEach(function(listener) {
- listener(path, curr);
- });
- }
- })
- };
- } else {
- container.listeners.push(listener);
- container.rawEmitters.push(rawEmitter);
- }
- var listenerIndex = container.listeners.length - 1;
-
- // removes this instance's listeners and closes the underlying fs.watchFile
- // instance if there are no more listeners left
- return function close() {
- delete container.listeners[listenerIndex];
- delete container.rawEmitters[listenerIndex];
- if (!Object.keys(container.listeners).length) {
- fs.unwatchFile(fullPath);
- delete FsWatchFileInstances[fullPath];
- }
- };
-}
-
-// fake constructor for attaching nodefs-specific prototype methods that
-// will be copied to FSWatcher's prototype
-function NodeFsHandler() {}
-
-// Private method: Watch file for changes with fs.watchFile or fs.watch.
-
-// * path - string, path to file or directory.
-// * listener - function, to be executed on fs change.
-
-// Returns close function for the watcher instance
-NodeFsHandler.prototype._watchWithNodeFs =
-function(path, listener) {
- var directory = sysPath.dirname(path);
- var basename = sysPath.basename(path);
- var parent = this._getWatchedDir(directory);
- parent.add(basename);
- var absolutePath = sysPath.resolve(path);
- var options = {persistent: this.options.persistent};
- if (!listener) listener = Function.prototype; // empty function
-
- var closer;
- if (this.options.usePolling) {
- options.interval = this.enableBinaryInterval && isBinaryPath(basename) ?
- this.options.binaryInterval : this.options.interval;
- closer = setFsWatchFileListener(path, absolutePath, options, {
- listener: listener,
- rawEmitter: this.emit.bind(this, 'raw')
- });
- } else {
- closer = setFsWatchListener(path, absolutePath, options, {
- listener: listener,
- errHandler: this._handleError.bind(this),
- rawEmitter: this.emit.bind(this, 'raw')
- });
- }
- return closer;
-};
-
-// Private method: Watch a file and emit add event if warranted
-
-// * file - string, the file's path
-// * stats - object, result of fs.stat
-// * initialAdd - boolean, was the file added at watch instantiation?
-// * callback - function, called when done processing as a newly seen file
-
-// Returns close function for the watcher instance
-NodeFsHandler.prototype._handleFile =
-function(file, stats, initialAdd, callback) {
- var dirname = sysPath.dirname(file);
- var basename = sysPath.basename(file);
- var parent = this._getWatchedDir(dirname);
- // stats is always present
- var prevStats = stats;
-
- // if the file is already being watched, do nothing
- if (parent.has(basename)) return callback();
-
- // kick off the watcher
- var closer = this._watchWithNodeFs(file, function(path, newStats) {
- if (!this._throttle('watch', file, 5)) return;
- if (!newStats || newStats && newStats.mtime.getTime() === 0) {
- fs.stat(file, function(error, newStats) {
- // Fix issues where mtime is null but file is still present
- if (error) {
- this._remove(dirname, basename);
- } else {
- // Check that change event was not fired because of changed only accessTime.
- var at = newStats.atime.getTime();
- var mt = newStats.mtime.getTime();
- if (!at || at <= mt || mt !== prevStats.mtime.getTime()) {
- this._emit('change', file, newStats);
- }
- prevStats = newStats;
- }
- }.bind(this));
- // add is about to be emitted if file not already tracked in parent
- } else if (parent.has(basename)) {
- // Check that change event was not fired because of changed only accessTime.
- var at = newStats.atime.getTime();
- var mt = newStats.mtime.getTime();
- if (!at || at <= mt || mt !== prevStats.mtime.getTime()) {
- this._emit('change', file, newStats);
- }
- prevStats = newStats;
- }
- }.bind(this));
-
- // emit an add event if we're supposed to
- if (!(initialAdd && this.options.ignoreInitial)) {
- if (!this._throttle('add', file, 0)) return;
- this._emit('add', file, stats);
- }
-
- if (callback) callback();
- return closer;
-};
-
-// Private method: Handle symlinks encountered while reading a dir
-
-// * entry - object, entry object returned by readdirp
-// * directory - string, path of the directory being read
-// * path - string, path of this item
-// * item - string, basename of this item
-
-// Returns true if no more processing is needed for this entry.
-NodeFsHandler.prototype._handleSymlink =
-function(entry, directory, path, item) {
- var full = entry.fullPath;
- var dir = this._getWatchedDir(directory);
-
- if (!this.options.followSymlinks) {
- // watch symlink directly (don't follow) and detect changes
- this._readyCount++;
- fs.realpath(path, function(error, linkPath) {
- if (dir.has(item)) {
- if (this._symlinkPaths[full] !== linkPath) {
- this._symlinkPaths[full] = linkPath;
- this._emit('change', path, entry.stat);
- }
- } else {
- dir.add(item);
- this._symlinkPaths[full] = linkPath;
- this._emit('add', path, entry.stat);
- }
- this._emitReady();
- }.bind(this));
- return true;
- }
-
- // don't follow the same symlink more than once
- if (this._symlinkPaths[full]) return true;
- else this._symlinkPaths[full] = true;
-};
-
-// Private method: Read directory to add / remove files from `@watched` list
-// and re-read it on change.
-
-// * dir - string, fs path.
-// * stats - object, result of fs.stat
-// * initialAdd - boolean, was the file added at watch instantiation?
-// * depth - int, depth relative to user-supplied path
-// * target - string, child path actually targeted for watch
-// * wh - object, common watch helpers for this path
-// * callback - function, called when dir scan is complete
-
-// Returns close function for the watcher instance
-NodeFsHandler.prototype._handleDir =
-function(dir, stats, initialAdd, depth, target, wh, callback) {
- var parentDir = this._getWatchedDir(sysPath.dirname(dir));
- var tracked = parentDir.has(sysPath.basename(dir));
- if (!(initialAdd && this.options.ignoreInitial) && !target && !tracked) {
- if (!wh.hasGlob || wh.globFilter(dir)) this._emit('addDir', dir, stats);
- }
-
- // ensure dir is tracked (harmless if redundant)
- parentDir.add(sysPath.basename(dir));
- this._getWatchedDir(dir);
-
- var read = function(directory, initialAdd, done) {
- // Normalize the directory name on Windows
- directory = sysPath.join(directory, '');
-
- if (!wh.hasGlob) {
- var throttler = this._throttle('readdir', directory, 1000);
- if (!throttler) return;
- }
-
- var previous = this._getWatchedDir(wh.path);
- var current = [];
-
- readdirp({
- root: directory,
- entryType: 'all',
- fileFilter: wh.filterPath,
- directoryFilter: wh.filterDir,
- depth: 0,
- lstat: true
- }).on('data', function(entry) {
- var item = entry.path;
- var path = sysPath.join(directory, item);
- current.push(item);
-
- if (entry.stat.isSymbolicLink() &&
- this._handleSymlink(entry, directory, path, item)) return;
-
- // Files that present in current directory snapshot
- // but absent in previous are added to watch list and
- // emit `add` event.
- if (item === target || !target && !previous.has(item)) {
- this._readyCount++;
-
- // ensure relativeness of path is preserved in case of watcher reuse
- path = sysPath.join(dir, sysPath.relative(dir, path));
-
- this._addToNodeFs(path, initialAdd, wh, depth + 1);
- }
- }.bind(this)).on('end', function() {
- var wasThrottled = throttler ? throttler.clear() : false;
- if (done) done();
-
- // Files that absent in current directory snapshot
- // but present in previous emit `remove` event
- // and are removed from @watched[directory].
- previous.children().filter(function(item) {
- return item !== directory &&
- current.indexOf(item) === -1 &&
- // in case of intersecting globs;
- // a path may have been filtered out of this readdir, but
- // shouldn't be removed because it matches a different glob
- (!wh.hasGlob || wh.filterPath({
- fullPath: sysPath.resolve(directory, item)
- }));
- }).forEach(function(item) {
- this._remove(directory, item);
- }, this);
-
- // one more time for any missed in case changes came in extremely quickly
- if (wasThrottled) read(directory, false);
- }.bind(this)).on('error', this._handleError.bind(this));
- }.bind(this);
-
- var closer;
-
- if (this.options.depth == null || depth <= this.options.depth) {
- if (!target) read(dir, initialAdd, callback);
- closer = this._watchWithNodeFs(dir, function(dirPath, stats) {
- // if current directory is removed, do nothing
- if (stats && stats.mtime.getTime() === 0) return;
-
- read(dirPath, false);
- });
- } else {
- callback();
- }
- return closer;
-};
-
-// Private method: Handle added file, directory, or glob pattern.
-// Delegates call to _handleFile / _handleDir after checks.
-
-// * path - string, path to file or directory.
-// * initialAdd - boolean, was the file added at watch instantiation?
-// * depth - int, depth relative to user-supplied path
-// * target - string, child path actually targeted for watch
-// * callback - function, indicates whether the path was found or not
-
-// Returns nothing
-NodeFsHandler.prototype._addToNodeFs =
-function(path, initialAdd, priorWh, depth, target, callback) {
- if (!callback) callback = Function.prototype;
- var ready = this._emitReady;
- if (this._isIgnored(path) || this.closed) {
- ready();
- return callback(null, false);
- }
-
- var wh = this._getWatchHelpers(path, depth);
- if (!wh.hasGlob && priorWh) {
- wh.hasGlob = priorWh.hasGlob;
- wh.globFilter = priorWh.globFilter;
- wh.filterPath = priorWh.filterPath;
- wh.filterDir = priorWh.filterDir;
- }
-
- // evaluate what is at the path we're being asked to watch
- fs[wh.statMethod](wh.watchPath, function(error, stats) {
- if (this._handleError(error)) return callback(null, path);
- if (this._isIgnored(wh.watchPath, stats)) {
- ready();
- return callback(null, false);
- }
-
- var initDir = function(dir, target) {
- return this._handleDir(dir, stats, initialAdd, depth, target, wh, ready);
- }.bind(this);
-
- var closer;
- if (stats.isDirectory()) {
- closer = initDir(wh.watchPath, target);
- } else if (stats.isSymbolicLink()) {
- var parent = sysPath.dirname(wh.watchPath);
- this._getWatchedDir(parent).add(wh.watchPath);
- this._emit('add', wh.watchPath, stats);
- closer = initDir(parent, path);
-
- // preserve this symlink's target path
- fs.realpath(path, function(error, targetPath) {
- this._symlinkPaths[sysPath.resolve(path)] = targetPath;
- ready();
- }.bind(this));
- } else {
- closer = this._handleFile(wh.watchPath, stats, initialAdd, ready);
- }
-
- if (closer) {
- this._closers[path] = this._closers[path] || [];
- this._closers[path].push(closer);
- }
- callback(null, false);
- }.bind(this));
-};
-
-module.exports = NodeFsHandler;