unsafe-index-root.test.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import { describe, it, expect, afterEach } from 'vitest';
  2. import * as fs from 'fs';
  3. import * as os from 'os';
  4. import * as path from 'path';
  5. import { unsafeIndexRootReason } from '../src/directory';
  6. /**
  7. * Guard for #845: the installer / `init` / `index` must refuse the home
  8. * directory and filesystem roots, which would otherwise index the entire tree
  9. * (multi-GB index, watcher churn, pre-1.0 macOS fd exhaustion that crashed the
  10. * machine). The classic trigger was running the installer from `$HOME`.
  11. */
  12. describe('unsafeIndexRootReason', () => {
  13. const tmpDirs: string[] = [];
  14. afterEach(() => {
  15. for (const d of tmpDirs.splice(0)) {
  16. try { fs.rmSync(d, { recursive: true, force: true }); } catch { /* ignore */ }
  17. }
  18. });
  19. it('flags the home directory', () => {
  20. const reason = unsafeIndexRootReason(os.homedir());
  21. expect(reason).toBeTruthy();
  22. expect(reason).toContain('home');
  23. });
  24. it('flags a parent of the home directory (broader than home)', () => {
  25. // dirname(home) is either a parent of home or — for a root-level home like
  26. // `/root` — the filesystem root; both are unsafe.
  27. expect(unsafeIndexRootReason(path.dirname(os.homedir()))).toBeTruthy();
  28. });
  29. it.runIf(process.platform !== 'win32')('flags the POSIX filesystem root', () => {
  30. expect(unsafeIndexRootReason('/')).toContain('filesystem root');
  31. });
  32. it('allows a normal project directory', () => {
  33. const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-unsafe-'));
  34. tmpDirs.push(dir);
  35. expect(unsafeIndexRootReason(dir)).toBeNull();
  36. // …and a nested subdir of it.
  37. const nested = path.join(dir, 'packages', 'app');
  38. fs.mkdirSync(nested, { recursive: true });
  39. expect(unsafeIndexRootReason(nested)).toBeNull();
  40. });
  41. it('matches the home directory case-insensitively on macOS/Windows', () => {
  42. if (process.platform !== 'darwin' && process.platform !== 'win32') return;
  43. // The FS is case-insensitive there, so an upper-cased home path must still flag.
  44. expect(unsafeIndexRootReason(os.homedir().toUpperCase())).toBeTruthy();
  45. });
  46. });