UNPKG

reviewit

Version:

A lightweight command-line tool that spins up a local web server to display Git commit diffs in a GitHub-like Files changed view

96 lines (95 loc) 3.59 kB
import simpleGit from 'simple-git'; import { validateDiffArguments, createCommitRangeString } from '../cli/utils.js'; export async function loadGitDiff(targetCommitish, baseCommitish) { // Validate arguments const validation = validateDiffArguments(targetCommitish, baseCommitish); if (!validation.valid) { throw new Error(validation.error); } const git = simpleGit(); let diff; // Handle target special chars (base is always a regular commit) if (targetCommitish === 'working') { // Show unstaged changes (working vs staged) diff = await git.diff(['--name-status']); } else if (targetCommitish === 'staged') { // Show staged changes against base commit diff = await git.diff(['--cached', baseCommitish, '--name-status']); } else if (targetCommitish === '.') { // Show all uncommitted changes against base commit diff = await git.diff([baseCommitish, '--name-status']); } else { // Both are regular commits: standard commit-to-commit comparison diff = await git.diff([ createCommitRangeString(baseCommitish, targetCommitish), '--name-status', ]); if (!diff.trim()) { // Try without parent (for initial commit) const diffInitial = await git.diff([targetCommitish, '--name-status']); if (!diffInitial.trim()) { throw new Error('No changes found in this commit'); } diff = diffInitial; } } const fileChanges = diff .split('\n') .filter((line) => line.trim()) .map((line) => { const [status, ...pathParts] = line.split('\t'); const path = pathParts.join('\t'); return { status, path }; }); // Get diff for each file individually const fileDiffs = await Promise.all(fileChanges.map(async ({ status, path }) => { let fileDiff = ''; // Handle individual file diffs (base is always a regular commit) if (targetCommitish === 'working') { // Show unstaged changes (working vs staged) fileDiff = await git.diff(['--', path]); } else if (targetCommitish === 'staged') { // Show staged changes against base commit fileDiff = await git.diff(['--cached', baseCommitish, '--', path]); } else if (targetCommitish === '.') { // Show all uncommitted changes against base commit fileDiff = await git.diff([baseCommitish, '--', path]); } else { try { // Both are regular commits: standard commit-to-commit comparison fileDiff = await git.diff([ createCommitRangeString(baseCommitish, targetCommitish), '--', path, ]); } catch { // For new files or if parent doesn't exist fileDiff = await git.diff([targetCommitish, '--', path]); } } const lines = fileDiff.split('\n'); let additions = 0; let deletions = 0; lines.forEach((line) => { if (line.startsWith('+') && !line.startsWith('+++')) additions++; if (line.startsWith('-') && !line.startsWith('---')) deletions++; }); return { path, status: status, diff: fileDiff, additions, deletions, }; })); return fileDiffs; }