diff --git a/packages/jest-haste-map/src/lib/RecrawlWarning.js b/packages/jest-haste-map/src/lib/RecrawlWarning.js new file mode 100644 index 000000000000..2e65459b6f9d --- /dev/null +++ b/packages/jest-haste-map/src/lib/RecrawlWarning.js @@ -0,0 +1,51 @@ +'use strict'; + +class RecrawlWarning { + constructor(root, count) { + this.root = root; + this.count = count; + } + + static findByRoot(root) { + for (let i = 0; i < this.RECRAWL_WARNINGS.length; i++) { + const warning = this.RECRAWL_WARNINGS[i]; + if (warning.root === root) { + return warning; + } + } + } + + static isRecrawlWarningDupe(warningMessage) { + if (typeof warningMessage !== 'string') { + return false; + } + const match = warningMessage.match(this.REGEXP); + if (!match) { + return false; + } + const count = Number(match[1]); + const root = match[2]; + + const warning = this.findByRoot(root); + + if (warning) { + // only keep the highest count, assume count to either stay the same or + // increase. + if (warning.count >= count) { + return true; + } else { + // update the existing warning to the latest (highest) count + warning.count = count; + return false; + } + } else { + this.RECRAWL_WARNINGS.push(new RecrawlWarning(root, count)); + return false; + } + } +} + +RecrawlWarning.RECRAWL_WARNINGS = []; +RecrawlWarning.REGEXP = /Recrawled this watch (\d+) times, most recently because:\n([^:]+)/; + +module.exports = RecrawlWarning; diff --git a/packages/jest-haste-map/src/lib/WatchmanWatcher.js b/packages/jest-haste-map/src/lib/WatchmanWatcher.js index 548843543d9f..b2172547a9ce 100644 --- a/packages/jest-haste-map/src/lib/WatchmanWatcher.js +++ b/packages/jest-haste-map/src/lib/WatchmanWatcher.js @@ -8,15 +8,16 @@ import assert from 'assert'; import {EventEmitter} from 'events'; import path from 'path'; +import anymatch from 'anymatch'; import watchman from 'fb-watchman'; import * as fs from 'graceful-fs'; -import common from 'sane/src/common'; -import RecrawlWarning from 'sane/src/utils/recrawl-warning-dedupe'; +import micromatch from 'micromatch'; +import RecrawlWarning from './RecrawlWarning'; -const CHANGE_EVENT = common.CHANGE_EVENT; -const DELETE_EVENT = common.DELETE_EVENT; -const ADD_EVENT = common.ADD_EVENT; -const ALL_EVENT = common.ALL_EVENT; +const CHANGE_EVENT = 'change'; +const DELETE_EVENT = 'delete'; +const ADD_EVENT = 'add'; +const ALL_EVENT = 'all'; const SUB_NAME = 'sane-sub'; /** @@ -29,7 +30,7 @@ const SUB_NAME = 'sane-sub'; */ export default function WatchmanWatcher(dir, opts) { - common.assignOptions(this, opts); + assignOptions(this, opts); this.root = path.resolve(dir); this.init(); } @@ -226,7 +227,7 @@ WatchmanWatcher.prototype.handleFileChange = function (changeDescriptor) { if ( !(self.capabilities.wildmatch && !this.hasIgnore) && - !common.isFileIncluded(this.globs, this.dot, this.doIgnore, relativePath) + !isFileIncluded(this.globs, this.dot, this.doIgnore, relativePath) ) { return; } @@ -321,3 +322,33 @@ function handleWarning(resp) { return false; } } + +function assignOptions(watcher, opts) { + opts = opts || {}; + watcher.globs = opts.glob || []; + watcher.dot = opts.dot || false; + watcher.ignored = opts.ignored || false; + + if (!Array.isArray(watcher.globs)) { + watcher.globs = [watcher.globs]; + } + watcher.hasIgnore = + Boolean(opts.ignored) && !(Array.isArray(opts) && opts.length > 0); + watcher.doIgnore = opts.ignored ? anymatch(opts.ignored) : () => false; + + if (opts.watchman && opts.watchmanPath) { + watcher.watchmanPath = opts.watchmanPath; + } + + return opts; +} + +function isFileIncluded(globs, dot, doIgnore, relativePath) { + if (doIgnore(relativePath)) { + return false; + } + return globs.length + ? micromatch.some(relativePath, globs, {dot}) + : dot || micromatch.some(relativePath, '**/*'); +} +