All files / src/diff apply.ts

100% Statements 28/28
81.25% Branches 13/16
100% Functions 2/2
100% Lines 26/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53              11x 11x 1x     10x     10x   10x 11x 11x   11x 25x 12x 13x 11x 2x 2x 2x 2x       11x   11x 14x 14x 1x   13x 2x           8x     7x    
import { parsePatch } from './parser.js';
 
/**
 * Apply a unified diff to file content.
 * Returns the modified content.
 */
export function applyDiffToContent(content: string, diff: string): string {
  const hunks = parsePatch(diff);
  if (hunks.length === 0) {
    throw new Error('No valid hunks found in diff');
  }
 
  const lines = content.split('\n');
 
  // Apply from bottom to top to avoid shifting line indices.
  const sortedHunks = [...hunks].sort((a, b) => b.oldStart - a.oldStart);
 
  for (const hunk of sortedHunks) {
    const oldLines: string[] = [];
    const newLines: string[] = [];
 
    for (const line of hunk.lines) {
      if (line.startsWith('-')) {
        oldLines.push(line.slice(1));
      } else if (line.startsWith('+')) {
        newLines.push(line.slice(1));
      E} else if (line.startsWith(' ') || line === '') {
        const contextLine = line.startsWith(' ') ? line.slice(1) : line;
        oldLines.push(contextLine);
        newLines.push(contextLine);
      }
    }
 
    const startIndex = hunk.oldStart - 1;
 
    for (let i = 0; i < oldLines.length; i++) {
      const lineIndex = startIndex + i;
      if (lineIndex >= lines.length) {
        throw new Error(`Hunk context mismatch: line ${lineIndex + 1} doesn't exist`);
      }
      if (lines[lineIndex] !== oldLines[i]) {
        throw new Error(
          `Hunk context mismatch at line ${lineIndex + 1}: expected "${oldLines[i]}", got "${lines[lineIndex]}"`
        );
      }
    }
 
    lines.splice(startIndex, oldLines.length, ...newLines);
  }
 
  return lines.join('\n');
}