Mercurial
diff hg-web/README.md @ 226:3fa4bf481f42
[merge] Merge hg-web into default
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sun, 02 Aug 2026 14:42:01 -0700 |
| parents | 3007ef5fc0ed |
| children | 8bb0ac8f4587 |
line wrap: on
line diff
--- a/hg-web/README.md Sun Aug 02 08:52:13 2026 -0700 +++ b/hg-web/README.md Sun Aug 02 14:42:01 2026 -0700 @@ -1,34 +1,286 @@ # hg-web -A web-based Mercurial repository browser. Provides a GitHub-style interface for browsing files, viewing code with syntax highlighting, and reading markdown documentation. +A custom Mercurial forge and repository browser. The application keeps the +networking and HTTP stack in C with Seobeo, while the hand-drawn web interface +is implemented in React and TypeScript. + +## Wiki tree -## Features +```text +hg-web +├── Runtime +│ ├── hg_web_server :6970 +│ │ ├── React application and static assets +│ │ ├── repository browsing API +│ │ ├── commit graph API +│ │ └── Mercurial wire-protocol proxy +│ └── hg serve :4444 +│ ├── repository files and graph data +│ └── Mercurial pull/push protocol +├── Backend +│ ├── main.c +│ └── ../seobeo +│ ├── s_network.c +│ ├── s_web.c +│ ├── s_http_client.c +│ └── s_ssl.c +├── Frontend +│ └── src +│ ├── main.tsx +│ ├── components +│ │ ├── app.tsx +│ │ ├── directory-browser.tsx +│ │ ├── graph.tsx +│ │ ├── header.tsx +│ │ ├── footer.tsx +│ │ ├── theme.tsx +│ │ └── repo-browser.tsx +│ ├── index.html +│ ├── index.css +│ ├── base.css +│ └── custom pencil, panda, and icon assets +├── Build +│ ├── BUILD +│ ├── ../gui_ze/gui_ze.bzl +│ ├── ../markdown_converter +│ └── ../third_party/highlight +└── Operations + └── deploy.sh +``` + +`repo-browser.tsx` is an older standalone browser implementation. The active +entry point is `main.tsx`, which renders `app.tsx`; `app.tsx` embeds +`directory-browser.tsx`. + +## Runtime topology -- Browse repository files and directories -- View code files with syntax highlighting (highlight.js) -- Render markdown files with WASM-based converter -- Dark/light theme support with system preference detection -- Prefetch on hover for faster navigation +```text +Browser + | + | HTTPS + v +nginx + | + | HTTP :6970 + v +hg_web_server (main.c + Seobeo) + | + | HTTP :4444 + v +hg serve (Zenbu Mercurial repository) +``` + +The C server owns the public routes. It serves the application shell and +assets, translates browser API requests into `hg serve` requests, and streams +Mercurial wire-protocol traffic without routing bundle data through the normal +buffered HTTP response path. + +## Request flows + +### Application shell + +```text +GET /, /directories, or /graph + -> GetReactHome + -> hg-web/src/index.html + -> /page.js + -> src/main.tsx + -> components/app.tsx +``` + +### Repository browser -## Structure +```text +directory-browser.tsx + -> GET /api/repo/list?path=... + -> ApiListDirectory + -> GET hg-serve/file/tip/<path>?style=json +file or README selection + -> GET /api/repo/file?path=... + -> ApiGetFile + -> GET hg-serve/raw-file/tip/<path> + -> highlight.js, markdown_converter WASM, or inline static preview ``` -hg-web/ -├── BUILD # Bazel build configuration -├── deploy.sh # Deployment script -├── main.c # C server handling API routes -└── src/ # Frontend source files + +Images, SVG, video, audio, and PDF files open in the forge preview modal. +Unknown binary files retain a download link. The raw file API supplies explicit +MIME types, `nosniff`, inline disposition for supported previews, and sandboxed +SVG responses. + +### Commit graph + +```text +graph.tsx + -> GET /api/graph/<revision>?graphtop=...&style=json + -> ApiGetGraph + -> GET hg-serve/graph/<revision>?... + -> React rows + custom pencil/panda canvas + +graph row selection + -> /changeset/<revision> + -> GET /api/changeset/<revision> + -> ApiGetChangeset + -> GET hg-serve/json-rev/<revision> + -> changeset metadata + rendered diff +``` + +### Mercurial clone, pull, and push + +```text +Mercurial client + -> GET or POST /repo + -> StreamHgWireProtocol + -> hg serve /?cmd=... + -> binary-safe streamed response ``` -## Building +## Route map + +| Method | Route | Owner | Purpose | +| --- | --- | --- | --- | +| `GET` | `/` | `GetReactHome` | Application shell | +| `GET` | `/directories` | `GetReactHome` | Legacy application-shell route | +| `GET` | `/directory` | `GetReactHome` | Repository browser application route | +| `GET` | `/graph` | `GetReactHome` | Commit graph application route | +| `GET` | `/changeset/:changeset_id` | `GetReactHome` | Changeset application route | +| `GET` | `/api/repo/list` | `ApiListDirectory` | Directory listing JSON | +| `GET` | `/api/repo/file` | `ApiGetFile` | Raw tracked file | +| `GET` | `/api/repo/readme` | `ApiGetReadme` | Directory README content | +| `GET` | `/api/graph/:graph_id` | `ApiGetGraph` | Mercurial graph JSON | +| `GET` | `/api/changeset/:changeset_id` | `ApiGetChangeset` | Changeset metadata and diff JSON | +| `GET`, `POST` | `/repo` | `StreamHgWireProtocol` | Mercurial wire protocol | + +## Frontend ownership + +| File | Responsibility | +| --- | --- | +| `src/components/app.tsx` | Client-side routes, landing page, tabs, and history | +| `src/components/directory-browser.tsx` | Breadcrumbs, listings, prefetch, file modals, README rendering | +| `src/components/graph.tsx` | Graph fetching, pagination, canvas edges, panda nodes | +| `src/components/theme.tsx` | Stored light/dark preference and system-theme integration | +| `src/components/header.tsx` | Forge identity and theme control | +| `src/components/footer.tsx` | Shared footer | +| `src/index.css`, `src/base.css` | Custom visual language and layout | + +Keep the custom assets and visual language in this package. New forge screens +should reuse the existing CSS variables, typography, textures, and components +instead of introducing a generic design system. + +## Build and local run + +Build the server and deployable bundle from the repository root: ```bash -bazel build //hg-web:hg_web +bazel build //hg-web:hg_web_server +bazel build //hg-web:hg_web_server_bundle +bazel test //hg-web:tests +bazel test //markdown_converter/tests:markdown_to_html_test +bazel test //seobeo/tests:all +``` + +`//hg-web:tests` creates a temporary two-commit Mercurial repository and runs +the application in pinned Chromium through Playwright. It covers shell routes, +files and README rendering, graph and changeset navigation, browser history, +console and page errors, API validation, Mercurial wire protocol, Markdown +script escaping, static assets, and backend outages. The test invokes the +workspace Mercurial CLI with an isolated configuration and home directory. + +Build and run the complete local stack with one Bazel command: + +```bash +bazel run //hg-web:dev +``` + +This starts `hg serve` on `127.0.0.1:4444` and `hg_web_server` on port `6970`. +Stopping the Bazel target stops both child processes. + +The bundle contains `hg_web_server` and `hg-web/src/`, including generated +`page.js`, markdown WASM, highlight.js, styles, and image assets. + +## Deployment contract + +The expected production layout is: + +```text +nginx + -> hg_web_server.service + -> /opt/hg_web_server_bundle_active/hg_web_server + -> working directory: /opt/hg_web_server_bundle_active + -> hg serve service on 127.0.0.1:4444 ``` -## API Endpoints +`deploy.sh` builds an optimized bundle into a revisioned release directory, +atomically repoints `/opt/hg_web_server_bundle_active`, restarts +`hg_web_server.service`, and checks `http://127.0.0.1:6970/`. A failed restart +or health check restores the previous release and restarts it. The service, +release root, active path, health URL, user, and group can be overridden with +environment variables. + +## Forge capability tree + +```text +Zenbu Forge +├── Repository +│ ├── File and directory browsing available +│ ├── Syntax highlighting available +│ ├── README rendering available +│ ├── Commit graph available +│ ├── Changeset detail and diff available +│ ├── Branches, bookmarks, and tags planned +│ ├── File history and blame planned +│ └── Search planned +├── Collaboration +│ ├── Authentication and authorization planned +│ ├── Changeset review planned +│ ├── Issues planned +│ └── Releases and artifacts planned +└── Automation + ├── Mercurial incoming/changegroup hook planned + ├── Durable SQLite job queue planned + ├── Isolated Bazel runner planned + ├── Live logs and job status API planned + ├── Forge status and log screens planned + ├── Artifact retention planned + └── Atomic deploy, health check, rollback available +``` + +## Automation data flow -The C server (`main.c`) provides: +The Actions-like subsystem should extend the existing server rather than +replace it: + +```text +hg push + -> Mercurial hook records repository + revision + -> small enqueue command writes a SQLite job + -> runner service claims one queued job + -> isolated shared checkout updates to the exact revision + -> Bazel build and test steps stream logs + -> job result and artifacts are recorded + -> hg-web status API exposes the result + -> custom React screens render runs, steps, logs, and artifacts + -> successful protected jobs may call atomic deployment +``` -- `GET /api/repo/list?path=` - List directory contents -- `GET /api/repo/file?path=` - Fetch file contents +Start with one runner on the same host. Keep the hook fast, never execute build +steps inside the Mercurial request, and make the queue durable before adding +parallel or remote runners. + +## Safe extension order + +1. Add branches, bookmarks, tags, file history, blame, and search. +2. Add the hook, SQLite queue, single runner, and retained logs. +3. Add run/status/log pages using the existing custom UI. +4. Add authentication and authorization before accepting public pushes or + user-defined automation. + +## Invariants + +- Keep public application code on Seobeo APIs. +- Decode and validate every path before forwarding it to Mercurial. +- Keep `/repo` binary-safe; bundle data can contain null bytes. +- Do not buffer large wire-protocol responses through the regular HTTP client. +- Keep backend route names synchronized with frontend fetch and navigation code. +- Preserve accurate status codes, content lengths, and content types. +- Keep secrets in service-owned environment files, not in source or job logs.