Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

file-finder.js 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /**
  2. * @fileoverview Util class to find config files.
  3. * @author Aliaksei Shytkin
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const fs = require("fs"),
  10. path = require("path");
  11. //------------------------------------------------------------------------------
  12. // Helpers
  13. //------------------------------------------------------------------------------
  14. /**
  15. * Get the entries for a directory. Including a try-catch may be detrimental to
  16. * function performance, so move it out here a separate function.
  17. * @param {string} directory The directory to search in.
  18. * @returns {string[]} The entries in the directory or an empty array on error.
  19. * @private
  20. */
  21. function getDirectoryEntries(directory) {
  22. try {
  23. return fs.readdirSync(directory);
  24. } catch (ex) {
  25. return [];
  26. }
  27. }
  28. /**
  29. * Create a hash of filenames from a directory listing
  30. * @param {string[]} entries Array of directory entries.
  31. * @param {string} directory Path to a current directory.
  32. * @param {string[]} supportedConfigs List of support filenames.
  33. * @returns {Object} Hashmap of filenames
  34. */
  35. function normalizeDirectoryEntries(entries, directory, supportedConfigs) {
  36. const fileHash = {};
  37. entries.forEach(entry => {
  38. if (supportedConfigs.indexOf(entry) >= 0) {
  39. const resolvedEntry = path.resolve(directory, entry);
  40. if (fs.statSync(resolvedEntry).isFile()) {
  41. fileHash[entry] = resolvedEntry;
  42. }
  43. }
  44. });
  45. return fileHash;
  46. }
  47. //------------------------------------------------------------------------------
  48. // API
  49. //------------------------------------------------------------------------------
  50. /**
  51. * FileFinder class
  52. */
  53. class FileFinder {
  54. /**
  55. * @param {string[]} files The basename(s) of the file(s) to find.
  56. * @param {stirng} cwd Current working directory
  57. */
  58. constructor(files, cwd) {
  59. this.fileNames = Array.isArray(files) ? files : [files];
  60. this.cwd = cwd || process.cwd();
  61. this.cache = {};
  62. }
  63. /**
  64. * Find all instances of files with the specified file names, in directory and
  65. * parent directories. Cache the results.
  66. * Does not check if a matching directory entry is a file.
  67. * Searches for all the file names in this.fileNames.
  68. * Is currently used by lib/config.js to find .eslintrc and package.json files.
  69. * @param {string} relativeDirectory The directory to start the search from.
  70. * @returns {GeneratorFunction} to iterate the file paths found
  71. */
  72. *findAllInDirectoryAndParents(relativeDirectory) {
  73. const cache = this.cache;
  74. const initialDirectory = relativeDirectory
  75. ? path.resolve(this.cwd, relativeDirectory)
  76. : this.cwd;
  77. if (Object.prototype.hasOwnProperty.call(cache, initialDirectory)) {
  78. yield* cache[initialDirectory];
  79. return; // to avoid doing the normal loop afterwards
  80. }
  81. const dirs = [];
  82. const fileNames = this.fileNames;
  83. let searched = 0;
  84. let directory = initialDirectory;
  85. do {
  86. dirs[searched++] = directory;
  87. cache[directory] = [];
  88. const filesMap = normalizeDirectoryEntries(getDirectoryEntries(directory), directory, fileNames);
  89. if (Object.keys(filesMap).length) {
  90. for (let k = 0; k < fileNames.length; k++) {
  91. if (filesMap[fileNames[k]]) {
  92. const filePath = filesMap[fileNames[k]];
  93. // Add the file path to the cache of each directory searched.
  94. for (let j = 0; j < searched; j++) {
  95. cache[dirs[j]].push(filePath);
  96. }
  97. yield filePath;
  98. break;
  99. }
  100. }
  101. }
  102. const child = directory;
  103. // Assign parent directory to directory.
  104. directory = path.dirname(directory);
  105. if (directory === child) {
  106. return;
  107. }
  108. } while (!Object.prototype.hasOwnProperty.call(cache, directory));
  109. // Add what has been cached previously to the cache of each directory searched.
  110. for (let i = 0; i < searched; i++) {
  111. cache[dirs[i]].push(...cache[directory]);
  112. }
  113. yield* cache[dirs[0]];
  114. }
  115. }
  116. module.exports = FileFinder;