├── .cargo └── config.toml ├── .dockerignore ├── .github └── workflows │ └── cd.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── README.md ├── build.rs ├── scripts ├── requirements.txt └── target.py ├── src ├── autoscan.rs ├── config.rs ├── drive.rs ├── lib.rs └── main.rs └── xtask ├── Cargo.toml └── src ├── commands ├── ci.rs ├── dist.rs ├── docker.rs └── mod.rs ├── lib.rs └── main.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | xtask = "run --release --package xtask --" -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | ** 3 | 4 | # Allow target/dist 5 | !/target/dist/** 6 | # Allow scripts 7 | !/scripts/** -------------------------------------------------------------------------------- /.github/workflows/cd.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Delivery 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | build: 9 | name: Build (${{ matrix.target }}) 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | matrix: 13 | include: 14 | # linux/amd64 15 | - os: ubuntu-latest 16 | target: x86_64-unknown-linux-musl 17 | # linux/arm64 18 | - os: ubuntu-latest 19 | target: aarch64-unknown-linux-musl 20 | # linux/arm/v7 21 | - os: ubuntu-latest 22 | target: armv7-unknown-linux-musleabihf 23 | # linux/arm/v6 24 | - os: ubuntu-latest 25 | target: arm-unknown-linux-musleabihf 26 | # MacOS: Intel (TODO: add Apple Silicon once Big Sur is available) 27 | - os: macos-latest 28 | target: x86_64-apple-darwin 29 | # Windows 30 | - os: windows-latest 31 | target: x86_64-pc-windows-msvc 32 | steps: 33 | - name: Check out code 34 | uses: actions/checkout@v2 35 | 36 | # With each cache weighing in at ~500MB per target, 37 | # and this repository maxing out at 5GB of caches, 38 | # it might make sense not to cache dependencies. 39 | - name: Cache dependencies 40 | uses: Swatinem/rust-cache@v1 41 | 42 | - name: Install Rust Cross 43 | run: cargo install cross 44 | 45 | - name: Run dist 46 | run: cargo xtask dist ${{ matrix.target }} 47 | 48 | - name: Upload artifacts 49 | uses: actions/upload-artifact@v2 50 | with: 51 | name: ${{ matrix.target }} 52 | path: ./target/dist/ 53 | if-no-files-found: error 54 | retention-days: 7 55 | 56 | docker: 57 | name: Build Docker image 58 | runs-on: ubuntu-latest 59 | needs: build 60 | steps: 61 | - name: Check out code 62 | uses: actions/checkout@v2 63 | 64 | - name: Set up Docker Buildx 65 | id: buildx 66 | uses: docker/setup-buildx-action@v1 67 | 68 | - name: Available platforms 69 | run: echo ${{ steps.buildx.outputs.platforms }} 70 | 71 | - name: Log in to GitHub Container Registry 72 | uses: docker/login-action@v1 73 | with: 74 | registry: ghcr.io 75 | username: ${{ github.repository_owner }} 76 | password: ${{ secrets.GITHUB_TOKEN }} 77 | 78 | # linux/amd64 79 | - uses: actions/download-artifact@v2 80 | with: 81 | name: x86_64-unknown-linux-musl 82 | path: target/dist 83 | 84 | # linux/arm64 85 | - uses: actions/download-artifact@v2 86 | with: 87 | name: aarch64-unknown-linux-musl 88 | path: target/dist 89 | 90 | # linux/arm/v7 91 | - uses: actions/download-artifact@v2 92 | with: 93 | name: armv7-unknown-linux-musleabihf 94 | path: target/dist 95 | 96 | # linux/arm/v6 97 | - uses: actions/download-artifact@v2 98 | with: 99 | name: arm-unknown-linux-musleabihf 100 | path: target/dist 101 | 102 | - name: Display structure of downloaded files 103 | run: ls -R 104 | working-directory: target/dist 105 | 106 | - name: Build and push 107 | run: cargo xtask docker build --push -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | *.env 3 | .mypy_cache 4 | .DS_Store 5 | .vscode 6 | 7 | # Rust-specific 8 | /target 9 | 10 | # Project-specific 11 | *.json 12 | *.toml 13 | !/.cargo/** 14 | !Cargo.toml 15 | 16 | # SQLite 17 | *.db 18 | *.db-shm 19 | *.db-wal 20 | 21 | # Keys 22 | *.pem -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "a-train" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "anyhow", 10 | "async-trait", 11 | "bernard", 12 | "chrono", 13 | "clap", 14 | "color-eyre", 15 | "eyre", 16 | "futures", 17 | "pretty_assertions", 18 | "reqwest", 19 | "serde", 20 | "serde_json", 21 | "thiserror", 22 | "tikv-jemallocator", 23 | "tokio", 24 | "toml", 25 | "tower", 26 | "tracing", 27 | "tracing-subscriber", 28 | "vergen", 29 | "wiremock", 30 | ] 31 | 32 | [[package]] 33 | name = "addr2line" 34 | version = "0.16.0" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" 37 | dependencies = [ 38 | "gimli", 39 | ] 40 | 41 | [[package]] 42 | name = "adler" 43 | version = "1.0.2" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 46 | 47 | [[package]] 48 | name = "ahash" 49 | version = "0.7.6" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 52 | dependencies = [ 53 | "getrandom 0.2.3", 54 | "once_cell", 55 | "version_check 0.9.3", 56 | ] 57 | 58 | [[package]] 59 | name = "aho-corasick" 60 | version = "0.7.18" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 63 | dependencies = [ 64 | "memchr", 65 | ] 66 | 67 | [[package]] 68 | name = "ansi_term" 69 | version = "0.12.1" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 72 | dependencies = [ 73 | "winapi", 74 | ] 75 | 76 | [[package]] 77 | name = "anyhow" 78 | version = "1.0.44" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" 81 | 82 | [[package]] 83 | name = "arrayvec" 84 | version = "0.5.2" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 87 | 88 | [[package]] 89 | name = "async-channel" 90 | version = "1.6.1" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" 93 | dependencies = [ 94 | "concurrent-queue", 95 | "event-listener", 96 | "futures-core", 97 | ] 98 | 99 | [[package]] 100 | name = "async-trait" 101 | version = "0.1.51" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" 104 | dependencies = [ 105 | "proc-macro2", 106 | "quote", 107 | "syn", 108 | ] 109 | 110 | [[package]] 111 | name = "atoi" 112 | version = "0.4.0" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5" 115 | dependencies = [ 116 | "num-traits", 117 | ] 118 | 119 | [[package]] 120 | name = "atty" 121 | version = "0.2.14" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 124 | dependencies = [ 125 | "hermit-abi", 126 | "libc", 127 | "winapi", 128 | ] 129 | 130 | [[package]] 131 | name = "autocfg" 132 | version = "1.0.1" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 135 | 136 | [[package]] 137 | name = "backoff" 138 | version = "0.3.0" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "9fe17f59a06fe8b87a6fc8bf53bb70b3aba76d7685f432487a68cd5552853625" 141 | dependencies = [ 142 | "futures-core", 143 | "getrandom 0.2.3", 144 | "instant", 145 | "pin-project", 146 | "rand 0.8.4", 147 | "tokio", 148 | ] 149 | 150 | [[package]] 151 | name = "backtrace" 152 | version = "0.3.61" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" 155 | dependencies = [ 156 | "addr2line", 157 | "cc", 158 | "cfg-if 1.0.0", 159 | "libc", 160 | "miniz_oxide", 161 | "object", 162 | "rustc-demangle", 163 | ] 164 | 165 | [[package]] 166 | name = "base64" 167 | version = "0.10.1" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" 170 | dependencies = [ 171 | "byteorder", 172 | ] 173 | 174 | [[package]] 175 | name = "base64" 176 | version = "0.12.3" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" 179 | 180 | [[package]] 181 | name = "base64" 182 | version = "0.13.0" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 185 | 186 | [[package]] 187 | name = "bernard" 188 | version = "0.1.0" 189 | source = "git+https://github.com/m-rots/bernard-rs?branch=main#cdcc81e61f0dc7d048dfc63ddd6162b749cfb8bf" 190 | dependencies = [ 191 | "backoff", 192 | "chrono", 193 | "futures", 194 | "itertools", 195 | "jsonwebtoken", 196 | "reqwest", 197 | "ring", 198 | "serde", 199 | "serde_json", 200 | "snafu", 201 | "sqlx", 202 | "tap", 203 | "tokio", 204 | "tracing", 205 | ] 206 | 207 | [[package]] 208 | name = "bitflags" 209 | version = "1.3.2" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 212 | 213 | [[package]] 214 | name = "block-buffer" 215 | version = "0.9.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 218 | dependencies = [ 219 | "generic-array", 220 | ] 221 | 222 | [[package]] 223 | name = "bumpalo" 224 | version = "3.8.0" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" 227 | 228 | [[package]] 229 | name = "byteorder" 230 | version = "1.4.3" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 233 | 234 | [[package]] 235 | name = "bytes" 236 | version = "1.1.0" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 239 | 240 | [[package]] 241 | name = "cache-padded" 242 | version = "1.1.1" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" 245 | 246 | [[package]] 247 | name = "cc" 248 | version = "1.0.71" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" 251 | 252 | [[package]] 253 | name = "cfg-if" 254 | version = "0.1.10" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 257 | 258 | [[package]] 259 | name = "cfg-if" 260 | version = "1.0.0" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 263 | 264 | [[package]] 265 | name = "chrono" 266 | version = "0.4.19" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 269 | dependencies = [ 270 | "libc", 271 | "num-integer", 272 | "num-traits", 273 | "serde", 274 | "time", 275 | "winapi", 276 | ] 277 | 278 | [[package]] 279 | name = "clap" 280 | version = "3.0.0-beta.5" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63" 283 | dependencies = [ 284 | "atty", 285 | "bitflags", 286 | "clap_derive", 287 | "indexmap", 288 | "lazy_static", 289 | "os_str_bytes", 290 | "strsim", 291 | "termcolor", 292 | "textwrap", 293 | "unicase", 294 | ] 295 | 296 | [[package]] 297 | name = "clap_derive" 298 | version = "3.0.0-beta.5" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3" 301 | dependencies = [ 302 | "heck", 303 | "proc-macro-error", 304 | "proc-macro2", 305 | "quote", 306 | "syn", 307 | ] 308 | 309 | [[package]] 310 | name = "color-eyre" 311 | version = "0.5.11" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "1f1885697ee8a177096d42f158922251a41973117f6d8a234cee94b9509157b7" 314 | dependencies = [ 315 | "backtrace", 316 | "color-spantrace", 317 | "eyre", 318 | "indenter", 319 | "once_cell", 320 | "owo-colors", 321 | "tracing-error", 322 | ] 323 | 324 | [[package]] 325 | name = "color-spantrace" 326 | version = "0.1.6" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "b6eee477a4a8a72f4addd4de416eb56d54bc307b284d6601bafdee1f4ea462d1" 329 | dependencies = [ 330 | "once_cell", 331 | "owo-colors", 332 | "tracing-core", 333 | "tracing-error", 334 | ] 335 | 336 | [[package]] 337 | name = "colored" 338 | version = "2.0.0" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" 341 | dependencies = [ 342 | "atty", 343 | "lazy_static", 344 | "winapi", 345 | ] 346 | 347 | [[package]] 348 | name = "concurrent-queue" 349 | version = "1.2.2" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" 352 | dependencies = [ 353 | "cache-padded", 354 | ] 355 | 356 | [[package]] 357 | name = "config" 358 | version = "0.10.1" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" 361 | dependencies = [ 362 | "lazy_static", 363 | "nom 5.1.2", 364 | "serde", 365 | ] 366 | 367 | [[package]] 368 | name = "cpufeatures" 369 | version = "0.2.1" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" 372 | dependencies = [ 373 | "libc", 374 | ] 375 | 376 | [[package]] 377 | name = "crc" 378 | version = "2.0.0" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "10c2722795460108a7872e1cd933a85d6ec38abc4baecad51028f702da28889f" 381 | dependencies = [ 382 | "crc-catalog", 383 | ] 384 | 385 | [[package]] 386 | name = "crc-catalog" 387 | version = "1.1.1" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403" 390 | 391 | [[package]] 392 | name = "crc32fast" 393 | version = "1.2.1" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 396 | dependencies = [ 397 | "cfg-if 1.0.0", 398 | ] 399 | 400 | [[package]] 401 | name = "crossbeam-channel" 402 | version = "0.3.9" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" 405 | dependencies = [ 406 | "crossbeam-utils 0.6.6", 407 | ] 408 | 409 | [[package]] 410 | name = "crossbeam-channel" 411 | version = "0.5.1" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" 414 | dependencies = [ 415 | "cfg-if 1.0.0", 416 | "crossbeam-utils 0.8.5", 417 | ] 418 | 419 | [[package]] 420 | name = "crossbeam-queue" 421 | version = "0.3.2" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9" 424 | dependencies = [ 425 | "cfg-if 1.0.0", 426 | "crossbeam-utils 0.8.5", 427 | ] 428 | 429 | [[package]] 430 | name = "crossbeam-utils" 431 | version = "0.6.6" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" 434 | dependencies = [ 435 | "cfg-if 0.1.10", 436 | "lazy_static", 437 | ] 438 | 439 | [[package]] 440 | name = "crossbeam-utils" 441 | version = "0.8.5" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" 444 | dependencies = [ 445 | "cfg-if 1.0.0", 446 | "lazy_static", 447 | ] 448 | 449 | [[package]] 450 | name = "ctor" 451 | version = "0.1.21" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" 454 | dependencies = [ 455 | "quote", 456 | "syn", 457 | ] 458 | 459 | [[package]] 460 | name = "deadpool" 461 | version = "0.7.0" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "3d126179d86aee4556e54f5f3c6bf6d9884e7cc52cef82f77ee6f90a7747616d" 464 | dependencies = [ 465 | "async-trait", 466 | "config", 467 | "crossbeam-queue", 468 | "num_cpus", 469 | "serde", 470 | "tokio", 471 | ] 472 | 473 | [[package]] 474 | name = "diff" 475 | version = "0.1.12" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" 478 | 479 | [[package]] 480 | name = "digest" 481 | version = "0.9.0" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 484 | dependencies = [ 485 | "generic-array", 486 | ] 487 | 488 | [[package]] 489 | name = "doc-comment" 490 | version = "0.3.3" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" 493 | 494 | [[package]] 495 | name = "dotenv" 496 | version = "0.15.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 499 | 500 | [[package]] 501 | name = "either" 502 | version = "1.6.1" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 505 | 506 | [[package]] 507 | name = "encoding_rs" 508 | version = "0.8.29" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" 511 | dependencies = [ 512 | "cfg-if 1.0.0", 513 | ] 514 | 515 | [[package]] 516 | name = "enum-iterator" 517 | version = "0.7.0" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" 520 | dependencies = [ 521 | "enum-iterator-derive", 522 | ] 523 | 524 | [[package]] 525 | name = "enum-iterator-derive" 526 | version = "0.7.0" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" 529 | dependencies = [ 530 | "proc-macro2", 531 | "quote", 532 | "syn", 533 | ] 534 | 535 | [[package]] 536 | name = "event-listener" 537 | version = "2.5.1" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" 540 | 541 | [[package]] 542 | name = "eyre" 543 | version = "0.6.5" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "221239d1d5ea86bf5d6f91c9d6bc3646ffe471b08ff9b0f91c44f115ac969d2b" 546 | dependencies = [ 547 | "indenter", 548 | "once_cell", 549 | ] 550 | 551 | [[package]] 552 | name = "fastrand" 553 | version = "1.5.0" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e" 556 | dependencies = [ 557 | "instant", 558 | ] 559 | 560 | [[package]] 561 | name = "flate2" 562 | version = "1.0.22" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" 565 | dependencies = [ 566 | "cfg-if 1.0.0", 567 | "crc32fast", 568 | "libc", 569 | "miniz_oxide", 570 | ] 571 | 572 | [[package]] 573 | name = "fnv" 574 | version = "1.0.7" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 577 | 578 | [[package]] 579 | name = "form_urlencoded" 580 | version = "1.0.1" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 583 | dependencies = [ 584 | "matches", 585 | "percent-encoding", 586 | ] 587 | 588 | [[package]] 589 | name = "fs_extra" 590 | version = "1.2.0" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394" 593 | 594 | [[package]] 595 | name = "futures" 596 | version = "0.3.17" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" 599 | dependencies = [ 600 | "futures-channel", 601 | "futures-core", 602 | "futures-executor", 603 | "futures-io", 604 | "futures-sink", 605 | "futures-task", 606 | "futures-util", 607 | ] 608 | 609 | [[package]] 610 | name = "futures-channel" 611 | version = "0.3.17" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" 614 | dependencies = [ 615 | "futures-core", 616 | "futures-sink", 617 | ] 618 | 619 | [[package]] 620 | name = "futures-core" 621 | version = "0.3.17" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" 624 | 625 | [[package]] 626 | name = "futures-executor" 627 | version = "0.3.17" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" 630 | dependencies = [ 631 | "futures-core", 632 | "futures-task", 633 | "futures-util", 634 | ] 635 | 636 | [[package]] 637 | name = "futures-intrusive" 638 | version = "0.4.0" 639 | source = "registry+https://github.com/rust-lang/crates.io-index" 640 | checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" 641 | dependencies = [ 642 | "futures-core", 643 | "lock_api", 644 | "parking_lot", 645 | ] 646 | 647 | [[package]] 648 | name = "futures-io" 649 | version = "0.3.17" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" 652 | 653 | [[package]] 654 | name = "futures-lite" 655 | version = "1.12.0" 656 | source = "registry+https://github.com/rust-lang/crates.io-index" 657 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 658 | dependencies = [ 659 | "fastrand", 660 | "futures-core", 661 | "futures-io", 662 | "memchr", 663 | "parking", 664 | "pin-project-lite", 665 | "waker-fn", 666 | ] 667 | 668 | [[package]] 669 | name = "futures-macro" 670 | version = "0.3.17" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" 673 | dependencies = [ 674 | "autocfg", 675 | "proc-macro-hack", 676 | "proc-macro2", 677 | "quote", 678 | "syn", 679 | ] 680 | 681 | [[package]] 682 | name = "futures-sink" 683 | version = "0.3.17" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" 686 | 687 | [[package]] 688 | name = "futures-task" 689 | version = "0.3.17" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" 692 | 693 | [[package]] 694 | name = "futures-timer" 695 | version = "3.0.2" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" 698 | 699 | [[package]] 700 | name = "futures-util" 701 | version = "0.3.17" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" 704 | dependencies = [ 705 | "autocfg", 706 | "futures-channel", 707 | "futures-core", 708 | "futures-io", 709 | "futures-macro", 710 | "futures-sink", 711 | "futures-task", 712 | "memchr", 713 | "pin-project-lite", 714 | "pin-utils", 715 | "proc-macro-hack", 716 | "proc-macro-nested", 717 | "slab", 718 | ] 719 | 720 | [[package]] 721 | name = "generic-array" 722 | version = "0.14.4" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 725 | dependencies = [ 726 | "typenum", 727 | "version_check 0.9.3", 728 | ] 729 | 730 | [[package]] 731 | name = "getrandom" 732 | version = "0.1.16" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 735 | dependencies = [ 736 | "cfg-if 1.0.0", 737 | "libc", 738 | "wasi 0.9.0+wasi-snapshot-preview1", 739 | ] 740 | 741 | [[package]] 742 | name = "getrandom" 743 | version = "0.2.3" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 746 | dependencies = [ 747 | "cfg-if 1.0.0", 748 | "libc", 749 | "wasi 0.10.2+wasi-snapshot-preview1", 750 | ] 751 | 752 | [[package]] 753 | name = "getset" 754 | version = "0.1.1" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504" 757 | dependencies = [ 758 | "proc-macro-error", 759 | "proc-macro2", 760 | "quote", 761 | "syn", 762 | ] 763 | 764 | [[package]] 765 | name = "gimli" 766 | version = "0.25.0" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" 769 | 770 | [[package]] 771 | name = "h2" 772 | version = "0.3.6" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | checksum = "6c06815895acec637cd6ed6e9662c935b866d20a106f8361892893a7d9234964" 775 | dependencies = [ 776 | "bytes", 777 | "fnv", 778 | "futures-core", 779 | "futures-sink", 780 | "futures-util", 781 | "http", 782 | "indexmap", 783 | "slab", 784 | "tokio", 785 | "tokio-util", 786 | "tracing", 787 | ] 788 | 789 | [[package]] 790 | name = "hashbrown" 791 | version = "0.11.2" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 794 | dependencies = [ 795 | "ahash", 796 | ] 797 | 798 | [[package]] 799 | name = "hashlink" 800 | version = "0.7.0" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" 803 | dependencies = [ 804 | "hashbrown", 805 | ] 806 | 807 | [[package]] 808 | name = "hdrhistogram" 809 | version = "6.3.4" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "08d331ebcdbca4acbefe5da8c3299b2e246f198a8294cc5163354e743398b89d" 812 | dependencies = [ 813 | "base64 0.10.1", 814 | "byteorder", 815 | "crossbeam-channel 0.3.9", 816 | "flate2", 817 | "nom 4.2.3", 818 | "num-traits", 819 | ] 820 | 821 | [[package]] 822 | name = "heck" 823 | version = "0.3.3" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" 826 | dependencies = [ 827 | "unicode-segmentation", 828 | ] 829 | 830 | [[package]] 831 | name = "hermit-abi" 832 | version = "0.1.19" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 835 | dependencies = [ 836 | "libc", 837 | ] 838 | 839 | [[package]] 840 | name = "hex" 841 | version = "0.4.3" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 844 | 845 | [[package]] 846 | name = "http" 847 | version = "0.2.5" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" 850 | dependencies = [ 851 | "bytes", 852 | "fnv", 853 | "itoa", 854 | ] 855 | 856 | [[package]] 857 | name = "http-body" 858 | version = "0.4.3" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" 861 | dependencies = [ 862 | "bytes", 863 | "http", 864 | "pin-project-lite", 865 | ] 866 | 867 | [[package]] 868 | name = "http-types" 869 | version = "2.12.0" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" 872 | dependencies = [ 873 | "anyhow", 874 | "async-channel", 875 | "base64 0.13.0", 876 | "futures-lite", 877 | "http", 878 | "infer", 879 | "pin-project-lite", 880 | "rand 0.7.3", 881 | "serde", 882 | "serde_json", 883 | "serde_qs", 884 | "serde_urlencoded", 885 | "url", 886 | ] 887 | 888 | [[package]] 889 | name = "httparse" 890 | version = "1.5.1" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" 893 | 894 | [[package]] 895 | name = "httpdate" 896 | version = "1.0.1" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" 899 | 900 | [[package]] 901 | name = "hyper" 902 | version = "0.14.13" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" 905 | dependencies = [ 906 | "bytes", 907 | "futures-channel", 908 | "futures-core", 909 | "futures-util", 910 | "h2", 911 | "http", 912 | "http-body", 913 | "httparse", 914 | "httpdate", 915 | "itoa", 916 | "pin-project-lite", 917 | "socket2", 918 | "tokio", 919 | "tower-service", 920 | "tracing", 921 | "want", 922 | ] 923 | 924 | [[package]] 925 | name = "hyper-rustls" 926 | version = "0.22.1" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" 929 | dependencies = [ 930 | "futures-util", 931 | "hyper", 932 | "log", 933 | "rustls", 934 | "tokio", 935 | "tokio-rustls", 936 | "webpki", 937 | ] 938 | 939 | [[package]] 940 | name = "idna" 941 | version = "0.2.3" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 944 | dependencies = [ 945 | "matches", 946 | "unicode-bidi", 947 | "unicode-normalization", 948 | ] 949 | 950 | [[package]] 951 | name = "indenter" 952 | version = "0.3.3" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" 955 | 956 | [[package]] 957 | name = "indexmap" 958 | version = "1.7.0" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" 961 | dependencies = [ 962 | "autocfg", 963 | "hashbrown", 964 | ] 965 | 966 | [[package]] 967 | name = "infer" 968 | version = "0.2.3" 969 | source = "registry+https://github.com/rust-lang/crates.io-index" 970 | checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" 971 | 972 | [[package]] 973 | name = "instant" 974 | version = "0.1.12" 975 | source = "registry+https://github.com/rust-lang/crates.io-index" 976 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 977 | dependencies = [ 978 | "cfg-if 1.0.0", 979 | ] 980 | 981 | [[package]] 982 | name = "ipnet" 983 | version = "2.3.1" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" 986 | 987 | [[package]] 988 | name = "itertools" 989 | version = "0.10.1" 990 | source = "registry+https://github.com/rust-lang/crates.io-index" 991 | checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" 992 | dependencies = [ 993 | "either", 994 | ] 995 | 996 | [[package]] 997 | name = "itoa" 998 | version = "0.4.8" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" 1001 | 1002 | [[package]] 1003 | name = "js-sys" 1004 | version = "0.3.55" 1005 | source = "registry+https://github.com/rust-lang/crates.io-index" 1006 | checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" 1007 | dependencies = [ 1008 | "wasm-bindgen", 1009 | ] 1010 | 1011 | [[package]] 1012 | name = "jsonwebtoken" 1013 | version = "7.2.0" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "afabcc15e437a6484fc4f12d0fd63068fe457bf93f1c148d3d9649c60b103f32" 1016 | dependencies = [ 1017 | "base64 0.12.3", 1018 | "pem", 1019 | "ring", 1020 | "serde", 1021 | "serde_json", 1022 | "simple_asn1", 1023 | ] 1024 | 1025 | [[package]] 1026 | name = "lazy_static" 1027 | version = "1.4.0" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1030 | 1031 | [[package]] 1032 | name = "lexical-core" 1033 | version = "0.7.6" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" 1036 | dependencies = [ 1037 | "arrayvec", 1038 | "bitflags", 1039 | "cfg-if 1.0.0", 1040 | "ryu", 1041 | "static_assertions", 1042 | ] 1043 | 1044 | [[package]] 1045 | name = "libc" 1046 | version = "0.2.104" 1047 | source = "registry+https://github.com/rust-lang/crates.io-index" 1048 | checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce" 1049 | 1050 | [[package]] 1051 | name = "libsqlite3-sys" 1052 | version = "0.22.2" 1053 | source = "registry+https://github.com/rust-lang/crates.io-index" 1054 | checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d" 1055 | dependencies = [ 1056 | "cc", 1057 | "pkg-config", 1058 | "vcpkg", 1059 | ] 1060 | 1061 | [[package]] 1062 | name = "lock_api" 1063 | version = "0.4.5" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" 1066 | dependencies = [ 1067 | "scopeguard", 1068 | ] 1069 | 1070 | [[package]] 1071 | name = "log" 1072 | version = "0.4.14" 1073 | source = "registry+https://github.com/rust-lang/crates.io-index" 1074 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 1075 | dependencies = [ 1076 | "cfg-if 1.0.0", 1077 | ] 1078 | 1079 | [[package]] 1080 | name = "matchers" 1081 | version = "0.0.1" 1082 | source = "registry+https://github.com/rust-lang/crates.io-index" 1083 | checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" 1084 | dependencies = [ 1085 | "regex-automata", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "matches" 1090 | version = "0.1.9" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 1093 | 1094 | [[package]] 1095 | name = "memchr" 1096 | version = "2.4.1" 1097 | source = "registry+https://github.com/rust-lang/crates.io-index" 1098 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 1099 | 1100 | [[package]] 1101 | name = "mime" 1102 | version = "0.3.16" 1103 | source = "registry+https://github.com/rust-lang/crates.io-index" 1104 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1105 | 1106 | [[package]] 1107 | name = "minimal-lexical" 1108 | version = "0.1.4" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677" 1111 | 1112 | [[package]] 1113 | name = "miniz_oxide" 1114 | version = "0.4.4" 1115 | source = "registry+https://github.com/rust-lang/crates.io-index" 1116 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 1117 | dependencies = [ 1118 | "adler", 1119 | "autocfg", 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "mio" 1124 | version = "0.7.14" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" 1127 | dependencies = [ 1128 | "libc", 1129 | "log", 1130 | "miow", 1131 | "ntapi", 1132 | "winapi", 1133 | ] 1134 | 1135 | [[package]] 1136 | name = "miow" 1137 | version = "0.3.7" 1138 | source = "registry+https://github.com/rust-lang/crates.io-index" 1139 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 1140 | dependencies = [ 1141 | "winapi", 1142 | ] 1143 | 1144 | [[package]] 1145 | name = "nom" 1146 | version = "4.2.3" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" 1149 | dependencies = [ 1150 | "memchr", 1151 | "version_check 0.1.5", 1152 | ] 1153 | 1154 | [[package]] 1155 | name = "nom" 1156 | version = "5.1.2" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 1159 | dependencies = [ 1160 | "lexical-core", 1161 | "memchr", 1162 | "version_check 0.9.3", 1163 | ] 1164 | 1165 | [[package]] 1166 | name = "nom" 1167 | version = "7.0.0" 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" 1169 | checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1" 1170 | dependencies = [ 1171 | "memchr", 1172 | "minimal-lexical", 1173 | "version_check 0.9.3", 1174 | ] 1175 | 1176 | [[package]] 1177 | name = "ntapi" 1178 | version = "0.3.6" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 1181 | dependencies = [ 1182 | "winapi", 1183 | ] 1184 | 1185 | [[package]] 1186 | name = "num-bigint" 1187 | version = "0.2.6" 1188 | source = "registry+https://github.com/rust-lang/crates.io-index" 1189 | checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" 1190 | dependencies = [ 1191 | "autocfg", 1192 | "num-integer", 1193 | "num-traits", 1194 | ] 1195 | 1196 | [[package]] 1197 | name = "num-integer" 1198 | version = "0.1.44" 1199 | source = "registry+https://github.com/rust-lang/crates.io-index" 1200 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 1201 | dependencies = [ 1202 | "autocfg", 1203 | "num-traits", 1204 | ] 1205 | 1206 | [[package]] 1207 | name = "num-traits" 1208 | version = "0.2.14" 1209 | source = "registry+https://github.com/rust-lang/crates.io-index" 1210 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 1211 | dependencies = [ 1212 | "autocfg", 1213 | ] 1214 | 1215 | [[package]] 1216 | name = "num_cpus" 1217 | version = "1.13.0" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 1220 | dependencies = [ 1221 | "hermit-abi", 1222 | "libc", 1223 | ] 1224 | 1225 | [[package]] 1226 | name = "object" 1227 | version = "0.26.2" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" 1230 | dependencies = [ 1231 | "memchr", 1232 | ] 1233 | 1234 | [[package]] 1235 | name = "once_cell" 1236 | version = "1.8.0" 1237 | source = "registry+https://github.com/rust-lang/crates.io-index" 1238 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 1239 | 1240 | [[package]] 1241 | name = "opaque-debug" 1242 | version = "0.3.0" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 1245 | 1246 | [[package]] 1247 | name = "os_str_bytes" 1248 | version = "4.2.0" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799" 1251 | dependencies = [ 1252 | "memchr", 1253 | ] 1254 | 1255 | [[package]] 1256 | name = "output_vt100" 1257 | version = "0.1.2" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" 1260 | dependencies = [ 1261 | "winapi", 1262 | ] 1263 | 1264 | [[package]] 1265 | name = "owo-colors" 1266 | version = "1.3.0" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55" 1269 | 1270 | [[package]] 1271 | name = "parking" 1272 | version = "2.0.0" 1273 | source = "registry+https://github.com/rust-lang/crates.io-index" 1274 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 1275 | 1276 | [[package]] 1277 | name = "parking_lot" 1278 | version = "0.11.2" 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" 1280 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 1281 | dependencies = [ 1282 | "instant", 1283 | "lock_api", 1284 | "parking_lot_core", 1285 | ] 1286 | 1287 | [[package]] 1288 | name = "parking_lot_core" 1289 | version = "0.8.5" 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" 1291 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 1292 | dependencies = [ 1293 | "cfg-if 1.0.0", 1294 | "instant", 1295 | "libc", 1296 | "redox_syscall", 1297 | "smallvec", 1298 | "winapi", 1299 | ] 1300 | 1301 | [[package]] 1302 | name = "pem" 1303 | version = "0.8.3" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" 1306 | dependencies = [ 1307 | "base64 0.13.0", 1308 | "once_cell", 1309 | "regex", 1310 | ] 1311 | 1312 | [[package]] 1313 | name = "percent-encoding" 1314 | version = "2.1.0" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1317 | 1318 | [[package]] 1319 | name = "pin-project" 1320 | version = "1.0.8" 1321 | source = "registry+https://github.com/rust-lang/crates.io-index" 1322 | checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" 1323 | dependencies = [ 1324 | "pin-project-internal", 1325 | ] 1326 | 1327 | [[package]] 1328 | name = "pin-project-internal" 1329 | version = "1.0.8" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" 1332 | dependencies = [ 1333 | "proc-macro2", 1334 | "quote", 1335 | "syn", 1336 | ] 1337 | 1338 | [[package]] 1339 | name = "pin-project-lite" 1340 | version = "0.2.7" 1341 | source = "registry+https://github.com/rust-lang/crates.io-index" 1342 | checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" 1343 | 1344 | [[package]] 1345 | name = "pin-utils" 1346 | version = "0.1.0" 1347 | source = "registry+https://github.com/rust-lang/crates.io-index" 1348 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1349 | 1350 | [[package]] 1351 | name = "pkg-config" 1352 | version = "0.3.20" 1353 | source = "registry+https://github.com/rust-lang/crates.io-index" 1354 | checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" 1355 | 1356 | [[package]] 1357 | name = "ppv-lite86" 1358 | version = "0.2.14" 1359 | source = "registry+https://github.com/rust-lang/crates.io-index" 1360 | checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" 1361 | 1362 | [[package]] 1363 | name = "pretty_assertions" 1364 | version = "0.7.2" 1365 | source = "registry+https://github.com/rust-lang/crates.io-index" 1366 | checksum = "1cab0e7c02cf376875e9335e0ba1da535775beb5450d21e1dffca068818ed98b" 1367 | dependencies = [ 1368 | "ansi_term", 1369 | "ctor", 1370 | "diff", 1371 | "output_vt100", 1372 | ] 1373 | 1374 | [[package]] 1375 | name = "proc-macro-error" 1376 | version = "1.0.4" 1377 | source = "registry+https://github.com/rust-lang/crates.io-index" 1378 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 1379 | dependencies = [ 1380 | "proc-macro-error-attr", 1381 | "proc-macro2", 1382 | "quote", 1383 | "syn", 1384 | "version_check 0.9.3", 1385 | ] 1386 | 1387 | [[package]] 1388 | name = "proc-macro-error-attr" 1389 | version = "1.0.4" 1390 | source = "registry+https://github.com/rust-lang/crates.io-index" 1391 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 1392 | dependencies = [ 1393 | "proc-macro2", 1394 | "quote", 1395 | "version_check 0.9.3", 1396 | ] 1397 | 1398 | [[package]] 1399 | name = "proc-macro-hack" 1400 | version = "0.5.19" 1401 | source = "registry+https://github.com/rust-lang/crates.io-index" 1402 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 1403 | 1404 | [[package]] 1405 | name = "proc-macro-nested" 1406 | version = "0.1.7" 1407 | source = "registry+https://github.com/rust-lang/crates.io-index" 1408 | checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" 1409 | 1410 | [[package]] 1411 | name = "proc-macro2" 1412 | version = "1.0.30" 1413 | source = "registry+https://github.com/rust-lang/crates.io-index" 1414 | checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" 1415 | dependencies = [ 1416 | "unicode-xid", 1417 | ] 1418 | 1419 | [[package]] 1420 | name = "quote" 1421 | version = "1.0.10" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" 1424 | dependencies = [ 1425 | "proc-macro2", 1426 | ] 1427 | 1428 | [[package]] 1429 | name = "rand" 1430 | version = "0.7.3" 1431 | source = "registry+https://github.com/rust-lang/crates.io-index" 1432 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1433 | dependencies = [ 1434 | "getrandom 0.1.16", 1435 | "libc", 1436 | "rand_chacha 0.2.2", 1437 | "rand_core 0.5.1", 1438 | "rand_hc 0.2.0", 1439 | ] 1440 | 1441 | [[package]] 1442 | name = "rand" 1443 | version = "0.8.4" 1444 | source = "registry+https://github.com/rust-lang/crates.io-index" 1445 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 1446 | dependencies = [ 1447 | "libc", 1448 | "rand_chacha 0.3.1", 1449 | "rand_core 0.6.3", 1450 | "rand_hc 0.3.1", 1451 | ] 1452 | 1453 | [[package]] 1454 | name = "rand_chacha" 1455 | version = "0.2.2" 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" 1457 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 1458 | dependencies = [ 1459 | "ppv-lite86", 1460 | "rand_core 0.5.1", 1461 | ] 1462 | 1463 | [[package]] 1464 | name = "rand_chacha" 1465 | version = "0.3.1" 1466 | source = "registry+https://github.com/rust-lang/crates.io-index" 1467 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1468 | dependencies = [ 1469 | "ppv-lite86", 1470 | "rand_core 0.6.3", 1471 | ] 1472 | 1473 | [[package]] 1474 | name = "rand_core" 1475 | version = "0.5.1" 1476 | source = "registry+https://github.com/rust-lang/crates.io-index" 1477 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1478 | dependencies = [ 1479 | "getrandom 0.1.16", 1480 | ] 1481 | 1482 | [[package]] 1483 | name = "rand_core" 1484 | version = "0.6.3" 1485 | source = "registry+https://github.com/rust-lang/crates.io-index" 1486 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 1487 | dependencies = [ 1488 | "getrandom 0.2.3", 1489 | ] 1490 | 1491 | [[package]] 1492 | name = "rand_hc" 1493 | version = "0.2.0" 1494 | source = "registry+https://github.com/rust-lang/crates.io-index" 1495 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1496 | dependencies = [ 1497 | "rand_core 0.5.1", 1498 | ] 1499 | 1500 | [[package]] 1501 | name = "rand_hc" 1502 | version = "0.3.1" 1503 | source = "registry+https://github.com/rust-lang/crates.io-index" 1504 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 1505 | dependencies = [ 1506 | "rand_core 0.6.3", 1507 | ] 1508 | 1509 | [[package]] 1510 | name = "redox_syscall" 1511 | version = "0.2.10" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" 1514 | dependencies = [ 1515 | "bitflags", 1516 | ] 1517 | 1518 | [[package]] 1519 | name = "regex" 1520 | version = "1.5.4" 1521 | source = "registry+https://github.com/rust-lang/crates.io-index" 1522 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 1523 | dependencies = [ 1524 | "aho-corasick", 1525 | "memchr", 1526 | "regex-syntax", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "regex-automata" 1531 | version = "0.1.10" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 1534 | dependencies = [ 1535 | "regex-syntax", 1536 | ] 1537 | 1538 | [[package]] 1539 | name = "regex-syntax" 1540 | version = "0.6.25" 1541 | source = "registry+https://github.com/rust-lang/crates.io-index" 1542 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 1543 | 1544 | [[package]] 1545 | name = "reqwest" 1546 | version = "0.11.6" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280" 1549 | dependencies = [ 1550 | "base64 0.13.0", 1551 | "bytes", 1552 | "encoding_rs", 1553 | "futures-core", 1554 | "futures-util", 1555 | "http", 1556 | "http-body", 1557 | "hyper", 1558 | "hyper-rustls", 1559 | "ipnet", 1560 | "js-sys", 1561 | "lazy_static", 1562 | "log", 1563 | "mime", 1564 | "percent-encoding", 1565 | "pin-project-lite", 1566 | "rustls", 1567 | "serde", 1568 | "serde_json", 1569 | "serde_urlencoded", 1570 | "tokio", 1571 | "tokio-rustls", 1572 | "url", 1573 | "wasm-bindgen", 1574 | "wasm-bindgen-futures", 1575 | "web-sys", 1576 | "webpki-roots", 1577 | "winreg", 1578 | ] 1579 | 1580 | [[package]] 1581 | name = "ring" 1582 | version = "0.16.20" 1583 | source = "registry+https://github.com/rust-lang/crates.io-index" 1584 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 1585 | dependencies = [ 1586 | "cc", 1587 | "libc", 1588 | "once_cell", 1589 | "spin", 1590 | "untrusted", 1591 | "web-sys", 1592 | "winapi", 1593 | ] 1594 | 1595 | [[package]] 1596 | name = "rustc-demangle" 1597 | version = "0.1.21" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" 1600 | 1601 | [[package]] 1602 | name = "rustls" 1603 | version = "0.19.1" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" 1606 | dependencies = [ 1607 | "base64 0.13.0", 1608 | "log", 1609 | "ring", 1610 | "sct", 1611 | "webpki", 1612 | ] 1613 | 1614 | [[package]] 1615 | name = "rustversion" 1616 | version = "1.0.5" 1617 | source = "registry+https://github.com/rust-lang/crates.io-index" 1618 | checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" 1619 | 1620 | [[package]] 1621 | name = "ryu" 1622 | version = "1.0.5" 1623 | source = "registry+https://github.com/rust-lang/crates.io-index" 1624 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1625 | 1626 | [[package]] 1627 | name = "scopeguard" 1628 | version = "1.1.0" 1629 | source = "registry+https://github.com/rust-lang/crates.io-index" 1630 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1631 | 1632 | [[package]] 1633 | name = "sct" 1634 | version = "0.6.1" 1635 | source = "registry+https://github.com/rust-lang/crates.io-index" 1636 | checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" 1637 | dependencies = [ 1638 | "ring", 1639 | "untrusted", 1640 | ] 1641 | 1642 | [[package]] 1643 | name = "serde" 1644 | version = "1.0.130" 1645 | source = "registry+https://github.com/rust-lang/crates.io-index" 1646 | checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" 1647 | dependencies = [ 1648 | "serde_derive", 1649 | ] 1650 | 1651 | [[package]] 1652 | name = "serde_derive" 1653 | version = "1.0.130" 1654 | source = "registry+https://github.com/rust-lang/crates.io-index" 1655 | checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" 1656 | dependencies = [ 1657 | "proc-macro2", 1658 | "quote", 1659 | "syn", 1660 | ] 1661 | 1662 | [[package]] 1663 | name = "serde_json" 1664 | version = "1.0.68" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" 1667 | dependencies = [ 1668 | "itoa", 1669 | "ryu", 1670 | "serde", 1671 | ] 1672 | 1673 | [[package]] 1674 | name = "serde_qs" 1675 | version = "0.8.5" 1676 | source = "registry+https://github.com/rust-lang/crates.io-index" 1677 | checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" 1678 | dependencies = [ 1679 | "percent-encoding", 1680 | "serde", 1681 | "thiserror", 1682 | ] 1683 | 1684 | [[package]] 1685 | name = "serde_urlencoded" 1686 | version = "0.7.0" 1687 | source = "registry+https://github.com/rust-lang/crates.io-index" 1688 | checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" 1689 | dependencies = [ 1690 | "form_urlencoded", 1691 | "itoa", 1692 | "ryu", 1693 | "serde", 1694 | ] 1695 | 1696 | [[package]] 1697 | name = "sha2" 1698 | version = "0.9.8" 1699 | source = "registry+https://github.com/rust-lang/crates.io-index" 1700 | checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" 1701 | dependencies = [ 1702 | "block-buffer", 1703 | "cfg-if 1.0.0", 1704 | "cpufeatures", 1705 | "digest", 1706 | "opaque-debug", 1707 | ] 1708 | 1709 | [[package]] 1710 | name = "sharded-slab" 1711 | version = "0.1.4" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 1714 | dependencies = [ 1715 | "lazy_static", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "signal-hook-registry" 1720 | version = "1.4.0" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1723 | dependencies = [ 1724 | "libc", 1725 | ] 1726 | 1727 | [[package]] 1728 | name = "simple_asn1" 1729 | version = "0.4.1" 1730 | source = "registry+https://github.com/rust-lang/crates.io-index" 1731 | checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b" 1732 | dependencies = [ 1733 | "chrono", 1734 | "num-bigint", 1735 | "num-traits", 1736 | ] 1737 | 1738 | [[package]] 1739 | name = "slab" 1740 | version = "0.4.5" 1741 | source = "registry+https://github.com/rust-lang/crates.io-index" 1742 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" 1743 | 1744 | [[package]] 1745 | name = "smallvec" 1746 | version = "1.7.0" 1747 | source = "registry+https://github.com/rust-lang/crates.io-index" 1748 | checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" 1749 | 1750 | [[package]] 1751 | name = "snafu" 1752 | version = "0.6.10" 1753 | source = "registry+https://github.com/rust-lang/crates.io-index" 1754 | checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" 1755 | dependencies = [ 1756 | "doc-comment", 1757 | "snafu-derive", 1758 | ] 1759 | 1760 | [[package]] 1761 | name = "snafu-derive" 1762 | version = "0.6.10" 1763 | source = "registry+https://github.com/rust-lang/crates.io-index" 1764 | checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" 1765 | dependencies = [ 1766 | "proc-macro2", 1767 | "quote", 1768 | "syn", 1769 | ] 1770 | 1771 | [[package]] 1772 | name = "socket2" 1773 | version = "0.4.2" 1774 | source = "registry+https://github.com/rust-lang/crates.io-index" 1775 | checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" 1776 | dependencies = [ 1777 | "libc", 1778 | "winapi", 1779 | ] 1780 | 1781 | [[package]] 1782 | name = "spin" 1783 | version = "0.5.2" 1784 | source = "registry+https://github.com/rust-lang/crates.io-index" 1785 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1786 | 1787 | [[package]] 1788 | name = "sqlformat" 1789 | version = "0.1.8" 1790 | source = "registry+https://github.com/rust-lang/crates.io-index" 1791 | checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4" 1792 | dependencies = [ 1793 | "itertools", 1794 | "nom 7.0.0", 1795 | "unicode_categories", 1796 | ] 1797 | 1798 | [[package]] 1799 | name = "sqlx" 1800 | version = "0.5.9" 1801 | source = "registry+https://github.com/rust-lang/crates.io-index" 1802 | checksum = "7911b0031a0247af40095838002999c7a52fba29d9739e93326e71a5a1bc9d43" 1803 | dependencies = [ 1804 | "sqlx-core", 1805 | "sqlx-macros", 1806 | ] 1807 | 1808 | [[package]] 1809 | name = "sqlx-core" 1810 | version = "0.5.9" 1811 | source = "registry+https://github.com/rust-lang/crates.io-index" 1812 | checksum = "aec89bfaca8f7737439bad16d52b07f1ccd0730520d3bf6ae9d069fe4b641fb1" 1813 | dependencies = [ 1814 | "ahash", 1815 | "atoi", 1816 | "bitflags", 1817 | "byteorder", 1818 | "bytes", 1819 | "chrono", 1820 | "crc", 1821 | "crossbeam-channel 0.5.1", 1822 | "crossbeam-queue", 1823 | "crossbeam-utils 0.8.5", 1824 | "either", 1825 | "futures-channel", 1826 | "futures-core", 1827 | "futures-intrusive", 1828 | "futures-util", 1829 | "hashlink", 1830 | "hex", 1831 | "indexmap", 1832 | "itoa", 1833 | "libc", 1834 | "libsqlite3-sys", 1835 | "log", 1836 | "memchr", 1837 | "once_cell", 1838 | "parking_lot", 1839 | "percent-encoding", 1840 | "rustls", 1841 | "sha2", 1842 | "smallvec", 1843 | "sqlformat", 1844 | "sqlx-rt", 1845 | "stringprep", 1846 | "thiserror", 1847 | "tokio-stream", 1848 | "url", 1849 | "webpki", 1850 | "webpki-roots", 1851 | "whoami", 1852 | ] 1853 | 1854 | [[package]] 1855 | name = "sqlx-macros" 1856 | version = "0.5.9" 1857 | source = "registry+https://github.com/rust-lang/crates.io-index" 1858 | checksum = "584866c833511b1a152e87a7ee20dee2739746f60c858b3c5209150bc4b466f5" 1859 | dependencies = [ 1860 | "dotenv", 1861 | "either", 1862 | "heck", 1863 | "once_cell", 1864 | "proc-macro2", 1865 | "quote", 1866 | "sha2", 1867 | "sqlx-core", 1868 | "sqlx-rt", 1869 | "syn", 1870 | "url", 1871 | ] 1872 | 1873 | [[package]] 1874 | name = "sqlx-rt" 1875 | version = "0.5.9" 1876 | source = "registry+https://github.com/rust-lang/crates.io-index" 1877 | checksum = "0d1bd069de53442e7a320f525a6d4deb8bb0621ac7a55f7eccbc2b58b57f43d0" 1878 | dependencies = [ 1879 | "once_cell", 1880 | "tokio", 1881 | "tokio-rustls", 1882 | ] 1883 | 1884 | [[package]] 1885 | name = "static_assertions" 1886 | version = "1.1.0" 1887 | source = "registry+https://github.com/rust-lang/crates.io-index" 1888 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1889 | 1890 | [[package]] 1891 | name = "stringprep" 1892 | version = "0.1.2" 1893 | source = "registry+https://github.com/rust-lang/crates.io-index" 1894 | checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1" 1895 | dependencies = [ 1896 | "unicode-bidi", 1897 | "unicode-normalization", 1898 | ] 1899 | 1900 | [[package]] 1901 | name = "strsim" 1902 | version = "0.10.0" 1903 | source = "registry+https://github.com/rust-lang/crates.io-index" 1904 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1905 | 1906 | [[package]] 1907 | name = "syn" 1908 | version = "1.0.80" 1909 | source = "registry+https://github.com/rust-lang/crates.io-index" 1910 | checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" 1911 | dependencies = [ 1912 | "proc-macro2", 1913 | "quote", 1914 | "unicode-xid", 1915 | ] 1916 | 1917 | [[package]] 1918 | name = "tap" 1919 | version = "1.0.1" 1920 | source = "registry+https://github.com/rust-lang/crates.io-index" 1921 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" 1922 | 1923 | [[package]] 1924 | name = "termcolor" 1925 | version = "1.1.2" 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" 1927 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 1928 | dependencies = [ 1929 | "winapi-util", 1930 | ] 1931 | 1932 | [[package]] 1933 | name = "textwrap" 1934 | version = "0.14.2" 1935 | source = "registry+https://github.com/rust-lang/crates.io-index" 1936 | checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" 1937 | dependencies = [ 1938 | "unicode-width", 1939 | ] 1940 | 1941 | [[package]] 1942 | name = "thiserror" 1943 | version = "1.0.30" 1944 | source = "registry+https://github.com/rust-lang/crates.io-index" 1945 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 1946 | dependencies = [ 1947 | "thiserror-impl", 1948 | ] 1949 | 1950 | [[package]] 1951 | name = "thiserror-impl" 1952 | version = "1.0.30" 1953 | source = "registry+https://github.com/rust-lang/crates.io-index" 1954 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 1955 | dependencies = [ 1956 | "proc-macro2", 1957 | "quote", 1958 | "syn", 1959 | ] 1960 | 1961 | [[package]] 1962 | name = "thread_local" 1963 | version = "1.1.3" 1964 | source = "registry+https://github.com/rust-lang/crates.io-index" 1965 | checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" 1966 | dependencies = [ 1967 | "once_cell", 1968 | ] 1969 | 1970 | [[package]] 1971 | name = "tikv-jemalloc-sys" 1972 | version = "0.4.2+5.2.1-patched.2" 1973 | source = "registry+https://github.com/rust-lang/crates.io-index" 1974 | checksum = "5844e429d797c62945a566f8da4e24c7fe3fbd5d6617fd8bf7a0b7dc1ee0f22e" 1975 | dependencies = [ 1976 | "cc", 1977 | "fs_extra", 1978 | "libc", 1979 | ] 1980 | 1981 | [[package]] 1982 | name = "tikv-jemallocator" 1983 | version = "0.4.1" 1984 | source = "registry+https://github.com/rust-lang/crates.io-index" 1985 | checksum = "3c14a5a604eb8715bc5785018a37d00739b180bcf609916ddf4393d33d49ccdf" 1986 | dependencies = [ 1987 | "libc", 1988 | "tikv-jemalloc-sys", 1989 | ] 1990 | 1991 | [[package]] 1992 | name = "time" 1993 | version = "0.1.43" 1994 | source = "registry+https://github.com/rust-lang/crates.io-index" 1995 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 1996 | dependencies = [ 1997 | "libc", 1998 | "winapi", 1999 | ] 2000 | 2001 | [[package]] 2002 | name = "tinyvec" 2003 | version = "1.5.0" 2004 | source = "registry+https://github.com/rust-lang/crates.io-index" 2005 | checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" 2006 | dependencies = [ 2007 | "tinyvec_macros", 2008 | ] 2009 | 2010 | [[package]] 2011 | name = "tinyvec_macros" 2012 | version = "0.1.0" 2013 | source = "registry+https://github.com/rust-lang/crates.io-index" 2014 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 2015 | 2016 | [[package]] 2017 | name = "tokio" 2018 | version = "1.12.0" 2019 | source = "registry+https://github.com/rust-lang/crates.io-index" 2020 | checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" 2021 | dependencies = [ 2022 | "autocfg", 2023 | "bytes", 2024 | "libc", 2025 | "memchr", 2026 | "mio", 2027 | "num_cpus", 2028 | "once_cell", 2029 | "parking_lot", 2030 | "pin-project-lite", 2031 | "signal-hook-registry", 2032 | "tokio-macros", 2033 | "winapi", 2034 | ] 2035 | 2036 | [[package]] 2037 | name = "tokio-macros" 2038 | version = "1.5.0" 2039 | source = "registry+https://github.com/rust-lang/crates.io-index" 2040 | checksum = "b2dd85aeaba7b68df939bd357c6afb36c87951be9e80bf9c859f2fc3e9fca0fd" 2041 | dependencies = [ 2042 | "proc-macro2", 2043 | "quote", 2044 | "syn", 2045 | ] 2046 | 2047 | [[package]] 2048 | name = "tokio-rustls" 2049 | version = "0.22.0" 2050 | source = "registry+https://github.com/rust-lang/crates.io-index" 2051 | checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" 2052 | dependencies = [ 2053 | "rustls", 2054 | "tokio", 2055 | "webpki", 2056 | ] 2057 | 2058 | [[package]] 2059 | name = "tokio-stream" 2060 | version = "0.1.7" 2061 | source = "registry+https://github.com/rust-lang/crates.io-index" 2062 | checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" 2063 | dependencies = [ 2064 | "futures-core", 2065 | "pin-project-lite", 2066 | "tokio", 2067 | ] 2068 | 2069 | [[package]] 2070 | name = "tokio-util" 2071 | version = "0.6.8" 2072 | source = "registry+https://github.com/rust-lang/crates.io-index" 2073 | checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" 2074 | dependencies = [ 2075 | "bytes", 2076 | "futures-core", 2077 | "futures-sink", 2078 | "log", 2079 | "pin-project-lite", 2080 | "tokio", 2081 | ] 2082 | 2083 | [[package]] 2084 | name = "toml" 2085 | version = "0.5.8" 2086 | source = "registry+https://github.com/rust-lang/crates.io-index" 2087 | checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" 2088 | dependencies = [ 2089 | "serde", 2090 | ] 2091 | 2092 | [[package]] 2093 | name = "tower" 2094 | version = "0.4.10" 2095 | source = "registry+https://github.com/rust-lang/crates.io-index" 2096 | checksum = "c00e500fff5fa1131c866b246041a6bf96da9c965f8fe4128cb1421f23e93c00" 2097 | dependencies = [ 2098 | "futures-core", 2099 | "futures-util", 2100 | "hdrhistogram", 2101 | "indexmap", 2102 | "pin-project", 2103 | "pin-project-lite", 2104 | "rand 0.8.4", 2105 | "slab", 2106 | "tokio", 2107 | "tokio-stream", 2108 | "tokio-util", 2109 | "tower-layer", 2110 | "tower-service", 2111 | "tracing", 2112 | ] 2113 | 2114 | [[package]] 2115 | name = "tower-layer" 2116 | version = "0.3.1" 2117 | source = "registry+https://github.com/rust-lang/crates.io-index" 2118 | checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" 2119 | 2120 | [[package]] 2121 | name = "tower-service" 2122 | version = "0.3.1" 2123 | source = "registry+https://github.com/rust-lang/crates.io-index" 2124 | checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" 2125 | 2126 | [[package]] 2127 | name = "tracing" 2128 | version = "0.1.29" 2129 | source = "registry+https://github.com/rust-lang/crates.io-index" 2130 | checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" 2131 | dependencies = [ 2132 | "cfg-if 1.0.0", 2133 | "log", 2134 | "pin-project-lite", 2135 | "tracing-attributes", 2136 | "tracing-core", 2137 | ] 2138 | 2139 | [[package]] 2140 | name = "tracing-attributes" 2141 | version = "0.1.18" 2142 | source = "registry+https://github.com/rust-lang/crates.io-index" 2143 | checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e" 2144 | dependencies = [ 2145 | "proc-macro2", 2146 | "quote", 2147 | "syn", 2148 | ] 2149 | 2150 | [[package]] 2151 | name = "tracing-core" 2152 | version = "0.1.21" 2153 | source = "registry+https://github.com/rust-lang/crates.io-index" 2154 | checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" 2155 | dependencies = [ 2156 | "lazy_static", 2157 | ] 2158 | 2159 | [[package]] 2160 | name = "tracing-error" 2161 | version = "0.1.2" 2162 | source = "registry+https://github.com/rust-lang/crates.io-index" 2163 | checksum = "b4d7c0b83d4a500748fa5879461652b361edf5c9d51ede2a2ac03875ca185e24" 2164 | dependencies = [ 2165 | "tracing", 2166 | "tracing-subscriber", 2167 | ] 2168 | 2169 | [[package]] 2170 | name = "tracing-log" 2171 | version = "0.1.2" 2172 | source = "registry+https://github.com/rust-lang/crates.io-index" 2173 | checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" 2174 | dependencies = [ 2175 | "lazy_static", 2176 | "log", 2177 | "tracing-core", 2178 | ] 2179 | 2180 | [[package]] 2181 | name = "tracing-serde" 2182 | version = "0.1.2" 2183 | source = "registry+https://github.com/rust-lang/crates.io-index" 2184 | checksum = "fb65ea441fbb84f9f6748fd496cf7f63ec9af5bca94dd86456978d055e8eb28b" 2185 | dependencies = [ 2186 | "serde", 2187 | "tracing-core", 2188 | ] 2189 | 2190 | [[package]] 2191 | name = "tracing-subscriber" 2192 | version = "0.2.25" 2193 | source = "registry+https://github.com/rust-lang/crates.io-index" 2194 | checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" 2195 | dependencies = [ 2196 | "ansi_term", 2197 | "chrono", 2198 | "lazy_static", 2199 | "matchers", 2200 | "regex", 2201 | "serde", 2202 | "serde_json", 2203 | "sharded-slab", 2204 | "smallvec", 2205 | "thread_local", 2206 | "tracing", 2207 | "tracing-core", 2208 | "tracing-log", 2209 | "tracing-serde", 2210 | ] 2211 | 2212 | [[package]] 2213 | name = "try-lock" 2214 | version = "0.2.3" 2215 | source = "registry+https://github.com/rust-lang/crates.io-index" 2216 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 2217 | 2218 | [[package]] 2219 | name = "typenum" 2220 | version = "1.14.0" 2221 | source = "registry+https://github.com/rust-lang/crates.io-index" 2222 | checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" 2223 | 2224 | [[package]] 2225 | name = "unicase" 2226 | version = "2.6.0" 2227 | source = "registry+https://github.com/rust-lang/crates.io-index" 2228 | checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" 2229 | dependencies = [ 2230 | "version_check 0.9.3", 2231 | ] 2232 | 2233 | [[package]] 2234 | name = "unicode-bidi" 2235 | version = "0.3.7" 2236 | source = "registry+https://github.com/rust-lang/crates.io-index" 2237 | checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" 2238 | 2239 | [[package]] 2240 | name = "unicode-normalization" 2241 | version = "0.1.19" 2242 | source = "registry+https://github.com/rust-lang/crates.io-index" 2243 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 2244 | dependencies = [ 2245 | "tinyvec", 2246 | ] 2247 | 2248 | [[package]] 2249 | name = "unicode-segmentation" 2250 | version = "1.8.0" 2251 | source = "registry+https://github.com/rust-lang/crates.io-index" 2252 | checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" 2253 | 2254 | [[package]] 2255 | name = "unicode-width" 2256 | version = "0.1.9" 2257 | source = "registry+https://github.com/rust-lang/crates.io-index" 2258 | checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" 2259 | 2260 | [[package]] 2261 | name = "unicode-xid" 2262 | version = "0.2.2" 2263 | source = "registry+https://github.com/rust-lang/crates.io-index" 2264 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 2265 | 2266 | [[package]] 2267 | name = "unicode_categories" 2268 | version = "0.1.1" 2269 | source = "registry+https://github.com/rust-lang/crates.io-index" 2270 | checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" 2271 | 2272 | [[package]] 2273 | name = "untrusted" 2274 | version = "0.7.1" 2275 | source = "registry+https://github.com/rust-lang/crates.io-index" 2276 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 2277 | 2278 | [[package]] 2279 | name = "url" 2280 | version = "2.2.2" 2281 | source = "registry+https://github.com/rust-lang/crates.io-index" 2282 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 2283 | dependencies = [ 2284 | "form_urlencoded", 2285 | "idna", 2286 | "matches", 2287 | "percent-encoding", 2288 | "serde", 2289 | ] 2290 | 2291 | [[package]] 2292 | name = "vcpkg" 2293 | version = "0.2.15" 2294 | source = "registry+https://github.com/rust-lang/crates.io-index" 2295 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2296 | 2297 | [[package]] 2298 | name = "vergen" 2299 | version = "5.1.15" 2300 | source = "registry+https://github.com/rust-lang/crates.io-index" 2301 | checksum = "265455aab08c55a1ab13f07c8d5e25c7d46900f4484dd7cbd682e77171f93f3c" 2302 | dependencies = [ 2303 | "anyhow", 2304 | "cfg-if 1.0.0", 2305 | "chrono", 2306 | "enum-iterator", 2307 | "getset", 2308 | "rustversion", 2309 | "thiserror", 2310 | ] 2311 | 2312 | [[package]] 2313 | name = "version_check" 2314 | version = "0.1.5" 2315 | source = "registry+https://github.com/rust-lang/crates.io-index" 2316 | checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" 2317 | 2318 | [[package]] 2319 | name = "version_check" 2320 | version = "0.9.3" 2321 | source = "registry+https://github.com/rust-lang/crates.io-index" 2322 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 2323 | 2324 | [[package]] 2325 | name = "waker-fn" 2326 | version = "1.1.0" 2327 | source = "registry+https://github.com/rust-lang/crates.io-index" 2328 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 2329 | 2330 | [[package]] 2331 | name = "want" 2332 | version = "0.3.0" 2333 | source = "registry+https://github.com/rust-lang/crates.io-index" 2334 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 2335 | dependencies = [ 2336 | "log", 2337 | "try-lock", 2338 | ] 2339 | 2340 | [[package]] 2341 | name = "wasi" 2342 | version = "0.9.0+wasi-snapshot-preview1" 2343 | source = "registry+https://github.com/rust-lang/crates.io-index" 2344 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 2345 | 2346 | [[package]] 2347 | name = "wasi" 2348 | version = "0.10.2+wasi-snapshot-preview1" 2349 | source = "registry+https://github.com/rust-lang/crates.io-index" 2350 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 2351 | 2352 | [[package]] 2353 | name = "wasm-bindgen" 2354 | version = "0.2.78" 2355 | source = "registry+https://github.com/rust-lang/crates.io-index" 2356 | checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" 2357 | dependencies = [ 2358 | "cfg-if 1.0.0", 2359 | "wasm-bindgen-macro", 2360 | ] 2361 | 2362 | [[package]] 2363 | name = "wasm-bindgen-backend" 2364 | version = "0.2.78" 2365 | source = "registry+https://github.com/rust-lang/crates.io-index" 2366 | checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" 2367 | dependencies = [ 2368 | "bumpalo", 2369 | "lazy_static", 2370 | "log", 2371 | "proc-macro2", 2372 | "quote", 2373 | "syn", 2374 | "wasm-bindgen-shared", 2375 | ] 2376 | 2377 | [[package]] 2378 | name = "wasm-bindgen-futures" 2379 | version = "0.4.28" 2380 | source = "registry+https://github.com/rust-lang/crates.io-index" 2381 | checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" 2382 | dependencies = [ 2383 | "cfg-if 1.0.0", 2384 | "js-sys", 2385 | "wasm-bindgen", 2386 | "web-sys", 2387 | ] 2388 | 2389 | [[package]] 2390 | name = "wasm-bindgen-macro" 2391 | version = "0.2.78" 2392 | source = "registry+https://github.com/rust-lang/crates.io-index" 2393 | checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" 2394 | dependencies = [ 2395 | "quote", 2396 | "wasm-bindgen-macro-support", 2397 | ] 2398 | 2399 | [[package]] 2400 | name = "wasm-bindgen-macro-support" 2401 | version = "0.2.78" 2402 | source = "registry+https://github.com/rust-lang/crates.io-index" 2403 | checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" 2404 | dependencies = [ 2405 | "proc-macro2", 2406 | "quote", 2407 | "syn", 2408 | "wasm-bindgen-backend", 2409 | "wasm-bindgen-shared", 2410 | ] 2411 | 2412 | [[package]] 2413 | name = "wasm-bindgen-shared" 2414 | version = "0.2.78" 2415 | source = "registry+https://github.com/rust-lang/crates.io-index" 2416 | checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" 2417 | 2418 | [[package]] 2419 | name = "web-sys" 2420 | version = "0.3.55" 2421 | source = "registry+https://github.com/rust-lang/crates.io-index" 2422 | checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" 2423 | dependencies = [ 2424 | "js-sys", 2425 | "wasm-bindgen", 2426 | ] 2427 | 2428 | [[package]] 2429 | name = "webpki" 2430 | version = "0.21.4" 2431 | source = "registry+https://github.com/rust-lang/crates.io-index" 2432 | checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" 2433 | dependencies = [ 2434 | "ring", 2435 | "untrusted", 2436 | ] 2437 | 2438 | [[package]] 2439 | name = "webpki-roots" 2440 | version = "0.21.1" 2441 | source = "registry+https://github.com/rust-lang/crates.io-index" 2442 | checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940" 2443 | dependencies = [ 2444 | "webpki", 2445 | ] 2446 | 2447 | [[package]] 2448 | name = "whoami" 2449 | version = "1.1.5" 2450 | source = "registry+https://github.com/rust-lang/crates.io-index" 2451 | checksum = "483a59fee1a93fec90eb08bc2eb4315ef10f4ebc478b3a5fadc969819cb66117" 2452 | dependencies = [ 2453 | "wasm-bindgen", 2454 | "web-sys", 2455 | ] 2456 | 2457 | [[package]] 2458 | name = "winapi" 2459 | version = "0.3.9" 2460 | source = "registry+https://github.com/rust-lang/crates.io-index" 2461 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2462 | dependencies = [ 2463 | "winapi-i686-pc-windows-gnu", 2464 | "winapi-x86_64-pc-windows-gnu", 2465 | ] 2466 | 2467 | [[package]] 2468 | name = "winapi-i686-pc-windows-gnu" 2469 | version = "0.4.0" 2470 | source = "registry+https://github.com/rust-lang/crates.io-index" 2471 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2472 | 2473 | [[package]] 2474 | name = "winapi-util" 2475 | version = "0.1.5" 2476 | source = "registry+https://github.com/rust-lang/crates.io-index" 2477 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 2478 | dependencies = [ 2479 | "winapi", 2480 | ] 2481 | 2482 | [[package]] 2483 | name = "winapi-x86_64-pc-windows-gnu" 2484 | version = "0.4.0" 2485 | source = "registry+https://github.com/rust-lang/crates.io-index" 2486 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2487 | 2488 | [[package]] 2489 | name = "winreg" 2490 | version = "0.7.0" 2491 | source = "registry+https://github.com/rust-lang/crates.io-index" 2492 | checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" 2493 | dependencies = [ 2494 | "winapi", 2495 | ] 2496 | 2497 | [[package]] 2498 | name = "wiremock" 2499 | version = "0.5.7" 2500 | source = "registry+https://github.com/rust-lang/crates.io-index" 2501 | checksum = "33807c11bd2c5a3896c36042ef2ca9663795bb7e4af2fe87474a159ea72c2159" 2502 | dependencies = [ 2503 | "async-trait", 2504 | "deadpool", 2505 | "futures", 2506 | "futures-timer", 2507 | "http-types", 2508 | "hyper", 2509 | "log", 2510 | "once_cell", 2511 | "regex", 2512 | "serde", 2513 | "serde_json", 2514 | "tokio", 2515 | ] 2516 | 2517 | [[package]] 2518 | name = "xshell" 2519 | version = "0.1.17" 2520 | source = "registry+https://github.com/rust-lang/crates.io-index" 2521 | checksum = "eaad2035244c56da05573d4d7fda5f903c60a5f35b9110e157a14a1df45a9f14" 2522 | dependencies = [ 2523 | "xshell-macros", 2524 | ] 2525 | 2526 | [[package]] 2527 | name = "xshell-macros" 2528 | version = "0.1.17" 2529 | source = "registry+https://github.com/rust-lang/crates.io-index" 2530 | checksum = "4916a4a3cad759e499a3620523bf9545cc162d7a06163727dde97ce9aaa4cf39" 2531 | 2532 | [[package]] 2533 | name = "xtask" 2534 | version = "0.1.0" 2535 | dependencies = [ 2536 | "anyhow", 2537 | "clap", 2538 | "colored", 2539 | "flate2", 2540 | "once_cell", 2541 | "xshell", 2542 | ] 2543 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "a-train" 3 | version = "0.1.0" 4 | authors = ["Storm Timmermans "] 5 | edition = "2018" 6 | build = "build.rs" 7 | publish = false 8 | 9 | [workspace] 10 | members = ["xtask"] 11 | 12 | [dependencies] 13 | anyhow = "1" 14 | async-trait = "0.1.51" 15 | bernard = { git = "https://github.com/m-rots/bernard-rs", branch = "main" } 16 | chrono = "0.4" 17 | clap = "3.0.0-beta.5" 18 | color-eyre = "0.5.11" 19 | eyre = "0.6.5" 20 | futures = "0.3" 21 | reqwest = { version = "0.11", default-features = false, features = [ 22 | "json", 23 | "rustls-tls", 24 | ] } 25 | serde = { version = "1", features = ["derive"] } 26 | thiserror = "1.0.26" 27 | tokio = { version = "1", features = ["full"] } 28 | toml = "0.5" 29 | tower = { version = "0.4.8", features = ["full"] } 30 | tracing = "0.1" 31 | # Still waiting for https://github.com/tokio-rs/tracing/issues/1309 to be backported. 32 | tracing-subscriber = "0.2" 33 | 34 | # Jemalloc for 64-bit MUSL as standard allocator has bad performance. 35 | [target.'cfg(all(target_env = "musl", target_pointer_width = "64"))'.dependencies] 36 | jemallocator = { version = "0.4", package = "tikv-jemallocator" } 37 | 38 | [build-dependencies] 39 | # TODO: enable git 40 | vergen = { version = "5", default-features = false, features = ["build"] } 41 | 42 | [dev-dependencies] 43 | pretty_assertions = "0.7" 44 | serde_json = "1" 45 | wiremock = "0.5" 46 | 47 | [profile.dev] 48 | split-debuginfo = "unpacked" 49 | 50 | [profile.release] 51 | lto = true 52 | codegen-units = 1 53 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM --platform=${BUILDPLATFORM} python:3.9-slim as build 2 | WORKDIR /dist 3 | ARG TARGETPLATFORM 4 | # Deps 5 | COPY ./scripts/requirements.txt . 6 | RUN pip3 install -r requirements.txt 7 | # Dist + script 8 | COPY ./target/dist/ . 9 | COPY ./scripts/target.py . 10 | RUN python3 ./target.py ${TARGETPLATFORM} 11 | RUN chmod +x ./a-train 12 | 13 | FROM --platform=${TARGETPLATFORM} scratch as runtime 14 | COPY --from=build /dist/a-train / 15 | VOLUME /data 16 | WORKDIR /data 17 | ENTRYPOINT [ "/a-train" ] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Autoscan](https://github.com/Cloudbox/autoscan), A-Train and [Bernard](https://github.com/m-rots/bernard-rs) are no longer actively maintained. All projects are considered feature frozen and when compatibility with Google Drive, Plex, Emby, Jellyfin and the -arrs inevitably breaks, no fixes will be provided and such an event will officially mark these projects as end of life. 2 | As all three projects have permissible open source licenses, feel free to start a fork and continue development. Ownership of these repositories as well as the Docker images will not be transferred. 3 | 4 | # A-Train 5 | 6 | A-Train is the official Autoscan trigger that listens for changes within Google Drive. 7 | It is the successor of Autoscan's Bernard trigger, which unfortunately contains enough logic errors to prompt a rewrite. 8 | 9 | - Supports **Shared Drives** 10 | - **Service Account**-based authentication 11 | - Does not support My Drive 12 | - Does not support encrypted files 13 | - Does not support alternative authentication methods 14 | 15 | ## Prerequisites 16 | 17 | A-Train works exclusively through [Shared Drives](https://support.google.com/a/answer/7212025) and [Service Accounts](https://cloud.google.com/iam/docs/service-accounts). 18 | Shared Drives can only be created on GSuite / Google Workspace accounts. 19 | 20 | First, you must [create a Service Account](https://cloud.google.com/iam/docs/creating-managing-service-accounts#iam-service-accounts-create-console) and [create a JSON key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating_service_account_keys). 21 | Afterwards, if you do not have one already, [create a Shared Drive within Google Drive](https://support.google.com/a/users/answer/9310249) and then add the email address of the Service Account to the Shared Drive (with `Reader` permission). 22 | 23 | Finally, activate the Drive API in the Google Cloud Project where you created the Service Account. 24 | 25 | ## Installation 26 | 27 | A-Train has multiple installation options: 28 | 29 | - Building A-Train from source (requires Rust to be installed) 30 | - Downloading the pre-compiled binary for your platform 31 | - Using the Docker image 32 | 33 | ### Docker 34 | 35 | The Docker image requires you to mount a volume with the A-Train configuration file (`a-train.toml`) and the Service Account key file (`account.json`) to `/data`. 36 | 37 | ```bash 38 | docker run -d \ 39 | --name a-train \ 40 | --volume /path/to/data:/data \ 41 | --restart unless-stopped \ 42 | ghcr.io/m-rots/a-train 43 | ``` 44 | 45 | ### From Source 46 | 47 | Requires the latest stable version of [Rust](https://www.rust-lang.org/tools/install) to be installed. 48 | 49 | ```bash 50 | cargo install --git https://github.com/m-rots/a-train --branch main 51 | ``` 52 | 53 | ## Configuration 54 | 55 | The configuration file should be named `a-train.toml`. 56 | 57 | - If you have installed A-Train from source or are using the binary, then A-Train will look for the `a-train.toml` and `account.json` files within the current working directory. 58 | - If you're using A-Train within Docker, then a directory should be mounted to `/data` containing the `a-train.toml` and `account.json` files. 59 | 60 | ```toml 61 | # a-train.toml 62 | [autoscan] 63 | # Replace the URL with your Autoscan URL. 64 | url = "http://localhost:3030" 65 | username = "hello there" 66 | password = "general kenobi" 67 | 68 | [drive] 69 | # Path to the Service Account key file, 70 | # relative to the configuration file. 71 | account = "./account.json" 72 | # One or more Shared Drive IDs 73 | drives = ["0A1xxxxxxxxxUk9PVA", "0A2xxxxxxxxxUk9PVA"] 74 | ``` 75 | 76 | ### How to get the ID of a Shared Drive? 77 | 78 | 1. Open Google Drive in your preferred browser. 79 | 2. Click on Shared Drives on the left. 80 | 3. Double click on the Shared Drive you want to add. 81 | 4. You should now see all the files and folders at the root of this Shared Drive. 82 | 5. Now click on your browser's URL bar and copy the most-right value. 83 | It should have a structure similar to `0A1xxxxxxxxxUk9PVA`. -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use vergen::{vergen, Config}; 2 | 3 | fn main() { 4 | // Generate the default 'cargo:' instruction output 5 | vergen(Config::default()).expect("Unable to generate build-time environment variables"); 6 | } 7 | -------------------------------------------------------------------------------- /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | click==7.1.2 -------------------------------------------------------------------------------- /scripts/target.py: -------------------------------------------------------------------------------- 1 | import click 2 | import gzip 3 | import os 4 | import shutil 5 | 6 | 7 | targets = { 8 | "linux/amd64": "x86_64-unknown-linux-musl", 9 | "linux/arm64": "aarch64-unknown-linux-musl", 10 | "linux/arm/v7": "armv7-unknown-linux-musleabihf", 11 | "linux/arm/v6": "arm-unknown-linux-musleabihf", 12 | } 13 | 14 | 15 | @click.command() 16 | @click.argument("platform", type=str) 17 | @click.option( 18 | "-d", "--directory", "directory", type=click.Path(exists=True, dir_okay=True) 19 | ) 20 | def copy_binary(directory: str, platform: str): 21 | target = targets[platform] 22 | src = f"a-train-{target}.gz" 23 | dst = "a-train" 24 | 25 | if directory is not None: 26 | os.chdir(directory) 27 | 28 | # Decompress the gz 29 | with gzip.open(src, "rb") as f_in: 30 | with open(dst, "wb") as f_out: 31 | shutil.copyfileobj(f_in, f_out) 32 | 33 | print(f"Decompressed {src!r} into {dst!r}") 34 | 35 | 36 | if __name__ == "__main__": 37 | copy_binary() -------------------------------------------------------------------------------- /src/autoscan.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use bernard::{ChangedPath, Path}; 3 | use eyre::eyre; 4 | use reqwest::{Client, ClientBuilder, IntoUrl, Request, Response, Url}; 5 | use serde::{Deserialize, Serialize}; 6 | use std::{collections::HashSet, path::PathBuf}; 7 | use thiserror::Error; 8 | use tower::{buffer::Buffer, util::BoxService, BoxError, Service as _, ServiceBuilder, ServiceExt}; 9 | use tracing::debug; 10 | 11 | type Service = Buffer, Request>; 12 | 13 | #[derive(Debug, Error)] 14 | pub enum AutoscanError { 15 | #[error("network error")] 16 | Network(#[from] eyre::Report), 17 | } 18 | 19 | impl From for AutoscanError { 20 | fn from(err: BoxError) -> Self { 21 | Self::Network(eyre!(err)) 22 | } 23 | } 24 | 25 | impl From for AutoscanError { 26 | fn from(err: reqwest::Error) -> Self { 27 | Self::Network(err.into()) 28 | } 29 | } 30 | 31 | #[async_trait] 32 | trait RequestExt { 33 | async fn svc_send + Send>( 34 | self, 35 | service: T, 36 | ) -> Result; 37 | } 38 | 39 | #[async_trait] 40 | impl RequestExt for reqwest::RequestBuilder { 41 | async fn svc_send + Send>( 42 | self, 43 | service: T, 44 | ) -> Result { 45 | let mut service = service.as_ref().clone(); 46 | 47 | let request = self.build()?; 48 | let response = service.ready().await?.call(request).await?; 49 | 50 | Ok(response) 51 | } 52 | } 53 | 54 | pub struct Autoscan { 55 | auth: Option, 56 | client: Client, 57 | service: Service, 58 | url: Url, 59 | } 60 | 61 | impl AsRef for Autoscan { 62 | fn as_ref(&self) -> &Service { 63 | &self.service 64 | } 65 | } 66 | 67 | impl Autoscan { 68 | pub(crate) fn new(auth: Option, client: Client, url: Url) -> Self { 69 | let service = { 70 | let client = client.clone(); 71 | let service = 72 | ServiceBuilder::new().service_fn(move |request: Request| client.execute(request)); 73 | 74 | Buffer::new(BoxService::new(service), 1024) 75 | }; 76 | 77 | Self { 78 | auth, 79 | client, 80 | service, 81 | url, 82 | } 83 | } 84 | 85 | pub(crate) fn builder(url: U, auth: Option) -> AutoscanBuilder { 86 | AutoscanBuilder::new(url, auth) 87 | } 88 | } 89 | 90 | #[derive(Debug, Deserialize)] 91 | pub struct Credentials { 92 | username: String, 93 | password: String, 94 | } 95 | 96 | pub(crate) struct AutoscanBuilder { 97 | auth: Option, 98 | client: ClientBuilder, 99 | url: Url, 100 | } 101 | 102 | impl AutoscanBuilder { 103 | pub(crate) fn new(url: U, auth: Option) -> Self { 104 | let url = url.into_url().expect("Invalid url"); 105 | 106 | AutoscanBuilder { 107 | auth, 108 | client: ClientBuilder::new(), 109 | url, 110 | } 111 | } 112 | 113 | pub(crate) fn proxy(mut self, url: U) -> Self { 114 | let proxy = reqwest::Proxy::all(url).unwrap(); 115 | 116 | self.client = self.client.proxy(proxy); 117 | self 118 | } 119 | 120 | pub(crate) fn build(self) -> Autoscan { 121 | let client = self.client.build().unwrap(); 122 | Autoscan::new(self.auth, client, self.url) 123 | } 124 | } 125 | 126 | #[derive(Debug, Default, Serialize)] 127 | #[cfg_attr(test, derive(Deserialize, PartialEq))] 128 | pub(crate) struct Payload { 129 | created: HashSet, 130 | deleted: HashSet, 131 | } 132 | 133 | impl Payload { 134 | pub(crate) fn is_empty(&self) -> bool { 135 | self.created.len() == 0 && self.deleted.len() == 0 136 | } 137 | } 138 | 139 | pub(crate) fn create_payload(changed_paths: Vec) -> Payload { 140 | let mut payload = Payload::default(); 141 | 142 | for path in changed_paths { 143 | match path { 144 | ChangedPath::Created(path) => match path { 145 | Path::File(mut file) => { 146 | // We're only interested in folders. 147 | // Thus we pop the file and retrieve the parent instead. 148 | file.path.pop(); 149 | payload.created.insert(file.path); 150 | } 151 | Path::Folder(folder) => { 152 | payload.created.insert(folder.path); 153 | } 154 | }, 155 | ChangedPath::Deleted(path) => { 156 | // Do not send this path to Autoscan 157 | // if the trash of a Drive is deleted permanently. 158 | if path.trashed() { 159 | continue; 160 | } 161 | 162 | match path { 163 | Path::File(mut file) => { 164 | // We're only interested in folders. 165 | // Thus we pop the file and retrieve the parent instead. 166 | file.path.pop(); 167 | payload.deleted.insert(file.path); 168 | } 169 | Path::Folder(folder) => { 170 | payload.deleted.insert(folder.path); 171 | } 172 | } 173 | } 174 | } 175 | } 176 | 177 | payload 178 | } 179 | 180 | impl Autoscan { 181 | pub(crate) async fn available(&self) -> Result<(), AutoscanError> { 182 | let mut url = self.url.clone(); 183 | url.set_path("/health"); 184 | 185 | self.client 186 | .get(url) 187 | .svc_send(&self) 188 | .await? 189 | .error_for_status()?; 190 | 191 | Ok(()) 192 | } 193 | 194 | #[tracing::instrument(skip(self, payload))] 195 | pub(crate) async fn send_payload( 196 | &self, 197 | drive_id: &str, 198 | payload: &Payload, 199 | ) -> Result<(), AutoscanError> { 200 | let mut url = self.url.clone(); 201 | url.set_path(&format!("/triggers/a-train/{}", drive_id)); 202 | 203 | let mut request = self.client.post(url).json(&payload); 204 | if let Some(auth) = &self.auth { 205 | request = request.basic_auth(&auth.username, Some(&auth.password)); 206 | } 207 | 208 | request.svc_send(&self).await?.error_for_status()?; 209 | debug!("changes received by autoscan"); 210 | 211 | Ok(()) 212 | } 213 | } 214 | 215 | #[cfg(test)] 216 | mod tests { 217 | use super::{create_payload, Autoscan, Payload}; 218 | use bernard::{ChangedPath, InnerPath, Path}; 219 | use pretty_assertions::assert_eq; 220 | use reqwest::{Client, Url}; 221 | use serde_json::{from_value, json}; 222 | use wiremock::matchers::{body_json, method, path}; 223 | use wiremock::{Mock, ResponseTemplate}; 224 | 225 | fn new_path(created: bool, folder: bool, inner: InnerPath) -> ChangedPath { 226 | match (created, folder) { 227 | (true, true) => ChangedPath::Created(Path::Folder(inner)), 228 | (false, true) => ChangedPath::Deleted(Path::Folder(inner)), 229 | (true, false) => ChangedPath::Created(Path::File(inner)), 230 | (false, false) => ChangedPath::Deleted(Path::File(inner)), 231 | } 232 | } 233 | 234 | fn new_inner(path: &str, trashed: bool) -> InnerPath { 235 | InnerPath { 236 | // drive_id and id are not used, so whatever 237 | drive_id: "test".to_string(), 238 | id: "test".to_string(), 239 | path: path.into(), 240 | trashed, 241 | } 242 | } 243 | 244 | impl Autoscan { 245 | fn new_test(url: &str) -> Self { 246 | Autoscan::new(None, Client::new(), Url::parse(url).unwrap()) 247 | } 248 | } 249 | 250 | #[tokio::test] 251 | async fn autoscan_request() { 252 | let server = wiremock::MockServer::start().await; 253 | let autoscan = Autoscan::new_test(&server.uri()); 254 | 255 | let payload: Payload = create_payload(vec![ 256 | new_path(true, true, new_inner("/this/is/a/full/path", false)), 257 | new_path(false, true, new_inner("/just/like/me", false)), 258 | ]); 259 | 260 | let expected_body = json!({ 261 | "created": [ 262 | "/this/is/a/full/path", 263 | ], 264 | "deleted": [ 265 | "/just/like/me" 266 | ], 267 | }); 268 | 269 | Mock::given(method("POST")) 270 | .and(path("/triggers/a-train/test123")) 271 | .and(body_json(&expected_body)) 272 | .respond_with(ResponseTemplate::new(200)) 273 | .expect(1) 274 | .mount(&server) 275 | .await; 276 | 277 | let result = autoscan.send_payload("test123", &payload).await; 278 | 279 | // First drop the server to evaluate the request. 280 | drop(server); 281 | // Afterwards, check the result. 282 | // This should happen last as the panic information is pretty useless. 283 | result.unwrap(); 284 | } 285 | 286 | /// Check whether folder paths keep as is. 287 | #[test] 288 | fn payload_folders_are_full_paths() { 289 | let payload: Payload = create_payload(vec![ 290 | new_path(true, true, new_inner("/this/is/a/full/path", false)), 291 | new_path(false, true, new_inner("/just/like/me", false)), 292 | ]); 293 | 294 | let expected_body = json!({ 295 | "created": [ 296 | "/this/is/a/full/path", 297 | ], 298 | "deleted": [ 299 | "/just/like/me" 300 | ], 301 | }); 302 | 303 | assert_eq!( 304 | payload, 305 | from_value(expected_body).expect("could not deserialize") 306 | ) 307 | } 308 | 309 | /// Check whether file paths are transformed into the path of the parent. 310 | #[test] 311 | fn payload_files_are_parents() { 312 | let payload: Payload = create_payload(vec![ 313 | new_path(true, false, new_inner("/keep me/but not me", false)), 314 | new_path(false, false, new_inner("/where/is/perry", false)), 315 | ]); 316 | 317 | let expected_body = json!({ 318 | "created": [ 319 | "/keep me", 320 | ], 321 | "deleted": [ 322 | "/where/is" 323 | ], 324 | }); 325 | 326 | assert_eq!( 327 | payload, 328 | from_value(expected_body).expect("could not deserialize") 329 | ) 330 | } 331 | 332 | /// Check whether file paths are transformed into the path of the parent. 333 | #[test] 334 | fn trashed_deleted_is_skipped() { 335 | let payload: Payload = create_payload(vec![new_path( 336 | false, 337 | false, 338 | new_inner("/trashed/and/now/deleted", true), 339 | )]); 340 | 341 | let expected_body = json!({ 342 | "created": [], 343 | "deleted": [], 344 | }); 345 | 346 | assert_eq!( 347 | payload, 348 | from_value(expected_body).expect("could not deserialize") 349 | ) 350 | } 351 | } 352 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use crate::autoscan::Credentials; 2 | use bernard::Account; 3 | use eyre::WrapErr; 4 | use serde::Deserialize; 5 | use std::path::{Path, PathBuf}; 6 | use thiserror::Error; 7 | 8 | #[derive(Error, Debug)] 9 | pub enum ConfigError { 10 | #[error(transparent)] 11 | UnexpectedError(#[from] eyre::Report), 12 | } 13 | 14 | #[derive(Debug, Deserialize)] 15 | pub struct Config { 16 | pub(crate) autoscan: AutoscanConfig, 17 | pub(crate) drive: DriveConfig, 18 | } 19 | 20 | #[derive(Debug, Deserialize)] 21 | pub(crate) struct AutoscanConfig { 22 | #[serde(flatten)] 23 | pub(crate) authentication: Option, 24 | pub(crate) url: String, 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | pub(crate) struct DriveConfig { 29 | pub(crate) account: PathBuf, 30 | pub(crate) drives: Vec, 31 | } 32 | 33 | impl Config { 34 | pub fn new>(path: T) -> Result { 35 | let path = path.as_ref(); 36 | 37 | let config = std::fs::read_to_string(path) 38 | .wrap_err_with(|| format!("Could not read config file at: {:?}", path))?; 39 | 40 | let config: Config = toml::from_str(&config).wrap_err("Configuration file is invalid")?; 41 | 42 | Ok(config) 43 | } 44 | 45 | pub fn account(&self) -> Result { 46 | let account = Account::from_file(&self.drive.account) 47 | .wrap_err_with(|| format!("Service Account is invalid: {:?}", self.drive.account))?; 48 | 49 | Ok(account) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/drive.rs: -------------------------------------------------------------------------------- 1 | use crate::{autoscan::create_payload, Atrain, Result}; 2 | use bernard::SyncKind; 3 | use futures::prelude::*; 4 | use tracing::warn; 5 | 6 | const CONCURRENCY: usize = 5; 7 | 8 | impl Atrain { 9 | async fn sync_drive(&self, drive_id: &str) -> Result<()> { 10 | match self.bernard.sync_drive(drive_id).await { 11 | // Do not send a payload to Autoscan on a full scan 12 | Ok(SyncKind::Full) => (), 13 | Ok(SyncKind::Partial(changes)) => { 14 | let changed_paths = changes.paths().await?; 15 | let payload = create_payload(changed_paths); 16 | 17 | if !payload.is_empty() { 18 | self.autoscan.send_payload(drive_id, &payload).await?; 19 | } 20 | } 21 | Err(err) => { 22 | // Can ignore a Partial Change List as it should recover eventually. 23 | if !err.is_partial_change_list() { 24 | return Err(err.into()); 25 | } 26 | 27 | warn!(%drive_id, "Encountered a Partial Change List.") 28 | } 29 | } 30 | 31 | Ok(()) 32 | } 33 | 34 | #[tracing::instrument(level = "trace", skip(self))] 35 | pub async fn sync(&self) -> Result<()> { 36 | // also fetch changes here and create+send response to Autoscan for each individual Drive. 37 | // https://stackoverflow.com/questions/51044467 38 | stream::iter(&self.drives) 39 | .map(|drive_id| self.sync_drive(drive_id)) 40 | .buffer_unordered(CONCURRENCY) 41 | .try_collect() 42 | .await 43 | } 44 | 45 | pub async fn close(self) { 46 | self.bernard.close().await 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use autoscan::{Autoscan, AutoscanBuilder}; 2 | use bernard::{Bernard, BernardBuilder}; 3 | use reqwest::IntoUrl; 4 | use thiserror::Error; 5 | 6 | mod autoscan; 7 | mod config; 8 | mod drive; 9 | 10 | pub use config::Config; 11 | 12 | #[derive(Debug, Error)] 13 | pub enum Error { 14 | #[error("Autoscan is unavailable")] 15 | AutoscanUnavailable(#[from] autoscan::AutoscanError), 16 | #[error("Bernard")] 17 | Bernard(#[from] bernard::Error), 18 | #[error(transparent)] 19 | Unexpected(#[from] eyre::Report), 20 | #[error("Invalid configuration")] 21 | Configuration(#[from] config::ConfigError), 22 | } 23 | 24 | pub type Result = std::result::Result; 25 | 26 | pub struct Atrain { 27 | autoscan: Autoscan, 28 | bernard: Bernard, 29 | drives: Vec, 30 | } 31 | 32 | impl Atrain { 33 | pub async fn tick(&self) -> Result<()> { 34 | use tokio::time::{sleep, Duration}; 35 | 36 | self.sync().await?; 37 | sleep(Duration::from_secs(60)).await; 38 | Ok(()) 39 | } 40 | } 41 | 42 | pub struct AtrainBuilder { 43 | autoscan: AutoscanBuilder, 44 | bernard: BernardBuilder, 45 | drives: Vec, 46 | } 47 | 48 | impl AtrainBuilder { 49 | pub fn new(config: Config, database_path: &str) -> Result { 50 | let account = config.account()?; 51 | 52 | Ok(Self { 53 | autoscan: Autoscan::builder(config.autoscan.url, config.autoscan.authentication), 54 | bernard: Bernard::builder(database_path, account), 55 | drives: config.drive.drives, 56 | }) 57 | } 58 | 59 | pub fn proxy(mut self, url: U) -> Self { 60 | self.autoscan = self.autoscan.proxy(url.clone()); 61 | self.bernard = self.bernard.proxy(url); 62 | self 63 | } 64 | 65 | pub async fn build(self) -> Result { 66 | let a_train = Atrain { 67 | autoscan: self.autoscan.build(), 68 | bernard: self.bernard.build().await.unwrap(), 69 | drives: self.drives, 70 | }; 71 | 72 | // Check whether Autoscan is available. 73 | a_train.autoscan.available().await?; 74 | Ok(a_train) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use a_train::Config; 2 | use clap::Parser; 3 | use std::env; 4 | use tokio::signal::ctrl_c; 5 | use tracing_subscriber::fmt::format::FmtSpan; 6 | 7 | // Use Jemalloc only for musl 64 bits platforms. 8 | // This fixes worse performance on MUSL builds. 9 | // More info: https://github.com/BurntSushi/ripgrep/blob/94e4b8e301302097dad48b292560ce135c4d4926/crates/core/main.rs#L44 10 | #[cfg(all(target_env = "musl", target_pointer_width = "64"))] 11 | #[global_allocator] 12 | static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; 13 | 14 | /// Google Drive support for Autoscan. 15 | #[derive(Parser)] 16 | #[clap(name = "A-Train", version = version())] 17 | struct Opt { 18 | /// Path to the configuration file 19 | #[clap(short, long, value_name = "FILE", default_value = "a-train.toml")] 20 | config: String, 21 | 22 | /// Path to the database file 23 | #[clap(long, alias = "db", value_name = "FILE", default_value = "a-train.db")] 24 | database: String, 25 | 26 | /// Proxy URL to use for debugging 27 | #[clap(short, long, value_name = "URL")] 28 | proxy: Option, 29 | } 30 | 31 | fn version() -> &'static str { 32 | env!("VERGEN_BUILD_SEMVER") 33 | } 34 | 35 | #[tokio::main] 36 | async fn main() -> eyre::Result<()> { 37 | color_eyre::install()?; 38 | 39 | let opt = Opt::parse(); 40 | 41 | tracing_subscriber::fmt() 42 | .with_env_filter( 43 | std::env::var("RUST_LOG").unwrap_or_else(|_| "a_train=info,bernard=info".to_owned()), 44 | ) 45 | .with_span_events(FmtSpan::CLOSE) 46 | .pretty() 47 | .init(); 48 | 49 | let config = Config::new(&opt.config)?; 50 | 51 | let mut a_train = a_train::AtrainBuilder::new(config, &opt.database)?; 52 | if let Some(url) = opt.proxy { 53 | a_train = a_train.proxy(url); 54 | } 55 | 56 | let a_train = a_train.build().await?; 57 | 58 | loop { 59 | tokio::select! { 60 | result = a_train.tick() => result?, 61 | _ = ctrl_c() => break, 62 | } 63 | } 64 | 65 | a_train.close().await; 66 | 67 | Ok(()) 68 | } 69 | -------------------------------------------------------------------------------- /xtask/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtask" 3 | version = "0.1.0" 4 | authors = ["Storm Timmermans "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | anyhow = "1" 11 | clap = "3.0.0-beta.2" 12 | colored = "2" 13 | flate2 = "1" 14 | once_cell = "1" 15 | xshell = "0.1" -------------------------------------------------------------------------------- /xtask/src/commands/ci.rs: -------------------------------------------------------------------------------- 1 | use crate::commands::{Section, XtaskCommand}; 2 | use clap::Parser; 3 | use xshell::cmd; 4 | 5 | #[derive(Parser)] 6 | pub(crate) struct Ci; 7 | 8 | fn cargo_clippy() -> xshell::Result<()> { 9 | let _s = Section::new("Clippy"); 10 | cmd!("cargo clippy --workspace").run() 11 | } 12 | 13 | fn cargo_test() -> xshell::Result<()> { 14 | let _s = Section::new("Test"); 15 | cmd!("cargo test --workspace").run() 16 | } 17 | 18 | impl XtaskCommand for Ci { 19 | fn run(&self) -> anyhow::Result<()> { 20 | cargo_clippy()?; 21 | cargo_test()?; 22 | 23 | Ok(()) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /xtask/src/commands/dist.rs: -------------------------------------------------------------------------------- 1 | use crate::commands::{dist_path, source_path, Section, XtaskCommand}; 2 | use anyhow::Context; 3 | use clap::Parser; 4 | use flate2::{write::GzEncoder, Compression}; 5 | use std::path::{Path, PathBuf}; 6 | use std::{fs, io}; 7 | use xshell::cmd; 8 | 9 | #[derive(Parser)] 10 | pub(crate) struct Dist { 11 | #[clap(long)] 12 | skip_build: bool, 13 | #[clap(required = true)] 14 | targets: Vec, 15 | } 16 | 17 | impl Dist { 18 | pub(crate) fn new(targets: I, skip_build: bool) -> Self 19 | where 20 | I: IntoIterator, 21 | T: Into, 22 | { 23 | Self { 24 | skip_build, 25 | targets: targets.into_iter().map(Into::into).collect(), 26 | } 27 | } 28 | } 29 | 30 | impl XtaskCommand for Dist { 31 | fn run(&self) -> anyhow::Result<()> { 32 | reset_dist()?; 33 | 34 | for target in &self.targets { 35 | if !self.skip_build { 36 | cross_build(target)?; 37 | } 38 | 39 | package(target)?; 40 | } 41 | 42 | Ok(()) 43 | } 44 | } 45 | 46 | fn reset_dist() -> anyhow::Result<()> { 47 | let _s = Section::new("Resetting dist directory"); 48 | 49 | let path = dist_path(); 50 | if path.exists() { 51 | fs::remove_dir_all(&path)?; 52 | } 53 | 54 | fs::create_dir_all(&path)?; 55 | Ok(()) 56 | } 57 | 58 | fn cross_build(target: &str) -> xshell::Result<()> { 59 | let _s = Section::new(format!("Build: {}", target)); 60 | cmd!("cross build --release --target {target} --package a-train").run() 61 | } 62 | 63 | fn package(target: &str) -> anyhow::Result<()> { 64 | let _s = Section::new(format!("Package: {}", target)); 65 | 66 | let src = source_path(target); 67 | 68 | // Ignore the error strip provides on cross-compiled binaries. 69 | // Should probably wait for Rust to provide stripping of its own 70 | // without requiring nightly. 71 | strip(&src).ok(); 72 | 73 | let dst = destination_path(target); 74 | gzip(&src, &dst)?; 75 | 76 | Ok(()) 77 | } 78 | 79 | fn strip(src: S) -> anyhow::Result<()> 80 | where 81 | S: AsRef, 82 | { 83 | let src = src.as_ref(); 84 | cmd!("strip {src}").run()?; 85 | Ok(()) 86 | } 87 | 88 | fn gzip(src: S, dst: T) -> anyhow::Result<()> 89 | where 90 | S: AsRef, 91 | T: AsRef, 92 | { 93 | // Open the source file 94 | let src = src.as_ref(); 95 | let src = fs::File::open(&src).context(format!("source path {:?} does not exist", &src))?; 96 | 97 | // Create the destination file 98 | let dst = dst.as_ref(); 99 | let dst = 100 | fs::File::create(&dst).context(format!("cannot create destination file at {:?}", &dst))?; 101 | 102 | // Compress the source content into the destination file 103 | let mut encoder = GzEncoder::new(dst, Compression::best()); 104 | let mut input = io::BufReader::new(src); 105 | io::copy(&mut input, &mut encoder)?; 106 | encoder.finish()?; 107 | 108 | Ok(()) 109 | } 110 | 111 | fn destination_path(target: &str) -> PathBuf { 112 | let suffix = if target.contains("-windows-") { 113 | ".exe.gz" 114 | } else { 115 | ".gz" 116 | }; 117 | 118 | dist_path().join(format!("a-train-{}{}", target, suffix)) 119 | } 120 | -------------------------------------------------------------------------------- /xtask/src/commands/docker.rs: -------------------------------------------------------------------------------- 1 | use crate::commands::XtaskCommand; 2 | use anyhow::ensure; 3 | use clap::Parser; 4 | use std::process::Command; 5 | 6 | /// Build the Docker image 7 | #[derive(Parser)] 8 | pub(crate) struct Docker { 9 | #[clap(subcommand)] 10 | cmd: SubCommand, 11 | } 12 | 13 | impl XtaskCommand for Docker { 14 | fn run(&self) -> anyhow::Result<()> { 15 | match self.cmd { 16 | SubCommand::Build(ref cmd) => cmd.run(), 17 | SubCommand::Prepare(ref cmd) => cmd.run(), 18 | } 19 | } 20 | } 21 | 22 | #[derive(Parser)] 23 | enum SubCommand { 24 | /// Build the Docker image. 25 | /// 26 | /// Requires you to run `cargo xtask docker prepare` first. 27 | Build(Build), 28 | 29 | /// Prepare the binaries for the Docker image. 30 | /// 31 | /// Calls `cargo xtask dist` under-the-hood with all the docker 32 | /// targets. 33 | Prepare(Prepare), 34 | } 35 | 36 | #[derive(Parser)] 37 | struct Build { 38 | /// Push the Docker image to the remote registry. 39 | #[clap(long)] 40 | push: bool, 41 | } 42 | 43 | impl XtaskCommand for Build { 44 | fn run(&self) -> anyhow::Result<()> { 45 | let platforms = vec!["linux/amd64", "linux/arm64", "linux/arm/v6", "linux/arm/v7"]; 46 | 47 | let mut cmd = Command::new("docker"); 48 | cmd.arg("buildx"); 49 | cmd.arg("build"); 50 | cmd.arg("."); 51 | cmd.arg("-t"); 52 | cmd.arg("ghcr.io/m-rots/a-train"); 53 | cmd.arg("--platform"); 54 | cmd.arg(platforms.join(",")); 55 | 56 | if self.push { 57 | cmd.arg("--push"); 58 | } 59 | 60 | let status = cmd.status()?; 61 | 62 | ensure!( 63 | status.success(), 64 | "Docker build unsuccessful with status: {}", 65 | status 66 | ); 67 | 68 | Ok(()) 69 | } 70 | } 71 | 72 | #[derive(Parser)] 73 | struct Prepare { 74 | #[clap(long)] 75 | skip_build: bool, 76 | } 77 | 78 | impl XtaskCommand for Prepare { 79 | fn run(&self) -> anyhow::Result<()> { 80 | let dist = super::dist::Dist::new( 81 | vec![ 82 | "x86_64-unknown-linux-musl", 83 | "aarch64-unknown-linux-musl", 84 | "arm-unknown-linux-musleabihf", 85 | "armv7-unknown-linux-musleabihf", 86 | ], 87 | self.skip_build, 88 | ); 89 | 90 | dist.run() 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /xtask/src/commands/mod.rs: -------------------------------------------------------------------------------- 1 | use colored::Colorize; 2 | use once_cell::sync::Lazy; 3 | use std::path::{Path, PathBuf}; 4 | use std::time::Instant; 5 | 6 | mod ci; 7 | mod dist; 8 | mod docker; 9 | 10 | pub(crate) use ci::Ci; 11 | pub(crate) use dist::Dist; 12 | pub(crate) use docker::Docker; 13 | 14 | pub(crate) trait XtaskCommand { 15 | fn run(&self) -> anyhow::Result<()>; 16 | } 17 | 18 | static GH_ACTIONS: Lazy = Lazy::new(|| std::env::var("GITHUB_ACTIONS").is_ok()); 19 | 20 | enum Platform { 21 | GitHubActions, 22 | Local, 23 | } 24 | 25 | impl Platform { 26 | fn current() -> Self { 27 | if *GH_ACTIONS { 28 | Self::GitHubActions 29 | } else { 30 | Self::Local 31 | } 32 | } 33 | } 34 | 35 | struct Section { 36 | name: String, 37 | start: Instant, 38 | } 39 | 40 | impl Section { 41 | fn new>(name: S) -> Self { 42 | let name = name.into(); 43 | 44 | match Platform::current() { 45 | Platform::GitHubActions => println!("::group::{}", &name), 46 | Platform::Local => println!( 47 | "\n{} {}", 48 | "-->".bright_purple(), 49 | name.bright_purple().bold() 50 | ), 51 | } 52 | 53 | let start = Instant::now(); 54 | Self { name, start } 55 | } 56 | } 57 | 58 | impl Drop for Section { 59 | fn drop(&mut self) { 60 | let info = format!("<-- {} ({:.2?})", self.name.bold(), self.start.elapsed()); 61 | println!("\n{}", info.dimmed()); 62 | 63 | match Platform::current() { 64 | Platform::GitHubActions => println!("::endgroup::"), 65 | Platform::Local => (), 66 | } 67 | } 68 | } 69 | 70 | fn project_root() -> PathBuf { 71 | Path::new(env!("CARGO_MANIFEST_DIR")) 72 | .parent() 73 | .unwrap() 74 | .to_path_buf() 75 | } 76 | 77 | fn dist_path() -> PathBuf { 78 | project_root().join("target").join("dist") 79 | } 80 | 81 | fn source_path(target: &str) -> PathBuf { 82 | let path = project_root() 83 | .join("target") 84 | .join(target) 85 | .join("release") 86 | .join("a-train"); 87 | 88 | if target.contains("-windows-") { 89 | path.with_extension("exe") 90 | } else { 91 | path 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /xtask/src/lib.rs: -------------------------------------------------------------------------------- 1 | use crate::commands::XtaskCommand; 2 | use clap::{AppSettings, Parser}; 3 | use commands::{Ci, Dist, Docker}; 4 | 5 | mod commands; 6 | 7 | #[derive(Parser)] 8 | #[clap(setting = AppSettings::PropagateVersion)] 9 | enum SubCommand { 10 | Ci(Ci), 11 | Dist(Dist), 12 | Docker(Docker), 13 | } 14 | 15 | #[derive(Parser)] 16 | struct Opt { 17 | #[clap(subcommand)] 18 | cmd: SubCommand, 19 | } 20 | 21 | pub fn run() -> anyhow::Result<()> { 22 | let opt = Opt::parse(); 23 | 24 | match opt.cmd { 25 | SubCommand::Ci(cmd) => cmd.run(), 26 | SubCommand::Dist(cmd) => cmd.run(), 27 | SubCommand::Docker(cmd) => cmd.run(), 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /xtask/src/main.rs: -------------------------------------------------------------------------------- 1 | fn main() -> anyhow::Result<()> { 2 | xtask::run() 3 | } 4 | --------------------------------------------------------------------------------