66c754e7

Archive
Tree [66c754e7] [>]
commit
66c754e7c2f0bc3fd45b7fd9a49af623a24214cb
parents
author
Christopher K. Schmitt <me@shmish.dev>
date
2026-07-08
committer
Christopher K. Schmitt <me@shmish.dev>
date
2026-07-08
changes
28
insertions
3881
deletions
0
Add initial routing, markdown rendering, and repo overview
A.gitignore
+/target
ACargo.lock
+# This file is automatically @generated by Cargo.+# It is not intended for manual editing.+version = 4++[[package]]+name = "aho-corasick"+version = "1.1.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"+dependencies = [+ "memchr",+]++[[package]]+name = "allocator-api2"+version = "0.2.21"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"++[[package]]+name = "anstream"+version = "1.0.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"+dependencies = [+ "anstyle",+ "anstyle-parse",+ "anstyle-query",+ "anstyle-wincon",+ "colorchoice",+ "is_terminal_polyfill",+ "utf8parse",+]++[[package]]+name = "anstyle"+version = "1.0.14"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"++[[package]]+name = "anstyle-parse"+version = "1.0.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"+dependencies = [+ "utf8parse",+]++[[package]]+name = "anstyle-query"+version = "1.1.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"+dependencies = [+ "windows-sys",+]++[[package]]+name = "anstyle-wincon"+version = "3.0.11"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"+dependencies = [+ "anstyle",+ "once_cell_polyfill",+ "windows-sys",+]++[[package]]+name = "anyhow"+version = "1.0.102"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"++[[package]]+name = "arc-swap"+version = "1.9.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207"+dependencies = [+ "rustversion",+]++[[package]]+name = "arrayvec"+version = "0.7.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"++[[package]]+name = "askama"+version = "0.15.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9b8246bcbf8eb97abef10c2d92166449680d41d55c0fc6978a91dec2e3619608"+dependencies = [+ "askama_macros",+ "itoa",+ "percent-encoding",+ "serde",+ "serde_json",+]++[[package]]+name = "askama_derive"+version = "0.15.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2f9670bc84a28bb3da91821ef74226949ab63f1265aff7c751634f1dd0e6f97c"+dependencies = [+ "askama_parser",+ "basic-toml",+ "memchr",+ "proc-macro2",+ "quote",+ "rustc-hash",+ "serde",+ "serde_derive",+ "syn",+]++[[package]]+name = "askama_macros"+version = "0.15.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f0756b45480437dded0565dfc568af62ccce146fb6cfe902e808ba86e445f44f"+dependencies = [+ "askama_derive",+]++[[package]]+name = "askama_parser"+version = "0.15.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5d0af3691ba3af77949c0b5a3925444b85cb58a0184cc7fec16c68ba2e7be868"+dependencies = [+ "rustc-hash",+ "serde",+ "serde_derive",+ "unicode-ident",+ "winnow 1.0.1",+]++[[package]]+name = "askama_web"+version = "0.15.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7eb6d818ce4fb74822f2676eb0047daf25a8b2cb88f0c9fe8ca690170a6cb6cd"+dependencies = [+ "askama",+ "askama_web_derive",+ "axum-core",+ "bytes",+ "http",+]++[[package]]+name = "askama_web_derive"+version = "0.2.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9767c17d33a63daf6da5872ffaf2ab0c289cd73ce7ed4f41d5ddf9149c004873"+dependencies = [+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "atomic-waker"+version = "1.1.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"++[[package]]+name = "axum"+version = "0.8.9"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90"+dependencies = [+ "axum-core",+ "bytes",+ "form_urlencoded",+ "futures-util",+ "http",+ "http-body",+ "http-body-util",+ "hyper",+ "hyper-util",+ "itoa",+ "matchit",+ "memchr",+ "mime",+ "percent-encoding",+ "pin-project-lite",+ "serde_core",+ "serde_json",+ "serde_path_to_error",+ "serde_urlencoded",+ "sync_wrapper",+ "tokio",+ "tower",+ "tower-layer",+ "tower-service",+ "tracing",+]++[[package]]+name = "axum-core"+version = "0.5.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"+dependencies = [+ "bytes",+ "futures-core",+ "http",+ "http-body",+ "http-body-util",+ "mime",+ "pin-project-lite",+ "sync_wrapper",+ "tower-layer",+ "tower-service",+ "tracing",+]++[[package]]+name = "basic-toml"+version = "0.1.10"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"+dependencies = [+ "serde",+]++[[package]]+name = "bitflags"+version = "2.11.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"++[[package]]+name = "block-buffer"+version = "0.10.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"+dependencies = [+ "generic-array",+]++[[package]]+name = "bstr"+version = "1.12.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"+dependencies = [+ "memchr",+ "regex-automata",+ "serde",+]++[[package]]+name = "byteorder"+version = "1.5.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"++[[package]]+name = "bytes"+version = "1.11.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"++[[package]]+name = "bytesize"+version = "2.3.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6bd91ee7b2422bcb158d90ef4d14f75ef67f340943fc4149891dcce8f8b972a3"++[[package]]+name = "cfg-if"+version = "1.0.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"++[[package]]+name = "clap"+version = "4.6.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"+dependencies = [+ "clap_builder",+ "clap_derive",+]++[[package]]+name = "clap_builder"+version = "4.6.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"+dependencies = [+ "anstream",+ "anstyle",+ "clap_lex",+ "strsim",+]++[[package]]+name = "clap_derive"+version = "4.6.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"+dependencies = [+ "heck",+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "clap_lex"+version = "1.1.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"++[[package]]+name = "clru"+version = "0.6.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "197fd99cb113a8d5d9b6376f3aa817f32c1078f2343b714fff7d2ca44fdf67d5"+dependencies = [+ "hashbrown 0.16.1",+]++[[package]]+name = "colorchoice"+version = "1.0.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"++[[package]]+name = "cpufeatures"+version = "0.2.17"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"+dependencies = [+ "libc",+]++[[package]]+name = "crc32fast"+version = "1.5.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"+dependencies = [+ "cfg-if",+]++[[package]]+name = "crossbeam-channel"+version = "0.5.15"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"+dependencies = [+ "crossbeam-utils",+]++[[package]]+name = "crossbeam-utils"+version = "0.8.21"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"++[[package]]+name = "crypto-common"+version = "0.1.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"+dependencies = [+ "generic-array",+ "typenum",+]++[[package]]+name = "dashmap"+version = "6.1.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"+dependencies = [+ "cfg-if",+ "crossbeam-utils",+ "hashbrown 0.14.5",+ "lock_api",+ "once_cell",+ "parking_lot_core",+]++[[package]]+name = "digest"+version = "0.10.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"+dependencies = [+ "block-buffer",+ "crypto-common",+]++[[package]]+name = "dunce"+version = "1.0.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"++[[package]]+name = "encoding_rs"+version = "0.8.35"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"+dependencies = [+ "cfg-if",+]++[[package]]+name = "equivalent"+version = "1.0.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"++[[package]]+name = "errno"+version = "0.3.14"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"+dependencies = [+ "libc",+ "windows-sys",+]++[[package]]+name = "faster-hex"+version = "0.10.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73"+dependencies = [+ "heapless",+ "serde",+]++[[package]]+name = "fastrand"+version = "2.4.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"++[[package]]+name = "filetime"+version = "0.2.27"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db"+dependencies = [+ "cfg-if",+ "libc",+ "libredox",+]++[[package]]+name = "fnv"+version = "1.0.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"++[[package]]+name = "foldhash"+version = "0.1.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"++[[package]]+name = "foldhash"+version = "0.2.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"++[[package]]+name = "form_urlencoded"+version = "1.2.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"+dependencies = [+ "percent-encoding",+]++[[package]]+name = "futures-channel"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"+dependencies = [+ "futures-core",+]++[[package]]+name = "futures-core"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"++[[package]]+name = "futures-task"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"++[[package]]+name = "futures-util"+version = "0.3.32"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"+dependencies = [+ "futures-core",+ "futures-task",+ "pin-project-lite",+ "slab",+]++[[package]]+name = "generic-array"+version = "0.14.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"+dependencies = [+ "typenum",+ "version_check",+]++[[package]]+name = "getopts"+version = "0.2.24"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"+dependencies = [+ "unicode-width",+]++[[package]]+name = "getrandom"+version = "0.4.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"+dependencies = [+ "cfg-if",+ "libc",+ "r-efi",+ "wasip2",+ "wasip3",+]++[[package]]+name = "gix"+version = "0.81.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0473c64d9ccbcfb9953a133b47c8b9a335b87ac6c52b983ee4b03d49000b0f3f"+dependencies = [+ "gix-actor",+ "gix-archive",+ "gix-attributes",+ "gix-blame",+ "gix-command",+ "gix-commitgraph",+ "gix-config",+ "gix-credentials",+ "gix-date",+ "gix-diff",+ "gix-dir",+ "gix-discover",+ "gix-error",+ "gix-features",+ "gix-filter",+ "gix-fs",+ "gix-glob",+ "gix-hash",+ "gix-hashtable",+ "gix-ignore",+ "gix-index",+ "gix-lock",+ "gix-mailmap",+ "gix-merge",+ "gix-negotiate",+ "gix-object",+ "gix-odb",+ "gix-pack",+ "gix-path",+ "gix-pathspec",+ "gix-prompt",+ "gix-protocol",+ "gix-ref",+ "gix-refspec",+ "gix-revision",+ "gix-revwalk",+ "gix-sec",+ "gix-shallow",+ "gix-status",+ "gix-submodule",+ "gix-tempfile",+ "gix-trace",+ "gix-traverse",+ "gix-url",+ "gix-utils",+ "gix-validate",+ "gix-worktree",+ "gix-worktree-state",+ "gix-worktree-stream",+ "nonempty",+ "parking_lot",+ "regex",+ "signal-hook",+ "smallvec",+ "thiserror",+]++[[package]]+name = "gix-actor"+version = "0.40.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0e5e5b518339d5e6718af108fd064d4e9ba33caf728cf487352873d76411df35"+dependencies = [+ "bstr",+ "gix-date",+ "gix-error",+ "winnow 0.7.15",+]++[[package]]+name = "gix-archive"+version = "0.30.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "651c99be11aac9b303483193ae50b45eb6e094da4f5ed797019b03948f51aad6"+dependencies = [+ "bstr",+ "gix-date",+ "gix-error",+ "gix-object",+ "gix-worktree-stream",+]++[[package]]+name = "gix-attributes"+version = "0.31.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c233d6eaa098c0ca5ce03236fd7a96e27f1abe72fad74b46003fbd11fe49563c"+dependencies = [+ "bstr",+ "gix-glob",+ "gix-path",+ "gix-quote",+ "gix-trace",+ "kstring",+ "smallvec",+ "thiserror",+ "unicode-bom",+]++[[package]]+name = "gix-bitmap"+version = "0.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e7add20f40d060db8c9b1314d499bac6ed7480f33eb113ce3e1cf5d6ff85d989"+dependencies = [+ "gix-error",+]++[[package]]+name = "gix-blame"+version = "0.11.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c77aaf9f7348f4da3ebfbfbbc35fa0d07155d98377856198dde6f695fd648705"+dependencies = [+ "gix-commitgraph",+ "gix-date",+ "gix-diff",+ "gix-error",+ "gix-hash",+ "gix-object",+ "gix-revwalk",+ "gix-trace",+ "gix-traverse",+ "gix-worktree",+ "smallvec",+ "thiserror",+]++[[package]]+name = "gix-chunk"+version = "0.7.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1096b6608fbe5d27fb4984e20f992b4e76fb8c613f6acb87d07c5831b53a6959"+dependencies = [+ "gix-error",+]++[[package]]+name = "gix-command"+version = "0.8.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b849c65a609f50d02f8a2774fe371650b3384a743c79c2a070ce0da49b7fb7da"+dependencies = [+ "bstr",+ "gix-path",+ "gix-quote",+ "gix-trace",+ "shell-words",+]++[[package]]+name = "gix-commitgraph"+version = "0.35.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3196655fd1443f3c58a48c114aa480be3e4e87b393d7292daaa0d543862eb445"+dependencies = [+ "bstr",+ "gix-chunk",+ "gix-error",+ "gix-hash",+ "memmap2",+ "nonempty",+]++[[package]]+name = "gix-config"+version = "0.54.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "08939b4c4ed7a663d0e64be9e1e9bdf23a1fb4fcee1febdf449f12229542e50d"+dependencies = [+ "bstr",+ "gix-config-value",+ "gix-features",+ "gix-glob",+ "gix-path",+ "gix-ref",+ "gix-sec",+ "memchr",+ "smallvec",+ "thiserror",+ "unicode-bom",+ "winnow 0.7.15",+]++[[package]]+name = "gix-config-value"+version = "0.17.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "441a300bc3645a1f45cba495b9175f90f47256ce43f2ee161da0031e3ac77c92"+dependencies = [+ "bitflags",+ "bstr",+ "gix-path",+ "libc",+ "thiserror",+]++[[package]]+name = "gix-credentials"+version = "0.37.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "38b2a34b8715e3bbd514f3d1705f5d51c4b250e5bfe506b9fb60b133c85c93d9"+dependencies = [+ "bstr",+ "gix-command",+ "gix-config-value",+ "gix-date",+ "gix-path",+ "gix-prompt",+ "gix-sec",+ "gix-trace",+ "gix-url",+ "thiserror",+]++[[package]]+name = "gix-date"+version = "0.15.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "39acf819aa9fee65e4838a2eec5cb2506e47ebb89e02a5ab9918196e491571ea"+dependencies = [+ "bstr",+ "gix-error",+ "itoa",+ "jiff",+ "smallvec",+]++[[package]]+name = "gix-diff"+version = "0.61.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "88f3b3475e5d3877d7c30c40827cc2441936ce890efc226e5ba4afe3a7ae33f0"+dependencies = [+ "bstr",+ "gix-attributes",+ "gix-command",+ "gix-filter",+ "gix-fs",+ "gix-hash",+ "gix-index",+ "gix-object",+ "gix-path",+ "gix-pathspec",+ "gix-tempfile",+ "gix-trace",+ "gix-traverse",+ "gix-worktree",+ "imara-diff 0.1.8",+ "imara-diff 0.2.0",+ "thiserror",+]++[[package]]+name = "gix-dir"+version = "0.23.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5da4604a360988f0ba8efe6f90093ca5a844f4a7f8e1a3dcda501ec44e600ea9"+dependencies = [+ "bstr",+ "gix-discover",+ "gix-fs",+ "gix-ignore",+ "gix-index",+ "gix-object",+ "gix-path",+ "gix-pathspec",+ "gix-trace",+ "gix-utils",+ "gix-worktree",+ "thiserror",+]++[[package]]+name = "gix-discover"+version = "0.49.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c65bd3330fe0cb9d40d875bf862fd5e8ad6fa4164ddbc4842fbeb889c3f0b2c6"+dependencies = [+ "bstr",+ "dunce",+ "gix-fs",+ "gix-path",+ "gix-ref",+ "gix-sec",+ "thiserror",+]++[[package]]+name = "gix-error"+version = "0.2.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2e86d01da904d4a9265def43bd42a18c5e6dc7000a73af512946ba14579c9fbd"+dependencies = [+ "bstr",+]++[[package]]+name = "gix-features"+version = "0.46.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "752493cd4b1d5eaaa0138a7493f65c96863fefa990fc021e0e519579e389ab20"+dependencies = [+ "bytes",+ "bytesize",+ "crc32fast",+ "crossbeam-channel",+ "gix-path",+ "gix-trace",+ "gix-utils",+ "libc",+ "once_cell",+ "parking_lot",+ "prodash",+ "thiserror",+ "walkdir",+ "zlib-rs",+]++[[package]]+name = "gix-filter"+version = "0.28.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d37598282a6566da6fb52667570c7fe0aedcb122ac886724a9e62a2180523e35"+dependencies = [+ "bstr",+ "encoding_rs",+ "gix-attributes",+ "gix-command",+ "gix-hash",+ "gix-object",+ "gix-packetline",+ "gix-path",+ "gix-quote",+ "gix-trace",+ "gix-utils",+ "smallvec",+ "thiserror",+]++[[package]]+name = "gix-fs"+version = "0.19.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a964b4aec683eb0bacb87533defa80805bb4768056371a47ab38b00a2d377b72"+dependencies = [+ "bstr",+ "fastrand",+ "gix-features",+ "gix-path",+ "gix-utils",+ "thiserror",+]++[[package]]+name = "gix-glob"+version = "0.24.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b03e6cd88cc0dc1eafa1fddac0fb719e4e74b6ea58dd016e71125fde4a326bee"+dependencies = [+ "bitflags",+ "bstr",+ "gix-features",+ "gix-path",+]++[[package]]+name = "gix-hash"+version = "0.23.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0fb896a02d9ab96fa518475a5f30ad3952010f801a8de5840f633f4a6b985dfb"+dependencies = [+ "faster-hex",+ "gix-features",+ "sha1-checked",+ "thiserror",+]++[[package]]+name = "gix-hashtable"+version = "0.13.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2664216fc5e89b51e756a4a3ac676315602ce2dac07acf1da959a22038d69b33"+dependencies = [+ "gix-hash",+ "hashbrown 0.16.1",+ "parking_lot",+]++[[package]]+name = "gix-ignore"+version = "0.19.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "09f915dcf6911e3027537166d34e13f0fe101ed12225178d2ae29cd1272cff26"+dependencies = [+ "bstr",+ "gix-glob",+ "gix-path",+ "gix-trace",+ "unicode-bom",+]++[[package]]+name = "gix-index"+version = "0.49.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1bae54ab14e4e74d5dda60b82ea7afad7c8eb3be68283d6d5f29bd2e6d47fff7"+dependencies = [+ "bitflags",+ "bstr",+ "filetime",+ "fnv",+ "gix-bitmap",+ "gix-features",+ "gix-fs",+ "gix-hash",+ "gix-lock",+ "gix-object",+ "gix-traverse",+ "gix-utils",+ "gix-validate",+ "hashbrown 0.16.1",+ "itoa",+ "libc",+ "memmap2",+ "rustix",+ "smallvec",+ "thiserror",+]++[[package]]+name = "gix-lock"+version = "21.0.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "054fbd0989700c69dc5aa80bc66944f05df1e15aa7391a9e42aca7366337905f"+dependencies = [+ "gix-tempfile",+ "gix-utils",+ "thiserror",+]++[[package]]+name = "gix-mailmap"+version = "0.32.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c7b4818da522786ec7e32a00884ee8fc40fa4c215c3997c0b15f7b62684d1199"+dependencies = [+ "bstr",+ "gix-actor",+ "gix-date",+ "gix-error",+]++[[package]]+name = "gix-merge"+version = "0.14.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f4606747466512d22c2dffc019142e1941238f543987ea51353c938cca80c500"+dependencies = [+ "bstr",+ "gix-command",+ "gix-diff",+ "gix-filter",+ "gix-fs",+ "gix-hash",+ "gix-index",+ "gix-object",+ "gix-path",+ "gix-quote",+ "gix-revision",+ "gix-revwalk",+ "gix-tempfile",+ "gix-trace",+ "gix-worktree",+ "imara-diff 0.1.8",+ "nonempty",+ "thiserror",+]++[[package]]+name = "gix-negotiate"+version = "0.29.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6ea064c7595eea08fdd01c70748af747d9acc40f727b61f4c8a2145a5c5fc28c"+dependencies = [+ "bitflags",+ "gix-commitgraph",+ "gix-date",+ "gix-hash",+ "gix-object",+ "gix-revwalk",+]++[[package]]+name = "gix-object"+version = "0.58.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cafb802bb688a7c1e69ef965612ff5ff859f046bfb616377e4a0ba4c01e43d47"+dependencies = [+ "bstr",+ "gix-actor",+ "gix-date",+ "gix-features",+ "gix-hash",+ "gix-hashtable",+ "gix-path",+ "gix-utils",+ "gix-validate",+ "itoa",+ "smallvec",+ "thiserror",+ "winnow 0.7.15",+]++[[package]]+name = "gix-odb"+version = "0.78.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "24833ae9323b4f7079575fb9f961cf9c414b0afbec428a536ab8e7dd93bc002b"+dependencies = [+ "arc-swap",+ "gix-features",+ "gix-fs",+ "gix-hash",+ "gix-hashtable",+ "gix-object",+ "gix-pack",+ "gix-path",+ "gix-quote",+ "parking_lot",+ "tempfile",+ "thiserror",+]++[[package]]+name = "gix-pack"+version = "0.68.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e3484119cd19859d7d7639413c27e192478fa354d3f4ff5f7e3c041e8040f0f4"+dependencies = [+ "clru",+ "gix-chunk",+ "gix-error",+ "gix-features",+ "gix-hash",+ "gix-hashtable",+ "gix-object",+ "gix-path",+ "memmap2",+ "smallvec",+ "thiserror",+ "uluru",+]++[[package]]+name = "gix-packetline"+version = "0.21.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "be19313dcdb7dff75a3ce2f99be00878458295bcc3b6c7f0005591597573345c"+dependencies = [+ "bstr",+ "faster-hex",+ "gix-trace",+ "thiserror",+]++[[package]]+name = "gix-path"+version = "0.11.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "09c31d4373bda7fab9eb01822927b55185a378d6e1bf737e0a54c743ad806658"+dependencies = [+ "bstr",+ "gix-trace",+ "gix-validate",+ "thiserror",+]++[[package]]+name = "gix-pathspec"+version = "0.16.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f89611f13544ca5ebeb68a502673814ef57200df60c24a61c2ce7b96f612f08b"+dependencies = [+ "bitflags",+ "bstr",+ "gix-attributes",+ "gix-config-value",+ "gix-glob",+ "gix-path",+ "thiserror",+]++[[package]]+name = "gix-prompt"+version = "0.14.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0f61f6264e1f6c5a951531fe127722c7522bc02ebda80c4528286bda4642055f"+dependencies = [+ "gix-command",+ "gix-config-value",+ "parking_lot",+ "rustix",+ "thiserror",+]++[[package]]+name = "gix-protocol"+version = "0.59.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4f38666350736b5877c79f57ddae02bde07a4ce186d889adc391e831cddcbe76"+dependencies = [+ "bstr",+ "gix-date",+ "gix-features",+ "gix-hash",+ "gix-ref",+ "gix-shallow",+ "gix-transport",+ "gix-utils",+ "maybe-async",+ "nonempty",+ "thiserror",+ "winnow 0.7.15",+]++[[package]]+name = "gix-quote"+version = "0.7.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "68533db71259c8776dd4e770d2b7b98696213ecdc1f5c9e3507119e274e0c578"+dependencies = [+ "bstr",+ "gix-error",+ "gix-utils",+]++[[package]]+name = "gix-ref"+version = "0.61.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c2159978abb99b7027c8579d15211e262ef0ef2594d5cecb3334fbcbdfe2997c"+dependencies = [+ "gix-actor",+ "gix-features",+ "gix-fs",+ "gix-hash",+ "gix-lock",+ "gix-object",+ "gix-path",+ "gix-tempfile",+ "gix-utils",+ "gix-validate",+ "memmap2",+ "thiserror",+ "winnow 0.7.15",+]++[[package]]+name = "gix-refspec"+version = "0.39.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "dc806ee13f437428f8a1ba4c72ecfaa3f20e14f5f0d4c2bc17d0b33e794aa6ac"+dependencies = [+ "bstr",+ "gix-error",+ "gix-glob",+ "gix-hash",+ "gix-revision",+ "gix-validate",+ "smallvec",+ "thiserror",+]++[[package]]+name = "gix-revision"+version = "0.43.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7c08f1ec5d1e6a524f8ba291c41f0ccaef64e48ed0e8cf790b3461cae45f6d3d"+dependencies = [+ "bitflags",+ "bstr",+ "gix-commitgraph",+ "gix-date",+ "gix-error",+ "gix-hash",+ "gix-hashtable",+ "gix-object",+ "gix-revwalk",+ "gix-trace",+ "nonempty",+]++[[package]]+name = "gix-revwalk"+version = "0.29.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0e4b2b87772b21ca449249e86d32febadba5cba32b0fcce804ab9cefc6f2111c"+dependencies = [+ "gix-commitgraph",+ "gix-date",+ "gix-error",+ "gix-hash",+ "gix-hashtable",+ "gix-object",+ "smallvec",+ "thiserror",+]++[[package]]+name = "gix-sec"+version = "0.13.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "bf82ae037de9c62850ce67beaa92ec8e3e17785ea307cdde7618edc215603b4f"+dependencies = [+ "bitflags",+ "gix-path",+ "libc",+ "windows-sys",+]++[[package]]+name = "gix-shallow"+version = "0.10.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "cbf60711c9083b2364b3fac8a352444af76b17201f3682fdebe74fa66d89a772"+dependencies = [+ "bstr",+ "gix-hash",+ "gix-lock",+ "nonempty",+ "thiserror",+]++[[package]]+name = "gix-status"+version = "0.28.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "23d6c598e3fdbc352fba1c5ba7e709e69402fafbc44d9295edad2e3c4738996b"+dependencies = [+ "bstr",+ "filetime",+ "gix-diff",+ "gix-dir",+ "gix-features",+ "gix-filter",+ "gix-fs",+ "gix-hash",+ "gix-index",+ "gix-object",+ "gix-path",+ "gix-pathspec",+ "gix-worktree",+ "portable-atomic",+ "thiserror",+]++[[package]]+name = "gix-submodule"+version = "0.28.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0ce5c3929c5e6821f651d35e8420f72fea3cfafe9fc1e928a61e718b462c72a5"+dependencies = [+ "bstr",+ "gix-config",+ "gix-path",+ "gix-pathspec",+ "gix-refspec",+ "gix-url",+ "thiserror",+]++[[package]]+name = "gix-tempfile"+version = "21.0.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d22227f6b203f511ff451c33c89899e87e4f571fc596b06f68e6e613a6508528"+dependencies = [+ "dashmap",+ "gix-fs",+ "libc",+ "parking_lot",+ "signal-hook",+ "signal-hook-registry",+ "tempfile",+]++[[package]]+name = "gix-trace"+version = "0.1.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f69a13643b8437d4ca6845e08143e847a36ca82903eed13303475d0ae8b162e0"++[[package]]+name = "gix-transport"+version = "0.55.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a521e39c6235ce63ed6c001e2dd79818c830b82c3b7b59247ee7b229c39ec9bb"+dependencies = [+ "bstr",+ "gix-command",+ "gix-features",+ "gix-packetline",+ "gix-quote",+ "gix-sec",+ "gix-url",+ "thiserror",+]++[[package]]+name = "gix-traverse"+version = "0.55.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "963dc2afcdb611092aa587c3f9365e749ac0a0892ff27662dbc75f26c953fbec"+dependencies = [+ "bitflags",+ "gix-commitgraph",+ "gix-date",+ "gix-hash",+ "gix-hashtable",+ "gix-object",+ "gix-revwalk",+ "smallvec",+ "thiserror",+]++[[package]]+name = "gix-url"+version = "0.35.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d28e8af3d42581190da884f013caf254d2fd4d6ab102408f08d21bfa11de6c8d"+dependencies = [+ "bstr",+ "gix-path",+ "percent-encoding",+ "thiserror",+]++[[package]]+name = "gix-utils"+version = "0.3.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "befcdbdfb1238d2854591f760a48711bed85e72d80a10e8f2f93f656746ef7c5"+dependencies = [+ "bstr",+ "fastrand",+ "unicode-normalization",+]++[[package]]+name = "gix-validate"+version = "0.11.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0ec1eff98d91941f47766367cba1be746bab662bad761d9891ae6f7882f7840b"+dependencies = [+ "bstr",+]++[[package]]+name = "gix-worktree"+version = "0.50.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e6bd5830cbc43c9c00918b826467d2afad685b195cb82329cde2b2d116d2c578"+dependencies = [+ "bstr",+ "gix-attributes",+ "gix-fs",+ "gix-glob",+ "gix-hash",+ "gix-ignore",+ "gix-index",+ "gix-object",+ "gix-path",+ "gix-validate",+]++[[package]]+name = "gix-worktree-state"+version = "0.28.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "644a1681f96e1be43c2a8384337d9d220e7624f50db54beda70997052aebf707"+dependencies = [+ "bstr",+ "gix-features",+ "gix-filter",+ "gix-fs",+ "gix-index",+ "gix-object",+ "gix-path",+ "gix-worktree",+ "io-close",+ "thiserror",+]++[[package]]+name = "gix-worktree-stream"+version = "0.30.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "24e3fb70a1f650a5cec7d5b8d10d6d6fe86daf3cf15bde08ba0c70988a2932c3"+dependencies = [+ "gix-attributes",+ "gix-error",+ "gix-features",+ "gix-filter",+ "gix-fs",+ "gix-hash",+ "gix-object",+ "gix-path",+ "gix-traverse",+ "parking_lot",+]++[[package]]+name = "hash32"+version = "0.3.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"+dependencies = [+ "byteorder",+]++[[package]]+name = "hashbrown"+version = "0.14.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"++[[package]]+name = "hashbrown"+version = "0.15.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"+dependencies = [+ "foldhash 0.1.5",+]++[[package]]+name = "hashbrown"+version = "0.16.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"+dependencies = [+ "allocator-api2",+ "equivalent",+ "foldhash 0.2.0",+]++[[package]]+name = "hashbrown"+version = "0.17.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"++[[package]]+name = "heapless"+version = "0.8.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"+dependencies = [+ "hash32",+ "stable_deref_trait",+]++[[package]]+name = "heck"+version = "0.5.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"++[[package]]+name = "http"+version = "1.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"+dependencies = [+ "bytes",+ "itoa",+]++[[package]]+name = "http-body"+version = "1.0.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"+dependencies = [+ "bytes",+ "http",+]++[[package]]+name = "http-body-util"+version = "0.1.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"+dependencies = [+ "bytes",+ "futures-core",+ "http",+ "http-body",+ "pin-project-lite",+]++[[package]]+name = "httparse"+version = "1.10.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"++[[package]]+name = "httpdate"+version = "1.0.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"++[[package]]+name = "human_format"+version = "1.2.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "eaec953f16e5bcf6b8a3cb3aa959b17e5577dbd2693e94554c462c08be22624b"++[[package]]+name = "hyper"+version = "1.9.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca"+dependencies = [+ "atomic-waker",+ "bytes",+ "futures-channel",+ "futures-core",+ "http",+ "http-body",+ "httparse",+ "httpdate",+ "itoa",+ "pin-project-lite",+ "smallvec",+ "tokio",+]++[[package]]+name = "hyper-util"+version = "0.1.20"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"+dependencies = [+ "bytes",+ "http",+ "http-body",+ "hyper",+ "pin-project-lite",+ "tokio",+ "tower-service",+]++[[package]]+name = "id-arena"+version = "2.3.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"++[[package]]+name = "imara-diff"+version = "0.1.8"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "17d34b7d42178945f775e84bc4c36dde7c1c6cdfea656d3354d009056f2bb3d2"+dependencies = [+ "hashbrown 0.15.5",+]++[[package]]+name = "imara-diff"+version = "0.2.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2f01d462f766df78ab820dd06f5eb700233c51f0f4c2e846520eaf4ba6aa5c5c"+dependencies = [+ "hashbrown 0.15.5",+ "memchr",+]++[[package]]+name = "indexmap"+version = "2.14.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"+dependencies = [+ "equivalent",+ "hashbrown 0.17.0",+ "serde",+ "serde_core",+]++[[package]]+name = "io-close"+version = "0.3.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc"+dependencies = [+ "libc",+ "winapi",+]++[[package]]+name = "is_terminal_polyfill"+version = "1.70.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"++[[package]]+name = "itoa"+version = "1.0.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"++[[package]]+name = "jiff"+version = "0.2.24"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d"+dependencies = [+ "jiff-static",+ "jiff-tzdb-platform",+ "log",+ "portable-atomic",+ "portable-atomic-util",+ "serde_core",+ "windows-sys",+]++[[package]]+name = "jiff-static"+version = "0.2.24"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7"+dependencies = [+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "jiff-tzdb"+version = "0.1.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076"++[[package]]+name = "jiff-tzdb-platform"+version = "0.1.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"+dependencies = [+ "jiff-tzdb",+]++[[package]]+name = "kstring"+version = "2.0.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1"+dependencies = [+ "static_assertions",+]++[[package]]+name = "leb128fmt"+version = "0.1.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"++[[package]]+name = "libc"+version = "0.2.185"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"++[[package]]+name = "libredox"+version = "0.1.16"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c"+dependencies = [+ "bitflags",+ "libc",+ "plain",+ "redox_syscall 0.7.4",+]++[[package]]+name = "linux-raw-sys"+version = "0.12.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"++[[package]]+name = "lock_api"+version = "0.4.14"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"+dependencies = [+ "scopeguard",+]++[[package]]+name = "log"+version = "0.4.29"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"++[[package]]+name = "matchit"+version = "0.8.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"++[[package]]+name = "maybe-async"+version = "0.2.10"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11"+dependencies = [+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "memchr"+version = "2.8.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"++[[package]]+name = "memmap2"+version = "0.9.10"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"+dependencies = [+ "libc",+]++[[package]]+name = "mime"+version = "0.3.17"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"++[[package]]+name = "mio"+version = "1.2.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"+dependencies = [+ "libc",+ "wasi",+ "windows-sys",+]++[[package]]+name = "nonempty"+version = "0.12.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9737e026353e5cd0736f98eddae28665118eb6f6600902a7f50db585621fecb6"++[[package]]+name = "once_cell"+version = "1.21.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"++[[package]]+name = "once_cell_polyfill"+version = "1.70.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"++[[package]]+name = "parking_lot"+version = "0.12.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"+dependencies = [+ "lock_api",+ "parking_lot_core",+]++[[package]]+name = "parking_lot_core"+version = "0.9.12"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"+dependencies = [+ "cfg-if",+ "libc",+ "redox_syscall 0.5.18",+ "smallvec",+ "windows-link",+]++[[package]]+name = "percent-encoding"+version = "2.3.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"++[[package]]+name = "pin-project-lite"+version = "0.2.17"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"++[[package]]+name = "plain"+version = "0.2.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"++[[package]]+name = "portable-atomic"+version = "1.13.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"++[[package]]+name = "portable-atomic-util"+version = "0.2.7"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618"+dependencies = [+ "portable-atomic",+]++[[package]]+name = "prettyplease"+version = "0.2.37"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"+dependencies = [+ "proc-macro2",+ "syn",+]++[[package]]+name = "proc-macro2"+version = "1.0.106"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"+dependencies = [+ "unicode-ident",+]++[[package]]+name = "prodash"+version = "31.0.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "962200e2d7d551451297d9fdce85138374019ada198e30ea9ede38034e27604c"+dependencies = [+ "bytesize",+ "human_format",+ "parking_lot",+]++[[package]]+name = "pulldown-cmark"+version = "0.13.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad"+dependencies = [+ "bitflags",+ "getopts",+ "memchr",+ "pulldown-cmark-escape",+ "unicase",+]++[[package]]+name = "pulldown-cmark-escape"+version = "0.11.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"++[[package]]+name = "quote"+version = "1.0.45"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"+dependencies = [+ "proc-macro2",+]++[[package]]+name = "r-efi"+version = "6.0.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"++[[package]]+name = "redox_syscall"+version = "0.5.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"+dependencies = [+ "bitflags",+]++[[package]]+name = "redox_syscall"+version = "0.7.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a"+dependencies = [+ "bitflags",+]++[[package]]+name = "regex"+version = "1.12.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"+dependencies = [+ "aho-corasick",+ "memchr",+ "regex-automata",+ "regex-syntax",+]++[[package]]+name = "regex-automata"+version = "0.4.14"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"+dependencies = [+ "aho-corasick",+ "memchr",+ "regex-syntax",+]++[[package]]+name = "regex-syntax"+version = "0.8.10"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"++[[package]]+name = "rustc-hash"+version = "2.1.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"++[[package]]+name = "rustix"+version = "1.1.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"+dependencies = [+ "bitflags",+ "errno",+ "libc",+ "linux-raw-sys",+ "windows-sys",+]++[[package]]+name = "rustversion"+version = "1.0.22"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"++[[package]]+name = "ryu"+version = "1.0.23"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"++[[package]]+name = "same-file"+version = "1.0.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"+dependencies = [+ "winapi-util",+]++[[package]]+name = "scopeguard"+version = "1.2.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"++[[package]]+name = "semver"+version = "1.0.28"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"++[[package]]+name = "serde"+version = "1.0.228"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"+dependencies = [+ "serde_core",+ "serde_derive",+]++[[package]]+name = "serde_core"+version = "1.0.228"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"+dependencies = [+ "serde_derive",+]++[[package]]+name = "serde_derive"+version = "1.0.228"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"+dependencies = [+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "serde_json"+version = "1.0.149"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"+dependencies = [+ "itoa",+ "memchr",+ "serde",+ "serde_core",+ "zmij",+]++[[package]]+name = "serde_path_to_error"+version = "0.1.20"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"+dependencies = [+ "itoa",+ "serde",+ "serde_core",+]++[[package]]+name = "serde_urlencoded"+version = "0.7.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"+dependencies = [+ "form_urlencoded",+ "itoa",+ "ryu",+ "serde",+]++[[package]]+name = "sha1"+version = "0.10.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"+dependencies = [+ "cfg-if",+ "cpufeatures",+ "digest",+]++[[package]]+name = "sha1-checked"+version = "0.10.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423"+dependencies = [+ "digest",+ "sha1",+]++[[package]]+name = "shell-words"+version = "1.1.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"++[[package]]+name = "signal-hook"+version = "0.4.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d"+dependencies = [+ "libc",+ "signal-hook-registry",+]++[[package]]+name = "signal-hook-registry"+version = "1.4.8"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"+dependencies = [+ "errno",+ "libc",+]++[[package]]+name = "slab"+version = "0.4.12"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"++[[package]]+name = "smallvec"+version = "1.15.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"++[[package]]+name = "socket2"+version = "0.6.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"+dependencies = [+ "libc",+ "windows-sys",+]++[[package]]+name = "stable_deref_trait"+version = "1.2.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"++[[package]]+name = "static_assertions"+version = "1.1.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"++[[package]]+name = "strsim"+version = "0.11.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"++[[package]]+name = "syn"+version = "2.0.117"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"+dependencies = [+ "proc-macro2",+ "quote",+ "unicode-ident",+]++[[package]]+name = "sync_wrapper"+version = "1.0.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"++[[package]]+name = "temp_name"+version = "0.1.0"+dependencies = [+ "askama",+ "askama_web",+ "axum",+ "clap",+ "gix",+ "jiff",+ "pulldown-cmark",+ "serde",+ "thiserror",+ "tokio",+]++[[package]]+name = "tempfile"+version = "3.27.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"+dependencies = [+ "fastrand",+ "getrandom",+ "once_cell",+ "rustix",+ "windows-sys",+]++[[package]]+name = "thiserror"+version = "2.0.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"+dependencies = [+ "thiserror-impl",+]++[[package]]+name = "thiserror-impl"+version = "2.0.18"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"+dependencies = [+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "tinyvec"+version = "1.11.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"+dependencies = [+ "tinyvec_macros",+]++[[package]]+name = "tinyvec_macros"+version = "0.1.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"++[[package]]+name = "tokio"+version = "1.52.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6"+dependencies = [+ "libc",+ "mio",+ "pin-project-lite",+ "socket2",+ "tokio-macros",+ "windows-sys",+]++[[package]]+name = "tokio-macros"+version = "2.7.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"+dependencies = [+ "proc-macro2",+ "quote",+ "syn",+]++[[package]]+name = "tower"+version = "0.5.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"+dependencies = [+ "futures-core",+ "futures-util",+ "pin-project-lite",+ "sync_wrapper",+ "tokio",+ "tower-layer",+ "tower-service",+ "tracing",+]++[[package]]+name = "tower-layer"+version = "0.3.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"++[[package]]+name = "tower-service"+version = "0.3.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"++[[package]]+name = "tracing"+version = "0.1.44"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"+dependencies = [+ "log",+ "pin-project-lite",+ "tracing-core",+]++[[package]]+name = "tracing-core"+version = "0.1.36"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"+dependencies = [+ "once_cell",+]++[[package]]+name = "typenum"+version = "1.20.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de"++[[package]]+name = "uluru"+version = "3.1.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7c8a2469e56e6e5095c82ccd3afb98dad95f7af7929aab6d8ba8d6e0f73657da"+dependencies = [+ "arrayvec",+]++[[package]]+name = "unicase"+version = "2.9.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"++[[package]]+name = "unicode-bom"+version = "2.0.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217"++[[package]]+name = "unicode-ident"+version = "1.0.24"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"++[[package]]+name = "unicode-normalization"+version = "0.1.25"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"+dependencies = [+ "tinyvec",+]++[[package]]+name = "unicode-width"+version = "0.2.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"++[[package]]+name = "unicode-xid"+version = "0.2.6"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"++[[package]]+name = "utf8parse"+version = "0.2.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"++[[package]]+name = "version_check"+version = "0.9.5"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"++[[package]]+name = "walkdir"+version = "2.5.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"+dependencies = [+ "same-file",+ "winapi-util",+]++[[package]]+name = "wasi"+version = "0.11.1+wasi-snapshot-preview1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"++[[package]]+name = "wasip2"+version = "1.0.3+wasi-0.2.9"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"+dependencies = [+ "wit-bindgen 0.57.1",+]++[[package]]+name = "wasip3"+version = "0.4.0+wasi-0.3.0-rc-2026-01-06"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"+dependencies = [+ "wit-bindgen 0.51.0",+]++[[package]]+name = "wasm-encoder"+version = "0.244.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"+dependencies = [+ "leb128fmt",+ "wasmparser",+]++[[package]]+name = "wasm-metadata"+version = "0.244.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"+dependencies = [+ "anyhow",+ "indexmap",+ "wasm-encoder",+ "wasmparser",+]++[[package]]+name = "wasmparser"+version = "0.244.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"+dependencies = [+ "bitflags",+ "hashbrown 0.15.5",+ "indexmap",+ "semver",+]++[[package]]+name = "winapi"+version = "0.3.9"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"+dependencies = [+ "winapi-i686-pc-windows-gnu",+ "winapi-x86_64-pc-windows-gnu",+]++[[package]]+name = "winapi-i686-pc-windows-gnu"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"++[[package]]+name = "winapi-util"+version = "0.1.11"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"+dependencies = [+ "windows-sys",+]++[[package]]+name = "winapi-x86_64-pc-windows-gnu"+version = "0.4.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"++[[package]]+name = "windows-link"+version = "0.2.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"++[[package]]+name = "windows-sys"+version = "0.61.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"+dependencies = [+ "windows-link",+]++[[package]]+name = "winnow"+version = "0.7.15"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"+dependencies = [+ "memchr",+]++[[package]]+name = "winnow"+version = "1.0.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"+dependencies = [+ "memchr",+]++[[package]]+name = "wit-bindgen"+version = "0.51.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"+dependencies = [+ "wit-bindgen-rust-macro",+]++[[package]]+name = "wit-bindgen"+version = "0.57.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"++[[package]]+name = "wit-bindgen-core"+version = "0.51.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"+dependencies = [+ "anyhow",+ "heck",+ "wit-parser",+]++[[package]]+name = "wit-bindgen-rust"+version = "0.51.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"+dependencies = [+ "anyhow",+ "heck",+ "indexmap",+ "prettyplease",+ "syn",+ "wasm-metadata",+ "wit-bindgen-core",+ "wit-component",+]++[[package]]+name = "wit-bindgen-rust-macro"+version = "0.51.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"+dependencies = [+ "anyhow",+ "prettyplease",+ "proc-macro2",+ "quote",+ "syn",+ "wit-bindgen-core",+ "wit-bindgen-rust",+]++[[package]]+name = "wit-component"+version = "0.244.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"+dependencies = [+ "anyhow",+ "bitflags",+ "indexmap",+ "log",+ "serde",+ "serde_derive",+ "serde_json",+ "wasm-encoder",+ "wasm-metadata",+ "wasmparser",+ "wit-parser",+]++[[package]]+name = "wit-parser"+version = "0.244.0"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"+dependencies = [+ "anyhow",+ "id-arena",+ "indexmap",+ "log",+ "semver",+ "serde",+ "serde_derive",+ "serde_json",+ "unicode-xid",+ "wasmparser",+]++[[package]]+name = "zlib-rs"+version = "0.6.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513"++[[package]]+name = "zmij"+version = "1.0.21"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
ACargo.toml
+[package]+name = "temp_name"+version = "0.1.0"+edition = "2024"++[dependencies]+askama = "0.15.6"+askama_web = { version = "0.15.2", features = ["axum-0.8"] }+axum = "0.8.9"+clap = { version = "4.6.1", features = ["derive"] }+gix = "0.81.0"+jiff = "0.2.24"+pulldown-cmark = "0.13.3"+serde = { version = "1.0.228", features = ["derive"] }+thiserror = "2.0.18"+tokio = { version = "1.52.1", features = ["rt-multi-thread", "macros"] }
Asrc/cli.rs
+//! Command-line arguments parsed at startup via clap.++use std::path::PathBuf;++use clap::Parser;++use crate::theme::Theme;++#[derive(Parser)]+pub struct Args {+    /// Path to the directory containing bare git repositories.+    #[arg(long, default_value = ".")]+    pub root: PathBuf,++    /// Hostname shown in the breadcrumb and used to build clone URLs.+    #[arg(long)]+    pub hostname: Option<String>,++    /// Path prefix prepended before the repository name in SSH clone URLs+    /// (e.g. `repos/` or `/srv/git/`).+    #[arg(long)]+    pub ssh_prefix: Option<String>,++    /// Built-in colour theme.+    #[arg(long, default_value = "auto")]+    pub theme: Theme,++    /// Path to a custom CSS file with theme variable overrides; takes+    /// precedence over --theme if provided.+    #[arg(long)]+    pub theme_file: Option<PathBuf>,+}
Asrc/error.rs
+use axum::http::StatusCode;+use axum::response::{IntoResponse, Response};+use thiserror::Error;++#[derive(Debug, Error)]+pub enum Error {+    #[error(transparent)]+    Io(#[from] std::io::Error),+    #[error("repository not found: {0}")]+    RepoNotFound(String),+    #[error("not found: {0}")]+    NotFound(String),+    #[error("bad request: {0}")]+    BadRequest(String),+    #[error("corrupt object: {0}")]+    GitCorrupt(String),+}++pub type Result<T> = std::result::Result<T, Error>;++impl IntoResponse for Error {+    fn into_response(self) -> Response {+        let status = match &self {+            Error::RepoNotFound(_) | Error::NotFound(_) => StatusCode::NOT_FOUND,+            Error::BadRequest(_) => StatusCode::BAD_REQUEST,+            Error::Io(_) | Error::GitCorrupt(_) => StatusCode::INTERNAL_SERVER_ERROR,+        };+        (status, self.to_string()).into_response()+    }+}
Asrc/main.rs
+mod cli;+mod error;+mod routes;+mod theme;++use std::sync::OnceLock;++use clap::Parser;+use tokio::net::TcpListener;++use crate::error::Result;+use crate::theme::{BASE_CSS, MARKDOWN_CSS};++/// Package name, sourced from `Cargo.toml` at compile time.+pub const PKG_NAME: &str = env!("CARGO_PKG_NAME");++/// Package version, sourced from `Cargo.toml` at compile time.+pub const PKG_VERSION: &str = env!("CARGO_PKG_VERSION");++/// Hostname used in breadcrumbs and clone URLs, set once from `--hostname`.+static HOSTNAME: OnceLock<String> = OnceLock::new();++/// SSH clone URL path prefix, set once from `--ssh-prefix`.+static SSH_PREFIX: OnceLock<String> = OnceLock::new();++/// Returns the configured hostname, or `"index"` if none was provided.+pub fn hostname() -> &'static str {+    HOSTNAME.get().map_or("index", |s| s.as_str())+}++/// Returns the configured SSH prefix, or an empty string if none was provided.+pub fn ssh_prefix() -> &'static str {+    SSH_PREFIX.get().map_or("", |s| s.as_str())+}++#[tokio::main]+async fn main() -> Result<()> {+    let args = cli::Args::parse();++    if let Some(hostname) = args.hostname {+        let _ = HOSTNAME.set(hostname);+    }+    if let Some(ssh_prefix) = args.ssh_prefix {+        let _ = SSH_PREFIX.set(ssh_prefix);+    }++    // Concatenate base styles, markdown styles, and theme variables into a+    // single stylesheet served at /style.css.+    let theme_vars = match args.theme_file {+        Some(path) => std::fs::read_to_string(path)?,+        None => args.theme.css().to_owned(),+    };+    let css = format!("{BASE_CSS}\n{MARKDOWN_CSS}\n{theme_vars}");++    let state = routes::AppState {+        root: args.root,+        css,+    };++    let router = routes::router(state);+    let socket = TcpListener::bind("0.0.0.0:3000").await?;++    axum::serve(socket, router).await?;++    Ok(())+}
Asrc/routes.rs
+mod archive;+mod branch;+mod commit;+mod raw;+mod repo;+mod tag;+mod tree;++use std::collections::HashMap;+use std::path::{Component, PathBuf};++use axum::Router;+use axum::extract::{FromRequestParts, Path, State};+use axum::http::header;+use axum::http::request::Parts;+use axum::response::IntoResponse;+use axum::routing::get;++use crate::error::{Error, Result};++/// Axum extractor that pulls the `{repo}` path parameter and validates it+/// contains no path traversal components before passing it to handlers.+pub struct RepoName(pub String);++impl<S: Send + Sync> FromRequestParts<S> for RepoName {+    type Rejection = Error;++    async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self> {+        let Path(params) = Path::<HashMap<String, String>>::from_request_parts(parts, state)+            .await+            .map_err(|e| Error::BadRequest(e.to_string()))?;++        let name = params+            .get("repo")+            .ok_or_else(|| Error::BadRequest("missing repo parameter".to_string()))?+            .clone();++        // Reject names containing non-normal components (e.g. `..`) to prevent+        // directory traversal.+        if std::path::Path::new(&name)+            .components()+            .any(|c| !matches!(c, Component::Normal(_)))+        {+            return Err(Error::BadRequest("invalid repository name".to_string()));+        }++        Ok(RepoName(name))+    }+}++/// Shared application state passed to all route handlers.+#[derive(Clone)]+pub struct AppState {+    /// Path to the directory containing bare git repositories.+    pub root: PathBuf,+    /// Concatenated CSS served at `/style.css`.+    pub css: String,+}++/// Serves the concatenated stylesheet.+async fn style(State(state): State<AppState>) -> impl IntoResponse {+    (+        [(header::CONTENT_TYPE, "text/css; charset=utf-8")],+        state.css,+    )+}++/// Builds the application router with all routes and shared state attached.+pub fn router(state: AppState) -> Router {+    Router::new()+        .route("/style.css", get(style))+        .route("/", get(repo::list))+        .route("/{repo}", get(repo::detail))+        .route("/{repo}/tags", get(tag::list))+        .route("/{repo}/tags/{*tag}", get(tag::detail))+        .route("/{repo}/branches", get(branch::list))+        .route("/{repo}/branches/{*branch}", get(branch::detail))+        .route("/{repo}/commits", get(commit::list))+        .route("/{repo}/commits/{sha}", get(commit::detail))+        .route("/{repo}/commits/{sha}/tree", get(tree::handler))+        .route("/{repo}/commits/{sha}/tree/{*path}", get(tree::handler))+        .route("/{repo}/commits/{sha}/raw/{*path}", get(raw::handler))+        .route("/{repo}/archive/{format}/{*ref}", get(archive::handler))+        .with_state(state)+}
Asrc/routes/archive.rs
+use axum::response::IntoResponse;++pub async fn handler() -> impl IntoResponse {+    "Archive handler"+}
Asrc/routes/branch.rs
+use axum::response::IntoResponse;++pub async fn list() -> impl IntoResponse {+    "Branch list"+}++pub async fn detail() -> impl IntoResponse {+    "Branch detail"+}
Asrc/routes/commit.rs
+use axum::response::IntoResponse;++pub async fn detail() -> impl IntoResponse {+    "Commit detail"+}++pub async fn list() -> impl IntoResponse {+    "Commit list"+}
Asrc/routes/raw.rs
+//! Route handler for serving raw file contents from a git repository.+//!+//! Covers one route: `/{repo}/commits/{sha}/raw/{*path}`.  The handler resolves+//! the rev-spec `{sha}:{path}` via `gix`, validates the path against directory+//! traversal, and serves the blob bytes with an appropriate `Content-Type`+//! header derived from the file extension.++use std::path::Component;++use axum::extract::{Path, State};+use axum::http::header;+use axum::response::IntoResponse;+use serde::Deserialize;++use crate::error::{Error, Result};+use crate::routes::{AppState, RepoName};++/// Path parameters for the raw file route.+#[derive(Deserialize)]+pub(super) struct RawPath {+    sha: String,+    path: String,+}++/// Serves the raw contents of a file at `{sha}:{path}` in the given repository+/// with an appropriate `Content-Type` header.+pub async fn handler(+    State(state): State<AppState>,+    RepoName(name): RepoName,+    Path(params): Path<RawPath>,+) -> Result<impl IntoResponse> {+    // Reject paths containing non-normal components (e.g. `..`) to prevent+    // directory traversal.+    if std::path::Path::new(&params.path)+        .components()+        .any(|c| !matches!(c, Component::Normal(_)))+    {+        return Err(Error::BadRequest("invalid path".to_string()));+    }++    let git_repo =+        gix::open(state.root.join(&name)).map_err(|_| Error::RepoNotFound(name.clone()))?;++    // Build a `sha:path` rev-spec and resolve it to a blob.+    let spec = format!("{}:{}", params.sha, params.path);+    let blob = git_repo+        .rev_parse_single(spec.as_str())+        .map_err(|_| Error::NotFound(spec.clone()))?+        .object()+        .map_err(|e| Error::GitCorrupt(e.to_string()))?+        .try_into_blob()+        .map_err(|_| Error::NotFound(spec))?;++    let content_type = content_type_for(&params.path);++    Ok(([(header::CONTENT_TYPE, content_type)], blob.data.to_vec()))+}++/// Returns a `Content-Type` string based on the file extension of `path`.+/// Falls back to `application/octet-stream` for unknown extensions.+fn content_type_for(path: &str) -> &'static str {+    match path.rsplit('.').next().unwrap_or("") {+        "png" => "image/png",+        "jpg" | "jpeg" => "image/jpeg",+        "gif" => "image/gif",+        "svg" => "image/svg+xml",+        "webp" => "image/webp",+        "ico" => "image/x-icon",+        "txt" | "md" => "text/plain; charset=utf-8",+        _ => "application/octet-stream",+    }+}
Asrc/routes/repo.rs
+//! Route handlers for repository pages.+//!+//! Covers two routes: the repository list (`/`) and the repository detail+//! page (`/{repo}`).  The detail handler opens the repository with `gix`,+//! collects branch and tag summaries by peeling each ref to its commit, and+//! reads the description from `.git/description`.  Refs that cannot be read+//! are silently skipped rather than treated as fatal errors.++use askama::Template;+use askama_web::WebTemplate;+use axum::extract::State;+use axum::response::IntoResponse;+use jiff::Timestamp;+use jiff::tz::{Offset, TimeZone};++use crate::error::{Error, Result};+use crate::routes::{AppState, RepoName};++/// Reads the repository description from `.git/description`, returning `None`+/// if the file is missing, empty, or contains the default git placeholder text.+fn repo_description(git_repo: &gix::Repository) -> Option<String> {+    std::fs::read_to_string(git_repo.path().join("description"))+        .ok()+        .map(|s| s.trim().to_string())+        .filter(|s| !s.is_empty() && !s.starts_with("Unnamed repository"))+}++/// Formats a commit's author date as a `YYYY-MM-DD` string in the commit's+/// local timezone, returning `None` if the time cannot be parsed.+fn commit_date(commit: &gix::Commit) -> Option<String> {+    let time = commit.time().ok()?;+    let zone = TimeZone::fixed(Offset::from_seconds(time.offset).ok()?);++    Timestamp::from_second(time.seconds)+        .map(|ts| ts.to_zoned(zone).date().to_string())+        .ok()+}++/// Returns `true` if `url` is a relative path that should be rewritten to+/// point at the raw file serving route.+fn is_relative_url(url: &str) -> bool {+    !url.starts_with("http://")+        && !url.starts_with("https://")+        && !url.starts_with('#')+        && !url.starts_with("mailto:")+        && !url.starts_with("data:")+}++/// Template context for a single branch.+struct BranchSummary {+    name: String,+    date: String,+    /// Whether this branch is the repository's HEAD.+    is_default: bool,+}++/// Template context for a single tag.+struct TagSummary {+    name: String,+    date: String,+}++/// Template context for the repository detail page.+#[derive(Template, WebTemplate)]+#[template(path = "repo.html")]+struct Repo {+    name: String,+    description: Option<String>,+    branches: Vec<BranchSummary>,+    tags: Vec<TagSummary>,+    commit_count: usize,+    /// README rendered to HTML, or `None` if no README was found.+    readme: Option<String>,+}++/// Renders the detail page for a single repository, including its branches,+/// tags, and description.  Returns [`Error::RepoNotFound`] if no repository+/// exists at the given name, or [`Error::GitCorrupt`] if the ref database+/// cannot be read.+pub async fn detail(+    State(state): State<AppState>,+    RepoName(name): RepoName,+) -> Result<impl IntoResponse> {+    let path = state.root.join(&name);+    let git_repo = gix::open(path).map_err(|_| Error::RepoNotFound(name.clone()))?;++    let platform = git_repo+        .references()+        .map_err(|e| Error::GitCorrupt(e.to_string()))?;++    let head_name = git_repo.head_name().ok().flatten();++    // `.tags()` returns a `Result<impl Iterator<Item = Result<Reference>>>`.+    // The first `.flatten()` unwraps the outer `Result`, the second unwraps+    // each `Result<Reference>`, silently discarding any errors.+    let tags: Vec<TagSummary> = platform+        .tags()+        .into_iter()+        .flatten()+        .flatten()+        .filter_map(|mut tag| {+            let commit = tag.peel_to_commit().ok()?;+            let date = commit_date(&commit)?;+            let name = tag.name().shorten().to_string();++            Some(TagSummary { name, date })+        })+        .collect();++    // Same double-flatten pattern as tags above.+    let branches: Vec<BranchSummary> = platform+        .local_branches()+        .into_iter()+        .flatten()+        .flatten()+        .filter_map(|mut branch| {+            let commit = branch.peel_to_commit().ok()?;+            let date = commit_date(&commit)?;+            let name = branch.name().shorten().to_string();+            let is_default = head_name+                .as_ref()+                .is_some_and(|h| h.as_ref() == branch.name());++            Some(BranchSummary {+                name,+                date,+                is_default,+            })+        })+        .collect();++    let description = repo_description(&git_repo);+    let head_id = git_repo.head_id().ok();+    let commit_count = head_id+        .as_ref()+        .and_then(|id| id.ancestors().all().ok())+        .map(|walk| walk.count())+        .unwrap_or(0);++    // Resolve HEAD to a SHA so we can build stable raw URLs for images.+    let head_sha = head_id.map(|id| id.to_string());++    // Try each candidate filename in order, stopping at the first one found.+    let readme = ["HEAD:README.md", "HEAD:README", "HEAD:readme.md"]+        .iter()+        .find_map(|&spec| {+            // Resolve the rev-spec to a blob, discarding any that don't exist+            // or aren't blobs (e.g. submodules).+            let blob = git_repo+                .rev_parse_single(spec)+                .ok()+                .and_then(|id| id.object().ok())+                .and_then(|obj| obj.try_into_blob().ok())?;++            // Silently skip non-UTF-8 content.+            let text = std::str::from_utf8(&blob.data).ok()?;++            use pulldown_cmark::{Event, Options, Parser, Tag, html};++            // Rewrite relative image URLs to the raw file serving route so+            // that images committed alongside the README render correctly.+            let mut rendered = String::new();+            let events = Parser::new_ext(text, Options::all()).map(|event| match event {+                Event::Start(Tag::Image {+                    link_type,+                    dest_url,+                    title,+                    id,+                }) => {+                    let dest_url = match &head_sha {+                        Some(sha) if is_relative_url(&dest_url) => {+                            format!("/{}/commits/{}/raw/{}", name, sha, dest_url).into()+                        }+                        _ => dest_url,+                    };+                    Event::Start(Tag::Image {+                        link_type,+                        dest_url,+                        title,+                        id,+                    })+                }+                _ => event,+            });+            html::push_html(&mut rendered, events);++            Some(rendered)+        });++    Ok(Repo {+        name,+        description,+        branches,+        tags,+        commit_count,+        readme,+    })+}++/// Template context for a single repository in the list.+struct RepoSummary {+    name: String,+    description: Option<String>,+    commit_count: usize,+    last_commit: Option<String>,+}++/// Template context for the repository list page.+#[derive(Template, WebTemplate)]+#[template(path = "repo_list.html")]+struct RepoList {+    repos: Vec<RepoSummary>,+}++/// Renders the repository list page by scanning the root directory for git+/// repositories.  Entries that cannot be opened as a git repository are+/// skipped.  The list is sorted by latest commit first.+pub async fn list(State(state): State<AppState>) -> Result<impl IntoResponse> {+    let mut repos: Vec<RepoSummary> = std::fs::read_dir(&state.root)?+        .filter_map(|entry| {+            let name = entry.ok()?.file_name().to_string_lossy().into_owned();+            let git_repo = gix::open(state.root.join(&name)).ok()?;+            let description = repo_description(&git_repo);++            let head_id = git_repo.head_id().ok();++            let commit_count = head_id+                .as_ref()+                .and_then(|id| id.ancestors().all().ok())+                .map(|walk| walk.count())+                .unwrap_or(0);++            let last_commit = head_id+                .and_then(|id| id.object().ok())+                .and_then(|obj| obj.try_into_commit().ok())+                .and_then(|commit| commit_date(&commit));++            Some(RepoSummary {+                name,+                description,+                commit_count,+                last_commit,+            })+        })+        .collect();++    repos.sort_by(|a, b| b.last_commit.cmp(&a.last_commit));++    Ok(RepoList { repos })+}
Asrc/routes/tag.rs
+use axum::response::IntoResponse;++pub async fn list() -> impl IntoResponse {+    "Tag list"+}++pub async fn detail() -> impl IntoResponse {+    "Tag detail"+}
Asrc/routes/tree.rs
+use axum::response::IntoResponse;++pub async fn handler() -> impl IntoResponse {+    "Tree handler"+}
Asrc/theme.rs
+//! Built-in color themes.++use clap::ValueEnum;++pub const BASE_CSS: &str = include_str!("../static/base.css");+pub const MARKDOWN_CSS: &str = include_str!("../static/markdown.css");++/// A built-in color theme.  `Auto` and `SolarizedAuto` follow the OS+/// light/dark preference via `prefers-color-scheme`.+#[derive(Clone, Default, ValueEnum)]+pub enum Theme {+    /// Follows the OS light/dark preference.+    #[default]+    Auto,+    Light,+    Dark,+    SolarizedAuto,+    SolarizedLight,+    SolarizedDark,+}++impl Theme {+    pub fn css(&self) -> &'static str {+        match self {+            Theme::Auto => include_str!("../static/auto.css"),+            Theme::Light => include_str!("../static/light.css"),+            Theme::Dark => include_str!("../static/dark.css"),+            Theme::SolarizedAuto => include_str!("../static/solarized_auto.css"),+            Theme::SolarizedLight => include_str!("../static/solarized_light.css"),+            Theme::SolarizedDark => include_str!("../static/solarized_dark.css"),+        }+    }+}
Astatic/auto.css
+:root {+  --background: #ffffff;+  --highlight:  #eeeeee;+  --secondary:  #aaaaaa;+  --primary:    #444444;+  --emphasized: #1a1a1a;++  --font-body:    system-ui, sans-serif;+  --font-mono:    ui-monospace, monospace;+  --font-heading: system-ui, sans-serif;++  --yellow:  #d4a017;+  --orange:  #d05a2b;+  --red:     #cc3333;+  --magenta: #bb3377;+  --violet:  #6655aa;+  --blue:    #3366cc;+  --cyan:    #1a9988;+  --green:   #558833;+}++@media (prefers-color-scheme: dark) {+  :root {+    --background: #1e1e1e;+    --highlight:  #252526;+    --secondary:  #555555;+    --primary:    #d4d4d4;+    --emphasized: #ffffff;+    --violet:     #9977cc;+    --blue:       #4fc1ff;+    --cyan:       #4ec9b0;+    --green:      #6a9955;+  }+}
Astatic/base.css
+*, *::before, *::after { box-sizing: border-box; }++footer {+  padding: 1rem;+  margin-top: 2rem;+  color: var(--secondary);+  font-size: .875rem;+  text-align: center;+}++html { overflow-x: clip; }++body {+  font-family: var(--font-body);+  max-width: 860px;+  margin: 0 auto;+  padding: 0;+  background: var(--background);+  color: var(--primary);+}++header {+  padding: .75rem 1rem;+  margin-bottom: .75rem;+}++header ul {+  list-style: none;+  margin: 0;+  padding: 0;+  display: flex;+  align-items: center;+  gap: .25rem;+  font-size: 1.2rem;+  min-width: 0;+}++header li {+  white-space: nowrap;+  overflow: hidden;+  text-overflow: ellipsis;+  min-width: 0;+}++header li:first-child { flex-shrink: 0; }+header li:last-child { flex-shrink: 1; }++header li + li::before {+  content: '/';+  margin-right: .25rem;+  color: var(--secondary);+}++header a {+  color: var(--primary);+  text-decoration: none;+}++header a:hover {+  color: var(--emphasized);+  text-decoration: underline;+  text-underline-offset: 4px;+}++main > h1, main > p {+  padding-left: 1rem;+  padding-right: 1rem;+}++main > h1 { margin-bottom: .75rem; }+main > p { margin-top: 0; }+.repo-commit-count { color: var(--secondary); }+main > article { padding: 0 1rem; }++.repo-list {+  display: flex;+  flex-direction: column;+}++.repo-card {+  display: flex;+  flex-direction: column;+  gap: .5rem;+  padding: 1rem 1.25rem;+  text-decoration: none;+  color: inherit;+}++.repo-card:hover { background: var(--highlight); }++.repo-name {+  font-size: 1.1rem;+  font-weight: 600;+  color: var(--emphasized);+}++.repo-desc {+  font-size: 1rem;+  color: var(--primary);+}++.repo-meta {+  display: flex;+  justify-content: space-between;+  font-size: .9rem;+  color: var(--secondary);+}++details {+  background: var(--highlight);+}++details:first-of-type {+  border-top: 1px solid var(--secondary);+}++summary {+  cursor: pointer;+  display: flex;+  align-items: center;+  padding: 0 1rem;+  min-height: 50px;+  font-family: var(--font-body);+  font-weight: bold;+}++summary::before {+  content: '+';+  font-family: var(--font-mono);+  margin-right: .5rem;+  color: var(--primary);+}++details[open] summary::before {+  content: '−';+}++details[open] summary {+  color: var(--emphasized);+}+++summary span {+  color: var(--secondary);+  margin-left: auto;+}++details > *:not(summary) {+  padding: 0 1rem .75rem;+  margin-bottom: 0;+}++details > ul {+  list-style: none;+  padding: 0;+  margin: 0;+}++details ul li {+  display: flex;+  align-items: center;+  gap: 1rem;+  min-height: 50px;+  padding: 0 1rem;+  color: var(--secondary);+  font-family: var(--font-mono);+  font-size: 1rem;+}++details ul li:has(a), details ul li:has(button) {+  padding: 0;+}++details ul li a,+details ul li button {+  display: flex;+  align-items: center;+  gap: 1rem;+  padding: 0 1rem;+  min-height: 50px;+  width: 100%;+  text-align: left;+  text-decoration: none;+  color: inherit;+  background: transparent;+  border: none;+  cursor: pointer;+  font-family: var(--font-mono);+  font-size: 1rem;+}++details ul li a:hover,+details ul li button:hover {+  background: var(--background);+}++/* First span grows to fill available space in both link and button rows */+details ul li a span:first-child,+details ul li button span:first-child {+  flex: 1;+  min-width: 0;+  overflow: hidden;+  text-overflow: ellipsis;+  white-space: nowrap;+  color: var(--primary);+}++/* Clone rows: animate URL text on copy, label fixed width on right */+details ul li button span:first-child { transition: opacity .1s; }+details ul li button span:nth-child(2) {+  flex-shrink: 0;+  min-width: 4rem;+  text-align: right;+  color: var(--secondary);+}++/* Branch/tag rows: remaining spans fixed on the right */+details ul li a span:not(:first-child) {+  flex-shrink: 0;+  color: var(--secondary);+}
Astatic/dark.css
+:root {+  --background: #1e1e1e;+  --highlight:  #252526;+  --secondary:  #555555;+  --primary:    #d4d4d4;+  --emphasized: #ffffff;++  --font-body:    system-ui, sans-serif;+  --font-mono:    ui-monospace, monospace;+  --font-heading: system-ui, sans-serif;++  --yellow:  #d4a017;+  --orange:  #d05a2b;+  --red:     #cc3333;+  --magenta: #bb3377;+  --violet:  #9977cc;+  --blue:    #4fc1ff;+  --cyan:    #4ec9b0;+  --green:   #6a9955;+}
Astatic/light.css
+:root {+  --background: #ffffff;+  --highlight:  #eeeeee;+  --secondary:  #aaaaaa;+  --primary:    #444444;+  --emphasized: #1a1a1a;++  --font-body:    system-ui, sans-serif;+  --font-mono:    ui-monospace, monospace;+  --font-heading: system-ui, sans-serif;++  --yellow:  #d4a017;+  --orange:  #d05a2b;+  --red:     #cc3333;+  --magenta: #bb3377;+  --violet:  #6655aa;+  --blue:    #3366cc;+  --cyan:    #1a9988;+  --green:   #558833;+}
Astatic/markdown.css
+article { line-height: 1.6; word-wrap: break-word; }++article h1, article h2, article h3,+article h4, article h5, article h6 {+  margin: 1.5rem 0 .5rem;+  font-family: var(--font-heading);+  font-weight: 600;+  color: var(--emphasized);+}++article h1 { font-size: 2em; border-bottom: 1px solid var(--highlight); padding-bottom: .3em; }+article h2 { font-size: 1.5em; border-bottom: 1px solid var(--highlight); padding-bottom: .3em; }+article h3 { font-size: 1.25em; }+article h4 { font-size: 1em; }++article p { margin: 0 0 1rem; }++article a { color: var(--blue); text-decoration: none; }+article a:hover { text-decoration: underline; text-underline-offset: .2rem; }++article strong, article b { font-weight: 600; }+article em, article i { font-style: italic; }++article ul, article ol { margin: 0 0 1rem; padding-left: 2rem; }+article li { margin: .25rem 0; }+article li > p { margin-top: .25rem; }++article blockquote {+  margin: 0 0 1rem;+  padding: 0 1em;+  color: var(--secondary);+  border-left: .25em solid var(--highlight);+}+article blockquote > :first-child { margin-top: 0; }+article blockquote > :last-child { margin-bottom: 0; }++article hr {+  height: .25em;+  margin: 1.5rem 0;+  padding: 0;+  border: 0;+  background-color: var(--highlight);+}++article img { max-width: 100%; box-sizing: content-box; }++article code {+  font-family: var(--font-mono);+  font-size: .875em;+  padding: .2em .4em;+  background-color: var(--highlight);+  border-radius: 4px;+  white-space: break-spaces;+}++article pre {+  font-family: var(--font-mono);+  font-size: .875em;+  line-height: 1.45;+  padding: 1rem;+  margin: 0 0 1rem;+  overflow-x: auto;+  min-width: 0;+  background-color: var(--highlight);+  border-radius: 6px;+}++article pre code {+  font-size: 100%;+  padding: 0;+  background: transparent;+  border-radius: 0;+  white-space: pre;+}++article table {+  border-spacing: 0;+  border-collapse: collapse;+  display: block;+  width: max-content;+  max-width: 100%;+  overflow-x: auto;+  margin: 0 0 1rem;+}++article table th {+  font-weight: 600;+}++article table th,+article table td {+  padding: 6px 13px;+  border: 1px solid var(--highlight);+}++article table tr { border-top: 1px solid var(--highlight); }+article table tr:nth-child(2n) { background-color: var(--highlight); }
Astatic/solarized_auto.css
+:root {+  --background: #fdf6e3;+  --highlight:  #eee8d5;+  --secondary:  #93a1a1;+  --primary:    #657b83;+  --emphasized: #586e75;++  --font-body:    system-ui, sans-serif;+  --font-mono:    ui-monospace, monospace;+  --font-heading: system-ui, sans-serif;++  --yellow:  #b58900;+  --orange:  #cb4b16;+  --red:     #dc322f;+  --magenta: #d33682;+  --violet:  #6c71c4;+  --blue:    #268bd2;+  --cyan:    #2aa198;+  --green:   #859900;+}++@media (prefers-color-scheme: dark) {+  :root {+    --background: #002b36;+    --highlight:  #073642;+    --secondary:  #586e75;+    --primary:    #839496;+    --emphasized: #93a1a1;+  }+}
Astatic/solarized_dark.css
+:root {+  --background: #002b36;+  --highlight:  #073642;+  --secondary:  #586e75;+  --primary:    #839496;+  --emphasized: #93a1a1;++  --font-body:    system-ui, sans-serif;+  --font-mono:    ui-monospace, monospace;+  --font-heading: system-ui, sans-serif;++  --yellow:  #b58900;+  --orange:  #cb4b16;+  --red:     #dc322f;+  --magenta: #d33682;+  --violet:  #6c71c4;+  --blue:    #268bd2;+  --cyan:    #2aa198;+  --green:   #859900;+}
Astatic/solarized_light.css
+:root {+  --background: #fdf6e3;+  --highlight:  #eee8d5;+  --secondary:  #93a1a1;+  --primary:    #657b83;+  --emphasized: #586e75;++  --font-body:    system-ui, sans-serif;+  --font-mono:    ui-monospace, monospace;+  --font-heading: system-ui, sans-serif;++  --yellow:  #b58900;+  --orange:  #cb4b16;+  --red:     #dc322f;+  --magenta: #d33682;+  --violet:  #6c71c4;+  --blue:    #268bd2;+  --cyan:    #2aa198;+  --green:   #859900;+}
Atemplates/base.html
+<!DOCTYPE html>+<html lang="en">+<head>+    <meta charset="UTF-8">+    <meta name="viewport" content="width=device-width, initial-scale=1.0">+    <title>{% block title %}{% endblock %}</title>+    <link rel="stylesheet" href="/style.css">+</head>+<body>+    <header>+        {% block breadcrumbs %}{% endblock %}+    </header>+    <main>+        {% block content %}{% endblock %}+    </main>+{% block scripts %}{% endblock %}+<footer>served with <a href="#">{{ crate::PKG_NAME }}</a> v{{ crate::PKG_VERSION }}</footer>+</body>+</html>
Atemplates/commit.html
+
Atemplates/commit_list.html
+
Atemplates/repo.html
+{% extends "base.html" %}++{% block title %}+{{ name }}+{% endblock %}++{% block breadcrumbs %}+<ul>+  <li><a href="/">{{ crate::hostname() }}</a></li>+  <li><a href="/{{ name }}">{{ name }}</a></li>+</ul>+{% endblock %}++{% block content %}+<h1>{{ name }}</h1>++{% if let Some(description) = description %}+<p>{{ description }}</p>+{% endif %}+<p class="repo-commit-count">{{ commit_count }} {% if commit_count == 1 %}commit{% else %}commits{% endif %}</p>++<details>+  <summary>Clone</summary>+  <ul>+    <li><button data-url="git@{{ crate::hostname() }}:{{ crate::ssh_prefix() }}{{ name }}.git"><span>git@{{ crate::hostname() }}:{{ crate::ssh_prefix() }}{{ name }}.git</span><span>SSH</span></button></li>+    <li><button data-url="https://{{ crate::hostname() }}/{{ name }}.git"><span>https://{{ crate::hostname() }}/{{ name }}.git</span><span>HTTPS</span></button></li>+  </ul>+</details>++<details>+  <summary>Branches <span>{{ branches.len() }}</span></summary>+  <ul>+    {% for branch in branches.iter().take(5) %}+    <li><a href="/{{ name }}/branches/{{ branch.name }}"><span>{{ branch.name }}</span>{% if branch.is_default %}<span>default</span>{% endif %}<span>{{ branch.date }}</span></a></li>+    {% endfor %}+    {% if branches.len() > 5 %}+    <li><a href="/{{ name }}/branches">see all {{ branches.len() }} branches</a></li>+    {% endif %}+    {% if branches.is_empty() %}+    <li>no branches</li>+    {% endif %}+  </ul>+</details>++<details>+  <summary>Tags <span>{{ tags.len() }}</span></summary>+  <ul>+    {% for tag in tags.iter().take(5) %}+    <li><a href="/{{ name }}/tags/{{ tag.name }}"><span>{{ tag.name }}</span><span>{{ tag.date }}</span></a></li>+    {% endfor %}+    {% if tags.len() > 5 %}+    <li><a href="/{{ name }}/tags">see all {{ tags.len() }} tags</a></li>+    {% endif %}+    {% if tags.is_empty() %}+    <li>no tags</li>+    {% endif %}+  </ul>+</details>++{% if let Some(readme) = readme %}+<article>+  {{ readme | safe }}+</article>+{% endif %}+{% endblock %}++{% block scripts %}+<script>+  document.querySelectorAll('[data-url]').forEach(btn => {+    const span = btn.querySelector('span:first-child');+    const url = btn.dataset.url;+    btn.addEventListener('click', () => {+      navigator.clipboard.writeText(url);+      span.style.opacity = '0';+      setTimeout(() => { span.textContent = 'copied!'; span.style.opacity = '1'; }, 100);+      setTimeout(() => {+        span.style.opacity = '0';+        setTimeout(() => { span.textContent = url; span.style.opacity = '1'; }, 100);+      }, 1100);+    });+  });+</script>+{% endblock %}
Atemplates/repo_list.html
+{% extends "base.html" %}++{% block title %}repos{% endblock %}++{% block breadcrumbs %}+<ul>+  <li><a href="/">{{ crate::hostname() }}</a></li>+</ul>+{% endblock %}++{% block content %}+{% if repos.is_empty() %}+<p>No repositories found.</p>+{% else %}+<div class="repo-list">+  {% for repo in repos %}+  <a href="/{{ repo.name }}" class="repo-card">+    <span class="repo-name">{{ repo.name }}</span>+    {% if let Some(desc) = &repo.description %}+    <span class="repo-desc">{{ desc }}</span>+    {% endif %}+    <span class="repo-meta"><span>{{ repo.commit_count }} {% if repo.commit_count == 1 %}commit{% else %}commits{% endif %}</span>{% if let Some(date) = &repo.last_commit %}<span>{{ date }}</span>{% endif %}</span>+  </a>+  {% endfor %}+</div>+{% endif %}+{% endblock %}