git-changed-untracked-dir.test.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /**
  2. * Regression test for #1213: `codegraph sync` silently skips untracked files
  3. * that live inside an untracked directory.
  4. *
  5. * `git status --porcelain` collapses an entirely-untracked directory into a
  6. * single `?? frontend/` entry. getGitChangedFiles must still surface the source
  7. * files inside it (via `-uall`) rather than dropping the whole directory.
  8. */
  9. import { describe, it, expect, afterEach } from 'vitest';
  10. import { execFileSync } from 'child_process';
  11. import * as fs from 'fs';
  12. import * as path from 'path';
  13. import * as os from 'os';
  14. import { getGitChangedFiles } from '../src/extraction/index';
  15. function git(cwd: string, args: string[]): void {
  16. execFileSync('git', args, { cwd, stdio: 'pipe' });
  17. }
  18. describe('getGitChangedFiles — untracked directories (#1213)', () => {
  19. const dirs: string[] = [];
  20. function makeRepo(): string {
  21. const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-1213-'));
  22. dirs.push(dir);
  23. git(dir, ['init']);
  24. git(dir, ['config', 'user.email', 'test@example.com']);
  25. git(dir, ['config', 'user.name', 'test']);
  26. fs.writeFileSync(path.join(dir, 'root.js'), 'function foo() {}\n');
  27. git(dir, ['add', 'root.js']);
  28. git(dir, ['commit', '-m', 'init']);
  29. return dir;
  30. }
  31. afterEach(() => {
  32. while (dirs.length) {
  33. fs.rmSync(dirs.pop()!, { recursive: true, force: true });
  34. }
  35. });
  36. it('detects source files inside a fully-untracked directory', () => {
  37. const dir = makeRepo();
  38. fs.mkdirSync(path.join(dir, 'frontend'));
  39. fs.writeFileSync(path.join(dir, 'frontend', 'app.js'), 'function bar() {}\n');
  40. const changes = getGitChangedFiles(dir);
  41. expect(changes).not.toBeNull();
  42. expect(changes!.added).toContain('frontend/app.js');
  43. });
  44. it('still recurses into an untracked embedded git repo (no -uall regression)', () => {
  45. // `-uall` must not break the embedded-repo path: git collapses a nested
  46. // repo to `?? embedded/` regardless of `-uall`, so its files are only
  47. // reachable through collectGitStatus's recursion.
  48. const dir = makeRepo();
  49. const embedded = path.join(dir, 'embedded');
  50. fs.mkdirSync(embedded);
  51. git(embedded, ['init']);
  52. fs.writeFileSync(path.join(embedded, 'inner.js'), 'function baz() {}\n');
  53. const changes = getGitChangedFiles(dir);
  54. expect(changes).not.toBeNull();
  55. expect(changes!.added).toContain('embedded/inner.js');
  56. });
  57. });