From aad1782be2ca65061ecb14db3a3ff98eb37ba781 Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Sun, 18 May 2025 22:45:45 +0900 Subject: [PATCH 1/5] fix: handle empty file added/deleted --- src/__fixtures__/added-empty-file | 3 +++ .../added-empty-file.test.ts.snap | 14 ++++++++++ src/__tests__/added-empty-file.test.ts | 10 +++++++ src/parse-git-diff.ts | 26 ++++++++++++++++--- 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/__fixtures__/added-empty-file create mode 100644 src/__tests__/__snapshots__/added-empty-file.test.ts.snap create mode 100644 src/__tests__/added-empty-file.test.ts diff --git a/src/__fixtures__/added-empty-file b/src/__fixtures__/added-empty-file new file mode 100644 index 0000000..b8e4b8f --- /dev/null +++ b/src/__fixtures__/added-empty-file @@ -0,0 +1,3 @@ +diff --git a/src/empty b/src/empty +new file mode 100644 +index 0000000..e69de29 \ No newline at end of file diff --git a/src/__tests__/__snapshots__/added-empty-file.test.ts.snap b/src/__tests__/__snapshots__/added-empty-file.test.ts.snap new file mode 100644 index 0000000..44f1615 --- /dev/null +++ b/src/__tests__/__snapshots__/added-empty-file.test.ts.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`added-empty-file parse \`added-empty-file\` 1`] = ` +{ + "files": [ + { + "chunks": [], + "path": "src/empty", + "type": "AddedFile", + }, + ], + "type": "GitDiff", +} +`; diff --git a/src/__tests__/added-empty-file.test.ts b/src/__tests__/added-empty-file.test.ts new file mode 100644 index 0000000..a4d3dd0 --- /dev/null +++ b/src/__tests__/added-empty-file.test.ts @@ -0,0 +1,10 @@ +import { getFixture } from './test-utils'; +import parseGitDiff from '../parse-git-diff'; + +describe('added-empty-file', () => { + const fixture = getFixture('added-empty-file'); + + it('parse `added-empty-file`', () => { + expect(parseGitDiff(fixture)).toMatchSnapshot(); + }); +}); diff --git a/src/parse-git-diff.ts b/src/parse-git-diff.ts index 1075956..b0341f6 100644 --- a/src/parse-git-diff.ts +++ b/src/parse-git-diff.ts @@ -46,7 +46,7 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined { if (!isComparisonInputLine(ctx.getCurLine())) { return; } - ctx.nextLine(); + const comparisonLineParsed = pasreComparisonInputLine(ctx); let isDeleted = false; let isNew = false; @@ -55,11 +55,15 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined { let pathAfter = ''; while (!ctx.isEof()) { const extHeader = parseExtendedHeader(ctx); + if (!extHeader) { break; } if (extHeader.type === ExtendedHeader.Deleted) isDeleted = true; - if (extHeader.type === ExtendedHeader.NewFile) isNew = true; + if (extHeader.type === ExtendedHeader.NewFile) { + isNew = true; + pathAfter = comparisonLineParsed?.to || ''; + } if (extHeader.type === ExtendedHeader.RenameFrom) { isRename = true; pathBefore = extHeader.path as string; @@ -89,11 +93,11 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined { chunks, path: chunks[0].pathBefore, }; - } else if (isNew && changeMarkers) { + } else if (isNew) { return { type: FileType.Added, chunks, - path: changeMarkers.added, + path: changeMarkers ? changeMarkers.added : pathAfter, }; } else if (isNew && chunks.length && chunks[0].type === 'BinaryFilesChunk') { return { @@ -133,6 +137,20 @@ function isComparisonInputLine(line: string): boolean { return line.indexOf('diff') === 0; } +function pasreComparisonInputLine( + ctx: Context +): { from: string; to: string } | null { + const line = ctx.getCurLine(); + const splitted = line.split(' ').reverse(); + const to = splitted.find((p) => p.startsWith('b/'))?.replace('b/', ''); + const from = splitted.find((p) => p.startsWith('a/'))?.replace('a/', ''); + ctx.nextLine(); + if (to && from) { + return { to, from }; + } + return null; +} + function parseChunks(context: Context): AnyChunk[] { const chunks: AnyChunk[] = []; From 3497a687bb546dc6c7cc369d4ccc1a970139054f Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Sun, 18 May 2025 22:50:22 +0900 Subject: [PATCH 2/5] fix: handle deleted empty files --- src/__fixtures__/deleted-empty-file | 3 +++ .../deleted-empty-file.test.ts.snap | 14 ++++++++++ src/__tests__/deleted-empty-file.test.ts | 10 +++++++ src/parse-git-diff.ts | 26 +++++++++---------- 4 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 src/__fixtures__/deleted-empty-file create mode 100644 src/__tests__/__snapshots__/deleted-empty-file.test.ts.snap create mode 100644 src/__tests__/deleted-empty-file.test.ts diff --git a/src/__fixtures__/deleted-empty-file b/src/__fixtures__/deleted-empty-file new file mode 100644 index 0000000..94c6d26 --- /dev/null +++ b/src/__fixtures__/deleted-empty-file @@ -0,0 +1,3 @@ +diff --git a/src/empty b/src/empty +deleted file mode 100644 +index e69de29..0000000 \ No newline at end of file diff --git a/src/__tests__/__snapshots__/deleted-empty-file.test.ts.snap b/src/__tests__/__snapshots__/deleted-empty-file.test.ts.snap new file mode 100644 index 0000000..59b07a9 --- /dev/null +++ b/src/__tests__/__snapshots__/deleted-empty-file.test.ts.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`deleted-empty-file parse \`deleted-empty-file\` 1`] = ` +{ + "files": [ + { + "chunks": [], + "path": "src/empty", + "type": "DeletedFile", + }, + ], + "type": "GitDiff", +} +`; diff --git a/src/__tests__/deleted-empty-file.test.ts b/src/__tests__/deleted-empty-file.test.ts new file mode 100644 index 0000000..d313986 --- /dev/null +++ b/src/__tests__/deleted-empty-file.test.ts @@ -0,0 +1,10 @@ +import { getFixture } from './test-utils'; +import parseGitDiff from '../parse-git-diff'; + +describe('deleted-empty-file', () => { + const fixture = getFixture('deleted-empty-file'); + + it('parse `deleted-empty-file`', () => { + expect(parseGitDiff(fixture)).toMatchSnapshot(); + }); +}); diff --git a/src/parse-git-diff.ts b/src/parse-git-diff.ts index b0341f6..0ce5eb9 100644 --- a/src/parse-git-diff.ts +++ b/src/parse-git-diff.ts @@ -59,7 +59,10 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined { if (!extHeader) { break; } - if (extHeader.type === ExtendedHeader.Deleted) isDeleted = true; + if (extHeader.type === ExtendedHeader.Deleted) { + isDeleted = true; + pathBefore = comparisonLineParsed?.from || ''; + } if (extHeader.type === ExtendedHeader.NewFile) { isNew = true; pathAfter = comparisonLineParsed?.to || ''; @@ -77,33 +80,30 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined { const changeMarkers = parseChangeMarkers(ctx); const chunks = parseChunks(ctx); - if (isDeleted && changeMarkers) { + if (isDeleted && chunks.length && chunks[0].type === 'BinaryFilesChunk') { return { type: FileType.Deleted, chunks, - path: changeMarkers.deleted, + path: chunks[0].pathBefore, }; - } else if ( - isDeleted && - chunks.length && - chunks[0].type === 'BinaryFilesChunk' - ) { + } + if (isDeleted) { return { type: FileType.Deleted, chunks, - path: chunks[0].pathBefore, + path: changeMarkers?.deleted || pathBefore, }; - } else if (isNew) { + } else if (isNew && chunks.length && chunks[0].type === 'BinaryFilesChunk') { return { type: FileType.Added, chunks, - path: changeMarkers ? changeMarkers.added : pathAfter, + path: chunks[0].pathAfter, }; - } else if (isNew && chunks.length && chunks[0].type === 'BinaryFilesChunk') { + } else if (isNew) { return { type: FileType.Added, chunks, - path: chunks[0].pathAfter, + path: changeMarkers?.added || pathAfter, }; } else if (isRename) { return { From 6ece4a5f12aedefc618aff1f30c444b0636c3bc2 Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Sun, 18 May 2025 22:53:40 +0900 Subject: [PATCH 3/5] add renamed empty file test --- src/__fixtures__/renamed-empty | 4 ++++ .../__snapshots__/renamed-empty.test.ts.snap | 15 +++++++++++++++ src/__tests__/renamed-empty-file.test.ts | 10 ++++++++++ src/__tests__/renamed-empty.test.ts | 10 ++++++++++ 4 files changed, 39 insertions(+) create mode 100644 src/__fixtures__/renamed-empty create mode 100644 src/__tests__/__snapshots__/renamed-empty.test.ts.snap create mode 100644 src/__tests__/renamed-empty-file.test.ts create mode 100644 src/__tests__/renamed-empty.test.ts diff --git a/src/__fixtures__/renamed-empty b/src/__fixtures__/renamed-empty new file mode 100644 index 0000000..8fee8b8 --- /dev/null +++ b/src/__fixtures__/renamed-empty @@ -0,0 +1,4 @@ +diff --git a/src/empty b/src/renamed-empty +similarity index 100% +rename from src/empty +rename to src/renamed-empty \ No newline at end of file diff --git a/src/__tests__/__snapshots__/renamed-empty.test.ts.snap b/src/__tests__/__snapshots__/renamed-empty.test.ts.snap new file mode 100644 index 0000000..3a32eef --- /dev/null +++ b/src/__tests__/__snapshots__/renamed-empty.test.ts.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renamed-empty parse \`renamed-empty\` 1`] = ` +{ + "files": [ + { + "chunks": [], + "pathAfter": "src/renamed-empty", + "pathBefore": "src/empty", + "type": "RenamedFile", + }, + ], + "type": "GitDiff", +} +`; diff --git a/src/__tests__/renamed-empty-file.test.ts b/src/__tests__/renamed-empty-file.test.ts new file mode 100644 index 0000000..9700b3a --- /dev/null +++ b/src/__tests__/renamed-empty-file.test.ts @@ -0,0 +1,10 @@ +import { getFixture } from './test-utils'; +import parseGitDiff from '../parse-git-diff'; + +describe('renamed-empty', () => { + const fixture = getFixture('renamed-empty'); + + it('parse `renamed-empty`', () => { + expect(parseGitDiff(fixture)).toMatchSnapshot(); + }); +}); diff --git a/src/__tests__/renamed-empty.test.ts b/src/__tests__/renamed-empty.test.ts new file mode 100644 index 0000000..9700b3a --- /dev/null +++ b/src/__tests__/renamed-empty.test.ts @@ -0,0 +1,10 @@ +import { getFixture } from './test-utils'; +import parseGitDiff from '../parse-git-diff'; + +describe('renamed-empty', () => { + const fixture = getFixture('renamed-empty'); + + it('parse `renamed-empty`', () => { + expect(parseGitDiff(fixture)).toMatchSnapshot(); + }); +}); From df508b79d00944db375f7eb2bcf2cf9d3159e08a Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Sun, 18 May 2025 22:56:48 +0900 Subject: [PATCH 4/5] Delete renamed-empty-file.test.ts --- src/__tests__/renamed-empty-file.test.ts | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/__tests__/renamed-empty-file.test.ts diff --git a/src/__tests__/renamed-empty-file.test.ts b/src/__tests__/renamed-empty-file.test.ts deleted file mode 100644 index 9700b3a..0000000 --- a/src/__tests__/renamed-empty-file.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { getFixture } from './test-utils'; -import parseGitDiff from '../parse-git-diff'; - -describe('renamed-empty', () => { - const fixture = getFixture('renamed-empty'); - - it('parse `renamed-empty`', () => { - expect(parseGitDiff(fixture)).toMatchSnapshot(); - }); -}); From 1fdb2f526e2ff2a1385b6ca11c6d94013cdc3e9b Mon Sep 17 00:00:00 2001 From: YeonJuan Date: Sun, 18 May 2025 22:59:07 +0900 Subject: [PATCH 5/5] fix typo --- src/parse-git-diff.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parse-git-diff.ts b/src/parse-git-diff.ts index 0ce5eb9..10426db 100644 --- a/src/parse-git-diff.ts +++ b/src/parse-git-diff.ts @@ -46,7 +46,7 @@ function parseFileChange(ctx: Context): AnyFileChange | undefined { if (!isComparisonInputLine(ctx.getCurLine())) { return; } - const comparisonLineParsed = pasreComparisonInputLine(ctx); + const comparisonLineParsed = parseComparisonInputLine(ctx); let isDeleted = false; let isNew = false; @@ -137,7 +137,7 @@ function isComparisonInputLine(line: string): boolean { return line.indexOf('diff') === 0; } -function pasreComparisonInputLine( +function parseComparisonInputLine( ctx: Context ): { from: string; to: string } | null { const line = ctx.getCurLine();