UNPKG

@jjdenhertog/ai-driven-development

Version:

AI-driven development workflow with learning capabilities for Claude

165 lines 7.59 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getCommits = getCommits; /* eslint-disable @typescript-eslint/prefer-destructuring */ /* eslint-disable max-depth */ const getGitInstance_1 = require("./getGitInstance"); const logger_1 = require("../logger"); const config_1 = require("../../config"); function getCommits(branch) { return __awaiter(this, void 0, void 0, function* () { try { const git = (0, getGitInstance_1.getGitInstance)(); (0, logger_1.log)(`Getting commits for branch: ${branch}`, 'info'); // Step 1: Get the branch tip reference let branchTip = null; try { // Try to get branch reference if it exists branchTip = yield git.raw(['rev-parse', `origin/${branch}`]).then(r => r.trim()); (0, logger_1.log)(`Found branch ${branch} at ${branchTip.slice(0, 8)}`, 'info'); } catch (_a) { // Branch doesn't exist, find it through merge commits (0, logger_1.log)(`Branch ${branch} not found, searching merge history`, 'info'); const mergeCommits = yield git.raw([ 'log', `origin/${config_1.MAIN_BRANCH}`, '--merges', '--grep', branch, '--pretty=format:%H %P', '-n', '10' ]); if (mergeCommits.trim()) { const lines = mergeCommits.trim().split('\n'); for (const line of lines) { const parts = line.split(' '); if (parts.length >= 3) { // eslint-disable-next-line @typescript-eslint/prefer-destructuring branchTip = parts[2]; // Second parent is the feature branch (0, logger_1.log)(`Found deleted branch via merge, tip at ${branchTip.slice(0, 8)}`, 'info'); break; } } } } if (!branchTip) { (0, logger_1.log)(`Could not find branch ${branch}`, 'error'); return null; } // Step 2: Find where the branch diverged from main // Use --first-parent to follow only the main branch history const divergencePoint = yield git.raw([ 'merge-base', '--fork-point', `origin/${config_1.MAIN_BRANCH}`, branchTip ]).then(r => r.trim()) .catch(() => null); let base = null; if (divergencePoint) { base = divergencePoint; (0, logger_1.log)(`Found fork point at ${base.slice(0, 8)}`, 'info'); } else { // Fallback: find the last commit that's in both histories const commonAncestor = yield git.raw([ 'merge-base', `origin/${config_1.MAIN_BRANCH}`, branchTip ]).then(r => r.trim()) .catch(() => null); if (!commonAncestor) { (0, logger_1.log)(`Could not find merge-base for branch ${branch}`, 'error'); return null; } // If merge-base returns the branch tip, branch is fully merged if (commonAncestor === branchTip) { // Find the parent of the merge commit const mergeInfo = yield git.raw([ 'log', `origin/${config_1.MAIN_BRANCH}`, '--merges', '--pretty=format:%H %P', '-n', '20' ]); const lines = mergeInfo.trim().split('\n'); for (const line of lines) { const parts = line.split(' '); if (parts.length >= 3 && parts[2] === branchTip) { base = parts[1]; // Use first parent as base (0, logger_1.log)(`Branch is merged, using merge parent ${base.slice(0, 8)} as base`, 'info'); break; } } if (!base) { (0, logger_1.log)(`Could not determine base for merged branch`, 'error'); return null; } } else { base = commonAncestor; (0, logger_1.log)(`Using merge-base ${base.slice(0, 8)}`, 'info'); } } // Get all commits from base to branch tip const commitList = yield git.raw([ 'rev-list', '--reverse', '--pretty=format:%H|%an|%ad|%s', '--date=iso-strict', `${base}..${branchTip}` ]); if (!commitList.trim()) { (0, logger_1.log)(`No commits found in branch ${branch}`, 'warn'); return null; } // Parse commits const commits = commitList .trim() .split('\n') .filter(line => !line.startsWith('commit ')) .map(line => { const [hash, author, date, message] = line.split('|'); const isAI = message.includes('(AI-generated)'); return { hash, author, date, message, isAI, fileChanges: [] }; }); (0, logger_1.log)(`Found ${commits.length} commits in branch ${branch}`, 'info'); // Get file changes for each commit for (const commit of commits) { const filesResult = yield git.raw([ 'diff-tree', '--no-commit-id', '--name-only', '-r', commit.hash ]); const files = filesResult.trim().split('\n') .filter(Boolean); for (const file of files) { try { const diff = yield git.raw(['show', commit.hash, '--', file]); commit.fileChanges.push({ file, diff }); } catch (_b) { // Skip files that can't be diffed } } } return commits; } catch (error) { (0, logger_1.log)(`Error getting commits: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error'); return null; } }); } //# sourceMappingURL=getCommits.js.map