Skip to content

Commit 3f643bd

Browse files
committed
yield patches one at a time
1 parent 13515b2 commit 3f643bd

File tree

4 files changed

+43
-50
lines changed

4 files changed

+43
-50
lines changed

web/src/lib/diff-viewer-multi-file.svelte.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
getGithubToken,
77
type GithubDiff,
88
type GithubDiffResult,
9-
splitMultiFilePatchGithub,
9+
parseMultiFilePatchGithub,
1010
} from "./github.svelte";
1111
import { type StructuredPatch } from "diff";
1212
import {
@@ -498,6 +498,9 @@ export class MultiFileDiffViewerState {
498498
// Pushing directly to the main array causes too many signals to update (lag)
499499
tempDetails.push(details);
500500
}
501+
if (tempDetails.length === 0) {
502+
throw new Error("No valid patches found in the provided data.");
503+
}
501504
tempDetails.sort(compareFileDetails);
502505
this.fileDetails.push(...tempDetails);
503506
return true;
@@ -520,13 +523,7 @@ export class MultiFileDiffViewerState {
520523
},
521524
async () => {
522525
const result = await resultPromise;
523-
const split = splitMultiFilePatchGithub(result.info, result.response);
524-
async function* generatePatches() {
525-
for (const patch of split) {
526-
yield patch;
527-
}
528-
}
529-
return generatePatches();
526+
return parseMultiFilePatchGithub(result.info, result.response);
530527
},
531528
);
532529
}

web/src/lib/github.svelte.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { browser } from "$app/environment";
22
import type { components } from "@octokit/openapi-types";
3-
import { splitMultiFilePatch, trimCommitHash } from "$lib/util";
3+
import { parseMultiFilePatch, trimCommitHash } from "$lib/util";
44
import { makeImageDetails } from "$lib/diff-viewer-multi-file.svelte";
55
import { PUBLIC_GITHUB_APP_NAME, PUBLIC_GITHUB_CLIENT_ID } from "$env/static/public";
66

@@ -139,8 +139,8 @@ export async function fetchGithubPRInfo(token: string | null, owner: string, rep
139139
}
140140
}
141141

142-
export function splitMultiFilePatchGithub(details: GithubDiff, patch: string) {
143-
return splitMultiFilePatch(patch, (from, to, status) => {
142+
export function parseMultiFilePatchGithub(details: GithubDiff, patch: string) {
143+
return parseMultiFilePatch(patch, (from, to, status) => {
144144
const token = getGithubToken();
145145
return makeImageDetails(
146146
from,

web/src/lib/util.ts

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,14 @@ export function binaryFileDummyDetails(fromFile: string, toFile: string, status:
9898

9999
const fileRegex = /diff --git a\/(\S+) b\/(\S+)\r?\n(?:.+\r?\n)*?(?=-- \r?\n|diff --git|$)/g;
100100

101-
function parseHeader(
102-
patch: string,
103-
fromFile: string,
104-
toFile: string,
105-
): {
101+
type BasicHeader = {
102+
fromFile: string;
103+
toFile: string;
106104
status: FileStatus;
107105
binary: boolean;
108-
} {
106+
};
107+
108+
function parseHeader(patch: string, fromFile: string, toFile: string): BasicHeader {
109109
let status: FileStatus = "modified";
110110
if (fromFile !== toFile) {
111111
status = "renamed_modified";
@@ -141,34 +141,42 @@ function parseHeader(
141141
lineStart = lineEnd + 1;
142142
}
143143

144-
return { status, binary };
144+
return { fromFile, toFile, status, binary };
145145
}
146146

147-
export function splitMultiFilePatch(
147+
export function parseMultiFilePatch(
148148
patchContent: string,
149149
imageFactory?: (fromFile: string, toFile: string, status: FileStatus) => ImageFileDetails | null,
150-
): FileDetails[] {
151-
const patches: FileDetails[] = [];
152-
// Process each file in the diff
153-
let fileMatch;
154-
while ((fileMatch = fileRegex.exec(patchContent)) !== null) {
155-
const [fullFileMatch, fromFile, toFile] = fileMatch;
156-
const { status, binary } = parseHeader(fullFileMatch, fromFile, toFile);
157-
158-
if (binary) {
159-
if (imageFactory !== undefined && isImageFile(fromFile) && isImageFile(toFile)) {
160-
const imageDetails = imageFactory(fromFile, toFile, status);
161-
if (imageDetails != null) {
162-
patches.push(imageDetails);
150+
): AsyncGenerator<FileDetails> {
151+
const split = splitMultiFilePatch(patchContent);
152+
async function* detailsGenerator() {
153+
for (const [header, content] of split) {
154+
if (header.binary) {
155+
if (imageFactory !== undefined && isImageFile(header.fromFile) && isImageFile(header.toFile)) {
156+
const imageDetails = imageFactory(header.fromFile, header.toFile, header.status);
157+
if (imageDetails != null) {
158+
yield imageDetails;
159+
continue;
160+
}
161+
} else {
162+
yield binaryFileDummyDetails(header.fromFile, header.toFile, header.status);
163163
continue;
164164
}
165-
} else {
166-
patches.push(binaryFileDummyDetails(fromFile, toFile, status));
167-
continue;
168165
}
166+
167+
yield makeTextDetails(header.fromFile, header.toFile, header.status, content);
169168
}
169+
}
170+
return detailsGenerator();
171+
}
170172

171-
patches.push(makeTextDetails(fromFile, toFile, status, fullFileMatch));
173+
export function splitMultiFilePatch(patchContent: string): [BasicHeader, string][] {
174+
const patches: [BasicHeader, string][] = [];
175+
let fileMatch;
176+
while ((fileMatch = fileRegex.exec(patchContent)) !== null) {
177+
const [fullFileMatch, fromFile, toFile] = fileMatch;
178+
const header = parseHeader(fullFileMatch, fromFile, toFile);
179+
patches.push([header, fullFileMatch]);
172180
}
173181
return patches;
174182
}

web/src/routes/OpenDiffDialog.svelte

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import { page } from "$app/state";
66
import { goto } from "$app/navigation";
77
import { makeImageDetails, makeTextDetails, MultiFileDiffViewerState } from "$lib/diff-viewer-multi-file.svelte";
8-
import { binaryFileDummyDetails, bytesEqual, isBinaryFile, isImageFile, splitMultiFilePatch } from "$lib/util";
8+
import { binaryFileDummyDetails, bytesEqual, isBinaryFile, isImageFile, parseMultiFilePatch } from "$lib/util";
99
import { onMount } from "svelte";
1010
import { createTwoFilesPatch } from "diff";
1111
import DirectorySelect from "$lib/components/files/DirectorySelect.svelte";
@@ -279,24 +279,12 @@
279279
return;
280280
}
281281
modalOpen = false;
282-
const files = splitMultiFilePatch(text);
283-
if (files.length === 0) {
284-
modalOpen = true;
285-
viewer.progressBar.setProgress(100, 100);
286-
alert("No valid patches found in the file.");
287-
return;
288-
}
289282
const success = await viewer.loadPatches(
290283
async () => {
291284
return { type: "file", fileName: meta.name };
292285
},
293286
async () => {
294-
async function* generatePatches() {
295-
for (const file of files) {
296-
yield file;
297-
}
298-
}
299-
return generatePatches();
287+
return parseMultiFilePatch(text);
300288
},
301289
);
302290
if (!success) {

0 commit comments

Comments
 (0)