From c856af78b169e9609eba4475d043a025cd59efd2 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Wed, 06 Jul 2022 01:56:48 +0100 Subject: [PATCH] Commit & metadata caching --- Cargo.lock | 535 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 4 +++- src/git.rs | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/main.rs | 11 +++++------ templates/index.html | 2 +- src/methods/index.rs | 10 ++++++---- src/methods/repo.rs | 13 +++++++------ 7 files changed, 671 insertions(+), 92 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8565f39..4b7d73e 100644 --- a/Cargo.lock +++ a/Cargo.lock @@ -12,6 +12,12 @@ ] [[package]] +name = "arc-swap" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f" + +[[package]] name = "askama" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -57,6 +63,34 @@ "serde", "syn", "toml", +] + +[[package]] +name = "async-io" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", ] [[package]] @@ -137,12 +171,61 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] +name = "bytecount" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" + +[[package]] name = "bytes" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + +[[package]] +name = "camino" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] [[package]] name = "cc" @@ -152,6 +235,12 @@ dependencies = [ "jobserver", ] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" @@ -182,6 +271,85 @@ checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.10", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", +] + +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "version_check", +] + +[[package]] +name = "event-listener" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" + +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", ] [[package]] @@ -247,6 +415,21 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] [[package]] name = "futures-macro" @@ -295,9 +478,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -314,6 +497,12 @@ "openssl-sys", "url", ] + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "hashbrown" @@ -329,6 +518,12 @@ dependencies = [ "libc", ] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" @@ -427,6 +622,15 @@ ] [[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] name = "itoa" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -439,6 +643,15 @@ checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" dependencies = [ "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +dependencies = [ + "wasm-bindgen", ] [[package]] @@ -508,8 +721,17 @@ version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "mach" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" dependencies = [ - "cfg-if", + "libc", ] [[package]] @@ -523,12 +745,27 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" + +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg", +] [[package]] name = "mime" @@ -560,8 +797,33 @@ dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", +] + +[[package]] +name = "moka" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b3caf8ff6db712c7f7fe018e7fb6d2ddbaf428b74f94a48fe075ef09a6b8a1" +dependencies = [ + "async-io", + "async-lock", + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils 0.8.10", + "futures-util", + "num_cpus", + "once_cell", + "parking_lot", + "quanta", + "scheduled-thread-pool", + "skeptic", + "smallvec", + "tagptr", + "thiserror", + "triomphe", + "uuid", ] [[package]] @@ -634,13 +896,10 @@ checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" [[package]] -name = "owning_ref" -version = "0.4.1" +name = "parking" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce" -dependencies = [ - "stable_deref_trait", -] +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" @@ -658,7 +917,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -714,6 +973,19 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "log", + "wepoll-ffi", + "winapi", +] [[package]] name = "proc-macro2" @@ -722,6 +994,33 @@ checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ "unicode-ident", +] + +[[package]] +name = "pulldown-cmark" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "quanta" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafd74c340a0a7e79415981ede3460df16b530fd071541901a57416eea950b17" +dependencies = [ + "crossbeam-utils 0.8.10", + "libc", + "mach", + "once_cell", + "raw-cpuid", + "wasi 0.10.2+wasi-snapshot-preview1", + "web-sys", + "winapi", ] [[package]] @@ -731,6 +1030,15 @@ checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ "proc-macro2", +] + +[[package]] +name = "raw-cpuid" +version = "10.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738bc47119e3eeccc7e94c4a506901aea5e7b4944ecd0829cbebf4af04ceda12" +dependencies = [ + "bitflags", ] [[package]] @@ -740,19 +1048,30 @@ checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", ] [[package]] name = "rgit" version = "0.1.0" dependencies = [ + "arc-swap", "askama", "axum", "clap", "futures", "git2", + "hex", "humantime", - "owning_ref", + "moka", "path-clean", "serde", "time", @@ -772,10 +1091,37 @@ checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" [[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 = "scheduled-thread-pool" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf" +dependencies = [ + "parking_lot", +] + +[[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +dependencies = [ + "serde", +] [[package]] name = "serde" @@ -839,6 +1185,21 @@ ] [[package]] +name = "skeptic" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" +dependencies = [ + "bytecount", + "cargo_metadata", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", +] + +[[package]] name = "slab" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -859,12 +1220,6 @@ "libc", "winapi", ] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" @@ -888,6 +1243,26 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] [[package]] name = "termcolor" @@ -903,6 +1278,26 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + +[[package]] +name = "thiserror" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "thread_local" @@ -1031,7 +1426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -1085,6 +1480,12 @@ ] [[package]] +name = "triomphe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eda0abf5a9b5ad4a5ac1393956ae03fb57033749d3983e2cac9afbfd5ae04ec2" + +[[package]] name = "try-lock" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1158,6 +1559,23 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] [[package]] name = "want" @@ -1168,12 +1586,91 @@ "log", "try-lock", ] + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" + +[[package]] +name = "web-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] [[package]] name = "winapi" diff --git a/Cargo.toml b/Cargo.toml index 5a09a41..9db11b0 100644 --- a/Cargo.toml +++ a/Cargo.toml @@ -7,13 +7,15 @@ [dependencies] askama = "0.11" +arc-swap = "1.5" axum = "0.5" clap = { version = "3.2", features = ["cargo"] } futures = "0.3" git2 = "0.14" +hex = "0.4" humantime = "2.1" +moka = { version = "0.9", features = ["future"] } path-clean = "0.1" -owning_ref = "0.4" serde = { version = "1.0", features = ["derive"] } time = "0.3" tokio = { version = "1.19", features = ["full"] } diff --git a/src/git.rs b/src/git.rs index 2d7eeb9..cfb66f8 100644 --- a/src/git.rs +++ a/src/git.rs @@ -1,98 +1,176 @@ -use std::{borrow::Cow, collections::BTreeMap, fmt::Display, path::Path, time::Duration}; - +use std::{ + borrow::Cow, + collections::BTreeMap, + path::{Path, PathBuf}, + sync::Arc, + time::Duration, +}; + +use arc_swap::ArcSwapOption; use git2::{Oid, Repository, Signature}; -use owning_ref::OwningHandle; use time::OffsetDateTime; pub type RepositoryMetadataList = BTreeMap, Vec>; + +#[derive(Clone)] +pub struct Git { + commits: moka::future::Cache>, + repository_metadata: Arc>, +} + +impl Default for Git { + fn default() -> Self { + Self { + commits: moka::future::Cache::new(100), + repository_metadata: Arc::new(ArcSwapOption::default()), + } + } +} + +impl Git { + pub async fn get_commit<'a>(&'a self, repo: PathBuf, commit: &str) -> Arc { + let commit = Oid::from_str(commit).unwrap(); + + self.commits + .get_with(commit.to_string(), async { + tokio::task::spawn_blocking(move || { + let repo = Repository::open_bare(repo).unwrap(); + let commit = repo.find_commit(commit).unwrap(); + + Arc::new(Commit::from(commit)) + }) + .await + .unwrap() + }) + .await + } + + pub async fn get_latest_commit<'a>(&'a self, repo: PathBuf) -> Commit { + tokio::task::spawn_blocking(move || { + let repo = Repository::open_bare(repo).unwrap(); + let head = repo.head().unwrap(); + let commit = head.peel_to_commit().unwrap(); + + Commit::from(commit) + }) + .await + .unwrap() + } + + pub async fn fetch_repository_metadata(&self) -> Arc { + if let Some(metadata) = self.repository_metadata.load().as_ref() { + return Arc::clone(&metadata); + } + + let start = Path::new("../test-git").canonicalize().unwrap(); + + let repos = tokio::task::spawn_blocking(move || { + let mut repos: RepositoryMetadataList = RepositoryMetadataList::new(); + fetch_repository_metadata_impl(&start, &start, &mut repos); + repos + }) + .await + .unwrap(); + let repos = Arc::new(repos); + self.repository_metadata.store(Some(repos.clone())); + + repos + } +} + #[derive(Debug)] pub struct RepositoryMetadata { pub name: String, pub description: Option>, pub owner: Option, pub last_modified: Duration, +} + +pub struct CommitUser { + name: String, + email: String, + time: String, } -pub struct CommitUser<'a>(Signature<'a>); +impl From> for CommitUser { + fn from(v: Signature<'_>) -> Self { + CommitUser { + name: v.name().unwrap().to_string(), + email: v.email().unwrap().to_string(), + time: OffsetDateTime::from_unix_timestamp(v.when().seconds()) + .unwrap() + .to_string(), + } + } +} -impl CommitUser<'_> { +impl CommitUser { pub fn name(&self) -> &str { - self.0.name().unwrap() + &self.name } pub fn email(&self) -> &str { - self.0.email().unwrap() + &self.email } - pub fn time(&self) -> String { - OffsetDateTime::from_unix_timestamp(self.0.when().seconds()) - .unwrap() - .to_string() + pub fn time(&self) -> &str { + &self.time } +} + +pub struct Commit { + author: CommitUser, + committer: CommitUser, + oid: String, + tree: String, + parents: Vec, + summary: String, + body: String, } -pub struct Commit(OwningHandle, Box>>); +impl From> for Commit { + fn from(commit: git2::Commit<'_>) -> Self { + Commit { + author: commit.author().into(), + committer: commit.committer().into(), + oid: commit.id().to_string(), + tree: commit.tree_id().to_string(), + parents: commit.parent_ids().map(|v| v.to_string()).collect(), + summary: commit.summary().unwrap().to_string(), + body: commit.body().map(ToString::to_string).unwrap_or_default(), + } + } +} impl Commit { - pub fn author(&self) -> CommitUser<'_> { - CommitUser(self.0.author()) + pub fn author(&self) -> &CommitUser { + &self.author } - pub fn committer(&self) -> CommitUser<'_> { - CommitUser(self.0.committer()) + pub fn committer(&self) -> &CommitUser { + &self.committer } - pub fn oid(&self) -> impl Display { - self.0.id() + pub fn oid(&self) -> &str { + &self.oid } - pub fn tree(&self) -> impl Display { - self.0.tree_id() + pub fn tree(&self) -> &str { + &self.tree } - pub fn parents(&self) -> impl Iterator { - self.0.parent_ids() + pub fn parents(&self) -> impl Iterator { + self.parents.iter().map(String::as_str) } pub fn summary(&self) -> &str { - self.0.summary().unwrap() + &self.summary } pub fn body(&self) -> &str { - self.0.message().unwrap() + &self.body } -} - -pub fn get_commit(path: &Path, commit: &str) -> Commit { - let repo = Repository::open_bare(path).unwrap(); - - let commit = OwningHandle::new_with_fn(Box::new(repo), |v| { - Box::new(unsafe { (*v).find_commit(Oid::from_str(commit).unwrap()).unwrap() }) - }); - - // TODO: we can cache this - Commit(commit) -} - -pub fn get_latest_commit(path: &Path) -> Commit { - let repo = Repository::open_bare(path).unwrap(); - - let commit = OwningHandle::new_with_fn(Box::new(repo), |v| { - let head = unsafe { (*v).head().unwrap() }; - Box::new(head.peel_to_commit().unwrap()) - }); - - // TODO: we can cache this - Commit(commit) -} - -pub fn fetch_repository_metadata() -> RepositoryMetadataList { - let start = Path::new("../test-git").canonicalize().unwrap(); - - let mut repos: RepositoryMetadataList = RepositoryMetadataList::new(); - fetch_repository_metadata_impl(&start, &start, &mut repos); - repos } fn fetch_repository_metadata_impl( diff --git a/src/main.rs b/src/main.rs index fd2a40e..5fc349e 100644 --- a/src/main.rs +++ a/src/main.rs @@ -1,14 +1,12 @@ #![deny(clippy::pedantic)] use axum::{ - body::Body, handler::Handler, http::HeaderValue, response::Response, routing::get, Router, + body::Body, handler::Handler, http::HeaderValue, response::Response, routing::get, Extension, + Router, }; use tower_layer::layer_fn; -use crate::{ - git::{fetch_repository_metadata, get_latest_commit}, - layers::logger::LoggingMiddleware, -}; +use crate::{git::Git, layers::logger::LoggingMiddleware}; mod git; mod layers; @@ -30,7 +28,8 @@ get(static_css(include_bytes!("../statics/style.css"))), ) .fallback(methods::repo::service.into_service()) - .layer(layer_fn(LoggingMiddleware)); + .layer(layer_fn(LoggingMiddleware)) + .layer(Extension(Git::default())); axum::Server::bind(&"127.0.0.1:3333".parse().unwrap()) .serve(app.into_make_service_with_connect_info::()) diff --git a/templates/index.html b/templates/index.html index b0fb288..6fdaf58 100644 --- a/templates/index.html +++ a/templates/index.html @@ -14,7 +14,7 @@ - {% for (path, repositories) in repositories %} + {% for (path, repositories) in repositories.iter() %} {% if let Some(path) = path %} {{ path }} {% endif %} diff --git a/src/methods/index.rs b/src/methods/index.rs index 9ca2503..6575bdc 100644 --- a/src/methods/index.rs +++ a/src/methods/index.rs @@ -1,19 +1,21 @@ use askama::Template; use axum::response::Html; +use axum::Extension; +use std::sync::Arc; -use crate::{fetch_repository_metadata, git::RepositoryMetadataList}; +use crate::{git::RepositoryMetadataList, Git}; #[allow(clippy::unused_async)] -pub async fn handle() -> Html { +pub async fn handle(Extension(git): Extension) -> Html { #[derive(Template)] #[template(path = "index.html")] pub struct View { - pub repositories: RepositoryMetadataList, + pub repositories: Arc, } Html( View { - repositories: fetch_repository_metadata(), + repositories: git.fetch_repository_metadata().await, } .render() .unwrap(), diff --git a/src/methods/repo.rs b/src/methods/repo.rs index a494568..915ea2f 100644 --- a/src/methods/repo.rs +++ a/src/methods/repo.rs @@ -1,11 +1,12 @@ use std::{ ops::Deref, path::{Path, PathBuf}, + sync::Arc, }; use askama::Template; -use axum::extract::Query; use axum::{ + extract::Query, handler::Handler, http::Request, response::{Html, IntoResponse, Response}, @@ -15,8 +16,7 @@ use serde::Deserialize; use tower::{util::BoxCloneService, Service}; -use crate::git::get_commit; -use crate::{get_latest_commit, git::Commit, layers::UnwrapInfallible}; +use crate::{git::Commit, layers::UnwrapInfallible, Git}; #[derive(Clone)] pub struct Repository(pub PathBuf); @@ -130,22 +130,23 @@ pub async fn handle_commit( Extension(repo): Extension, Extension(RepositoryPath(repository_path)): Extension, + Extension(git): Extension, Query(query): Query, ) -> Html { #[derive(Template)] #[template(path = "repo/commit.html")] pub struct View { pub repo: Repository, - pub commit: Commit, + pub commit: Arc, } Html( View { repo, commit: if let Some(commit) = query.id { - get_commit(&repository_path, &commit) + git.get_commit(repository_path, &commit).await } else { - get_latest_commit(&repository_path) + Arc::new(git.get_latest_commit(repository_path).await) }, } .render() -- rgit 0.1.3