1import type { Database } from "bun:sqlite";2import { type Bucket, BucketWriteError, KEPR_PREFIX } from "../bucket/reader.ts";3import { filesAt, objectBytes, stripCount } from "../mirror/queries.ts";4import { buildTarball } from "./tar.ts";56const tarballsOf = (repo: string) => `${KEPR_PREFIX}tarballs/${repo}/`;789101112131415export async function cachedTarball(16 bucket: Bucket,17 db: Database,18 repo: string,19 saveId: string,20): Promise<Uint8Array> {21 const stored = await bucket.get(`${tarballsOf(repo)}${stripCount(db)}/${saveId}.tar.gz`);22 if (stored) return stored;23 24 25 const key = `${tarballsOf(repo)}${stripCount(db)}/${saveId}.tar.gz`;26 const files = filesAt(db, saveId).map((file) => {27 const bytes = objectBytes(db, file.hash);28 if (!bytes) throw new Error(`${repo}: object ${file.hash} is missing from the mirror`);29 return { path: file.path, bytes, executable: file.executable };30 });31 const tarball = buildTarball(`${repo}-${saveId.slice(0, 8)}`, files);32 try {33 await bucket.put(key, tarball, "application/gzip");34 } catch (error) {35 if (!(error instanceof BucketWriteError)) throw error;36 }37 return tarball;38}394041export async function dropTarballs(bucket: Bucket, repo: string): Promise<void> {42 for (const key of await bucket.list(tarballsOf(repo))) await bucket.remove(key);43}