import type { Hono } from "hono"; import { fileAt, headId, history, type Save, saveByPrefix } from "../mirror/queries.ts"; import { type Html, html } from "./html.ts"; import { cacheFor, notFound, openPublicRepo, type PageContext, type PublicRepo, page, relativeTime, } from "./layout.ts"; const RECENT = 20; export function registerArchivesPage(app: Hono, ctx: PageContext): void { app.get("/:repo/archives", (c) => { const repo = openPublicRepo(ctx, c.req.param("repo")); if (!repo) return notFound(c, ctx); const name = repo.settings.name; const id = headId(repo.mirror); const head = id ? saveByPrefix(repo.mirror, id) : null; const recent = history(repo.mirror, RECENT + 1, 0).filter((save) => save.id !== head?.id); cacheFor(c, false); return c.html( page(ctx, { title: `archives · ${name}`, description: `Source tarballs of ${name}, one per save.`, path: `/${name}/archives`, body: html`

archives

${ head ? [ row(ctx, repo, head, true), ...recent.slice(0, RECENT).map((save) => row(ctx, repo, save, false)), ] : html`

no saves yet

` }
`, }), ); }); } // HEAD's row names HEAD.tar.gz, which always follows the newest save; the others pin their save. // The `nix profile add` line shows only where the save has a flake to install, as in Kepr 2. function row(ctx: PageContext, repo: PublicRepo, save: Save, isHead: boolean): Html { const name = repo.settings.name; const file = isHead ? "HEAD" : save.id; const tarball = `/${name}/archive/${file}.tar.gz`; const nix = `nix profile add https://${ctx.domain}${tarball}`; const curl = `curl -fL https://${ctx.domain}${tarball} | tar xz`; const koh = `koh steal ${ctx.domain}/${name}`; const hasFlake = fileAt(repo.mirror, save.id, "flake.nix") !== null; // HEAD can be a checkpoint, which has no page of its own (§21.4). const id = save.is_checkpoint ? html`${save.id}` : html`${save.id}`; return html`

${ isHead && html`HEAD` }${id}${html`${save.message.split("\n")[0]}`}${html`${relativeTime(save.created_at)}`}

${ hasFlake && html`
${nix}
` }
`; }