import { env } from "cloudflare:workers";
import { batch, chunks, first, placeholders, run, stmt } from "../db";
import { loadRepoById } from "../repos";
import { branchSha, listRefs } from "../git/refs";
import { withStore } from "../git/store";
import type { GitStore } from "../git/store";
import { diffTreesBounded } from "../git/diff";
import type { RepoRow } from "~/lib/types";
const FILES_PER_MESSAGE = 100;
const MAX_INDEXED_FILES = 5000;
const MAX_INDEXED_BYTES = 128 * 1024;
const BINARY_SNIFF = 8000;
const READ_CONCURRENCY = 8;
const SKIPPED_MODES = new Set(["120000", "160000"]);
const decoder = new TextDecoder("utf-8", { fatal: true });
type IndexJob = { commit: string; tree: string; base: string | null; offset: number };
export type CodeIndexMessage = { kind: "code.index"; repoId: string; job?: IndexJob };
type Plan = { full: boolean; upserts: Array<{ path: string; sha: string }>; deletes: string[] };
async function planChanges(store: GitStore, base: string | null, tree: string): Promise<Plan> {
if (base) {
const { changes, truncated } = await diffTreesBounded(store, base, tree);
if (!truncated) {
const upserts: Plan["upserts"] = [];
const deletes: string[] = [];
for (const change of changes) {
if (change.oldPath) deletes.push(change.oldPath);
if (change.status === "deleted" || !change.newSha || SKIPPED_MODES.has(change.newMode ?? "")) {
deletes.push(change.path);
} else {
upserts.push({ path: change.path, sha: change.newSha });
}
}
return { full: false, upserts, deletes };
}
}