FileCache.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. 'use strict';
  2. const debug = require('debug')('stylelint:file-cache');
  3. const fileEntryCache = require('file-entry-cache');
  4. const getCacheFile = require('./getCacheFile');
  5. const hash = require('./hash');
  6. const pkg = require('../../package.json');
  7. const path = require('path');
  8. const CACHE_STRATEGY_METADATA = 'metadata';
  9. const CACHE_STRATEGY_CONTENT = 'content';
  10. const DEFAULT_CACHE_LOCATION = './.stylelintcache';
  11. const DEFAULT_CACHE_STRATEGY = CACHE_STRATEGY_METADATA;
  12. /** @typedef {import('file-entry-cache').FileDescriptor["meta"] & { hashOfConfig?: string }} CacheMetadata */
  13. class FileCache {
  14. constructor(
  15. cacheLocation = DEFAULT_CACHE_LOCATION,
  16. cacheStrategy = DEFAULT_CACHE_STRATEGY,
  17. cwd = process.cwd(),
  18. ) {
  19. if (![CACHE_STRATEGY_METADATA, CACHE_STRATEGY_CONTENT].includes(cacheStrategy)) {
  20. throw new Error(
  21. `"${cacheStrategy}" cache strategy is unsupported. Specify either "${CACHE_STRATEGY_METADATA}" or "${CACHE_STRATEGY_CONTENT}"`,
  22. );
  23. }
  24. const cacheFile = path.resolve(getCacheFile(cacheLocation, cwd));
  25. const useCheckSum = cacheStrategy === CACHE_STRATEGY_CONTENT;
  26. debug(`Cache file is created at ${cacheFile}`);
  27. this._fileCache = fileEntryCache.create(cacheFile, undefined, useCheckSum);
  28. this._hashOfConfig = '';
  29. }
  30. /**
  31. * @param {import('stylelint').Config} config
  32. */
  33. calcHashOfConfig(config) {
  34. if (this._hashOfConfig) return;
  35. const stylelintVersion = pkg.version;
  36. const configString = JSON.stringify(config || {});
  37. this._hashOfConfig = hash(`${stylelintVersion}_${configString}`);
  38. }
  39. /**
  40. * @param {string} absoluteFilepath
  41. * @return {boolean}
  42. */
  43. hasFileChanged(absoluteFilepath) {
  44. // Get file descriptor compares current metadata against cached
  45. // one and stores the result to "changed" prop.w
  46. const descriptor = this._fileCache.getFileDescriptor(absoluteFilepath);
  47. /** @type {CacheMetadata} */
  48. const meta = descriptor.meta || {};
  49. const changed = descriptor.changed || meta.hashOfConfig !== this._hashOfConfig;
  50. if (!changed) {
  51. debug(`Skip linting ${absoluteFilepath}. File hasn't changed.`);
  52. }
  53. // Mutate file descriptor object and store config hash to each file.
  54. // Running lint with different config should invalidate the cache.
  55. if (meta.hashOfConfig !== this._hashOfConfig) {
  56. meta.hashOfConfig = this._hashOfConfig;
  57. }
  58. return changed;
  59. }
  60. reconcile() {
  61. this._fileCache.reconcile();
  62. }
  63. destroy() {
  64. this._fileCache.destroy();
  65. }
  66. /**
  67. * @param {string} absoluteFilepath
  68. */
  69. removeEntry(absoluteFilepath) {
  70. this._fileCache.removeEntry(absoluteFilepath);
  71. }
  72. }
  73. module.exports = FileCache;