From be4c7c84d8c3c1174387737f0ebc1bc0597de6d0 Mon Sep 17 00:00:00 2001 From: Martin Zagora Date: Tue, 23 Aug 2016 10:51:05 +1000 Subject: [PATCH] explain better forgotten arg name in jsdoc jsdoc comment do a bit of renaming remove unnecessary export refactor FileWatcherDomain --- src/filesystem/FileSystem.js | 22 ++--- src/filesystem/WatchedRoot.js | 8 +- .../impls/appshell/AppshellFileSystem.js | 8 +- .../impls/appshell/node/ChokidarWatcher.js | 78 +++++++++++++++++ .../impls/appshell/node/FileWatcherDomain.js | 83 ++----------------- src/project/ProjectManager.js | 2 +- src/project/ProjectModel.js | 9 +- 7 files changed, 112 insertions(+), 98 deletions(-) create mode 100644 src/filesystem/impls/appshell/node/ChokidarWatcher.js diff --git a/src/filesystem/FileSystem.js b/src/filesystem/FileSystem.js index 5e8bd50be..8a3227dec 100644 --- a/src/filesystem/FileSystem.js +++ b/src/filesystem/FileSystem.js @@ -262,7 +262,7 @@ define(function (require, exports, module) { var impl = this._impl, recursiveWatch = impl.recursiveWatch, commandName = shouldWatch ? "watchPath" : "unwatchPath", - ignored = watchedRoot.globFilter; + filterGlobs = watchedRoot.filterGlobs; if (recursiveWatch) { // The impl can watch the entire subtree with one call on the root (we also fall into this case for @@ -274,7 +274,7 @@ define(function (require, exports, module) { } else { // The impl will handle finding all subdirectories to watch. this._enqueueWatchRequest(function (requestCb) { - impl[commandName].call(impl, entry.fullPath, ignored, requestCb); + impl[commandName].call(impl, entry.fullPath, filterGlobs, requestCb); }.bind(this), callback); } } else if (shouldWatch) { @@ -315,7 +315,7 @@ define(function (require, exports, module) { }; entriesToWatch.forEach(function (entry) { - impl.watchPath(entry.fullPath, ignored, watchCallback); + impl.watchPath(entry.fullPath, filterGlobs, watchCallback); }); }); }, callback); @@ -852,17 +852,17 @@ define(function (require, exports, module) { * @param {function(string): boolean} filter - Returns true if a particular item should * be watched, given its name (not full path). Items that are ignored are also * filtered from Directory.getContents() results within this subtree. - * @param {string} globFilter - glob compatible string definition for filtering out events - * on the node side. + * @param {Array} filterGlobs - glob compatible string definitions for + * filtering out events on the node side. * @param {function(?string)=} callback - A function that is called when the watch has * completed. If the watch fails, the function will have a non-null FileSystemError * string parametr. */ - FileSystem.prototype.watch = function (entry, filter, globFilter, callback) { - // make globFilter an optional argument to stay backwards compatible - if (typeof callback === "undefined" && typeof globFilter === "function") { - callback = globFilter; - globFilter = null; + FileSystem.prototype.watch = function (entry, filter, filterGlobs, callback) { + // make filterGlobs an optional argument to stay backwards compatible + if (typeof callback === "undefined" && typeof filterGlobs === "function") { + callback = filterGlobs; + filterGlobs = null; } var fullPath = entry.fullPath; @@ -891,7 +891,7 @@ define(function (require, exports, module) { return; } - var watchedRoot = new WatchedRoot(entry, filter, globFilter); + var watchedRoot = new WatchedRoot(entry, filter, filterGlobs); this._watchedRoots[fullPath] = watchedRoot; diff --git a/src/filesystem/WatchedRoot.js b/src/filesystem/WatchedRoot.js index 4cde822ad..f4582a3f7 100644 --- a/src/filesystem/WatchedRoot.js +++ b/src/filesystem/WatchedRoot.js @@ -37,12 +37,12 @@ define(function (require, exports, module) { * @constructor * @param {File|Directory} entry * @param {function(string, string):boolean} filter - * @param {string} globFilter + * @param {Array} filterGlobs */ - function WatchedRoot(entry, filter, globFilter) { + function WatchedRoot(entry, filter, filterGlobs) { this.entry = entry; this.filter = filter; - this.globFilter = globFilter; + this.filterGlobs = filterGlobs; } // Status constants @@ -63,7 +63,7 @@ define(function (require, exports, module) { /** * @type {string} */ - WatchedRoot.prototype.globFilter = null; + WatchedRoot.prototype.filterGlobs = null; /** * @type {number} diff --git a/src/filesystem/impls/appshell/AppshellFileSystem.js b/src/filesystem/impls/appshell/AppshellFileSystem.js index 17d77e46b..fb48557a5 100644 --- a/src/filesystem/impls/appshell/AppshellFileSystem.js +++ b/src/filesystem/impls/appshell/AppshellFileSystem.js @@ -533,9 +533,9 @@ define(function (require, exports, module) { /** * Stop providing change notifications for the file or directory at the * given path, calling back asynchronously with a possibly null FileSystemError - * string when the operation is complete. This function needs to mirror the - * signature of watchPath and hence the ignored argument is passed from - * FileSystem code + * string when the operation is complete. + * This function needs to mirror the signature of watchPath + * because of FileSystem.prototype._watchOrUnwatchEntry implementation. * * @param {string} path * @param {function(?string)=} callback @@ -577,7 +577,7 @@ define(function (require, exports, module) { /** * Indicates whether or not recursive watching notifications are supported - * by the watchPath call. With chokidar, every platform supports recursive watching. + * by the watchPath call. * * @type {boolean} */ diff --git a/src/filesystem/impls/appshell/node/ChokidarWatcher.js b/src/filesystem/impls/appshell/node/ChokidarWatcher.js new file mode 100644 index 000000000..c67e6d4db --- /dev/null +++ b/src/filesystem/impls/appshell/node/ChokidarWatcher.js @@ -0,0 +1,78 @@ +var fspath = require("path"); +var chokidar = require('chokidar'); + +/** + * Transform Node's native fs.stats to a format that can be sent through domain + * @param {stats} nodeFsStats Node's fs.stats result + * @return {object} Can be consumed by new FileSystemStats(object); in Brackets + */ +function normalizeStats(nodeFsStats) { + // from shell: If "filename" is a symlink, + // realPath should be the actual path to the linked object + // not implemented in shell yet + return { + isFile: nodeFsStats.isFile(), + isDirectory: nodeFsStats.isDirectory(), + mtime: nodeFsStats.mtime, + size: nodeFsStats.size, + realPath: null, + hash: nodeFsStats.mtime.getTime() + }; +} + +function watchPath(path, ignored, _watcherMap) { + if (_watcherMap.hasOwnProperty(path)) { + return; + } + + try { + var watcher = chokidar.watch(path, { + persistent: true, + ignoreInitial: true, + ignorePermissionErrors: true, + followSymlinks: true, + ignored: ignored, + usePolling: process.platform === "win32" + }); + + watcher.on("all", function (type, filename, nodeFsStats) { + var event; + switch (type) { + case "change": + event = "changed"; + break; + case "add": + case "addDir": + event = "created"; + break; + case "unlink": + case "unlinkDir": + event = "deleted"; + break; + default: + event = null; + } + if (!event || !filename) { + return; + } + // make sure stats are normalized for domain transfer + var statsObj = nodeFsStats ? normalizeStats(nodeFsStats) : null; + // make sure it's normalized + filename = filename.replace(/\\/g, "/"); + var parentDirPath = fspath.dirname(filename) + "/"; + var entryName = fspath.basename(filename); + _domainManager.emitEvent("fileWatcher", "change", [event, parentDirPath, entryName, statsObj]); + }); + + _watcherMap[path] = watcher; + + watcher.on("error", function (err) { + console.error("Error watching file " + path + ": " + (err && err.message)); + unwatchPath(path); + }); + } catch (err) { + console.warn("Failed to watch file " + path + ": " + (err && err.message)); + } +} + +exports.watchPath = watchPath; diff --git a/src/filesystem/impls/appshell/node/FileWatcherDomain.js b/src/filesystem/impls/appshell/node/FileWatcherDomain.js index ba11b2f81..22bdb7093 100644 --- a/src/filesystem/impls/appshell/node/FileWatcherDomain.js +++ b/src/filesystem/impls/appshell/node/FileWatcherDomain.js @@ -25,10 +25,13 @@ "use strict"; -var fspath = require("path"); -var fs = require("fs"); var os = require("os"); -var chokidar = require('chokidar'); +var watcherImpl; +if (process.platform === "win32") { + watcherImpl = require("./ChokidarWatcher"); // TODO: "./CSharpWatcher" +} else { + watcherImpl = require("./ChokidarWatcher"); +} var _domainManager, _watcherMap = {}; @@ -64,83 +67,13 @@ function unwatchPath(path) { }); } -/** - * Transform Node's native fs.stats to a format that can be sent through domain - * @param {stats} Node's fs.stats result - * @return {object} Can be consumed by new FileSystemStats(object); in Brackets - */ -function normalizeStats(nodeFsStats) { - // from shell: If "filename" is a symlink, - // realPath should be the actual path to the linked object - // not implemented in shell yet - return { - isFile: nodeFsStats.isFile(), - isDirectory: nodeFsStats.isDirectory(), - mtime: nodeFsStats.mtime, - size: nodeFsStats.size, - realPath: null, - hash: nodeFsStats.mtime.getTime() - }; -} - /** * Watch a file or directory. * @param {string} path File or directory to watch. - * @param {array} ignored List of File or directory to NOT watch. + * @param {array} ignored List of entries to ignore during watching. */ function watchPath(path, ignored) { - if (_watcherMap.hasOwnProperty(path)) { - return; - } - - try { - var watcher = chokidar.watch(path, { - persistent: true, - ignoreInitial: true, - ignorePermissionErrors: true, - followSymlinks: true, - ignored: ignored, - usePolling: process.platform === "win32" - }); - - watcher.on("all", function (type, filename, nodeFsStats) { - var event; - switch (type) { - case "change": - event = "changed"; - break; - case "add": - case "addDir": - event = "created"; - break; - case "unlink": - case "unlinkDir": - event = "deleted"; - break; - default: - event = null; - } - if (!event || !filename) { - return; - } - // make sure stats are normalized for domain transfer - var statsObj = nodeFsStats ? normalizeStats(nodeFsStats) : null; - // make sure it's normalized - filename = filename.replace(/\\/g, "/"); - var parentDirPath = fspath.dirname(filename) + "/"; - var entryName = fspath.basename(filename); - _domainManager.emitEvent("fileWatcher", "change", [event, parentDirPath, entryName, statsObj]); - }); - - _watcherMap[path] = watcher; - - watcher.on("error", function (err) { - console.error("Error watching file " + path + ": " + (err && err.message)); - unwatchPath(path); - }); - } catch (err) { - console.warn("Failed to watch file " + path + ": " + (err && err.message)); - } + return watcherImpl.watchPath(path, ignored, _watcherMap); } /** diff --git a/src/project/ProjectManager.js b/src/project/ProjectManager.js index 166cb89b9..c004385e2 100644 --- a/src/project/ProjectManager.js +++ b/src/project/ProjectManager.js @@ -738,7 +738,7 @@ define(function (require, exports, module) { FileSystem.on("change", _fileSystemChange); FileSystem.on("rename", _fileSystemRename); - FileSystem.watch(FileSystem.getDirectoryForPath(rootPath), ProjectModel._shouldShowName, ProjectModel.exclusionGlob, function (err) { + FileSystem.watch(FileSystem.getDirectoryForPath(rootPath), ProjectModel._shouldShowName, ProjectModel.defaultIgnoreGlobs, function (err) { if (err === FileSystemError.TOO_MANY_ENTRIES) { if (!_projectWarnedForTooManyFiles) { _showErrorDialog(ERR_TYPE_MAX_FILES); diff --git a/src/project/ProjectModel.js b/src/project/ProjectModel.js index 247253b85..d283d47a2 100644 --- a/src/project/ProjectModel.js +++ b/src/project/ProjectModel.js @@ -63,7 +63,11 @@ define(function (require, exports, module) { * Glob definition of files and folders that should be excluded directly * inside node domain watching with chokidar */ - var exclusionGlob = "**/(.pyc|.git|.gitmodules|.svn|.DS_Store|Thumbs.db|.hg|CVS|.hgtags|.idea|.c9revisions|.SyncArchive|.SyncID|.SyncIgnore|node_modules)"; + var defaultIgnoreGlobs = [ + "**/(.pyc|.git|.gitmodules|.svn|.DS_Store|Thumbs.db|.hg|CVS|.hgtags|.idea|.c9revisions|.SyncArchive|.SyncID|.SyncIgnore)", + "**/bower_components", + "**/node_modules" + ]; /** * @private @@ -1355,12 +1359,11 @@ define(function (require, exports, module) { exports._addWelcomeProjectPath = _addWelcomeProjectPath; exports._isWelcomeProjectPath = _isWelcomeProjectPath; exports._ensureTrailingSlash = _ensureTrailingSlash; - exports._exclusionListRegEx = _exclusionListRegEx; exports._shouldShowName = _shouldShowName; exports._invalidChars = _invalidChars; exports.shouldShow = shouldShow; - exports.exclusionGlob = exclusionGlob; + exports.defaultIgnoreGlobs = defaultIgnoreGlobs; exports.isValidFilename = isValidFilename; exports.EVENT_CHANGE = EVENT_CHANGE; exports.EVENT_SHOULD_SELECT = EVENT_SHOULD_SELECT;