* Capture untracked files (git diff doesn't include them). * Respects size limits and skips binary files.
()
| 614 | * Respects size limits and skips binary files. |
| 615 | */ |
| 616 | async function captureUntrackedFiles(): Promise< |
| 617 | Array<{ path: string; content: string }> |
| 618 | > { |
| 619 | const { stdout, code } = await execFileNoThrow( |
| 620 | gitExe(), |
| 621 | ['ls-files', '--others', '--exclude-standard'], |
| 622 | { preserveOutputOnError: false }, |
| 623 | ) |
| 624 | |
| 625 | const trimmed = stdout.trim() |
| 626 | if (code !== 0 || !trimmed) { |
| 627 | return [] |
| 628 | } |
| 629 | |
| 630 | const files = trimmed.split('\n').filter(Boolean) |
| 631 | const result: Array<{ path: string; content: string }> = [] |
| 632 | let totalSize = 0 |
| 633 | |
| 634 | for (const filePath of files) { |
| 635 | // Check file count limit |
| 636 | if (result.length >= MAX_FILE_COUNT) { |
| 637 | logForDebugging( |
| 638 | `Untracked file capture: reached max file count (${MAX_FILE_COUNT})`, |
| 639 | ) |
| 640 | break |
| 641 | } |
| 642 | |
| 643 | // Skip binary files by extension - zero I/O |
| 644 | if (hasBinaryExtension(filePath)) { |
| 645 | continue |
| 646 | } |
| 647 | |
| 648 | try { |
| 649 | const stats = await stat(filePath) |
| 650 | const fileSize = stats.size |
| 651 | |
| 652 | // Skip files exceeding per-file limit |
| 653 | if (fileSize > MAX_FILE_SIZE_BYTES) { |
| 654 | logForDebugging( |
| 655 | `Untracked file capture: skipping ${filePath} (exceeds ${MAX_FILE_SIZE_BYTES} bytes)`, |
| 656 | ) |
| 657 | continue |
| 658 | } |
| 659 | |
| 660 | // Check total size limit |
| 661 | if (totalSize + fileSize > MAX_TOTAL_SIZE_BYTES) { |
| 662 | logForDebugging( |
| 663 | `Untracked file capture: reached total size limit (${MAX_TOTAL_SIZE_BYTES} bytes)`, |
| 664 | ) |
| 665 | break |
| 666 | } |
| 667 | |
| 668 | // Empty file - no need to open |
| 669 | if (fileSize === 0) { |
| 670 | result.push({ path: filePath, content: '' }) |
| 671 | continue |
| 672 | } |
| 673 |
no test coverage detected