Mercurial
comparison hg-web/README.md @ 218:921ca3086879 hg-web
[hg-web] Add architecture wiki tree
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sun, 02 Aug 2026 08:34:28 -0700 |
| parents | b818a4561a3c |
| children | ce7f4400c2de |
comparison
equal
deleted
inserted
replaced
| 194:fb28063dc490 | 218:921ca3086879 |
|---|---|
| 1 # hg-web | 1 # hg-web |
| 2 | 2 |
| 3 A web-based Mercurial repository browser. Provides a GitHub-style interface for browsing files, viewing code with syntax highlighting, and reading markdown documentation. | 3 A custom Mercurial forge and repository browser. The application keeps the |
| 4 | 4 networking and HTTP stack in C with Seobeo, while the hand-drawn web interface |
| 5 ## Features | 5 is implemented in React and TypeScript. |
| 6 | 6 |
| 7 - Browse repository files and directories | 7 ## Wiki tree |
| 8 - View code files with syntax highlighting (highlight.js) | 8 |
| 9 - Render markdown files with WASM-based converter | 9 ```text |
| 10 - Dark/light theme support with system preference detection | 10 hg-web |
| 11 - Prefetch on hover for faster navigation | 11 ├── Runtime |
| 12 | 12 │ ├── hg_web_server :6970 |
| 13 ## Structure | 13 │ │ ├── React application and static assets |
| 14 | 14 │ │ ├── repository browsing API |
| 15 ``` | 15 │ │ ├── commit graph API |
| 16 hg-web/ | 16 │ │ └── Mercurial wire-protocol proxy |
| 17 ├── BUILD # Bazel build configuration | 17 │ └── hg serve :4444 |
| 18 ├── deploy.sh # Deployment script | 18 │ ├── repository files and graph data |
| 19 ├── main.c # C server handling API routes | 19 │ └── Mercurial pull/push protocol |
| 20 └── src/ # Frontend source files | 20 ├── Backend |
| 21 ``` | 21 │ ├── main.c |
| 22 | 22 │ └── ../seobeo |
| 23 ## Building | 23 │ ├── s_network.c |
| 24 │ ├── s_web.c | |
| 25 │ ├── s_http_client.c | |
| 26 │ └── s_ssl.c | |
| 27 ├── Frontend | |
| 28 │ └── src | |
| 29 │ ├── main.tsx | |
| 30 │ ├── components | |
| 31 │ │ ├── app.tsx | |
| 32 │ │ ├── directory-browser.tsx | |
| 33 │ │ ├── graph.tsx | |
| 34 │ │ ├── header.tsx | |
| 35 │ │ ├── footer.tsx | |
| 36 │ │ ├── theme.tsx | |
| 37 │ │ └── repo-browser.tsx | |
| 38 │ ├── index.html | |
| 39 │ ├── index.css | |
| 40 │ ├── base.css | |
| 41 │ └── custom pencil, panda, icon, and background assets | |
| 42 ├── Build | |
| 43 │ ├── BUILD | |
| 44 │ ├── ../gui_ze/gui_ze.bzl | |
| 45 │ ├── ../markdown_converter | |
| 46 │ └── ../third_party/highlight | |
| 47 └── Operations | |
| 48 └── deploy.sh | |
| 49 ``` | |
| 50 | |
| 51 `repo-browser.tsx` is an older standalone browser implementation. The active | |
| 52 entry point is `main.tsx`, which renders `app.tsx`; `app.tsx` embeds | |
| 53 `directory-browser.tsx`. | |
| 54 | |
| 55 ## Runtime topology | |
| 56 | |
| 57 ```text | |
| 58 Browser | |
| 59 | | |
| 60 | HTTPS | |
| 61 v | |
| 62 nginx | |
| 63 | | |
| 64 | HTTP :6970 | |
| 65 v | |
| 66 hg_web_server (main.c + Seobeo) | |
| 67 | | |
| 68 | HTTP :4444 | |
| 69 v | |
| 70 hg serve (Zenbu Mercurial repository) | |
| 71 ``` | |
| 72 | |
| 73 The C server owns the public routes. It serves the application shell and | |
| 74 assets, translates browser API requests into `hg serve` requests, and streams | |
| 75 Mercurial wire-protocol traffic without routing bundle data through the normal | |
| 76 buffered HTTP response path. | |
| 77 | |
| 78 ## Request flows | |
| 79 | |
| 80 ### Application shell | |
| 81 | |
| 82 ```text | |
| 83 GET /, /directories, or /graph | |
| 84 -> GetReactHome | |
| 85 -> hg-web/src/index.html | |
| 86 -> /page.js | |
| 87 -> src/main.tsx | |
| 88 -> components/app.tsx | |
| 89 ``` | |
| 90 | |
| 91 ### Repository browser | |
| 92 | |
| 93 ```text | |
| 94 directory-browser.tsx | |
| 95 -> GET /api/repo/list?path=... | |
| 96 -> ApiListDirectory | |
| 97 -> GET hg-serve/file/tip/<path>?style=json | |
| 98 | |
| 99 file or README selection | |
| 100 -> GET /api/repo/file?path=... | |
| 101 -> ApiGetFile | |
| 102 -> GET hg-serve/raw-file/tip/<path> | |
| 103 -> highlight.js or markdown_converter WASM | |
| 104 ``` | |
| 105 | |
| 106 ### Commit graph | |
| 107 | |
| 108 ```text | |
| 109 graph.tsx | |
| 110 -> GET /api/graph/<revision>?graphtop=...&style=json | |
| 111 -> ApiGetGraph | |
| 112 -> GET hg-serve/graph/<revision>?... | |
| 113 -> React rows + custom pencil/panda canvas | |
| 114 ``` | |
| 115 | |
| 116 ### Mercurial clone, pull, and push | |
| 117 | |
| 118 ```text | |
| 119 Mercurial client | |
| 120 -> GET or POST /repo | |
| 121 -> StreamHgWireProtocol | |
| 122 -> hg serve /?cmd=... | |
| 123 -> binary-safe streamed response | |
| 124 ``` | |
| 125 | |
| 126 ## Route map | |
| 127 | |
| 128 | Method | Route | Owner | Purpose | | |
| 129 | --- | --- | --- | --- | | |
| 130 | `GET` | `/` | `GetReactHome` | Application shell | | |
| 131 | `GET` | `/directories` | `GetReactHome` | Legacy application-shell route | | |
| 132 | `GET` | `/graph` | `GetReactHome` | Commit graph application route | | |
| 133 | `GET` | `/api/repo/list` | `ApiListDirectory` | Directory listing JSON | | |
| 134 | `GET` | `/api/repo/file` | `ApiGetFile` | Raw tracked file | | |
| 135 | `GET` | `/api/repo/readme` | `ApiGetReadme` | Alias of the raw-file handler | | |
| 136 | `GET` | `/api/graph/:graph_id` | `ApiGetGraph` | Mercurial graph JSON | | |
| 137 | `GET`, `POST` | `/repo` | `StreamHgWireProtocol` | Mercurial wire protocol | | |
| 138 | |
| 139 ## Frontend ownership | |
| 140 | |
| 141 | File | Responsibility | | |
| 142 | --- | --- | | |
| 143 | `src/components/app.tsx` | Client-side routes, landing page, tabs, and history | | |
| 144 | `src/components/directory-browser.tsx` | Breadcrumbs, listings, prefetch, file modals, README rendering | | |
| 145 | `src/components/graph.tsx` | Graph fetching, pagination, canvas edges, panda nodes | | |
| 146 | `src/components/theme.tsx` | Stored light/dark preference and system-theme integration | | |
| 147 | `src/components/header.tsx` | Forge identity and theme control | | |
| 148 | `src/components/footer.tsx` | Shared footer | | |
| 149 | `src/index.css`, `src/base.css` | Custom visual language and layout | | |
| 150 | |
| 151 Keep the custom assets and visual language in this package. New forge screens | |
| 152 should reuse the existing CSS variables, typography, textures, and components | |
| 153 instead of introducing a generic design system. | |
| 154 | |
| 155 ## Build and local run | |
| 156 | |
| 157 Build the server and deployable bundle from the repository root: | |
| 24 | 158 |
| 25 ```bash | 159 ```bash |
| 26 bazel build //hg-web:hg_web | 160 bazel build //hg-web:hg_web_server |
| 27 ``` | 161 bazel build //hg-web:hg_web_server_bundle |
| 28 | 162 ``` |
| 29 ## API Endpoints | 163 |
| 30 | 164 Run the Mercurial backend: |
| 31 The C server (`main.c`) provides: | 165 |
| 32 | 166 ```bash |
| 33 - `GET /api/repo/list?path=` - List directory contents | 167 hg serve -a 127.0.0.1 -p 4444 |
| 34 - `GET /api/repo/file?path=` - Fetch file contents | 168 ``` |
| 169 | |
| 170 Run the deployable bundle from its own directory so the static root resolves: | |
| 171 | |
| 172 ```bash | |
| 173 cd bazel-bin/hg-web/hg_web_server_bundle | |
| 174 ./hg_web_server | |
| 175 ``` | |
| 176 | |
| 177 The bundle contains `hg_web_server` and `hg-web/src/`, including generated | |
| 178 `page.js`, markdown WASM, highlight.js, styles, and image assets. | |
| 179 | |
| 180 ## Deployment contract | |
| 181 | |
| 182 The expected production layout is: | |
| 183 | |
| 184 ```text | |
| 185 nginx | |
| 186 -> hg_web_server.service | |
| 187 -> /opt/hg_web_server_bundle_active/hg_web_server | |
| 188 -> working directory: /opt/hg_web_server_bundle_active | |
| 189 -> hg serve service on 127.0.0.1:4444 | |
| 190 ``` | |
| 191 | |
| 192 `deploy.sh` currently builds an optimized bundle, copies it to `/opt`, swaps | |
| 193 the active directory, changes ownership to `hg_web_server:zenbu_team`, and | |
| 194 restarts `hg_web_server.service`. | |
| 195 | |
| 196 ## Forge capability tree | |
| 197 | |
| 198 ```text | |
| 199 Zenbu Forge | |
| 200 ├── Repository | |
| 201 │ ├── File and directory browsing available | |
| 202 │ ├── Syntax highlighting available | |
| 203 │ ├── README rendering available | |
| 204 │ ├── Commit graph available | |
| 205 │ ├── Changeset detail and diff planned | |
| 206 │ ├── Branches, bookmarks, and tags planned | |
| 207 │ ├── File history and blame planned | |
| 208 │ └── Search planned | |
| 209 ├── Collaboration | |
| 210 │ ├── Authentication and authorization planned | |
| 211 │ ├── Changeset review planned | |
| 212 │ ├── Issues planned | |
| 213 │ └── Releases and artifacts planned | |
| 214 └── Automation | |
| 215 ├── Mercurial incoming/changegroup hook planned | |
| 216 ├── Durable SQLite job queue planned | |
| 217 ├── Isolated Bazel runner planned | |
| 218 ├── Live logs and job status API planned | |
| 219 ├── Forge status and log screens planned | |
| 220 ├── Artifact retention planned | |
| 221 └── Atomic deploy, health check, rollback planned | |
| 222 ``` | |
| 223 | |
| 224 ## Automation data flow | |
| 225 | |
| 226 The Actions-like subsystem should extend the existing server rather than | |
| 227 replace it: | |
| 228 | |
| 229 ```text | |
| 230 hg push | |
| 231 -> Mercurial hook records repository + revision | |
| 232 -> small enqueue command writes a SQLite job | |
| 233 -> runner service claims one queued job | |
| 234 -> isolated shared checkout updates to the exact revision | |
| 235 -> Bazel build and test steps stream logs | |
| 236 -> job result and artifacts are recorded | |
| 237 -> hg-web status API exposes the result | |
| 238 -> custom React screens render runs, steps, logs, and artifacts | |
| 239 -> successful protected jobs may call atomic deployment | |
| 240 ``` | |
| 241 | |
| 242 Start with one runner on the same host. Keep the hook fast, never execute build | |
| 243 steps inside the Mercurial request, and make the queue durable before adding | |
| 244 parallel or remote runners. | |
| 245 | |
| 246 ## Safe extension order | |
| 247 | |
| 248 1. Harden proxy errors, path validation, response headers, and timeouts. | |
| 249 2. Add changeset detail and diff APIs, then wire graph clicks to those screens. | |
| 250 3. Make deployment atomic with health checks and rollback. | |
| 251 4. Add the hook, SQLite queue, single runner, and retained logs. | |
| 252 5. Add run/status/log pages using the existing custom UI. | |
| 253 6. Add authentication and authorization before accepting public pushes or | |
| 254 user-defined automation. | |
| 255 | |
| 256 ## Invariants | |
| 257 | |
| 258 - Keep public application code on Seobeo APIs. | |
| 259 - Decode and validate every path before forwarding it to Mercurial. | |
| 260 - Keep `/repo` binary-safe; bundle data can contain null bytes. | |
| 261 - Do not buffer large wire-protocol responses through the regular HTTP client. | |
| 262 - Keep backend route names synchronized with frontend fetch and navigation code. | |
| 263 - Preserve accurate status codes, content lengths, and content types. | |
| 264 - Keep secrets in service-owned environment files, not in source or job logs. |