mirror of
https://github.com/deps-rs/deps.rs.git
synced 2024-11-22 10:26:30 +00:00
Merge pull request #53 from deps-rs/fut03
This commit is contained in:
commit
0fa8e46425
21 changed files with 1026 additions and 1066 deletions
718
Cargo.lock
generated
718
Cargo.lock
generated
|
@ -12,6 +12,12 @@ version = "1.0.32"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b602bfe940d21c130f3895acd65221e8a61270debe89d628b9cb4e3ccb8569b"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
|
@ -74,22 +80,17 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
|||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.4.12"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"either",
|
||||
"iovec",
|
||||
]
|
||||
checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
|
||||
|
||||
[[package]]
|
||||
name = "cadence"
|
||||
version = "0.13.2"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99612ce0a00efdaf3d81a5e8e17f0eed55a10e862033183c847a0365983af88c"
|
||||
checksum = "e45b9cdf75cdddb0877f8af74c345d06b0c8a924c5115d2467d94d7e4bdf9180"
|
||||
dependencies = [
|
||||
"crossbeam",
|
||||
"crossbeam-channel",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -121,9 +122,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.18"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d021fddb7bd3e734370acfa4a83f34095571d8570c039f1420d77540f68d5772"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
|
@ -133,15 +134,6 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.7.0"
|
||||
|
@ -175,44 +167,11 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.2.12"
|
||||
name = "crossbeam-channel"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
|
||||
checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"maybe-uninit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"maybe-uninit",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"maybe-uninit",
|
||||
]
|
||||
|
@ -239,9 +198,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.10"
|
||||
version = "0.99.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba"
|
||||
checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -257,12 +216,6 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
|
@ -308,18 +261,97 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
|||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.1.29"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
|
||||
checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-cpupool"
|
||||
version = "0.1.8"
|
||||
name = "futures-channel"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
|
||||
checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"num_cpus",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project",
|
||||
"pin-utils",
|
||||
"proc-macro-hack",
|
||||
"proc-macro-nested",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -365,20 +397,21 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
|||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.1.26"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
|
||||
checksum = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"http",
|
||||
"indexmap",
|
||||
"log",
|
||||
"slab",
|
||||
"string",
|
||||
"tokio-io",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -416,9 +449,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.1.21"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0"
|
||||
checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"fnv",
|
||||
|
@ -427,14 +460,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "http-body"
|
||||
version = "0.1.0"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
|
||||
checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"http",
|
||||
"tokio-buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -444,46 +475,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.12.35"
|
||||
name = "httpdate"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6"
|
||||
checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.13.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"futures-cpupool",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2",
|
||||
"http",
|
||||
"http-body",
|
||||
"httparse",
|
||||
"iovec",
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"log",
|
||||
"net2",
|
||||
"rustc_version",
|
||||
"time",
|
||||
"pin-project",
|
||||
"socket2",
|
||||
"tokio",
|
||||
"tokio-buf",
|
||||
"tokio-executor",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
"tokio-tcp",
|
||||
"tokio-threadpool",
|
||||
"tokio-timer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.3.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f"
|
||||
checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio-io",
|
||||
"tokio",
|
||||
"tokio-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -600,15 +631,6 @@ version = "0.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.11"
|
||||
|
@ -673,13 +695,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.5.6"
|
||||
name = "memchr"
|
||||
version = "2.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
|
@ -694,12 +713,24 @@ dependencies = [
|
|||
"kernel32-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"miow 0.2.1",
|
||||
"net2",
|
||||
"slab",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-named-pipes"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
|
||||
dependencies = [
|
||||
"log",
|
||||
"mio",
|
||||
"miow 0.3.5",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-uds"
|
||||
version = "0.6.8"
|
||||
|
@ -723,6 +754,16 @@ dependencies = [
|
|||
"ws2_32-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.4"
|
||||
|
@ -835,32 +876,6 @@ dependencies = [
|
|||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cloudabi",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"rustc_version",
|
||||
"smallvec",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
|
@ -910,6 +925,38 @@ dependencies = [
|
|||
"sha-1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f48fad7cfbff853437be7cf54d7b993af21f53be7f0988cbfe4a51535aa77205"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24c6d293bdd3ca5a1697997854c6cf7855e43fb6a0ba1c47af57a5bcafd158ae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fe74897791e156a0cd8cce0db31b9b2198e67877316bf3086c3acd187f719f0"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.18"
|
||||
|
@ -931,6 +978,18 @@ version = "0.2.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-nested"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.23"
|
||||
|
@ -998,9 +1057,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
|||
|
||||
[[package]]
|
||||
name = "relative-path"
|
||||
version = "0.3.7"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e614f96449605730b4f7ad2c019e88c1652d730634b4eba07b810801856635e3"
|
||||
checksum = "65aff7c83039e88c1c0b4bedf8dfa93d6ec84d5fc2945b37c1fa4186f46c5f94"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
@ -1016,18 +1075,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "route-recognizer"
|
||||
version = "0.1.13"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea509065eb0b3c446acdd0102f0d46567dc30902dc0be91d6552035d92b0f4f8"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver 0.9.0",
|
||||
]
|
||||
checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e"
|
||||
|
||||
[[package]]
|
||||
name = "rustsec"
|
||||
|
@ -1097,18 +1147,6 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "0.4.4"
|
||||
|
@ -1196,9 +1234,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.57"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
|
||||
checksum = "a230ea9107ca2220eea9d46de97eddcb04cd00e92d13dda78e478dd33fa82bd4"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1232,6 +1270,7 @@ dependencies = [
|
|||
"lru-cache",
|
||||
"maud",
|
||||
"once_cell",
|
||||
"pin-project",
|
||||
"relative-path",
|
||||
"route-recognizer",
|
||||
"rustsec",
|
||||
|
@ -1241,10 +1280,18 @@ dependencies = [
|
|||
"serde_json",
|
||||
"slog",
|
||||
"slog-json",
|
||||
"tokio-core",
|
||||
"tokio-service",
|
||||
"tokio",
|
||||
"toml",
|
||||
"try_future",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1271,15 +1318,6 @@ dependencies = [
|
|||
"slog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
||||
dependencies = [
|
||||
"maybe-uninit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smol_str"
|
||||
version = "0.1.17"
|
||||
|
@ -1290,12 +1328,15 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "string"
|
||||
version = "0.2.1"
|
||||
name = "socket2"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
|
||||
checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1362,223 +1403,61 @@ checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "0.1.22"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
|
||||
checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"tokio-codec",
|
||||
"tokio-current-thread",
|
||||
"tokio-executor",
|
||||
"tokio-fs",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
"tokio-sync",
|
||||
"tokio-tcp",
|
||||
"tokio-threadpool",
|
||||
"tokio-timer",
|
||||
"tokio-udp",
|
||||
"tokio-uds",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-buf"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"either",
|
||||
"futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-codec"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"tokio-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-core"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"iovec",
|
||||
"log",
|
||||
"mio",
|
||||
"scoped-tls",
|
||||
"tokio",
|
||||
"tokio-executor",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
"tokio-timer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-current-thread"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"tokio-executor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-executor"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-fs"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"tokio-io",
|
||||
"tokio-threadpool",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-io"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-reactor"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"futures",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"parking_lot",
|
||||
"slab",
|
||||
"tokio-executor",
|
||||
"tokio-io",
|
||||
"tokio-sync",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-service"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162"
|
||||
dependencies = [
|
||||
"futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-sync"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tcp"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"futures-core",
|
||||
"iovec",
|
||||
"mio",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-threadpool"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils",
|
||||
"futures",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"num_cpus",
|
||||
"slab",
|
||||
"tokio-executor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-timer"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"futures",
|
||||
"slab",
|
||||
"tokio-executor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-udp"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"log",
|
||||
"mio",
|
||||
"tokio-codec",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-uds"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures",
|
||||
"iovec",
|
||||
"libc",
|
||||
"log",
|
||||
"memchr",
|
||||
"mio",
|
||||
"mio-named-pipes",
|
||||
"mio-uds",
|
||||
"tokio-codec",
|
||||
"tokio-io",
|
||||
"tokio-reactor",
|
||||
"num_cpus",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"tokio-macros",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tls"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a70f4fcd7b3b24fb194f837560168208f669ca8cb70d0c4b862944452396343"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1590,21 +1469,39 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0987850db3733619253fe60e17cb59b82d37c7e6c0236bb81e4d6b87c879f27"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "try-lock"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
|
||||
[[package]]
|
||||
name = "try_future"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30454186ee38f29e06f386c6e9f773b7c33e85430db6f90e4597419b4c5baad7"
|
||||
dependencies = [
|
||||
"futures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.6.2"
|
||||
|
@ -1666,11 +1563,10 @@ checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
|
|||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
|
||||
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"log",
|
||||
"try-lock",
|
||||
]
|
||||
|
|
20
Cargo.toml
20
Cargo.toml
|
@ -14,28 +14,26 @@ members = [
|
|||
badge = { path = "./libs/badge" }
|
||||
|
||||
anyhow = "1"
|
||||
cadence = "0.13"
|
||||
cadence = "0.21"
|
||||
derive_more = "0.99"
|
||||
futures = "0.1"
|
||||
hyper = "0.12"
|
||||
hyper-tls = "0.3"
|
||||
futures = "0.3"
|
||||
hyper = "0.13"
|
||||
hyper-tls = "0.4"
|
||||
indexmap = { version = "1", features = ["serde-1"] }
|
||||
lru-cache = "0.1"
|
||||
lru-cache = "0.1" # TODO: replace unmaintained crate
|
||||
maud = "0.22"
|
||||
once_cell = "1.4"
|
||||
relative-path = { version = "0.3.7", features = ["serde"] }
|
||||
route-recognizer = "0.1"
|
||||
pin-project = "0.4"
|
||||
relative-path = { version = "1.3", features = ["serde"] }
|
||||
route-recognizer = "0.2"
|
||||
rustsec = "0.21"
|
||||
semver = { version = "0.11", features = ["serde"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
slog = "2"
|
||||
slog-json = "2"
|
||||
tokio-core = "0.1"
|
||||
tokio-service = "0.1"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
toml = "0.5"
|
||||
try_future = "0.1"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
sass-rs = "0.2"
|
||||
|
|
2
rust-toolchain
Normal file
2
rust-toolchain
Normal file
|
@ -0,0 +1,2 @@
|
|||
nightly-2020-09-27
|
||||
|
|
@ -1,66 +1,55 @@
|
|||
use anyhow::{anyhow, ensure, Error};
|
||||
use futures::stream::futures_unordered;
|
||||
use futures::{Future, Poll, Stream};
|
||||
use anyhow::Error;
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::models::crates::{AnalyzedDependencies, CrateDeps};
|
||||
use crate::{engine::machines::analyzer::DependencyAnalyzer, Engine};
|
||||
|
||||
use super::super::machines::analyzer::DependencyAnalyzer;
|
||||
use super::super::Engine;
|
||||
pub async fn analyze_dependencies(
|
||||
engine: Engine,
|
||||
deps: CrateDeps,
|
||||
) -> Result<AnalyzedDependencies, Error> {
|
||||
let advisory_db = engine.fetch_advisory_db().await?;
|
||||
|
||||
pub struct AnalyzeDependenciesFuture {
|
||||
inner: Box<dyn Future<Item = AnalyzedDependencies, Error = Error> + Send>,
|
||||
}
|
||||
let mut analyzer = DependencyAnalyzer::new(&deps, Some(advisory_db));
|
||||
|
||||
impl AnalyzeDependenciesFuture {
|
||||
pub fn new(engine: Engine, deps: CrateDeps) -> Self {
|
||||
let future =
|
||||
engine.fetch_advisory_db().and_then(move |advisory_db| {
|
||||
let analyzer = DependencyAnalyzer::new(&deps, Some(advisory_db));
|
||||
let main_deps =
|
||||
deps.main.into_iter().filter_map(
|
||||
|(name, dep)| {
|
||||
if dep.is_external() {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
);
|
||||
let dev_deps =
|
||||
deps.dev.into_iter().filter_map(
|
||||
|(name, dep)| {
|
||||
if dep.is_external() {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
);
|
||||
let build_deps =
|
||||
deps.build.into_iter().filter_map(
|
||||
|(name, dep)| {
|
||||
if dep.is_external() {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
let main_deps = deps.main.into_iter().filter_map(|(name, dep)| {
|
||||
if dep.is_external() {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let dev_deps = deps.dev.into_iter().filter_map(|(name, dep)| {
|
||||
if dep.is_external() {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let build_deps = deps.build.into_iter().filter_map(|(name, dep)| {
|
||||
if dep.is_external() {
|
||||
Some(name)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
let deps_iter = main_deps.chain(dev_deps).chain(build_deps);
|
||||
let mut releases = engine.fetch_releases(deps_iter);
|
||||
|
||||
let release_futures =
|
||||
engine.fetch_releases(main_deps.chain(dev_deps).chain(build_deps));
|
||||
|
||||
futures_unordered(release_futures)
|
||||
.fold(analyzer, |mut analyzer, releases| {
|
||||
analyzer.process(releases);
|
||||
Ok(analyzer) as Result<_, Error>
|
||||
})
|
||||
.map(|analyzer| analyzer.finalize())
|
||||
});
|
||||
|
||||
AnalyzeDependenciesFuture {
|
||||
inner: Box::new(future),
|
||||
}
|
||||
for release in releases.next().await {
|
||||
let release = release?;
|
||||
analyzer.process(release)
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for AnalyzeDependenciesFuture {
|
||||
type Item = AnalyzedDependencies;
|
||||
type Error = Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.inner.poll()
|
||||
}
|
||||
Ok(analyzer.finalize())
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::mem;
|
||||
use std::{future::Future, mem, pin::Pin, task::Context, task::Poll};
|
||||
|
||||
use anyhow::{anyhow, ensure, Error};
|
||||
use futures::stream::FuturesOrdered;
|
||||
use futures::{try_ready, Async, Future, Poll, Stream};
|
||||
use anyhow::Error;
|
||||
use futures::{ready, Stream};
|
||||
use futures::{stream::FuturesOrdered, FutureExt};
|
||||
use relative_path::RelativePathBuf;
|
||||
|
||||
use crate::models::repo::RepoPath;
|
||||
|
@ -11,24 +11,28 @@ use super::super::machines::crawler::ManifestCrawler;
|
|||
pub use super::super::machines::crawler::ManifestCrawlerOutput;
|
||||
use super::super::Engine;
|
||||
|
||||
#[pin_project::pin_project]
|
||||
pub struct CrawlManifestFuture {
|
||||
repo_path: RepoPath,
|
||||
engine: Engine,
|
||||
crawler: ManifestCrawler,
|
||||
futures:
|
||||
FuturesOrdered<Box<dyn Future<Item = (RelativePathBuf, String), Error = Error> + Send>>,
|
||||
#[pin]
|
||||
futures: FuturesOrdered<
|
||||
Pin<Box<dyn Future<Output = Result<(RelativePathBuf, String), Error>> + Send>>,
|
||||
>,
|
||||
}
|
||||
|
||||
impl CrawlManifestFuture {
|
||||
pub fn new(engine: &Engine, repo_path: RepoPath, entry_point: RelativePathBuf) -> Self {
|
||||
let future: Box<dyn Future<Item = _, Error = _> + Send> = Box::new(
|
||||
engine
|
||||
.retrieve_manifest_at_path(&repo_path, &entry_point)
|
||||
.map(move |contents| (entry_point, contents)),
|
||||
);
|
||||
let engine = engine.clone();
|
||||
let crawler = ManifestCrawler::new();
|
||||
let mut futures = FuturesOrdered::new();
|
||||
|
||||
let future: Pin<Box<dyn Future<Output = _> + Send>> = Box::pin(
|
||||
engine
|
||||
.retrieve_manifest_at_path(&repo_path, &entry_point)
|
||||
.map(move |contents| contents.map(|c| (entry_point, c))),
|
||||
);
|
||||
futures.push(future);
|
||||
|
||||
CrawlManifestFuture {
|
||||
|
@ -41,27 +45,33 @@ impl CrawlManifestFuture {
|
|||
}
|
||||
|
||||
impl Future for CrawlManifestFuture {
|
||||
type Item = ManifestCrawlerOutput;
|
||||
type Error = Error;
|
||||
type Output = Result<ManifestCrawlerOutput, Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
match try_ready!(self.futures.poll()) {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.as_mut().project();
|
||||
|
||||
match ready!(this.futures.poll_next(cx)) {
|
||||
None => {
|
||||
let crawler = mem::replace(&mut self.crawler, ManifestCrawler::new());
|
||||
Ok(Async::Ready(crawler.finalize()))
|
||||
Poll::Ready(Ok(crawler.finalize()))
|
||||
}
|
||||
Some((path, raw_manifest)) => {
|
||||
|
||||
Some(Ok((path, raw_manifest))) => {
|
||||
let output = self.crawler.step(path, raw_manifest)?;
|
||||
|
||||
for path in output.paths_of_interest.into_iter() {
|
||||
let future: Box<dyn Future<Item = _, Error = _> + Send> = Box::new(
|
||||
let future: Pin<Box<dyn Future<Output = _> + Send>> = Box::pin(
|
||||
self.engine
|
||||
.retrieve_manifest_at_path(&self.repo_path, &path)
|
||||
.map(move |contents| (path, contents)),
|
||||
.map(move |contents| contents.map(|c| ((path, c)))),
|
||||
);
|
||||
self.futures.push(future);
|
||||
}
|
||||
self.poll()
|
||||
|
||||
self.poll(cx)
|
||||
}
|
||||
|
||||
Some(Err(err)) => Poll::Ready(Err(err.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
mod analyze;
|
||||
mod crawl;
|
||||
|
||||
pub use self::analyze::AnalyzeDependenciesFuture;
|
||||
pub use self::analyze::analyze_dependencies;
|
||||
pub use self::crawl::CrawlManifestFuture;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::{anyhow, ensure, Error};
|
||||
use anyhow::Error;
|
||||
use indexmap::IndexMap;
|
||||
use relative_path::RelativePathBuf;
|
||||
|
||||
|
|
|
@ -1,51 +1,57 @@
|
|||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
panic::RefUnwindSafe,
|
||||
sync::{Arc, Mutex},
|
||||
task::{Context, Poll},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, ensure, Error};
|
||||
use cadence::prelude::*;
|
||||
use anyhow::{anyhow, Error};
|
||||
use cadence::{MetricSink, NopMetricSink, StatsdClient};
|
||||
use futures::future::join_all;
|
||||
use futures::{future, Future};
|
||||
use hyper::client::{HttpConnector, ResponseFuture};
|
||||
use hyper::{Body, Client, Request, Response};
|
||||
use futures::{future::try_join_all, stream::FuturesUnordered, Future, FutureExt, Stream};
|
||||
use hyper::{
|
||||
client::{HttpConnector, ResponseFuture},
|
||||
service::Service,
|
||||
Body, Client, Request, Response,
|
||||
};
|
||||
use hyper_tls::HttpsConnector;
|
||||
use once_cell::sync::Lazy;
|
||||
use relative_path::{RelativePath, RelativePathBuf};
|
||||
use rustsec::database::Database;
|
||||
use semver::VersionReq;
|
||||
use slog::Logger;
|
||||
use tokio_service::Service;
|
||||
|
||||
use crate::utils::cache::Cache;
|
||||
|
||||
use crate::models::crates::{AnalyzedDependencies, CrateName, CratePath, CrateRelease};
|
||||
use crate::models::repo::{RepoPath, Repository};
|
||||
|
||||
use crate::interactors::crates::{GetPopularCrates, QueryCrate};
|
||||
use crate::interactors::github::GetPopularRepos;
|
||||
use crate::interactors::rustsec::FetchAdvisoryDatabase;
|
||||
use crate::interactors::RetrieveFileAtPath;
|
||||
use crate::models::crates::{AnalyzedDependencies, CrateName, CratePath, CrateRelease};
|
||||
use crate::models::repo::{RepoPath, Repository};
|
||||
use crate::utils::cache::Cache;
|
||||
|
||||
mod fut;
|
||||
mod machines;
|
||||
|
||||
use self::fut::AnalyzeDependenciesFuture;
|
||||
use self::fut::analyze_dependencies;
|
||||
use self::fut::CrawlManifestFuture;
|
||||
|
||||
type HttpClient = Client<HttpsConnector<HttpConnector>>;
|
||||
// type HttpClient = Client<HttpConnector>;
|
||||
|
||||
// workaround for hyper 0.12 not implementing Service for Client
|
||||
#[derive(Debug, Clone)]
|
||||
struct ServiceHttpClient(HttpClient);
|
||||
|
||||
impl Service for ServiceHttpClient {
|
||||
type Request = Request<Body>;
|
||||
impl Service<Request<Body>> for ServiceHttpClient {
|
||||
type Response = Response<Body>;
|
||||
type Error = hyper::Error;
|
||||
type Future = ResponseFuture;
|
||||
|
||||
fn call(&self, req: Self::Request) -> Self::Future {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.0.poll_ready(cx).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
fn call(&mut self, req: Request<Body>) -> Self::Future {
|
||||
self.0.request(req)
|
||||
}
|
||||
}
|
||||
|
@ -55,15 +61,16 @@ pub struct Engine {
|
|||
client: HttpClient,
|
||||
logger: Logger,
|
||||
metrics: StatsdClient,
|
||||
query_crate: Arc<Cache<QueryCrate<ServiceHttpClient>>>,
|
||||
get_popular_crates: Arc<Cache<GetPopularCrates<ServiceHttpClient>>>,
|
||||
get_popular_repos: Arc<Cache<GetPopularRepos<ServiceHttpClient>>>,
|
||||
retrieve_file_at_path: Arc<RetrieveFileAtPath<ServiceHttpClient>>,
|
||||
fetch_advisory_db: Arc<Cache<FetchAdvisoryDatabase<ServiceHttpClient>>>,
|
||||
// TODO: use futures aware mutex
|
||||
query_crate: Arc<Mutex<Cache<QueryCrate<ServiceHttpClient>, CrateName>>>,
|
||||
get_popular_crates: Arc<Mutex<Cache<GetPopularCrates<ServiceHttpClient>, ()>>>,
|
||||
get_popular_repos: Arc<Mutex<Cache<GetPopularRepos<ServiceHttpClient>, ()>>>,
|
||||
retrieve_file_at_path: Arc<Mutex<RetrieveFileAtPath<ServiceHttpClient>>>,
|
||||
fetch_advisory_db: Arc<Mutex<Cache<FetchAdvisoryDatabase<ServiceHttpClient>, ()>>>,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
pub fn new(client: Client<HttpsConnector<HttpConnector>>, logger: Logger) -> Engine {
|
||||
pub fn new(client: HttpClient, logger: Logger) -> Engine {
|
||||
let metrics = StatsdClient::from_sink("engine", NopMetricSink);
|
||||
|
||||
let service_client = ServiceHttpClient(client.clone());
|
||||
|
@ -93,19 +100,20 @@ impl Engine {
|
|||
client: client.clone(),
|
||||
logger,
|
||||
metrics,
|
||||
query_crate: Arc::new(query_crate),
|
||||
get_popular_crates: Arc::new(get_popular_crates),
|
||||
get_popular_repos: Arc::new(get_popular_repos),
|
||||
retrieve_file_at_path: Arc::new(RetrieveFileAtPath(service_client)),
|
||||
fetch_advisory_db: Arc::new(fetch_advisory_db),
|
||||
query_crate: Arc::new(Mutex::new(query_crate)),
|
||||
get_popular_crates: Arc::new(Mutex::new(get_popular_crates)),
|
||||
get_popular_repos: Arc::new(Mutex::new(get_popular_repos)),
|
||||
retrieve_file_at_path: Arc::new(Mutex::new(RetrieveFileAtPath(service_client))),
|
||||
fetch_advisory_db: Arc::new(Mutex::new(fetch_advisory_db)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_metrics<M: MetricSink + Send + Sync + 'static>(&mut self, sink: M) {
|
||||
pub fn set_metrics<M: MetricSink + Send + Sync + RefUnwindSafe + 'static>(&mut self, sink: M) {
|
||||
self.metrics = StatsdClient::from_sink("engine", sink);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnalyzeDependenciesOutcome {
|
||||
pub crates: Vec<(CrateName, AnalyzedDependencies)>,
|
||||
pub duration: Duration,
|
||||
|
@ -132,141 +140,150 @@ impl AnalyzeDependenciesOutcome {
|
|||
}
|
||||
|
||||
impl Engine {
|
||||
pub fn get_popular_repos(&self) -> impl Future<Item = Vec<Repository>, Error = Error> + Send {
|
||||
self.get_popular_repos.call(()).from_err().map(|repos| {
|
||||
repos
|
||||
.iter()
|
||||
.filter(|repo| !POPULAR_REPO_BLOCK_LIST.contains(&repo.path))
|
||||
.cloned()
|
||||
.collect()
|
||||
})
|
||||
pub async fn get_popular_repos(&self) -> Result<Vec<Repository>, Error> {
|
||||
let repos = self.get_popular_repos.lock().unwrap().call(());
|
||||
let repos = repos.await?;
|
||||
|
||||
let filtered_repos = repos
|
||||
.iter()
|
||||
.filter(|repo| !POPULAR_REPO_BLOCK_LIST.contains(&repo.path))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
Ok(filtered_repos)
|
||||
}
|
||||
|
||||
pub fn get_popular_crates(&self) -> impl Future<Item = Vec<CratePath>, Error = Error> + Send {
|
||||
self.get_popular_crates
|
||||
.call(())
|
||||
.from_err()
|
||||
.map(|crates| crates.clone())
|
||||
pub async fn get_popular_crates(&self) -> Result<Vec<CratePath>, Error> {
|
||||
let crates = self.get_popular_crates.lock().unwrap().call(());
|
||||
let crates = crates.await?;
|
||||
Ok(crates.clone())
|
||||
}
|
||||
|
||||
pub fn analyze_repo_dependencies(
|
||||
pub async fn analyze_repo_dependencies(
|
||||
&self,
|
||||
repo_path: RepoPath,
|
||||
) -> impl Future<Item = AnalyzeDependenciesOutcome, Error = Error> + Send {
|
||||
) -> Result<AnalyzeDependenciesOutcome, Error> {
|
||||
let start = Instant::now();
|
||||
|
||||
let entry_point = RelativePath::new("/").to_relative_path_buf();
|
||||
let manifest_future = CrawlManifestFuture::new(self, repo_path.clone(), entry_point);
|
||||
|
||||
let engine = self.clone();
|
||||
manifest_future.and_then(move |manifest_output| {
|
||||
let engine_for_analyze = engine.clone();
|
||||
let futures = manifest_output
|
||||
.crates
|
||||
.into_iter()
|
||||
.map(move |(crate_name, deps)| {
|
||||
let analyzed_deps_future =
|
||||
AnalyzeDependenciesFuture::new(engine_for_analyze.clone(), deps);
|
||||
|
||||
analyzed_deps_future.map(move |analyzed_deps| (crate_name, analyzed_deps))
|
||||
});
|
||||
let manifest_future = CrawlManifestFuture::new(self, repo_path.clone(), entry_point);
|
||||
let manifest_output = manifest_future.await?;
|
||||
|
||||
join_all(futures).and_then(move |crates| {
|
||||
let duration = start.elapsed();
|
||||
engine
|
||||
.metrics
|
||||
.time_duration_with_tags("analyze_duration", duration)
|
||||
.with_tag("repo_site", repo_path.site.as_ref())
|
||||
.with_tag("repo_qual", repo_path.qual.as_ref())
|
||||
.with_tag("repo_name", repo_path.name.as_ref())
|
||||
.send()?;
|
||||
|
||||
Ok(AnalyzeDependenciesOutcome { crates, duration })
|
||||
let engine_for_analyze = engine.clone();
|
||||
let futures = manifest_output
|
||||
.crates
|
||||
.into_iter()
|
||||
.map(|(crate_name, deps)| async {
|
||||
let analyzed_deps = analyze_dependencies(engine_for_analyze.clone(), deps).await?;
|
||||
Ok::<_, Error>((crate_name, analyzed_deps))
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let crates = try_join_all(futures).await?;
|
||||
|
||||
let duration = start.elapsed();
|
||||
// engine
|
||||
// .metrics
|
||||
// .time_duration_with_tags("analyze_duration", duration)
|
||||
// .with_tag("repo_site", repo_path.site.as_ref())
|
||||
// .with_tag("repo_qual", repo_path.qual.as_ref())
|
||||
// .with_tag("repo_name", repo_path.name.as_ref())
|
||||
// .send()?;
|
||||
|
||||
Ok(AnalyzeDependenciesOutcome { crates, duration })
|
||||
}
|
||||
|
||||
pub fn analyze_crate_dependencies(
|
||||
pub async fn analyze_crate_dependencies(
|
||||
&self,
|
||||
crate_path: CratePath,
|
||||
) -> impl Future<Item = AnalyzeDependenciesOutcome, Error = Error> + Send {
|
||||
) -> Result<AnalyzeDependenciesOutcome, Error> {
|
||||
let start = Instant::now();
|
||||
|
||||
let query_future = self.query_crate.call(crate_path.name.clone()).from_err();
|
||||
let query_response = self
|
||||
.query_crate
|
||||
.lock()
|
||||
.unwrap()
|
||||
.call(crate_path.name.clone());
|
||||
let query_response = query_response.await?;
|
||||
|
||||
let engine = self.clone();
|
||||
query_future.and_then(move |query_response| {
|
||||
match query_response
|
||||
.releases
|
||||
.iter()
|
||||
.find(|release| release.version == crate_path.version)
|
||||
{
|
||||
None => future::Either::A(future::err(anyhow!(
|
||||
"could not find crate release with version {}",
|
||||
crate_path.version
|
||||
))),
|
||||
Some(release) => {
|
||||
let analyzed_deps_future =
|
||||
AnalyzeDependenciesFuture::new(engine.clone(), release.deps.clone());
|
||||
|
||||
future::Either::B(analyzed_deps_future.map(move |analyzed_deps| {
|
||||
let crates = vec![(crate_path.name, analyzed_deps)].into_iter().collect();
|
||||
let duration = start.elapsed();
|
||||
match query_response
|
||||
.releases
|
||||
.iter()
|
||||
.find(|release| release.version == crate_path.version)
|
||||
{
|
||||
None => Err(anyhow!(
|
||||
"could not find crate release with version {}",
|
||||
crate_path.version
|
||||
)),
|
||||
|
||||
AnalyzeDependenciesOutcome { crates, duration }
|
||||
}))
|
||||
}
|
||||
Some(release) => {
|
||||
let analyzed_deps =
|
||||
analyze_dependencies(engine.clone(), release.deps.clone()).await?;
|
||||
|
||||
let crates = vec![(crate_path.name, analyzed_deps)];
|
||||
let duration = start.elapsed();
|
||||
|
||||
Ok(AnalyzeDependenciesOutcome { crates, duration })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_latest_crate_release(
|
||||
pub async fn find_latest_crate_release(
|
||||
&self,
|
||||
name: CrateName,
|
||||
req: VersionReq,
|
||||
) -> impl Future<Item = Option<CrateRelease>, Error = Error> + Send {
|
||||
self.query_crate
|
||||
.call(name)
|
||||
.from_err()
|
||||
.map(move |query_response| {
|
||||
query_response
|
||||
.releases
|
||||
.iter()
|
||||
.filter(|release| req.matches(&release.version))
|
||||
.max_by(|r1, r2| r1.version.cmp(&r2.version))
|
||||
.cloned()
|
||||
})
|
||||
) -> Result<Option<CrateRelease>, Error> {
|
||||
let query_response = self.query_crate.lock().unwrap().call(name);
|
||||
let query_response = query_response.await?;
|
||||
|
||||
let latest = query_response
|
||||
.releases
|
||||
.iter()
|
||||
.filter(|release| req.matches(&release.version))
|
||||
.max_by(|r1, r2| r1.version.cmp(&r2.version))
|
||||
.cloned();
|
||||
|
||||
Ok(latest)
|
||||
}
|
||||
|
||||
fn fetch_releases<I: IntoIterator<Item = CrateName>>(
|
||||
&self,
|
||||
names: I,
|
||||
) -> impl Iterator<Item = impl Future<Item = Vec<CrateRelease>, Error = Error>> {
|
||||
) -> impl Stream<Item = Result<Vec<CrateRelease>, Error>> {
|
||||
let engine = self.clone();
|
||||
names.into_iter().map(move |name| {
|
||||
engine
|
||||
.query_crate
|
||||
.call(name)
|
||||
.from_err()
|
||||
.map(|resp| resp.releases.clone())
|
||||
})
|
||||
|
||||
names
|
||||
.into_iter()
|
||||
.map(|name| {
|
||||
engine
|
||||
.query_crate
|
||||
.lock()
|
||||
.unwrap()
|
||||
.call(name)
|
||||
.map(|resp| resp.map(|r| r.releases.clone()))
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>()
|
||||
}
|
||||
|
||||
fn retrieve_manifest_at_path(
|
||||
&self,
|
||||
repo_path: &RepoPath,
|
||||
path: &RelativePathBuf,
|
||||
) -> impl Future<Item = String, Error = Error> + Send {
|
||||
) -> impl Future<Output = Result<String, Error>> {
|
||||
let manifest_path = path.join(RelativePath::new("Cargo.toml"));
|
||||
|
||||
self.retrieve_file_at_path
|
||||
.lock()
|
||||
.unwrap()
|
||||
.call((repo_path.clone(), manifest_path))
|
||||
}
|
||||
|
||||
fn fetch_advisory_db(&self) -> impl Future<Item = Arc<Database>, Error = Error> + Send {
|
||||
self.fetch_advisory_db
|
||||
.call(())
|
||||
.from_err()
|
||||
.map(|db| db.clone())
|
||||
fn fetch_advisory_db(&self) -> impl Future<Output = Result<Arc<Database>, Error>> {
|
||||
self.fetch_advisory_db.lock().unwrap().call(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{anyhow, ensure, Error};
|
||||
use anyhow::Error;
|
||||
use hyper::Uri;
|
||||
use relative_path::RelativePathBuf;
|
||||
|
||||
|
@ -8,12 +8,14 @@ const BITBUCKET_USER_CONTENT_BASE_URI: &'static str = "https://bitbucket.org";
|
|||
|
||||
pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result<Uri, Error> {
|
||||
let path_str: &str = path.as_ref();
|
||||
Ok(format!(
|
||||
|
||||
let url = format!(
|
||||
"{}/{}/{}/raw/HEAD/{}",
|
||||
BITBUCKET_USER_CONTENT_BASE_URI,
|
||||
repo_path.qual.as_ref(),
|
||||
repo_path.name.as_ref(),
|
||||
path_str
|
||||
)
|
||||
.parse::<Uri>()?)
|
||||
);
|
||||
|
||||
Ok(url.parse::<Uri>()?)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
use std::str;
|
||||
use std::pin::Pin;
|
||||
use std::{future::Future, task::Poll};
|
||||
use std::{str, task::Context};
|
||||
|
||||
use anyhow::{anyhow, ensure, Error};
|
||||
use futures::{future, Future, IntoFuture, Stream};
|
||||
use hyper::{Body, Error as HyperError, Method, Request, Response, Uri, header::USER_AGENT};
|
||||
use anyhow::{anyhow, Error};
|
||||
use futures::{
|
||||
future::{err, ok, ready},
|
||||
TryFutureExt,
|
||||
};
|
||||
use hyper::{
|
||||
body, header::USER_AGENT, service::Service, Body, Error as HyperError, Request, Response, Uri,
|
||||
};
|
||||
use semver::{Version, VersionReq};
|
||||
use serde::Deserialize;
|
||||
use tokio_service::Service;
|
||||
|
||||
use crate::models::crates::{CrateDep, CrateDeps, CrateName, CratePath, CrateRelease};
|
||||
|
||||
|
@ -65,6 +71,7 @@ fn convert_pkgs(
|
|||
Ok(QueryCrateResponse { releases: releases })
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QueryCrateResponse {
|
||||
pub releases: Vec<CrateRelease>,
|
||||
}
|
||||
|
@ -72,19 +79,20 @@ pub struct QueryCrateResponse {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct QueryCrate<S>(pub S);
|
||||
|
||||
impl<S> Service for QueryCrate<S>
|
||||
impl<S> Service<CrateName> for QueryCrate<S>
|
||||
where
|
||||
S: Service<Request = Request<Body>, Response = Response<Body>, Error = HyperError>
|
||||
+ Clone
|
||||
+ 'static,
|
||||
S: Service<Request<Body>, Response = Response<Body>, Error = HyperError> + Clone,
|
||||
S::Future: Send + 'static,
|
||||
{
|
||||
type Request = CrateName;
|
||||
type Response = QueryCrateResponse;
|
||||
type Error = Error;
|
||||
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error> + Send>;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
||||
|
||||
fn call(&self, crate_name: CrateName) -> Self::Future {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.0.poll_ready(cx).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
fn call(&mut self, crate_name: CrateName) -> Self::Future {
|
||||
let lower_name = crate_name.as_ref().to_lowercase();
|
||||
|
||||
let path = match lower_name.len() {
|
||||
|
@ -94,35 +102,41 @@ where
|
|||
_ => format!("{}/{}/{}", &lower_name[0..2], &lower_name[2..4], lower_name),
|
||||
};
|
||||
|
||||
let uri =
|
||||
try_future_box!(format!("{}/master/{}", CRATES_INDEX_BASE_URI, path).parse::<Uri>());
|
||||
let uri = format!("{}/master/{}", CRATES_INDEX_BASE_URI, path);
|
||||
let uri = uri.parse::<Uri>().expect("TODO: MAP ERROR PROPERLY");
|
||||
|
||||
let request = Request::get(uri.clone())
|
||||
.header(USER_AGENT, "deps.rs")
|
||||
.body(Body::empty()).unwrap();
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
Box::new(self.0.call(request).from_err().and_then(move |response| {
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
try_future!(Err(anyhow!("Status code {} for URI {}", status, uri)));
|
||||
}
|
||||
Box::pin(
|
||||
self.0
|
||||
.call(request)
|
||||
.map_err(|err| err.into())
|
||||
.and_then(move |response| {
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
return err(anyhow!("Status code {} for URI {}", status, uri));
|
||||
}
|
||||
|
||||
let body_future = response.into_body().concat2().from_err();
|
||||
let decode_future = body_future.and_then(move |body| {
|
||||
let string_body = str::from_utf8(body.as_ref())?;
|
||||
let packages = string_body
|
||||
.lines()
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| serde_json::from_str::<RegistryPackage>(s))
|
||||
.collect::<Result<_, _>>()?;
|
||||
Ok(packages)
|
||||
});
|
||||
|
||||
decode_future
|
||||
.and_then(move |pkgs| convert_pkgs(&crate_name, pkgs))
|
||||
.into()
|
||||
}))
|
||||
ok(response)
|
||||
})
|
||||
.and_then(|response| body::to_bytes(response.into_body()).err_into())
|
||||
.and_then(|body| ready(String::from_utf8(body.to_vec())).err_into())
|
||||
.and_then(|string_body| {
|
||||
ready(
|
||||
string_body
|
||||
.lines()
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(serde_json::from_str)
|
||||
.collect::<Result<_, _>>(),
|
||||
)
|
||||
.err_into()
|
||||
})
|
||||
.and_then(move |pkgs| ready(convert_pkgs(&crate_name, pkgs))),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,44 +168,46 @@ fn convert_summary(response: SummaryResponse) -> Result<Vec<CratePath>, Error> {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct GetPopularCrates<S>(pub S);
|
||||
|
||||
impl<S> Service for GetPopularCrates<S>
|
||||
impl<S> Service<()> for GetPopularCrates<S>
|
||||
where
|
||||
S: Service<Request = Request<Body>, Response = Response<Body>, Error = HyperError>
|
||||
+ Clone
|
||||
+ 'static,
|
||||
S: Service<Request<Body>, Response = Response<Body>, Error = HyperError> + Clone,
|
||||
S::Future: Send + 'static,
|
||||
{
|
||||
type Request = ();
|
||||
type Response = Vec<CratePath>;
|
||||
type Error = Error;
|
||||
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error> + Send>;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
||||
|
||||
fn call(&self, _req: ()) -> Self::Future {
|
||||
let service = self.0.clone();
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.0.poll_ready(cx).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
let uri = format!("{}/summary", CRATES_API_BASE_URI)
|
||||
.parse::<Uri>()
|
||||
.unwrap();
|
||||
fn call(&mut self, _req: ()) -> Self::Future {
|
||||
let mut service = self.0.clone();
|
||||
|
||||
let uri = format!("{}/summary", CRATES_API_BASE_URI);
|
||||
let uri = uri.parse::<Uri>().unwrap();
|
||||
let request = Request::get(uri.clone())
|
||||
.header(USER_AGENT, "deps.rs")
|
||||
.body(Body::empty()).unwrap();
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
Box::new(service.call(request).from_err().and_then(move |response| {
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
future::Either::A(future::err(anyhow!(
|
||||
"Status code {} for URI {}",
|
||||
status,
|
||||
uri
|
||||
)))
|
||||
} else {
|
||||
let body_future = response.into_body().concat2().from_err();
|
||||
let decode_future = body_future.and_then(|body| {
|
||||
let summary = serde_json::from_slice::<SummaryResponse>(&body)?;
|
||||
convert_summary(summary)
|
||||
});
|
||||
future::Either::B(decode_future)
|
||||
}
|
||||
}))
|
||||
Box::pin(
|
||||
service
|
||||
.call(request)
|
||||
.map_err(|err| err.into())
|
||||
.and_then(move |response| {
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
err(anyhow!("Status code {} for URI {}", status, uri))
|
||||
} else {
|
||||
ok(response)
|
||||
}
|
||||
})
|
||||
.and_then(|response| body::to_bytes(response.into_body()).err_into())
|
||||
.and_then(|bytes| {
|
||||
ready(serde_json::from_slice::<SummaryResponse>(&bytes)).err_into()
|
||||
})
|
||||
.and_then(|summary| ready(convert_summary(summary)).err_into()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
use anyhow::{anyhow, ensure, Error};
|
||||
use futures::{Future, Stream};
|
||||
use hyper::header::USER_AGENT;
|
||||
use hyper::{Body, Error as HyperError, Method, Request, Response, Uri};
|
||||
use std::{future::Future, pin::Pin, task::Context, task::Poll};
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use futures::{
|
||||
future::{err, ok, ready},
|
||||
TryFutureExt,
|
||||
};
|
||||
use hyper::{
|
||||
body, header::USER_AGENT, service::Service, Body, Error as HyperError, Request, Response, Uri,
|
||||
};
|
||||
use relative_path::RelativePathBuf;
|
||||
use serde::Deserialize;
|
||||
use tokio_service::Service;
|
||||
|
||||
use crate::models::repo::{RepoPath, Repository};
|
||||
|
||||
|
@ -43,57 +48,63 @@ struct GithubOwner {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct GetPopularRepos<S>(pub S);
|
||||
|
||||
impl<S> Service for GetPopularRepos<S>
|
||||
impl<S> Service<()> for GetPopularRepos<S>
|
||||
where
|
||||
S: Service<Request = Request<Body>, Response = Response<Body>, Error = HyperError>
|
||||
+ Clone
|
||||
+ 'static,
|
||||
S: Service<Request<Body>, Response = Response<Body>, Error = HyperError> + Clone,
|
||||
S::Future: Send + 'static,
|
||||
{
|
||||
type Request = ();
|
||||
type Response = Vec<Repository>;
|
||||
type Error = Error;
|
||||
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error> + Send>;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
||||
|
||||
fn call(&self, _req: ()) -> Self::Future {
|
||||
let uri = try_future_box!(format!(
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.0.poll_ready(cx).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
fn call(&mut self, _req: ()) -> Self::Future {
|
||||
let uri = format!(
|
||||
"{}/search/repositories?q=language:rust&sort=stars",
|
||||
GITHUB_API_BASE_URI
|
||||
)
|
||||
.parse::<Uri>());
|
||||
.parse::<Uri>()
|
||||
.expect("TODO: handle error properly");
|
||||
|
||||
let mut request = Request::get(uri);
|
||||
request.header(USER_AGENT, "deps.rs");
|
||||
let request = request.body(Body::empty()).unwrap();
|
||||
let request = Request::get(uri)
|
||||
.header(USER_AGENT, "deps.rs")
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
Box::new(self.0.call(request).from_err().and_then(|response| {
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
try_future!(Err(anyhow!(
|
||||
"Status code {} for popular repo search",
|
||||
status
|
||||
)));
|
||||
}
|
||||
Box::pin(
|
||||
self.0
|
||||
.call(request)
|
||||
.err_into()
|
||||
.and_then(|response| {
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
return err(anyhow!("Status code {} for popular repo search", status));
|
||||
}
|
||||
|
||||
let body_future = response.into_body().concat2().from_err();
|
||||
let decode_future = body_future
|
||||
.and_then(|body| serde_json::from_slice(body.as_ref()).map_err(|err| err.into()));
|
||||
decode_future
|
||||
.and_then(|search_response: GithubSearchResponse| {
|
||||
search_response
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
let path =
|
||||
RepoPath::from_parts("github", &item.owner.login, &item.name)?;
|
||||
Ok(Repository {
|
||||
path,
|
||||
description: item.description,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
ok(response)
|
||||
})
|
||||
.into()
|
||||
}))
|
||||
.and_then(|response| body::to_bytes(response.into_body()).err_into())
|
||||
.and_then(|bytes| ready(serde_json::from_slice(bytes.as_ref())).err_into())
|
||||
.and_then(|search_response: GithubSearchResponse| {
|
||||
ready(
|
||||
search_response
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
let path =
|
||||
RepoPath::from_parts("github", &item.owner.login, &item.name)?;
|
||||
|
||||
Ok(Repository {
|
||||
path,
|
||||
description: item.description,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<_>, Error>>(),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{anyhow, ensure, Error};
|
||||
use anyhow::Error;
|
||||
use hyper::Uri;
|
||||
use relative_path::RelativePathBuf;
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
use anyhow::{anyhow, ensure, Error};
|
||||
use futures::{Future, Stream};
|
||||
use hyper::{Body, Error as HyperError, Method, Request, Response, header::USER_AGENT};
|
||||
use std::{future::Future, task::Poll};
|
||||
use std::{pin::Pin, task::Context};
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use futures::{
|
||||
future::{err, ok, ready},
|
||||
TryFutureExt,
|
||||
};
|
||||
use hyper::{
|
||||
body, header::USER_AGENT, service::Service, Body, Error as HyperError, Request, Response,
|
||||
};
|
||||
use relative_path::RelativePathBuf;
|
||||
use tokio_service::Service;
|
||||
|
||||
use crate::models::repo::{RepoPath, RepoSite};
|
||||
|
||||
|
@ -15,41 +22,52 @@ pub mod rustsec;
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct RetrieveFileAtPath<S>(pub S);
|
||||
|
||||
impl<S> Service for RetrieveFileAtPath<S>
|
||||
impl<S> Service<(RepoPath, RelativePathBuf)> for RetrieveFileAtPath<S>
|
||||
where
|
||||
S: Service<Request = Request<Body>, Response = Response<Body>, Error = HyperError>
|
||||
+ Clone
|
||||
+ 'static,
|
||||
S: Service<Request<Body>, Response = Response<Body>, Error = HyperError> + Clone,
|
||||
S::Future: Send + 'static,
|
||||
{
|
||||
type Request = (RepoPath, RelativePathBuf);
|
||||
type Response = String;
|
||||
type Error = Error;
|
||||
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error> + Send>;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
||||
|
||||
fn call(&self, req: Self::Request) -> Self::Future {
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
self.0.poll_ready(cx).map_err(|err| err.into())
|
||||
}
|
||||
|
||||
fn call(&mut self, req: (RepoPath, RelativePathBuf)) -> Self::Future {
|
||||
let (repo_path, path) = req;
|
||||
let uri = match &repo_path.site {
|
||||
&RepoSite::Github => try_future_box!(github::get_manifest_uri(&repo_path, &path)),
|
||||
&RepoSite::Gitlab => try_future_box!(gitlab::get_manifest_uri(&repo_path, &path)),
|
||||
&RepoSite::Bitbucket => try_future_box!(bitbucket::get_manifest_uri(&repo_path, &path)),
|
||||
RepoSite::Github => github::get_manifest_uri(&repo_path, &path),
|
||||
RepoSite::Gitlab => gitlab::get_manifest_uri(&repo_path, &path),
|
||||
RepoSite::Bitbucket => bitbucket::get_manifest_uri(&repo_path, &path),
|
||||
};
|
||||
|
||||
let uri = match uri {
|
||||
Ok(uri) => uri,
|
||||
Err(error) => return Box::pin(err(error)),
|
||||
};
|
||||
|
||||
let request = Request::get(uri.clone())
|
||||
.header(USER_AGENT, "deps.rs")
|
||||
.body(Body::empty()).unwrap();
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
Box::new(self.0.call(request).from_err().and_then(move |response| {
|
||||
let status = response.status();
|
||||
if !status.is_success() {
|
||||
try_future!(Err(anyhow!("Status code {} for URI {}", status, uri)));
|
||||
}
|
||||
Box::pin(
|
||||
self.0
|
||||
.call(request)
|
||||
.err_into()
|
||||
.and_then(move |response| {
|
||||
let status = response.status();
|
||||
|
||||
let body_future = response.into_body().concat2().from_err();
|
||||
|
||||
body_future
|
||||
.and_then(|body| String::from_utf8(body.to_vec()).map_err(|err| err.into()))
|
||||
.into()
|
||||
}))
|
||||
if status.is_success() {
|
||||
ok(response)
|
||||
} else {
|
||||
err(anyhow!("Status code {} for URI {}", status, uri))
|
||||
}
|
||||
})
|
||||
.and_then(|response| body::to_bytes(response.into_body()).err_into())
|
||||
.and_then(|bytes| ready(String::from_utf8(bytes.to_vec())).err_into()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,36 @@
|
|||
use std::str;
|
||||
use std::sync::Arc;
|
||||
use std::{pin::Pin, sync::Arc, task::Context, task::Poll};
|
||||
|
||||
use anyhow::{anyhow, ensure, Error};
|
||||
use futures::{future, future::done, Future, IntoFuture, Stream};
|
||||
use hyper::{Body, Error as HyperError, Method, Request, Response};
|
||||
use anyhow::Error;
|
||||
use futures::{future::ready, Future};
|
||||
use hyper::{service::Service, Body, Error as HyperError, Request, Response};
|
||||
use rustsec::database::Database;
|
||||
use rustsec::repository::DEFAULT_URL;
|
||||
use tokio_service::Service;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FetchAdvisoryDatabase<S>(pub S);
|
||||
|
||||
impl<S> Service for FetchAdvisoryDatabase<S>
|
||||
impl<S> Service<()> for FetchAdvisoryDatabase<S>
|
||||
where
|
||||
S: Service<Request = Request<Body>, Response = Response<Body>, Error = HyperError>
|
||||
+ Clone
|
||||
+ 'static,
|
||||
S: Service<Request<Body>, Response = Response<Body>, Error = HyperError> + Clone,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ();
|
||||
type Response = Arc<Database>;
|
||||
type Error = Error;
|
||||
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error> + Send>;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
|
||||
|
||||
fn call(&self, _req: ()) -> Self::Future {
|
||||
let service = self.0.clone();
|
||||
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
// TODO: should be this when async client is used again
|
||||
// self.0.poll_ready(cx).map_err(|err| err.into())
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
Box::new(done(
|
||||
// TODO: make fetch async again
|
||||
fn call(&mut self, _req: ()) -> Self::Future {
|
||||
let _service = self.0.clone();
|
||||
|
||||
Box::pin(ready(
|
||||
rustsec::Database::fetch()
|
||||
.map(|db| Arc::new(db))
|
||||
.map_err(|err| anyhow!("err fetching rustsec DB")),
|
||||
.map_err(|err| err.into()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +40,7 @@ where
|
|||
|
||||
// impl<S> Service for FetchAdvisoryDatabase<S>
|
||||
// where
|
||||
// S: Service<Request = Request, Response = Response, Error = HyperError> + Clone + 'static,
|
||||
// S: Service<Request = Request, Response = Response, Error = HyperError> + Clone,
|
||||
// S::Future: 'static,
|
||||
// {
|
||||
// type Request = ();
|
||||
|
|
62
src/main.rs
62
src/main.rs
|
@ -1,22 +1,20 @@
|
|||
#![deny(rust_2018_idioms)]
|
||||
#![allow(unused)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate try_future;
|
||||
|
||||
use std::env;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
|
||||
use std::sync::Mutex;
|
||||
use std::{
|
||||
env,
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket},
|
||||
sync::Mutex,
|
||||
};
|
||||
|
||||
use cadence::{QueuingMetricSink, UdpMetricSink};
|
||||
use futures::{Future, Stream};
|
||||
use hyper::server::conn::AddrStream;
|
||||
use hyper::service::{make_service_fn, service_fn_ok};
|
||||
use hyper::Client;
|
||||
use hyper::{
|
||||
server::conn::AddrStream,
|
||||
service::{make_service_fn, service_fn},
|
||||
Client, Server,
|
||||
};
|
||||
use hyper_tls::HttpsConnector;
|
||||
use slog::Drain;
|
||||
use slog::{info, o};
|
||||
use tokio_core::reactor::Core;
|
||||
use slog::{o, Drain};
|
||||
|
||||
mod engine;
|
||||
mod interactors;
|
||||
|
@ -26,7 +24,7 @@ mod server;
|
|||
mod utils;
|
||||
|
||||
use self::engine::Engine;
|
||||
use self::server::Server;
|
||||
use self::server::App;
|
||||
|
||||
fn init_metrics() -> QueuingMetricSink {
|
||||
let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
|
||||
|
@ -36,21 +34,15 @@ fn init_metrics() -> QueuingMetricSink {
|
|||
QueuingMetricSink::from(sink)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let logger = slog::Logger::root(
|
||||
Mutex::new(slog_json::Json::default(std::io::stderr())).map(slog::Fuse),
|
||||
o!("version" => env!("CARGO_PKG_VERSION")),
|
||||
);
|
||||
|
||||
let metrics = init_metrics();
|
||||
|
||||
let mut core = Core::new().expect("failed to create event loop");
|
||||
|
||||
let handle = core.handle();
|
||||
|
||||
let connector = HttpsConnector::new(4).expect("failed to create https connector");
|
||||
|
||||
let client = Client::builder().build(connector);
|
||||
let client = Client::builder().build(HttpsConnector::new());
|
||||
|
||||
let port = env::var("PORT")
|
||||
.unwrap_or_else(|_| "8080".to_string())
|
||||
|
@ -62,15 +54,23 @@ fn main() {
|
|||
let mut engine = Engine::new(client.clone(), logger.clone());
|
||||
engine.set_metrics(metrics);
|
||||
|
||||
let server = Server::new(logger.clone(), engine);
|
||||
let make_svc = make_service_fn(move |socket: &AddrStream| {
|
||||
let server = server.clone();
|
||||
futures::future::ok::<_, hyper::Error>(server)
|
||||
let make_svc = make_service_fn(move |_socket: &AddrStream| {
|
||||
let logger = logger.clone();
|
||||
let engine = engine.clone();
|
||||
|
||||
async move {
|
||||
let server = App::new(logger.clone(), engine.clone());
|
||||
Ok::<_, hyper::Error>(service_fn(move |req| {
|
||||
let server = server.clone();
|
||||
async move { server.handle(req).await }
|
||||
}))
|
||||
}
|
||||
});
|
||||
let server = hyper::Server::bind(&addr).serve(make_svc);
|
||||
let server = Server::bind(&addr).serve(make_svc);
|
||||
|
||||
println!("Server running on port {}", port);
|
||||
hyper::rt::run(server.map_err(|e| {
|
||||
|
||||
if let Err(e) = server.await {
|
||||
eprintln!("server error: {}", e);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::borrow::Borrow;
|
||||
use std::str::FromStr;
|
||||
use std::{borrow::Borrow, str::FromStr};
|
||||
|
||||
use anyhow::{anyhow, ensure, Error};
|
||||
use anyhow::{anyhow, Error};
|
||||
use indexmap::IndexMap;
|
||||
use relative_path::RelativePathBuf;
|
||||
use semver::{Version, VersionReq};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::{anyhow, ensure, Error};
|
||||
use anyhow::{anyhow, Error};
|
||||
use indexmap::IndexMap;
|
||||
use relative_path::RelativePathBuf;
|
||||
use semver::VersionReq;
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use std::{env, sync::Arc};
|
||||
|
||||
use futures::{future, Future, IntoFuture};
|
||||
use hyper::header::{CONTENT_TYPE, LOCATION};
|
||||
use hyper::service::Service;
|
||||
use hyper::{Body, Error as HyperError, Method, Request, Response, StatusCode};
|
||||
use futures::future;
|
||||
use hyper::{
|
||||
header::{CONTENT_TYPE, LOCATION},
|
||||
Body, Error as HyperError, Method, Request, Response, StatusCode,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use route_recognizer::{Params, Router};
|
||||
use semver::VersionReq;
|
||||
use slog::Logger;
|
||||
use slog::{error, o};
|
||||
use slog::{error, o, Logger};
|
||||
|
||||
mod assets;
|
||||
mod views;
|
||||
|
@ -19,13 +18,13 @@ use crate::models::crates::{CrateName, CratePath};
|
|||
use crate::models::repo::RepoPath;
|
||||
use crate::models::SubjectPath;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
enum StatusFormat {
|
||||
Html,
|
||||
Svg,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum StaticFile {
|
||||
StyleCss,
|
||||
FaviconPng,
|
||||
|
@ -40,14 +39,14 @@ enum Route {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Server {
|
||||
pub struct App {
|
||||
logger: Logger,
|
||||
engine: Engine,
|
||||
router: Arc<Router<Route>>,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn new(logger: Logger, engine: Engine) -> Server {
|
||||
impl App {
|
||||
pub fn new(logger: Logger, engine: Engine) -> App {
|
||||
let mut router = Router::new();
|
||||
|
||||
router.add("/", Route::Index);
|
||||
|
@ -74,21 +73,14 @@ impl Server {
|
|||
Route::CrateStatus(StatusFormat::Svg),
|
||||
);
|
||||
|
||||
Server {
|
||||
App {
|
||||
logger,
|
||||
engine,
|
||||
router: Arc::new(router),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Service for Server {
|
||||
type ReqBody = Body;
|
||||
type ResBody = Body;
|
||||
type Error = hyper::Error;
|
||||
type Future = Box<dyn Future<Item = Response<Self::ResBody>, Error = Self::Error> + Send>;
|
||||
|
||||
fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
|
||||
pub async fn handle(&self, req: Request<Body>) -> Result<Response<Body>, HyperError> {
|
||||
let logger = self
|
||||
.logger
|
||||
.new(o!("http_path" => req.uri().path().to_owned()));
|
||||
|
@ -97,188 +89,194 @@ impl Service for Server {
|
|||
match route_match.handler {
|
||||
&Route::Index => {
|
||||
if *req.method() == Method::GET {
|
||||
return Box::new(self.index(req, route_match.params, logger));
|
||||
return self.index(req, route_match.params, logger).await;
|
||||
}
|
||||
}
|
||||
&Route::RepoStatus(format) => {
|
||||
if *req.method() == Method::GET {
|
||||
return Box::new(self.repo_status(req, route_match.params, logger, format));
|
||||
return self
|
||||
.repo_status(req, route_match.params, logger, format)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
&Route::CrateStatus(format) => {
|
||||
if *req.method() == Method::GET {
|
||||
return Box::new(self.crate_status(
|
||||
req,
|
||||
route_match.params,
|
||||
logger,
|
||||
format,
|
||||
));
|
||||
return self
|
||||
.crate_status(req, route_match.params, logger, format)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
&Route::CrateRedirect => {
|
||||
if *req.method() == Method::GET {
|
||||
return Box::new(self.crate_redirect(req, route_match.params, logger));
|
||||
return self.crate_redirect(req, route_match.params, logger).await;
|
||||
}
|
||||
}
|
||||
&Route::Static(file) => {
|
||||
if *req.method() == Method::GET {
|
||||
return Box::new(future::ok(Server::static_file(file)));
|
||||
return Ok(App::static_file(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut response = Response::builder();
|
||||
response.status(StatusCode::NOT_FOUND);
|
||||
Box::new(future::ok(response.body(Body::empty()).unwrap()))
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::NOT_FOUND)
|
||||
.body(Body::empty())
|
||||
.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl Server {
|
||||
fn index(
|
||||
impl App {
|
||||
async fn index(
|
||||
&self,
|
||||
_req: Request<Body>,
|
||||
_params: Params,
|
||||
logger: Logger,
|
||||
) -> impl Future<Item = Response<Body>, Error = HyperError> + Send {
|
||||
self.engine
|
||||
.get_popular_repos()
|
||||
.join(self.engine.get_popular_crates())
|
||||
.then(move |popular_result| match popular_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response =
|
||||
views::html::error::render("Could not retrieve popular items", "");
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
future::ok(response)
|
||||
}
|
||||
Ok((popular_repos, popular_crates)) => {
|
||||
future::ok(views::html::index::render(popular_repos, popular_crates))
|
||||
}
|
||||
})
|
||||
) -> Result<Response<Body>, HyperError> {
|
||||
let engine = self.engine.clone();
|
||||
|
||||
let popular =
|
||||
future::try_join(engine.get_popular_repos(), engine.get_popular_crates()).await;
|
||||
|
||||
match popular {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response =
|
||||
views::html::error::render("Could not retrieve popular items", "");
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
Ok(response)
|
||||
}
|
||||
Ok((popular_repos, popular_crates)) => {
|
||||
Ok(views::html::index::render(popular_repos, popular_crates))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn repo_status(
|
||||
async fn repo_status(
|
||||
&self,
|
||||
_req: Request<Body>,
|
||||
params: Params,
|
||||
logger: Logger,
|
||||
format: StatusFormat,
|
||||
) -> impl Future<Item = Response<Body>, Error = HyperError> + Send {
|
||||
) -> Result<Response<Body>, HyperError> {
|
||||
let server = self.clone();
|
||||
|
||||
let site = params.find("site").expect("route param 'site' not found");
|
||||
let qual = params.find("qual").expect("route param 'qual' not found");
|
||||
let name = params.find("name").expect("route param 'name' not found");
|
||||
|
||||
RepoPath::from_parts(site, qual, name)
|
||||
.into_future()
|
||||
.then(move |repo_path_result| match repo_path_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not parse repository path",
|
||||
"Please make sure to provide a valid repository path.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
future::Either::A(future::ok(response))
|
||||
let repo_path_result = RepoPath::from_parts(site, qual, name);
|
||||
|
||||
match repo_path_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not parse repository path",
|
||||
"Please make sure to provide a valid repository path.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
Ok(repo_path) => {
|
||||
let analyze_result = server
|
||||
.engine
|
||||
.analyze_repo_dependencies(repo_path.clone())
|
||||
.await;
|
||||
|
||||
match analyze_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let response =
|
||||
App::status_format_analysis(None, format, SubjectPath::Repo(repo_path));
|
||||
Ok(response)
|
||||
}
|
||||
Ok(analysis_outcome) => {
|
||||
let response = App::status_format_analysis(
|
||||
Some(analysis_outcome),
|
||||
format,
|
||||
SubjectPath::Repo(repo_path),
|
||||
);
|
||||
Ok(response)
|
||||
}
|
||||
}
|
||||
Ok(repo_path) => future::Either::B(
|
||||
server
|
||||
.engine
|
||||
.analyze_repo_dependencies(repo_path.clone())
|
||||
.then(move |analyze_result| match analyze_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let response = Server::status_format_analysis(
|
||||
None,
|
||||
format,
|
||||
SubjectPath::Repo(repo_path),
|
||||
);
|
||||
future::ok(response)
|
||||
}
|
||||
Ok(analysis_outcome) => {
|
||||
let response = Server::status_format_analysis(
|
||||
Some(analysis_outcome),
|
||||
format,
|
||||
SubjectPath::Repo(repo_path),
|
||||
);
|
||||
future::ok(response)
|
||||
}
|
||||
}),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn crate_redirect(
|
||||
async fn crate_redirect(
|
||||
&self,
|
||||
_req: Request<Body>,
|
||||
params: Params,
|
||||
logger: Logger,
|
||||
) -> impl Future<Item = Response<Body>, Error = HyperError> + Send {
|
||||
) -> Result<Response<Body>, HyperError> {
|
||||
let engine = self.engine.clone();
|
||||
|
||||
let name = params.find("name").expect("route param 'name' not found");
|
||||
let crate_name_result = name.parse::<CrateName>();
|
||||
|
||||
name.parse::<CrateName>()
|
||||
.into_future()
|
||||
.then(move |crate_name_result| match crate_name_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not parse crate name",
|
||||
"Please make sure to provide a valid crate name.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
future::Either::A(future::ok(response))
|
||||
match crate_name_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not parse crate name",
|
||||
"Please make sure to provide a valid crate name.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
Ok(crate_name) => {
|
||||
let release_result = engine
|
||||
.find_latest_crate_release(crate_name, VersionReq::any())
|
||||
.await;
|
||||
|
||||
match release_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not fetch crate information",
|
||||
"Please make sure to provide a valid crate name.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::NOT_FOUND;
|
||||
Ok(response)
|
||||
}
|
||||
Ok(None) => {
|
||||
let mut response = views::html::error::render(
|
||||
"Could not fetch crate information",
|
||||
"Please make sure to provide a valid crate name.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::NOT_FOUND;
|
||||
Ok(response)
|
||||
}
|
||||
Ok(Some(release)) => {
|
||||
let redirect_url = format!(
|
||||
"{}/crate/{}/{}",
|
||||
&SELF_BASE_URL as &str,
|
||||
release.name.as_ref(),
|
||||
release.version
|
||||
);
|
||||
|
||||
let res = Response::builder()
|
||||
.status(StatusCode::TEMPORARY_REDIRECT)
|
||||
.header(LOCATION, redirect_url)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
Ok(crate_name) => future::Either::B(
|
||||
engine
|
||||
.find_latest_crate_release(crate_name, VersionReq::any())
|
||||
.then(move |release_result| match release_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not fetch crate information",
|
||||
"Please make sure to provide a valid crate name.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::NOT_FOUND;
|
||||
future::ok(response)
|
||||
}
|
||||
Ok(None) => {
|
||||
let mut response = views::html::error::render(
|
||||
"Could not fetch crate information",
|
||||
"Please make sure to provide a valid crate name.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::NOT_FOUND;
|
||||
future::ok(response)
|
||||
}
|
||||
Ok(Some(release)) => {
|
||||
let mut response = Response::builder();
|
||||
response.status(StatusCode::TEMPORARY_REDIRECT);
|
||||
let url = format!(
|
||||
"{}/crate/{}/{}",
|
||||
&SELF_BASE_URL as &str,
|
||||
release.name.as_ref(),
|
||||
release.version
|
||||
);
|
||||
response.header(LOCATION, url);
|
||||
|
||||
let response = response.body(Body::empty()).unwrap();
|
||||
future::ok(response)
|
||||
}
|
||||
}),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn crate_status(
|
||||
async fn crate_status(
|
||||
&self,
|
||||
_req: Request<Body>,
|
||||
params: Params,
|
||||
logger: Logger,
|
||||
format: StatusFormat,
|
||||
) -> impl Future<Item = Response<Body>, Error = HyperError> + Send {
|
||||
) -> Result<Response<Body>, HyperError> {
|
||||
let server = self.clone();
|
||||
|
||||
let name = params.find("name").expect("route param 'name' not found");
|
||||
|
@ -286,43 +284,46 @@ impl Server {
|
|||
.find("version")
|
||||
.expect("route param 'version' not found");
|
||||
|
||||
CratePath::from_parts(name, version)
|
||||
.into_future()
|
||||
.then(move |crate_path_result| match crate_path_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not parse crate path",
|
||||
"Please make sure to provide a valid crate name and version.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
future::Either::A(future::ok(response))
|
||||
let crate_path_result = CratePath::from_parts(name, version);
|
||||
|
||||
match crate_path_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let mut response = views::html::error::render(
|
||||
"Could not parse crate path",
|
||||
"Please make sure to provide a valid crate name and version.",
|
||||
);
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
Ok(response)
|
||||
}
|
||||
Ok(crate_path) => {
|
||||
let analyze_result = server
|
||||
.engine
|
||||
.analyze_crate_dependencies(crate_path.clone())
|
||||
.await;
|
||||
|
||||
match analyze_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let response = App::status_format_analysis(
|
||||
None,
|
||||
format,
|
||||
SubjectPath::Crate(crate_path),
|
||||
);
|
||||
Ok(response)
|
||||
}
|
||||
Ok(analysis_outcome) => {
|
||||
let response = App::status_format_analysis(
|
||||
Some(analysis_outcome),
|
||||
format,
|
||||
SubjectPath::Crate(crate_path),
|
||||
);
|
||||
|
||||
Ok(response)
|
||||
}
|
||||
}
|
||||
Ok(crate_path) => future::Either::B(
|
||||
server
|
||||
.engine
|
||||
.analyze_crate_dependencies(crate_path.clone())
|
||||
.then(move |analyze_result| match analyze_result {
|
||||
Err(err) => {
|
||||
error!(logger, "error: {}", err);
|
||||
let response = Server::status_format_analysis(
|
||||
None,
|
||||
format,
|
||||
SubjectPath::Crate(crate_path),
|
||||
);
|
||||
future::ok(response)
|
||||
}
|
||||
Ok(analysis_outcome) => {
|
||||
let response = Server::status_format_analysis(
|
||||
Some(analysis_outcome),
|
||||
format,
|
||||
SubjectPath::Crate(crate_path),
|
||||
);
|
||||
future::ok(response)
|
||||
}
|
||||
}),
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn status_format_analysis(
|
||||
|
|
|
@ -8,7 +8,7 @@ pub mod error;
|
|||
pub mod index;
|
||||
pub mod status;
|
||||
|
||||
use super::super::SELF_BASE_URL;
|
||||
use crate::server::SELF_BASE_URL;
|
||||
|
||||
fn render_html<B: Render>(title: &str, body: B) -> Response<Body> {
|
||||
let rendered = html! {
|
||||
|
|
|
@ -6,8 +6,7 @@ use crate::engine::AnalyzeDependenciesOutcome;
|
|||
use crate::models::crates::{AnalyzedDependencies, AnalyzedDependency, CrateName};
|
||||
use crate::models::repo::RepoSite;
|
||||
use crate::models::SubjectPath;
|
||||
|
||||
use super::super::badge;
|
||||
use crate::server::views::badge;
|
||||
|
||||
fn dependency_tables(crate_name: CrateName, deps: AnalyzedDependencies) -> Markup {
|
||||
html! {
|
||||
|
|
|
@ -1,29 +1,31 @@
|
|||
use std::fmt::{Debug, Formatter, Result as FmtResult};
|
||||
use std::hash::Hash;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Mutex;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{
|
||||
fmt::{Debug, Formatter, Result as FmtResult},
|
||||
hash::Hash,
|
||||
sync::Mutex,
|
||||
task::Context,
|
||||
task::Poll,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, ensure, Error};
|
||||
use futures::future::{FromErr, Shared, SharedItem};
|
||||
use futures::{Future, Poll};
|
||||
use anyhow::Error;
|
||||
use hyper::service::Service;
|
||||
use lru_cache::LruCache;
|
||||
use tokio_service::Service;
|
||||
|
||||
pub struct Cache<S>
|
||||
pub struct Cache<S, Req>
|
||||
where
|
||||
S: Service<Error = Error>,
|
||||
S::Request: Hash + Eq,
|
||||
S: Service<Req>,
|
||||
Req: Hash + Eq,
|
||||
{
|
||||
inner: S,
|
||||
duration: Duration,
|
||||
cache: Mutex<LruCache<S::Request, (Instant, Shared<FromErr<S::Future, Error>>)>>,
|
||||
#[allow(unused)]
|
||||
cache: Mutex<LruCache<Req, (Instant, S::Response)>>,
|
||||
}
|
||||
|
||||
impl<S> Debug for Cache<S>
|
||||
impl<S, Req> Debug for Cache<S, Req>
|
||||
where
|
||||
S: Service<Error = Error> + Debug,
|
||||
S::Request: Hash + Eq,
|
||||
S: Service<Req> + Debug,
|
||||
Req: Hash + Eq,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
|
||||
fmt.debug_struct("Cache")
|
||||
|
@ -33,12 +35,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Cache<S>
|
||||
impl<S, Req> Cache<S, Req>
|
||||
where
|
||||
S: Service<Error = Error>,
|
||||
S::Request: Hash + Eq,
|
||||
S: Service<Req>,
|
||||
Req: Hash + Eq,
|
||||
{
|
||||
pub fn new(service: S, duration: Duration, capacity: usize) -> Cache<S> {
|
||||
pub fn new(service: S, duration: Duration, capacity: usize) -> Cache<S, Req> {
|
||||
Cache {
|
||||
inner: service,
|
||||
duration: duration,
|
||||
|
@ -47,63 +49,62 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Service for Cache<S>
|
||||
impl<S, Req> Service<Req> for Cache<S, Req>
|
||||
where
|
||||
S: Service<Error = Error>,
|
||||
S::Request: Clone + Hash + Eq,
|
||||
S: Service<Req, Error = Error>,
|
||||
S::Response: Clone,
|
||||
Req: Clone + Hash + Eq,
|
||||
{
|
||||
type Request = S::Request;
|
||||
type Response = CachedItem<S::Response>;
|
||||
type Response = S::Response;
|
||||
type Error = Error;
|
||||
type Future = Cached<S::Future>;
|
||||
// WAS: type Future = Cached<S::Future>;
|
||||
// type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
|
||||
type Future = S::Future;
|
||||
|
||||
fn call(&self, req: Self::Request) -> Self::Future {
|
||||
let now = Instant::now();
|
||||
let mut cache = self.cache.lock().expect("lock poisoned");
|
||||
if let Some(&mut (valid_until, ref shared_future)) = cache.get_mut(&req) {
|
||||
if valid_until > now {
|
||||
if let Some(Ok(_)) = shared_future.peek() {
|
||||
return Cached(shared_future.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
let shared_future = self.inner.call(req.clone()).from_err().shared();
|
||||
cache.insert(req, (now + self.duration, shared_future.clone()));
|
||||
Cached(shared_future)
|
||||
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn call(&mut self, req: Req) -> Self::Future {
|
||||
// TODO: re-add caching
|
||||
// Box::pin({
|
||||
// let now = Instant::now();
|
||||
// let mut cache = self.cache.lock().expect("lock poisoned");
|
||||
|
||||
// if let Some(&mut (valid_until, ref cached_response)) = cache.get_mut(&req) {
|
||||
// if valid_until > now {
|
||||
// return Box::pin(ok(cached_response.clone()));
|
||||
// }
|
||||
// }
|
||||
|
||||
self.inner.call(req.clone())
|
||||
// .and_then(|response| {
|
||||
// // cache.insert(req, (now + self.duration, response.clone()));
|
||||
// ok(response)
|
||||
// })
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Cached<F: Future<Error = Error>>(Shared<FromErr<F, Error>>);
|
||||
// pub struct Cached<F: Future>(Shared<F>);
|
||||
|
||||
impl<F> Debug for Cached<F>
|
||||
where
|
||||
F: Future<Error = Error> + Debug,
|
||||
F::Item: Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
|
||||
self.0.fmt(fmt)
|
||||
}
|
||||
}
|
||||
// impl<F> Debug for Cached<F>
|
||||
// where
|
||||
// F: Future + Debug,
|
||||
// F::Output: Debug,
|
||||
// {
|
||||
// fn fmt(&self, fmt: &mut Formatter<'_>) -> FmtResult {
|
||||
// self.0.fmt(fmt)
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<F: Future<Error = Error>> Future for Cached<F> {
|
||||
type Item = CachedItem<F::Item>;
|
||||
type Error = Error;
|
||||
// // WAS: impl<F: Future<Error = Error>> Future for Cached<F> {
|
||||
// impl<F: Future> Future for Cached<F> {
|
||||
// type Output = Result<F::Output, Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.0
|
||||
.poll()
|
||||
.map_err(|_err| anyhow!("TODO: shared error not clone-able"))
|
||||
.map(|item| item.map(CachedItem))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CachedItem<T>(SharedItem<T>);
|
||||
|
||||
impl<T> Deref for CachedItem<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
&self.0.deref()
|
||||
}
|
||||
}
|
||||
// fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// self.0
|
||||
// .poll()
|
||||
// .map_err(|_err| anyhow!("TODO: shared error not clone-able"))
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in a new issue