1234import { expect, test } from "bun:test";5import { existsSync, renameSync } from "node:fs";6import { mkdtemp } from "node:fs/promises";7import { tmpdir } from "node:os";8import { join } from "node:path";9import { startSyncWorker } from "../src/bucket/sync.ts";10import { fileAt, headId } from "../src/mirror/queries.ts";11import { closeMirror, openMirror } from "../src/mirror/store.ts";12import { openKeprDb } from "../src/server/db.ts";13import { makeKohBucket } from "./fixture.ts";1415test("the sync worker syncs, holds and hides", async () => {16 const fx = await makeKohBucket("worked");17 const dataDir = await mkdtemp(join(tmpdir(), "kepr-worker-"));18 const kepr = openKeprDb(dataDir);19 const syncer = startSyncWorker(dataDir, { kind: "folder", path: fx.bucketDir });20 await syncer.syncAll();21 const mirror = () => openMirror(join(dataDir, "mirror"), fx.repo);22 const head = fx.saveIds[0] as string;23 expect(headId(mirror())).toBe(head);2425 const order: string[] = [];26 let release = () => {};27 const held = syncer.hold(async () => {28 order.push("held");29 await new Promise<void>((resolve) => {30 release = resolve;31 });32 order.push("released");33 });34 for (let i = 0; i < 100 && order.length === 0; i++) await Bun.sleep(10);35 const synced2 = syncer.syncAll().then(() => order.push("synced"));36 await Bun.sleep(50);37 expect(order).toEqual(["held"]);38 release();39 await Promise.all([held, synced2]);40 expect(order).toEqual(["held", "released", "synced"]);4142 kepr.query("UPDATE repos SET hidden_paths = 'secret.txt' WHERE name = ?").run(fx.repo);43 await syncer.applyHidden([fx.repo]);44 expect(fileAt(mirror(), head, "secret.txt")).toBeNull();45 expect(fileAt(mirror(), head, "src/main.ts")).not.toBeNull();46});4748test("a hidden list edited during a rename reaches the repo under its new name", async () => {49 const fx = await makeKohBucket("before");50 const dataDir = await mkdtemp(join(tmpdir(), "kepr-worker-"));51 const mirrorDir = join(dataDir, "mirror");52 const kepr = openKeprDb(dataDir);53 const syncer = startSyncWorker(dataDir, { kind: "folder", path: fx.bucketDir });54 await syncer.syncAll();55 const head = fx.saveIds[0] as string;56 let edited: Promise<void> = Promise.resolve();57 await syncer.hold(async () => {58 kepr.query("UPDATE repos SET hidden_paths = 'secret.txt' WHERE name = 'before'").run();59 edited = syncer.applyHidden(["before"]);60 61 kepr.query("UPDATE repos SET name = 'after' WHERE name = 'before'").run();62 kepr.query("INSERT INTO renamed (old, new) VALUES ('before', 'after')").run();63 closeMirror(mirrorDir, "before");64 for (const suffix of ["", "-wal", "-shm"]) {65 const path = join(mirrorDir, `before.db${suffix}`);66 if (existsSync(path)) renameSync(path, join(mirrorDir, `after.db${suffix}`));67 }68 });69 await edited;70 expect(fileAt(openMirror(mirrorDir, "after"), head, "secret.txt")).toBeNull();71 expect(existsSync(join(mirrorDir, "before.db"))).toBe(false);72});