node.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. 'use strict';
  2. var _fs;
  3. function _load_fs() {
  4. return _fs = _interopRequireDefault(require('fs'));
  5. }
  6. var _path;
  7. function _load_path() {
  8. return _path = _interopRequireDefault(require('path'));
  9. }
  10. var _child_process;
  11. function _load_child_process() {
  12. return _child_process = require('child_process');
  13. }
  14. var _constants;
  15. function _load_constants() {
  16. return _constants = _interopRequireDefault(require('../constants'));
  17. }
  18. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  19. /**
  20. * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
  21. *
  22. * This source code is licensed under the MIT license found in the
  23. * LICENSE file in the root directory of this source tree.
  24. *
  25. *
  26. */
  27. function find(roots, extensions, ignore, callback) {
  28. const result = [];
  29. let activeCalls = 0;
  30. function search(directory) {
  31. activeCalls++;
  32. (_fs || _load_fs()).default.readdir(directory, (err, names) => {
  33. activeCalls--;
  34. names.forEach(file => {
  35. file = (_path || _load_path()).default.join(directory, file);
  36. if (ignore(file)) {
  37. return;
  38. }
  39. activeCalls++;
  40. (_fs || _load_fs()).default.lstat(file, (err, stat) => {
  41. activeCalls--;
  42. if (!err && stat && !stat.isSymbolicLink()) {
  43. if (stat.isDirectory()) {
  44. search(file);
  45. } else {
  46. const ext = (_path || _load_path()).default.extname(file).substr(1);
  47. if (extensions.indexOf(ext) !== -1) {
  48. result.push([file, stat.mtime.getTime()]);
  49. }
  50. }
  51. }
  52. if (activeCalls === 0) {
  53. callback(result);
  54. }
  55. });
  56. });
  57. if (activeCalls === 0) {
  58. callback(result);
  59. }
  60. });
  61. }
  62. if (roots.length > 0) {
  63. roots.forEach(search);
  64. } else {
  65. callback(result);
  66. }
  67. }
  68. function findNative(roots, extensions, ignore, callback) {
  69. const args = [].concat(roots);
  70. args.push('-type', 'f');
  71. if (extensions.length) {
  72. args.push('(');
  73. }
  74. extensions.forEach((ext, index) => {
  75. if (index) {
  76. args.push('-o');
  77. }
  78. args.push('-iname');
  79. args.push('*.' + ext);
  80. });
  81. if (extensions.length) {
  82. args.push(')');
  83. }
  84. const child = (0, (_child_process || _load_child_process()).spawn)('find', args);
  85. let stdout = '';
  86. child.stdout.setEncoding('utf-8');
  87. child.stdout.on('data', data => stdout += data);
  88. child.stdout.on('close', () => {
  89. const lines = stdout.trim().split('\n').filter(x => !ignore(x));
  90. const result = [];
  91. let count = lines.length;
  92. if (!count) {
  93. callback([]);
  94. } else {
  95. lines.forEach(path => {
  96. (_fs || _load_fs()).default.stat(path, (err, stat) => {
  97. if (!err && stat) {
  98. result.push([path, stat.mtime.getTime()]);
  99. }
  100. if (--count === 0) {
  101. callback(result);
  102. }
  103. });
  104. });
  105. }
  106. });
  107. }
  108. module.exports = function nodeCrawl(options) {
  109. const data = options.data,
  110. extensions = options.extensions,
  111. forceNodeFilesystemAPI = options.forceNodeFilesystemAPI,
  112. ignore = options.ignore,
  113. roots = options.roots;
  114. return new Promise(resolve => {
  115. const callback = list => {
  116. const files = Object.create(null);
  117. list.forEach(fileData => {
  118. const name = fileData[0];
  119. const mtime = fileData[1];
  120. const existingFile = data.files[name];
  121. if (existingFile && existingFile[(_constants || _load_constants()).default.MTIME] === mtime) {
  122. files[name] = existingFile;
  123. } else {
  124. // See ../constants.js
  125. files[name] = ['', mtime, 0, []];
  126. }
  127. });
  128. data.files = files;
  129. resolve(data);
  130. };
  131. if (forceNodeFilesystemAPI || process.platform === 'win32') {
  132. find(roots, extensions, ignore, callback);
  133. } else {
  134. findNative(roots, extensions, ignore, callback);
  135. }
  136. });
  137. };