Skip to content

Commit a881d08

Browse files
authored
fix: handle parsing deleted, added empty files (#37)
* fix: handle empty file added/deleted * fix: handle deleted empty files * add renamed empty file test * Delete renamed-empty-file.test.ts * fix typo
1 parent e8ed56d commit a881d08

10 files changed

+116
-15
lines changed

src/__fixtures__/added-empty-file

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
diff --git a/src/empty b/src/empty
2+
new file mode 100644
3+
index 0000000..e69de29

src/__fixtures__/deleted-empty-file

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
diff --git a/src/empty b/src/empty
2+
deleted file mode 100644
3+
index e69de29..0000000

src/__fixtures__/renamed-empty

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
diff --git a/src/empty b/src/renamed-empty
2+
similarity index 100%
3+
rename from src/empty
4+
rename to src/renamed-empty
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`added-empty-file parse \`added-empty-file\` 1`] = `
4+
{
5+
"files": [
6+
{
7+
"chunks": [],
8+
"path": "src/empty",
9+
"type": "AddedFile",
10+
},
11+
],
12+
"type": "GitDiff",
13+
}
14+
`;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`deleted-empty-file parse \`deleted-empty-file\` 1`] = `
4+
{
5+
"files": [
6+
{
7+
"chunks": [],
8+
"path": "src/empty",
9+
"type": "DeletedFile",
10+
},
11+
],
12+
"type": "GitDiff",
13+
}
14+
`;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`renamed-empty parse \`renamed-empty\` 1`] = `
4+
{
5+
"files": [
6+
{
7+
"chunks": [],
8+
"pathAfter": "src/renamed-empty",
9+
"pathBefore": "src/empty",
10+
"type": "RenamedFile",
11+
},
12+
],
13+
"type": "GitDiff",
14+
}
15+
`;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { getFixture } from './test-utils';
2+
import parseGitDiff from '../parse-git-diff';
3+
4+
describe('added-empty-file', () => {
5+
const fixture = getFixture('added-empty-file');
6+
7+
it('parse `added-empty-file`', () => {
8+
expect(parseGitDiff(fixture)).toMatchSnapshot();
9+
});
10+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { getFixture } from './test-utils';
2+
import parseGitDiff from '../parse-git-diff';
3+
4+
describe('deleted-empty-file', () => {
5+
const fixture = getFixture('deleted-empty-file');
6+
7+
it('parse `deleted-empty-file`', () => {
8+
expect(parseGitDiff(fixture)).toMatchSnapshot();
9+
});
10+
});

src/__tests__/renamed-empty.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { getFixture } from './test-utils';
2+
import parseGitDiff from '../parse-git-diff';
3+
4+
describe('renamed-empty', () => {
5+
const fixture = getFixture('renamed-empty');
6+
7+
it('parse `renamed-empty`', () => {
8+
expect(parseGitDiff(fixture)).toMatchSnapshot();
9+
});
10+
});

src/parse-git-diff.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined {
4646
if (!isComparisonInputLine(ctx.getCurLine())) {
4747
return;
4848
}
49-
ctx.nextLine();
49+
const comparisonLineParsed = parseComparisonInputLine(ctx);
5050

5151
let isDeleted = false;
5252
let isNew = false;
@@ -55,11 +55,18 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined {
5555
let pathAfter = '';
5656
while (!ctx.isEof()) {
5757
const extHeader = parseExtendedHeader(ctx);
58+
5859
if (!extHeader) {
5960
break;
6061
}
61-
if (extHeader.type === ExtendedHeader.Deleted) isDeleted = true;
62-
if (extHeader.type === ExtendedHeader.NewFile) isNew = true;
62+
if (extHeader.type === ExtendedHeader.Deleted) {
63+
isDeleted = true;
64+
pathBefore = comparisonLineParsed?.from || '';
65+
}
66+
if (extHeader.type === ExtendedHeader.NewFile) {
67+
isNew = true;
68+
pathAfter = comparisonLineParsed?.to || '';
69+
}
6370
if (extHeader.type === ExtendedHeader.RenameFrom) {
6471
isRename = true;
6572
pathBefore = extHeader.path as string;
@@ -73,33 +80,30 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined {
7380
const changeMarkers = parseChangeMarkers(ctx);
7481
const chunks = parseChunks(ctx);
7582

76-
if (isDeleted && changeMarkers) {
83+
if (isDeleted && chunks.length && chunks[0].type === 'BinaryFilesChunk') {
7784
return {
7885
type: FileType.Deleted,
7986
chunks,
80-
path: changeMarkers.deleted,
87+
path: chunks[0].pathBefore,
8188
};
82-
} else if (
83-
isDeleted &&
84-
chunks.length &&
85-
chunks[0].type === 'BinaryFilesChunk'
86-
) {
89+
}
90+
if (isDeleted) {
8791
return {
8892
type: FileType.Deleted,
8993
chunks,
90-
path: chunks[0].pathBefore,
94+
path: changeMarkers?.deleted || pathBefore,
9195
};
92-
} else if (isNew && changeMarkers) {
96+
} else if (isNew && chunks.length && chunks[0].type === 'BinaryFilesChunk') {
9397
return {
9498
type: FileType.Added,
9599
chunks,
96-
path: changeMarkers.added,
100+
path: chunks[0].pathAfter,
97101
};
98-
} else if (isNew && chunks.length && chunks[0].type === 'BinaryFilesChunk') {
102+
} else if (isNew) {
99103
return {
100104
type: FileType.Added,
101105
chunks,
102-
path: chunks[0].pathAfter,
106+
path: changeMarkers?.added || pathAfter,
103107
};
104108
} else if (isRename) {
105109
return {
@@ -133,6 +137,20 @@ function isComparisonInputLine(line: string): boolean {
133137
return line.indexOf('diff') === 0;
134138
}
135139

140+
function parseComparisonInputLine(
141+
ctx: Context
142+
): { from: string; to: string } | null {
143+
const line = ctx.getCurLine();
144+
const splitted = line.split(' ').reverse();
145+
const to = splitted.find((p) => p.startsWith('b/'))?.replace('b/', '');
146+
const from = splitted.find((p) => p.startsWith('a/'))?.replace('a/', '');
147+
ctx.nextLine();
148+
if (to && from) {
149+
return { to, from };
150+
}
151+
return null;
152+
}
153+
136154
function parseChunks(context: Context): AnyChunk[] {
137155
const chunks: AnyChunk[] = [];
138156

0 commit comments

Comments
 (0)