diff.ts•2.09 kB
/**
 * @fileoverview CLI provider git diff operation
 * @module services/git/providers/cli/operations/commits/diff
 */
import type { RequestContext } from '@/utils/index.js';
import type {
  GitDiffOptions,
  GitDiffResult,
  GitOperationContext,
} from '../../../../types.js';
import {
  buildGitCommand,
  mapGitError,
  parseGitDiffStat,
} from '../../utils/index.js';
/**
 * Execute git diff to show changes.
 *
 * @param options - Diff options
 * @param context - Operation context
 * @param execGit - Function to execute git commands
 * @returns Diff result
 */
export async function executeDiff(
  options: GitDiffOptions,
  context: GitOperationContext,
  execGit: (
    args: string[],
    cwd: string,
    ctx: RequestContext,
  ) => Promise<{ stdout: string; stderr: string }>,
): Promise<GitDiffResult> {
  try {
    const args: string[] = [];
    if (options.staged) {
      args.push('--cached');
    }
    if (options.commit1) {
      args.push(options.commit1);
    }
    if (options.commit2) {
      args.push(options.commit2);
    }
    if (options.path) {
      args.push('--', options.path);
    }
    if (options.unified) {
      args.push(`--unified=${options.unified}`);
    }
    // Get diff content
    const diffCmd = buildGitCommand({ command: 'diff', args: [...args] });
    const diffResult = await execGit(
      diffCmd,
      context.workingDirectory,
      context.requestContext,
    );
    // Get diff stats
    const statCmd = buildGitCommand({
      command: 'diff',
      args: [...args, '--stat'],
    });
    const statResult = await execGit(
      statCmd,
      context.workingDirectory,
      context.requestContext,
    );
    const stats = parseGitDiffStat(statResult.stdout);
    const hasBinary = diffResult.stdout.includes('Binary files');
    const result = {
      diff: diffResult.stdout,
      filesChanged: stats.files.length,
      insertions: stats.totalAdditions,
      deletions: stats.totalDeletions,
      binary: hasBinary,
    };
    return result;
  } catch (error) {
    throw mapGitError(error, 'diff');
  }
}