UNPKG

gitlify

Version:

A powerful CLI tool to analyze uncommitted git changes with detailed reports, function detection, and beautiful terminal output

136 lines (117 loc) 3.83 kB
const { exec } = require('child_process'); const { promisify } = require('util'); const execAsync = promisify(exec); const InputValidator = require('./utils/validator.js'); const { GitError, SecurityError, ErrorHandler } = require('./utils/error-handler.js'); const config = require('./config.js'); class GitAnalyzer { constructor() { this.cwd = process.cwd(); } async isGitRepository() { try { await execAsync('git rev-parse --git-dir', { cwd: this.cwd }); return true; } catch (error) { return false; } } async getStatus() { try { const gitOptions = config.getGitOptions(); const { stdout } = await execAsync('git status --porcelain', { cwd: this.cwd, ...gitOptions }); const lines = stdout.trim().split('\n').filter(line => line.length > 0); // Validate file paths const validatedFiles = lines.map(line => { const status = line.substring(0, 2).trim(); const filePath = line.substring(3); // Validate file path try { InputValidator.validateFilePath(filePath); } catch (error) { throw new SecurityError(`Invalid file path in git status: ${filePath}`, { originalError: error.message }); } return { status, filePath }; }); return { hasChanges: validatedFiles.length > 0, files: validatedFiles }; } catch (error) { throw new GitError('Failed to get git status', { originalError: error.message, command: 'git status --porcelain' }); } } async getDiff() { try { const gitOptions = config.getGitOptions(); // Get diff for staged changes const { stdout: stagedDiff } = await execAsync('git diff --cached', { cwd: this.cwd, ...gitOptions }); // Get diff for unstaged changes const { stdout: unstagedDiff } = await execAsync('git diff', { cwd: this.cwd, ...gitOptions }); return { staged: stagedDiff, unstaged: unstagedDiff, combined: stagedDiff + '\n' + unstagedDiff }; } catch (error) { throw new GitError('Failed to get git diff', { originalError: error.message, command: 'git diff' }); } } async getFileContent(filePath) { try { // Input validation InputValidator.validateFilePath(filePath); const gitOptions = config.getGitOptions(); const { stdout } = await execAsync(`git show HEAD:${filePath}`, { cwd: this.cwd, ...gitOptions }); return stdout; } catch (error) { // File might not exist in HEAD, return empty content if (error.code === 'ENOENT' || error.message.includes('does not exist')) { return ''; } throw new GitError('Failed to get file content from git', { originalError: error.message, filePath: filePath }); } } async getCurrentFileContent(filePath) { try { const fs = require('fs'); // Path validation and resolution const fullPath = InputValidator.validateAndResolvePath(filePath, this.cwd); // File size validation InputValidator.validateFileSize(fullPath, config.maxFileSize); return fs.readFileSync(fullPath, 'utf8'); } catch (error) { if (error.code === 'ENOENT') { return ''; } throw new FileSystemError('Failed to read current file content', { originalError: error.message, filePath: filePath }); } } } module.exports = GitAnalyzer;