node.js 4.1 KB

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