UNPKG

react-scripts

Version:
132 lines (112 loc) 3.74 kB
/** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * */ 'use strict'; const H = require('../constants'); const path = require('../fastpath'); const watchman = require('fb-watchman'); const watchmanURL = 'https://facebook.github.io/watchman/docs/troubleshooting.html'; function isDescendant(root, child) { return child.startsWith(root); } function WatchmanError(error) { return new Error( `Watchman error: ${ error.message.trim() }. Make sure watchman ` + `is running for this project. See ${ watchmanURL }.`); } module.exports = function watchmanCrawl( roots, extensions, ignore, data) { return new Promise((resolve, reject) => { const client = new watchman.Client(); client.on('error', error => reject(error)); const cmd = args => new Promise((resolve, reject) => { client.command(args, (error, result) => { if (error) { reject(error); } else { resolve(result); } }); }); const clocks = data.clocks; let files = data.files; return Promise.all(roots.map(root => cmd(['watch-project', root]))). then(responses => { const watchmanRoots = Array.from( new Set(responses.map(response => response.watch))); return Promise.all(watchmanRoots.map(root => { // Build up an expression to filter the output by the relevant roots. const dirExpr = ['anyof']; roots.forEach(subRoot => { if (isDescendant(root, subRoot)) { dirExpr.push(['dirname', path.relative(root, subRoot)]); } }); const expression = [ 'allof', ['type', 'f'], ['anyof'].concat(extensions.map( extension => ['suffix', extension])), dirExpr]; const fields = ['name', 'exists', 'mtime_ms']; const query = clocks[root] // Use the `since` generator if we have a clock available ? { expression, fields, since: clocks[root] } // Otherwise use the `suffix` generator : { expression, fields, suffix: extensions }; return cmd(['query', root, query]).then(response => ({ root, response })); })).then(pairs => { // Reset the file map if watchman was restarted and sends us a list of // files. if (pairs.some(pair => pair.response.is_fresh_instance)) { files = Object.create(null); } pairs.forEach(pair => { const root = pair.root; const response = pair.response; if ('warning' in response) { console.warn('watchman warning: ', response.warning); } clocks[root] = response.clock; response.files.forEach(fileData => { const name = root + path.sep + fileData.name; if (!fileData.exists) { delete files[name]; } else if (!ignore(name)) { const mtime = fileData.mtime_ms.toNumber(); const isNew = !data.files[name] || data.files[name][H.MTIME] !== mtime; if (isNew) { // See ../constants.js files[name] = ['', mtime, 0, []]; } else { files[name] = data.files[name]; } } }); }); }); }). then(() => { client.end(); data.files = files; resolve(data); }). catch(error => { client.end(); reject(WatchmanError(error)); }); }); };