woaru
Version:
Universal Project Setup Autopilot - Analyze and automatically configure development tools for ANY programming language
166 lines • 5.76 kB
JavaScript
import { spawn } from 'child_process';
import * as path from 'path';
import fs from 'fs-extra';
export class GitDiffAnalyzer {
projectPath;
constructor(projectPath) {
this.projectPath = projectPath;
}
async isGitRepository() {
return await fs.pathExists(path.join(this.projectPath, '.git'));
}
async getChangedFilesSince(baseBranch = 'main') {
if (!(await this.isGitRepository())) {
throw new Error('Not a git repository');
}
return new Promise((resolve, reject) => {
const gitProcess = spawn('git', ['diff', '--name-only', `${baseBranch}...HEAD`], {
cwd: this.projectPath,
stdio: 'pipe',
});
let stdout = '';
let stderr = '';
gitProcess.stdout.on('data', (data) => {
stdout += data.toString();
});
gitProcess.stderr.on('data', (data) => {
stderr += data.toString();
});
gitProcess.on('close', (code) => {
if (code !== 0) {
reject(new Error(`Git command failed: ${stderr}`));
return;
}
const changedFiles = stdout
.trim()
.split('\n')
.filter(file => file.length > 0)
.map(file => path.resolve(this.projectPath, file))
.filter(file => fs.existsSync(file)); // Only include files that still exist
resolve({
changedFiles,
baseBranch,
totalChanges: changedFiles.length,
});
});
gitProcess.on('error', error => {
reject(new Error(`Failed to execute git command: ${error.message}`));
});
});
}
async getCurrentBranch() {
return new Promise((resolve, reject) => {
const gitProcess = spawn('git', ['branch', '--show-current'], {
cwd: this.projectPath,
stdio: 'pipe',
});
let stdout = '';
let stderr = '';
gitProcess.stdout.on('data', (data) => {
stdout += data.toString();
});
gitProcess.stderr.on('data', (data) => {
stderr += data.toString();
});
gitProcess.on('close', (code) => {
if (code !== 0) {
reject(new Error(`Failed to get current branch: ${stderr}`));
return;
}
resolve(stdout.trim());
});
});
}
async getCommitsSince(baseBranch = 'main') {
return new Promise((resolve, reject) => {
const gitProcess = spawn('git', ['log', '--oneline', `${baseBranch}...HEAD`], {
cwd: this.projectPath,
stdio: 'pipe',
});
let stdout = '';
let stderr = '';
gitProcess.stdout.on('data', (data) => {
stdout += data.toString();
});
gitProcess.stderr.on('data', (data) => {
stderr += data.toString();
});
gitProcess.on('close', (code) => {
if (code !== 0) {
reject(new Error(`Failed to get commits: ${stderr}`));
return;
}
const commits = stdout
.trim()
.split('\n')
.filter(line => line.length > 0);
resolve(commits);
});
});
}
filterFilesByExtension(files, extensions) {
return files.filter(file => {
const ext = path.extname(file).toLowerCase();
return extensions.includes(ext);
});
}
categorizeChangedFiles(files) {
const result = {
source: [],
config: [],
tests: [],
docs: [],
other: [],
};
files.forEach(file => {
const filename = path.basename(file);
const ext = path.extname(file).toLowerCase();
const relativePath = path.relative(this.projectPath, file);
// Configuration files
if ([
'package.json',
'tsconfig.json',
'requirements.txt',
'Cargo.toml',
'go.mod',
].includes(filename) ||
['.eslintrc', '.prettierrc', 'jest.config', 'pyproject.toml'].some(config => filename.includes(config))) {
result.config.push(file);
}
// Test files
else if (relativePath.includes('test') ||
relativePath.includes('spec') ||
filename.includes('.test.') ||
filename.includes('.spec.')) {
result.tests.push(file);
}
// Documentation
else if (['.md', '.txt', '.rst'].includes(ext) ||
relativePath.includes('docs')) {
result.docs.push(file);
}
// Source files
else if ([
'.js',
'.jsx',
'.ts',
'.tsx',
'.py',
'.rs',
'.go',
'.java',
'.cs',
'.php',
'.rb',
].includes(ext)) {
result.source.push(file);
}
// Everything else
else {
result.other.push(file);
}
});
return result;
}
}
//# sourceMappingURL=GitDiffAnalyzer.js.map