Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/patch/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ import type { StructuredPatch } from '../types.js';
export function parsePatch(uniDiff: string): StructuredPatch[] {
const diffstr = uniDiff.split(/\n/),
list: Partial<StructuredPatch>[] = [];

// If the final line of the patch is missing the trailing newline character
// that should be present, we forgive that, but if the final character of
// the patch is a newline as expected, we don't consider there to be a
// further blank line afterwards. We remove that blank line here:
if (diffstr[diffstr.length - 1] == '') {
diffstr.pop();
}

let i = 0;

// These helper functions identify line types that can appear between files
Expand Down Expand Up @@ -494,10 +503,14 @@ export function parsePatch(uniDiff: string): StructuredPatch[] {

// Perform sanity checking
if (addCount !== hunk.newLines) {
throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
throw new Error(
`New line count did not match for hunk at line ${chunkHeaderIndex + 1}; expected ${hunk.newLines} but got ${addCount}`
);
}
if (removeCount !== hunk.oldLines) {
throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1));
throw new Error(
`Old line count did not match for hunk at line ${chunkHeaderIndex + 1}; expected ${hunk.oldLines} but got ${removeCount}`
);
}

// Check for extra hunk-body-like lines after the declared line counts
Expand Down
20 changes: 18 additions & 2 deletions test/patch/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,10 +666,10 @@ more garbage

expect(function() {
parsePatch('@@ -1 +1,4 @@');
}).to['throw']('Added line count did not match for hunk at line 1');
}).to['throw']('New line count did not match for hunk at line 1; expected 4 but got 0');
expect(function() {
parsePatch('@@ -1,4 +1 @@');
}).to['throw']('Removed line count did not match for hunk at line 1');
}).to['throw']('Old line count did not match for hunk at line 1; expected 4 but got 0');
});


Expand Down Expand Up @@ -939,6 +939,22 @@ line3
expect(() => {parsePatch(patchStr);}).to.throw('Hunk at line 5 contained invalid line line3');
});

it('should emit a useful error message if the final hunk of the patch file ends prematurely', () => {
const patchStr = `Index: test
===================================================================
--- from\theader1
+++ to\theader2
@@ -1,4 +1,5 @@
line2
line3
+line4
line5`;
// eslint-disable-next-line dot-notation
expect(() => { parsePatch(patchStr); }).to.throw(
'New line count did not match for hunk at line 5; expected 5 but got 4'
);
});

it('should parse a single-file `diff --git` patch', function() {
expect(parsePatch(
`diff --git a/file.txt b/file.txt
Expand Down