From a26acfec5b4ed30053281fa10be8f77163ed5150 Mon Sep 17 00:00:00 2001 From: lukasz Date: Sun, 22 Apr 2018 15:39:28 +0200 Subject: [PATCH] refactor(watcher): refactor watcher.js --- lib/watcher.js | 130 ++++++++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 78 deletions(-) diff --git a/lib/watcher.js b/lib/watcher.js index 284a45088..0af95c0e5 100644 --- a/lib/watcher.js +++ b/lib/watcher.js @@ -1,118 +1,92 @@ -var chokidar = require('chokidar') -var mm = require('minimatch') -var expandBraces = require('expand-braces') +'use strict' -var helper = require('./helper') -var log = require('./logger').create('watcher') +const chokidar = require('chokidar') +const mm = require('minimatch') +const expandBraces = require('expand-braces') -var DIR_SEP = require('path').sep +const helper = require('./helper') +const log = require('./logger').create('watcher') -// Get parent folder, that be watched (does not contain any special globbing character) -var baseDirFromPattern = function (pattern) { +const DIR_SEP = require('path').sep + +function baseDirFromPattern (pattern) { return pattern - .replace(/[/\\][^/\\]*\*.*$/, '') // remove parts with * - .replace(/[/\\][^/\\]*[!+]\(.*$/, '') // remove parts with !(...) and +(...) + .replace(/[/\\][^/\\]*\*.*$/, '') // remove parts with * + .replace(/[/\\][^/\\]*[!+]\(.*$/, '') // remove parts with !(...) and +(...) .replace(/[/\\][^/\\]*\)\?.*$/, '') || DIR_SEP // remove parts with (...)? } -var watchPatterns = function (patterns, watcher) { - // filter only unique non url patterns paths - var pathsToWatch = [] - var uniqueMap = {} - var path +function watchPatterns (patterns, watcher) { + let pathsToWatch = new Set() // expand ['a/{b,c}'] to ['a/b', 'a/c'] - patterns = expandBraces(patterns) - - patterns.forEach(function (pattern) { - path = baseDirFromPattern(pattern) - if (!uniqueMap[path]) { - uniqueMap[path] = true - pathsToWatch.push(path) - } - }) + expandBraces(patterns) + .forEach(path => pathsToWatch.add(baseDirFromPattern(path))) + pathsToWatch = Array.from(pathsToWatch) // watch only common parents, no sub paths - pathsToWatch.forEach(function (path) { - if (!pathsToWatch.some(function (p) { - return p !== path && path.substr(0, p.length + 1) === p + DIR_SEP - })) { + pathsToWatch.forEach(path => { + if (!pathsToWatch.some(p => p !== path && path.substr(0, p.length + 1) === p + DIR_SEP)) { watcher.add(path) log.debug('Watching "%s"', path) } }) } -// Function to test if a path should be ignored by chokidar. -var createIgnore = function (patterns, excludes) { +function checkAnyPathMatch (patterns, path) { + return patterns.some(pattern => mm(path, pattern, {dot: true})) +} + +function createIgnore (patterns, excludes) { return function (path, stat) { if (!stat || stat.isDirectory()) { return false } - // Check if the path matches any of the watched patterns. - if (!patterns.some(function (pattern) { - return mm(path, pattern, {dot: true}) - })) { - return true - } - - // Check if the path matches any of the exclude patterns. - if (excludes.some(function (pattern) { - return mm(path, pattern, {dot: true}) - })) { - return true - } - - return false + return !checkAnyPathMatch(patterns, path) || checkAnyPathMatch(excludes, path) } } -var onlyWatchedTrue = function (pattern) { - return pattern.watched -} - -var getWatchedPatterns = function (patternObjects) { - return patternObjects.filter(onlyWatchedTrue).map(function (patternObject) { - return patternObject.pattern - }) +function getWatchedPatterns (patterns) { + return patterns + .reduce((array, pattern) => { + if (pattern.watched) { + array.push(pattern.pattern) + } + return array + }, []) } exports.watch = function (patterns, excludes, fileList, usePolling, emitter) { - var watchedPatterns = getWatchedPatterns(patterns) - var options = { + const watchedPatterns = getWatchedPatterns(patterns) + + const watcher = new chokidar.FSWatcher({ usePolling: usePolling, ignorePermissionErrors: true, ignoreInitial: true, ignored: createIgnore(watchedPatterns, excludes) - } - var chokidarWatcher = new chokidar.FSWatcher(options) + }) - watchPatterns(watchedPatterns, chokidarWatcher) + watchPatterns(watchedPatterns, watcher) - var bind = function (fn) { - return function (path) { - return fn.call(fileList, helper.normalizeWinPath(path)) - } - } + watcher + .on('add', path => fileList.addFile(helper.normalizeWinPath(path))) + .on('change', path => fileList.changeFile(helper.normalizeWinPath(path))) + .on('unlink', path => fileList.removeFile(helper.normalizeWinPath(path))) + .on('error', log.debug.bind(log)) - // register events - chokidarWatcher.on('add', bind(fileList.addFile)) - .on('change', bind(fileList.changeFile)) - .on('unlink', bind(fileList.removeFile)) - // If we don't subscribe; unhandled errors from Chokidar will bring Karma down - // (see GH Issue #959) - .on('error', function (e) { - log.debug(e) - }) - - emitter.on('exit', function (done) { - chokidarWatcher.close() + emitter.on('exit', done => { + watcher.close() done() }) - return chokidarWatcher + return watcher } -exports.watch.$inject = ['config.files', 'config.exclude', 'fileList', 'config.usePolling', - 'emitter'] +exports.watch.$inject = [ + 'config.files', + 'config.exclude', + 'fileList', + 'config.usePolling', + 'emitter' +]