Skip to content

Commit 241d52a

Browse files
fix(gitDiff): keep hunk content lines beginning with -- or ++ (Gitlawb#1646)
The metadata-skip block in parseGitDiff matched line.startsWith('---') and line.startsWith('+++') on every line, including lines inside a hunk. A removed line whose content starts with '--' becomes the diff line '---...', and an added line whose content starts with '++' becomes '+++...'; both were treated as file-header lines and dropped, so the rendered diff silently lost real changes. These header markers only appear in the file preamble before the first @@ hunk header, so the skip block is now gated on !currentHunk. Inside a hunk, +/-/space lines are content and are kept. Adds parseGitDiff tests covering the dropped-content case, the regression that header lines are still skipped, and a normal hunk.
1 parent bd3ad89 commit 241d52a

2 files changed

Lines changed: 90 additions & 9 deletions

File tree

src/utils/gitDiff.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { describe, expect, it } from 'bun:test'
2+
import { parseGitDiff } from './gitDiff.js'
3+
4+
describe('parseGitDiff', () => {
5+
it('keeps hunk content lines whose text starts with -- or ++', () => {
6+
// A removed line whose content is "--legacy-peer-deps" appears in the diff
7+
// as "---legacy-peer-deps"; an added line "++quiet-flag" appears as
8+
// "+++quiet-flag". Both must be retained as hunk content, not mistaken for
9+
// the "---"/"+++" file-header lines.
10+
const diff = [
11+
'diff --git a/run.sh b/run.sh',
12+
'index abc1234..def5678 100644',
13+
'--- a/run.sh',
14+
'+++ b/run.sh',
15+
'@@ -1,3 +1,3 @@',
16+
' npm install \\',
17+
'---legacy-peer-deps',
18+
'+++quiet-flag',
19+
' echo done',
20+
'',
21+
].join('\n')
22+
23+
const hunks = parseGitDiff(diff).get('run.sh')
24+
expect(hunks).toBeDefined()
25+
const lines = hunks![0]!.lines
26+
expect(lines).toContain('---legacy-peer-deps')
27+
expect(lines).toContain('+++quiet-flag')
28+
expect(lines).toContain(' npm install \\')
29+
expect(lines).toContain(' echo done')
30+
})
31+
32+
it('still drops the file-header --- / +++ / index lines from hunk content', () => {
33+
const diff = [
34+
'diff --git a/a.txt b/a.txt',
35+
'index 1111111..2222222 100644',
36+
'--- a/a.txt',
37+
'+++ b/a.txt',
38+
'@@ -1 +1 @@',
39+
'-old',
40+
'+new',
41+
'',
42+
].join('\n')
43+
44+
const lines = parseGitDiff(diff).get('a.txt')![0]!.lines
45+
expect(lines).toContain('-old')
46+
expect(lines).toContain('+new')
47+
expect(lines).not.toContain('--- a/a.txt')
48+
expect(lines).not.toContain('+++ b/a.txt')
49+
expect(lines).not.toContain('index 1111111..2222222 100644')
50+
})
51+
52+
it('parses a normal hunk with added, removed and context lines', () => {
53+
const diff = [
54+
'diff --git a/src/x.ts b/src/x.ts',
55+
'index 1111111..2222222 100644',
56+
'--- a/src/x.ts',
57+
'+++ b/src/x.ts',
58+
'@@ -1,3 +1,3 @@',
59+
' const a = 1',
60+
'-const b = 2',
61+
'+const b = 3',
62+
' const c = 4',
63+
'',
64+
].join('\n')
65+
66+
const hunks = parseGitDiff(diff).get('src/x.ts')
67+
expect(hunks).toBeDefined()
68+
expect(hunks![0]!.oldStart).toBe(1)
69+
expect(hunks![0]!.newStart).toBe(1)
70+
const lines = hunks![0]!.lines
71+
expect(lines).toContain('-const b = 2')
72+
expect(lines).toContain('+const b = 3')
73+
expect(lines).toContain(' const a = 1')
74+
})
75+
})

src/utils/gitDiff.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,22 @@ export function parseGitDiff(
248248
continue
249249
}
250250

251-
// Skip binary file markers and other metadata
251+
// Skip binary file markers and other metadata. These only appear in the
252+
// file preamble before the first @@ hunk header, so only match them when
253+
// we are not yet inside a hunk. Once inside a hunk, a line such as
254+
// "---legacy-peer-deps" (a removed line whose content starts with "--")
255+
// or "+++count" (an added line whose content starts with "++") is real
256+
// diff content and must not be dropped as a "+++"/"---" header.
252257
if (
253-
line.startsWith('index ') ||
254-
line.startsWith('---') ||
255-
line.startsWith('+++') ||
256-
line.startsWith('new file') ||
257-
line.startsWith('deleted file') ||
258-
line.startsWith('old mode') ||
259-
line.startsWith('new mode') ||
260-
line.startsWith('Binary files')
258+
!currentHunk &&
259+
(line.startsWith('index ') ||
260+
line.startsWith('---') ||
261+
line.startsWith('+++') ||
262+
line.startsWith('new file') ||
263+
line.startsWith('deleted file') ||
264+
line.startsWith('old mode') ||
265+
line.startsWith('new mode') ||
266+
line.startsWith('Binary files'))
261267
) {
262268
continue
263269
}

0 commit comments

Comments
 (0)