import { structuredPatch } from "diff";
import { env, waitUntil } from "cloudflare:workers";
import type { GitStore } from "./store";
import type { DiffResult, FileChange } from "~/lib/types";
const MAX_CONTENT_FILES = 300;
const MAX_TREE_READS = 2000;
const MAX_CHANGED_FILES = 5000;
const MAX_EDIT_LENGTH = 20_000;
const DIFF_TIMEOUT_MS = 1500;
const MAX_BLOB_BYTES = 512 * 1024;
const BINARY_SNIFF_BYTES = 8000;
const BLOB_CONCURRENCY = 8;
const CONTEXT_LINES = 3;
const MAX_CACHED_PATCH_BYTES = 4 * 1024 * 1024;
const DIFF_CACHE_TTL_SECONDS = 60 * 60 * 24 * 7;
const DIFF_CACHE_VERSION = "v1";
const decoder = new TextDecoder();
type Entry = { name: string; mode: string; hash: string; type: ArtifactsTreeEntryType };
function joinPath(parent: string, name: string): string {
return parent ? `${parent}/${name}` : name;
}
async function entriesOf(store: GitStore, sha: string | null): Promise<Map<string, Entry>> {
if (!sha) return new Map();
const entries = (await store.tree(sha)) ?? [];
return new Map(entries.map((entry) => [entry.name, entry]));
}
type Budget = { treeReads: number };
function exhausted(budget: Budget, out: FileChange[]): boolean {
return budget.treeReads >= MAX_TREE_READS || out.length >= MAX_CHANGED_FILES;
}
async function collectAll(
store: GitStore,
entry: Entry,