directory.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /**
  2. * Directory Management
  3. *
  4. * Manages the .codegraph/ directory structure.
  5. */
  6. import * as fs from 'fs';
  7. import * as path from 'path';
  8. /**
  9. * CodeGraph directory name
  10. */
  11. export const CODEGRAPH_DIR = '.codegraph';
  12. /**
  13. * Get the .codegraph directory path for a project
  14. */
  15. export function getCodeGraphDir(projectRoot: string): string {
  16. return path.join(projectRoot, CODEGRAPH_DIR);
  17. }
  18. /**
  19. * Check if a project has been initialized with CodeGraph
  20. */
  21. export function isInitialized(projectRoot: string): boolean {
  22. const codegraphDir = getCodeGraphDir(projectRoot);
  23. return fs.existsSync(codegraphDir) && fs.statSync(codegraphDir).isDirectory();
  24. }
  25. /**
  26. * Create the .codegraph directory structure
  27. */
  28. export function createDirectory(projectRoot: string): void {
  29. const codegraphDir = getCodeGraphDir(projectRoot);
  30. if (fs.existsSync(codegraphDir)) {
  31. throw new Error(`CodeGraph already initialized in ${projectRoot}`);
  32. }
  33. // Create main directory
  34. fs.mkdirSync(codegraphDir, { recursive: true });
  35. // Create .gitignore inside .codegraph
  36. const gitignorePath = path.join(codegraphDir, '.gitignore');
  37. const gitignoreContent = `# CodeGraph data files
  38. # These are local to each machine and should not be committed
  39. # Database
  40. *.db
  41. *.db-wal
  42. *.db-shm
  43. # Cache
  44. cache/
  45. # Logs
  46. *.log
  47. `;
  48. fs.writeFileSync(gitignorePath, gitignoreContent, 'utf-8');
  49. }
  50. /**
  51. * Remove the .codegraph directory
  52. */
  53. export function removeDirectory(projectRoot: string): void {
  54. const codegraphDir = getCodeGraphDir(projectRoot);
  55. if (!fs.existsSync(codegraphDir)) {
  56. return;
  57. }
  58. // Recursively remove directory
  59. fs.rmSync(codegraphDir, { recursive: true, force: true });
  60. }
  61. /**
  62. * Get all files in the .codegraph directory
  63. */
  64. export function listDirectoryContents(projectRoot: string): string[] {
  65. const codegraphDir = getCodeGraphDir(projectRoot);
  66. if (!fs.existsSync(codegraphDir)) {
  67. return [];
  68. }
  69. const files: string[] = [];
  70. function walkDir(dir: string, prefix: string = ''): void {
  71. const entries = fs.readdirSync(dir, { withFileTypes: true });
  72. for (const entry of entries) {
  73. const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
  74. if (entry.isDirectory()) {
  75. walkDir(path.join(dir, entry.name), relativePath);
  76. } else {
  77. files.push(relativePath);
  78. }
  79. }
  80. }
  81. walkDir(codegraphDir);
  82. return files;
  83. }
  84. /**
  85. * Get the total size of the .codegraph directory in bytes
  86. */
  87. export function getDirectorySize(projectRoot: string): number {
  88. const codegraphDir = getCodeGraphDir(projectRoot);
  89. if (!fs.existsSync(codegraphDir)) {
  90. return 0;
  91. }
  92. let totalSize = 0;
  93. function walkDir(dir: string): void {
  94. const entries = fs.readdirSync(dir, { withFileTypes: true });
  95. for (const entry of entries) {
  96. const fullPath = path.join(dir, entry.name);
  97. if (entry.isDirectory()) {
  98. walkDir(fullPath);
  99. } else {
  100. const stats = fs.statSync(fullPath);
  101. totalSize += stats.size;
  102. }
  103. }
  104. }
  105. walkDir(codegraphDir);
  106. return totalSize;
  107. }
  108. /**
  109. * Ensure a subdirectory exists within .codegraph
  110. */
  111. export function ensureSubdirectory(projectRoot: string, subdirName: string): string {
  112. const subdirPath = path.join(getCodeGraphDir(projectRoot), subdirName);
  113. if (!fs.existsSync(subdirPath)) {
  114. fs.mkdirSync(subdirPath, { recursive: true });
  115. }
  116. return subdirPath;
  117. }
  118. /**
  119. * Check if the .codegraph directory has valid structure
  120. */
  121. export function validateDirectory(projectRoot: string): {
  122. valid: boolean;
  123. errors: string[];
  124. } {
  125. const errors: string[] = [];
  126. const codegraphDir = getCodeGraphDir(projectRoot);
  127. if (!fs.existsSync(codegraphDir)) {
  128. errors.push('CodeGraph directory does not exist');
  129. return { valid: false, errors };
  130. }
  131. if (!fs.statSync(codegraphDir).isDirectory()) {
  132. errors.push('.codegraph exists but is not a directory');
  133. return { valid: false, errors };
  134. }
  135. // Check for required files
  136. const gitignorePath = path.join(codegraphDir, '.gitignore');
  137. if (!fs.existsSync(gitignorePath)) {
  138. errors.push('.gitignore missing in .codegraph directory');
  139. }
  140. return {
  141. valid: errors.length === 0,
  142. errors,
  143. };
  144. }