UNPKG

ripple-ai-detector

Version:

🌊 Ripple AI Bug Detector - Built by an AI that knows its flaws. Catch AI-generated bugs before you commit.

201 lines • 7.45 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.GitManager = void 0; const simple_git_1 = __importDefault(require("simple-git")); const path_1 = __importDefault(require("path")); const file_utils_1 = require("../utils/file-utils"); class GitManager { git; cwd; constructor(cwd = process.cwd()) { this.cwd = cwd; this.git = (0, simple_git_1.default)(cwd); } // Check if current directory is a git repository async isGitRepository() { try { await this.git.status(); return true; } catch { return false; } } // Get git repository information async getGitInfo() { try { const isRepo = await this.isGitRepository(); if (!isRepo) { return { isRepository: false, hasChanges: false, stagedFiles: [], modifiedFiles: [] }; } const status = await this.git.status(); const branch = await this.git.revparse(['--abbrev-ref', 'HEAD']); const commit = await this.git.revparse(['HEAD']).catch(() => undefined); return { isRepository: true, branch: branch.trim(), commit: commit?.trim(), hasChanges: status.files.length > 0, stagedFiles: status.staged, modifiedFiles: status.modified }; } catch (error) { throw new Error(`Git operation failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Get staged files (ready to commit) async getStagedFiles() { try { const isRepo = await this.isGitRepository(); if (!isRepo) { return []; } const status = await this.git.status(); // Get staged files and convert to absolute paths const stagedFiles = status.staged .filter(file => file_utils_1.FileUtils.isSupportedFile(file)) .map(file => path_1.default.resolve(this.cwd, file)); return stagedFiles; } catch (error) { throw new Error(`Failed to get staged files: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Get all modified files (staged + unstaged) async getModifiedFiles() { try { const isRepo = await this.isGitRepository(); if (!isRepo) { return []; } const status = await this.git.status(); // Combine staged and modified files const allModified = [...new Set([...status.staged, ...status.modified])] .filter(file => file_utils_1.FileUtils.isSupportedFile(file)) .map(file => path_1.default.resolve(this.cwd, file)); return allModified; } catch (error) { throw new Error(`Failed to get modified files: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Get all JavaScript/TypeScript files in repository async getAllJSFiles() { try { const files = await file_utils_1.FileUtils.getJSFiles(this.cwd); // Filter out files that are ignored by git const filteredFiles = []; for (const file of files) { const relativePath = path_1.default.relative(this.cwd, file); const isIgnored = await this.isFileIgnored(relativePath); if (!isIgnored) { filteredFiles.push(file); } } return filteredFiles; } catch (error) { throw new Error(`Failed to get JS files: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Check if file is ignored by git async isFileIgnored(filePath) { try { const isRepo = await this.isGitRepository(); if (!isRepo) { return false; } const result = await this.git.raw(['check-ignore', filePath]).catch(() => null); return result !== null; } catch { return false; } } // Get diff for specific files async getDiff(files) { try { const isRepo = await this.isGitRepository(); if (!isRepo) { return ''; } if (files && files.length > 0) { // Get diff for specific files const relativePaths = files.map(file => path_1.default.relative(this.cwd, file)); return await this.git.diff(['--cached', ...relativePaths]); } else { // Get diff for all staged files return await this.git.diff(['--cached']); } } catch (error) { throw new Error(`Failed to get diff: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Get changes for analysis async getChanges(files) { try { const isRepo = await this.isGitRepository(); if (!isRepo) { return []; } const status = await this.git.status(); const changes = []; // Process staged files for (const file of status.staged) { if (!files || files.some(f => path_1.default.resolve(this.cwd, file) === f)) { const diff = await this.git.diff(['--cached', '--numstat', file]); const stats = this.parseNumstat(diff); changes.push({ file: path_1.default.resolve(this.cwd, file), status: 'modified', // Staged files are considered modified additions: stats.additions, deletions: stats.deletions }); } } return changes; } catch (error) { throw new Error(`Failed to get changes: ${error instanceof Error ? error.message : 'Unknown error'}`); } } // Parse numstat output to get additions/deletions parseNumstat(numstat) { const lines = numstat.trim().split('\n').filter(line => line.length > 0); if (lines.length === 0) { return { additions: 0, deletions: 0 }; } const parts = lines[0].split('\t'); return { additions: parseInt(parts[0]) || 0, deletions: parseInt(parts[1]) || 0 }; } // Get recent commits (for AI pattern detection) async getRecentCommits(count = 10) { try { const isRepo = await this.isGitRepository(); if (!isRepo) { return []; } const log = await this.git.log({ maxCount: count }); return [...log.all]; } catch (error) { throw new Error(`Failed to get recent commits: ${error instanceof Error ? error.message : 'Unknown error'}`); } } } exports.GitManager = GitManager; //# sourceMappingURL=git-manager.js.map