diff options
| author | Rutger Broekhoff | 2024-01-19 00:21:09 +0100 |
|---|---|---|
| committer | Rutger Broekhoff | 2024-01-19 00:21:09 +0100 |
| commit | 5156228f18f08255a1f5c7e22097b8e367881e19 (patch) | |
| tree | 8caccbf4d6d47b9f365d091d5b3426c4e6f7dafa | |
| parent | b07332d62c347326baade26e3a3c281b83172615 (diff) | |
| download | gitolfs3-5156228f18f08255a1f5c7e22097b8e367881e19.tar.gz gitolfs3-5156228f18f08255a1f5c7e22097b8e367881e19.zip | |
Rust code dump
| -rw-r--r-- | cmd/git-lfs-authenticate/main.c | 13 | ||||
| -rw-r--r-- | flake.lock | 20 | ||||
| -rw-r--r-- | flake.nix | 9 | ||||
| -rw-r--r-- | rs/.gitignore | 1 | ||||
| -rw-r--r-- | rs/Cargo.lock | 2022 | ||||
| -rw-r--r-- | rs/Cargo.toml | 7 | ||||
| -rw-r--r-- | rs/common/Cargo.toml | 10 | ||||
| -rw-r--r-- | rs/common/src/lib.rs | 337 | ||||
| -rw-r--r-- | rs/git-lfs-authenticate/Cargo.toml | 8 | ||||
| -rw-r--r-- | rs/git-lfs-authenticate/src/main.rs | 239 | ||||
| -rw-r--r-- | rs/server/Cargo.toml | 15 | ||||
| -rw-r--r-- | rs/server/src/main.rs | 347 |
12 files changed, 3020 insertions, 8 deletions
diff --git a/cmd/git-lfs-authenticate/main.c b/cmd/git-lfs-authenticate/main.c index 71481e9..a7ec031 100644 --- a/cmd/git-lfs-authenticate/main.c +++ b/cmd/git-lfs-authenticate/main.c | |||
| @@ -65,8 +65,6 @@ void checkrepopath(const char *path) { | |||
| 65 | die("Bad repository name: Is unresolved path"); | 65 | die("Bad repository name: Is unresolved path"); |
| 66 | if (strlen(path) > 100) | 66 | if (strlen(path) > 100) |
| 67 | die("Bad repository name: Longer than 100 characters"); | 67 | die("Bad repository name: Longer than 100 characters"); |
| 68 | if (hassuffix(path, "/")) | ||
| 69 | die("Bad repositry name: Unexpected trailing slash"); | ||
| 70 | if (hasprefix(path, "/")) | 68 | if (hasprefix(path, "/")) |
| 71 | die("Bad repository name: Unexpected absolute path"); | 69 | die("Bad repository name: Unexpected absolute path"); |
| 72 | if (!hassuffix(path, ".git")) | 70 | if (!hassuffix(path, ".git")) |
| @@ -152,6 +150,10 @@ void u64tobe(uint64_t x, uint8_t b[8]) { | |||
| 152 | b[7] = (uint8_t)(x >> 0); | 150 | b[7] = (uint8_t)(x >> 0); |
| 153 | } | 151 | } |
| 154 | 152 | ||
| 153 | void *memcat(void *dest, const void *src, size_t n) { | ||
| 154 | return memcpy(dest, src, n) + n; | ||
| 155 | } | ||
| 156 | |||
| 155 | #define MAX_TAG_SIZE EVP_MAX_MD_SIZE | 157 | #define MAX_TAG_SIZE EVP_MAX_MD_SIZE |
| 156 | 158 | ||
| 157 | typedef struct taginfo { | 159 | typedef struct taginfo { |
| @@ -161,10 +163,6 @@ typedef struct taginfo { | |||
| 161 | const int64_t expiresat_s; | 163 | const int64_t expiresat_s; |
| 162 | } taginfo_t; | 164 | } taginfo_t; |
| 163 | 165 | ||
| 164 | void *memcat(void *dest, const void *src, size_t n) { | ||
| 165 | return memcpy(dest, src, n) + n; | ||
| 166 | } | ||
| 167 | |||
| 168 | void maketag(const taginfo_t info, uint8_t key[KEYSIZE], uint8_t dest[MAX_TAG_SIZE], uint32_t *len) { | 166 | void maketag(const taginfo_t info, uint8_t key[KEYSIZE], uint8_t dest[MAX_TAG_SIZE], uint32_t *len) { |
| 169 | uint8_t expiresat_b[8]; | 167 | uint8_t expiresat_b[8]; |
| 170 | u64tobe(info.expiresat_s, expiresat_b); | 168 | u64tobe(info.expiresat_s, expiresat_b); |
| @@ -247,7 +245,8 @@ int main(int argc, char *argv[]) { | |||
| 247 | char hextag[MAX_HEXTAG_STRLEN + 1]; | 245 | char hextag[MAX_HEXTAG_STRLEN + 1]; |
| 248 | makehextag(taginfo, key, hextag); | 246 | makehextag(taginfo, key, hextag); |
| 249 | 247 | ||
| 250 | printf("{\"header\":{\"Authorization\":\"Gitolfs3-Hmac-Sha256 %s\"},\"expires_in\":%ld,\"href\":\"", hextag, expiresin_s); | 248 | printf("{\"header\":{\"Authorization\":\"Gitolfs3-Hmac-Sha256 %s\"}," |
| 249 | "\"expires_in\":%ld,\"href\":\"", hextag, expiresin_s); | ||
| 251 | printescjson(hrefbase); | 250 | printescjson(hrefbase); |
| 252 | printescjson(repopath); | 251 | printescjson(repopath); |
| 253 | printf("/info/lfs?p=1&te=%ld\"}\n", expiresat_s); | 252 | printf("/info/lfs?p=1&te=%ld\"}\n", expiresat_s); |
| @@ -1,5 +1,24 @@ | |||
| 1 | { | 1 | { |
| 2 | "nodes": { | 2 | "nodes": { |
| 3 | "crane": { | ||
| 4 | "inputs": { | ||
| 5 | "nixpkgs": [ | ||
| 6 | "nixpkgs" | ||
| 7 | ] | ||
| 8 | }, | ||
| 9 | "locked": { | ||
| 10 | "lastModified": 1701384536, | ||
| 11 | "narHash": "sha256-PdYjpXmkn4FYJU7uvmCa54b0PPXBgDZHJaJpSEWR1Ek=", | ||
| 12 | "rev": "07c531adf572dafd494db0672cdac00e48216171", | ||
| 13 | "revCount": 469, | ||
| 14 | "type": "tarball", | ||
| 15 | "url": "https://api.flakehub.com/f/pinned/ipetkov/crane/0.15.1/018c226e-9985-758b-9809-17419c4ebd2d/source.tar.gz" | ||
| 16 | }, | ||
| 17 | "original": { | ||
| 18 | "type": "tarball", | ||
| 19 | "url": "https://flakehub.com/f/ipetkov/crane/0.15.1.tar.gz" | ||
| 20 | } | ||
| 21 | }, | ||
| 3 | "flake-utils": { | 22 | "flake-utils": { |
| 4 | "inputs": { | 23 | "inputs": { |
| 5 | "systems": "systems" | 24 | "systems": "systems" |
| @@ -33,6 +52,7 @@ | |||
| 33 | }, | 52 | }, |
| 34 | "root": { | 53 | "root": { |
| 35 | "inputs": { | 54 | "inputs": { |
| 55 | "crane": "crane", | ||
| 36 | "flake-utils": "flake-utils", | 56 | "flake-utils": "flake-utils", |
| 37 | "nixpkgs": "nixpkgs" | 57 | "nixpkgs": "nixpkgs" |
| 38 | } | 58 | } |
| @@ -2,9 +2,11 @@ | |||
| 2 | inputs = { | 2 | inputs = { |
| 3 | nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2311.*.tar.gz"; | 3 | nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2311.*.tar.gz"; |
| 4 | flake-utils.url = "https://flakehub.com/f/numtide/flake-utils/0.1.88.tar.gz"; | 4 | flake-utils.url = "https://flakehub.com/f/numtide/flake-utils/0.1.88.tar.gz"; |
| 5 | crane.url = "https://flakehub.com/f/ipetkov/crane/0.15.1.tar.gz"; | ||
| 6 | crane.inputs.nixpkgs.follows = "nixpkgs"; | ||
| 5 | }; | 7 | }; |
| 6 | 8 | ||
| 7 | outputs = { self, nixpkgs, flake-utils, ... }@inputs: | 9 | outputs = { self, crane, nixpkgs, flake-utils, ... }@inputs: |
| 8 | flake-utils.lib.eachDefaultSystem | 10 | flake-utils.lib.eachDefaultSystem |
| 9 | (system: | 11 | (system: |
| 10 | let | 12 | let |
| @@ -13,6 +15,8 @@ | |||
| 13 | overlays = [ ]; | 15 | overlays = [ ]; |
| 14 | }; | 16 | }; |
| 15 | 17 | ||
| 18 | craneLib = crane.lib.${system}; | ||
| 19 | |||
| 16 | gitolfs3 = pkgs.buildGoModule { | 20 | gitolfs3 = pkgs.buildGoModule { |
| 17 | name = "gitolfs3"; | 21 | name = "gitolfs3"; |
| 18 | src = ./.; | 22 | src = ./.; |
| @@ -21,6 +25,9 @@ | |||
| 21 | in | 25 | in |
| 22 | { | 26 | { |
| 23 | packages.gitolfs3 = gitolfs3; | 27 | packages.gitolfs3 = gitolfs3; |
| 28 | packages.gitolfs3-rs = craneLib.buildPackage { | ||
| 29 | src = craneLib.cleanCargoSource (craneLib.path ./rs); | ||
| 30 | }; | ||
| 24 | packages.default = self.packages.${system}.gitolfs3; | 31 | packages.default = self.packages.${system}.gitolfs3; |
| 25 | 32 | ||
| 26 | devShells.default = pkgs.mkShell { | 33 | devShells.default = pkgs.mkShell { |
diff --git a/rs/.gitignore b/rs/.gitignore new file mode 100644 index 0000000..b83d222 --- /dev/null +++ b/rs/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| /target/ | |||
diff --git a/rs/Cargo.lock b/rs/Cargo.lock new file mode 100644 index 0000000..6069bcb --- /dev/null +++ b/rs/Cargo.lock | |||
| @@ -0,0 +1,2022 @@ | |||
| 1 | # This file is automatically @generated by Cargo. | ||
| 2 | # It is not intended for manual editing. | ||
| 3 | version = 3 | ||
| 4 | |||
| 5 | [[package]] | ||
| 6 | name = "addr2line" | ||
| 7 | version = "0.21.0" | ||
| 8 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" | ||
| 10 | dependencies = [ | ||
| 11 | "gimli", | ||
| 12 | ] | ||
| 13 | |||
| 14 | [[package]] | ||
| 15 | name = "adler" | ||
| 16 | version = "1.0.2" | ||
| 17 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" | ||
| 19 | |||
| 20 | [[package]] | ||
| 21 | name = "ahash" | ||
| 22 | version = "0.7.7" | ||
| 23 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 24 | checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" | ||
| 25 | dependencies = [ | ||
| 26 | "getrandom", | ||
| 27 | "once_cell", | ||
| 28 | "version_check", | ||
| 29 | ] | ||
| 30 | |||
| 31 | [[package]] | ||
| 32 | name = "android-tzdata" | ||
| 33 | version = "0.1.1" | ||
| 34 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 35 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" | ||
| 36 | |||
| 37 | [[package]] | ||
| 38 | name = "android_system_properties" | ||
| 39 | version = "0.1.5" | ||
| 40 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 41 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" | ||
| 42 | dependencies = [ | ||
| 43 | "libc", | ||
| 44 | ] | ||
| 45 | |||
| 46 | [[package]] | ||
| 47 | name = "async-trait" | ||
| 48 | version = "0.1.77" | ||
| 49 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 50 | checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" | ||
| 51 | dependencies = [ | ||
| 52 | "proc-macro2", | ||
| 53 | "quote", | ||
| 54 | "syn 2.0.48", | ||
| 55 | ] | ||
| 56 | |||
| 57 | [[package]] | ||
| 58 | name = "attohttpc" | ||
| 59 | version = "0.22.0" | ||
| 60 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 61 | checksum = "1fcf00bc6d5abb29b5f97e3c61a90b6d3caa12f3faf897d4a3e3607c050a35a7" | ||
| 62 | dependencies = [ | ||
| 63 | "http 0.2.11", | ||
| 64 | "log", | ||
| 65 | "native-tls", | ||
| 66 | "serde", | ||
| 67 | "serde_json", | ||
| 68 | "url", | ||
| 69 | ] | ||
| 70 | |||
| 71 | [[package]] | ||
| 72 | name = "autocfg" | ||
| 73 | version = "1.1.0" | ||
| 74 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 75 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" | ||
| 76 | |||
| 77 | [[package]] | ||
| 78 | name = "aws-creds" | ||
| 79 | version = "0.34.1" | ||
| 80 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 81 | checksum = "3776743bb68d4ad02ba30ba8f64373f1be4e082fe47651767171ce75bb2f6cf5" | ||
| 82 | dependencies = [ | ||
| 83 | "attohttpc", | ||
| 84 | "dirs", | ||
| 85 | "log", | ||
| 86 | "quick-xml", | ||
| 87 | "rust-ini", | ||
| 88 | "serde", | ||
| 89 | "thiserror", | ||
| 90 | "time", | ||
| 91 | "url", | ||
| 92 | ] | ||
| 93 | |||
| 94 | [[package]] | ||
| 95 | name = "aws-region" | ||
| 96 | version = "0.25.4" | ||
| 97 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 98 | checksum = "42fed2b9fca70f2908268d057a607f2a906f47edbf856ea8587de9038d264e22" | ||
| 99 | dependencies = [ | ||
| 100 | "thiserror", | ||
| 101 | ] | ||
| 102 | |||
| 103 | [[package]] | ||
| 104 | name = "axum" | ||
| 105 | version = "0.7.4" | ||
| 106 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 107 | checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" | ||
| 108 | dependencies = [ | ||
| 109 | "async-trait", | ||
| 110 | "axum-core", | ||
| 111 | "bytes", | ||
| 112 | "futures-util", | ||
| 113 | "http 1.0.0", | ||
| 114 | "http-body 1.0.0", | ||
| 115 | "http-body-util", | ||
| 116 | "hyper 1.1.0", | ||
| 117 | "hyper-util", | ||
| 118 | "itoa", | ||
| 119 | "matchit", | ||
| 120 | "memchr", | ||
| 121 | "mime", | ||
| 122 | "percent-encoding", | ||
| 123 | "pin-project-lite", | ||
| 124 | "rustversion", | ||
| 125 | "serde", | ||
| 126 | "serde_json", | ||
| 127 | "serde_path_to_error", | ||
| 128 | "serde_urlencoded", | ||
| 129 | "sync_wrapper", | ||
| 130 | "tokio", | ||
| 131 | "tower", | ||
| 132 | "tower-layer", | ||
| 133 | "tower-service", | ||
| 134 | "tracing", | ||
| 135 | ] | ||
| 136 | |||
| 137 | [[package]] | ||
| 138 | name = "axum-core" | ||
| 139 | version = "0.4.3" | ||
| 140 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 141 | checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" | ||
| 142 | dependencies = [ | ||
| 143 | "async-trait", | ||
| 144 | "bytes", | ||
| 145 | "futures-util", | ||
| 146 | "http 1.0.0", | ||
| 147 | "http-body 1.0.0", | ||
| 148 | "http-body-util", | ||
| 149 | "mime", | ||
| 150 | "pin-project-lite", | ||
| 151 | "rustversion", | ||
| 152 | "sync_wrapper", | ||
| 153 | "tower-layer", | ||
| 154 | "tower-service", | ||
| 155 | "tracing", | ||
| 156 | ] | ||
| 157 | |||
| 158 | [[package]] | ||
| 159 | name = "backtrace" | ||
| 160 | version = "0.3.69" | ||
| 161 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 162 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" | ||
| 163 | dependencies = [ | ||
| 164 | "addr2line", | ||
| 165 | "cc", | ||
| 166 | "cfg-if", | ||
| 167 | "libc", | ||
| 168 | "miniz_oxide", | ||
| 169 | "object", | ||
| 170 | "rustc-demangle", | ||
| 171 | ] | ||
| 172 | |||
| 173 | [[package]] | ||
| 174 | name = "base64" | ||
| 175 | version = "0.13.1" | ||
| 176 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 177 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" | ||
| 178 | |||
| 179 | [[package]] | ||
| 180 | name = "base64" | ||
| 181 | version = "0.21.7" | ||
| 182 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 183 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" | ||
| 184 | |||
| 185 | [[package]] | ||
| 186 | name = "bitflags" | ||
| 187 | version = "1.3.2" | ||
| 188 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 189 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" | ||
| 190 | |||
| 191 | [[package]] | ||
| 192 | name = "bitflags" | ||
| 193 | version = "2.4.2" | ||
| 194 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 195 | checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" | ||
| 196 | |||
| 197 | [[package]] | ||
| 198 | name = "block-buffer" | ||
| 199 | version = "0.10.4" | ||
| 200 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 201 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" | ||
| 202 | dependencies = [ | ||
| 203 | "generic-array", | ||
| 204 | ] | ||
| 205 | |||
| 206 | [[package]] | ||
| 207 | name = "bumpalo" | ||
| 208 | version = "3.14.0" | ||
| 209 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 210 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" | ||
| 211 | |||
| 212 | [[package]] | ||
| 213 | name = "bytes" | ||
| 214 | version = "1.5.0" | ||
| 215 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 216 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" | ||
| 217 | |||
| 218 | [[package]] | ||
| 219 | name = "cc" | ||
| 220 | version = "1.0.83" | ||
| 221 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 222 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" | ||
| 223 | dependencies = [ | ||
| 224 | "libc", | ||
| 225 | ] | ||
| 226 | |||
| 227 | [[package]] | ||
| 228 | name = "cfg-if" | ||
| 229 | version = "1.0.0" | ||
| 230 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 231 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||
| 232 | |||
| 233 | [[package]] | ||
| 234 | name = "chrono" | ||
| 235 | version = "0.4.31" | ||
| 236 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 237 | checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" | ||
| 238 | dependencies = [ | ||
| 239 | "android-tzdata", | ||
| 240 | "iana-time-zone", | ||
| 241 | "js-sys", | ||
| 242 | "num-traits", | ||
| 243 | "serde", | ||
| 244 | "wasm-bindgen", | ||
| 245 | "windows-targets 0.48.5", | ||
| 246 | ] | ||
| 247 | |||
| 248 | [[package]] | ||
| 249 | name = "common" | ||
| 250 | version = "0.1.0" | ||
| 251 | dependencies = [ | ||
| 252 | "chrono", | ||
| 253 | "hmac-sha256", | ||
| 254 | "serde", | ||
| 255 | "subtle", | ||
| 256 | ] | ||
| 257 | |||
| 258 | [[package]] | ||
| 259 | name = "core-foundation" | ||
| 260 | version = "0.9.4" | ||
| 261 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 262 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" | ||
| 263 | dependencies = [ | ||
| 264 | "core-foundation-sys", | ||
| 265 | "libc", | ||
| 266 | ] | ||
| 267 | |||
| 268 | [[package]] | ||
| 269 | name = "core-foundation-sys" | ||
| 270 | version = "0.8.6" | ||
| 271 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 272 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" | ||
| 273 | |||
| 274 | [[package]] | ||
| 275 | name = "cpufeatures" | ||
| 276 | version = "0.2.12" | ||
| 277 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 278 | checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" | ||
| 279 | dependencies = [ | ||
| 280 | "libc", | ||
| 281 | ] | ||
| 282 | |||
| 283 | [[package]] | ||
| 284 | name = "crypto-common" | ||
| 285 | version = "0.1.6" | ||
| 286 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 287 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" | ||
| 288 | dependencies = [ | ||
| 289 | "generic-array", | ||
| 290 | "typenum", | ||
| 291 | ] | ||
| 292 | |||
| 293 | [[package]] | ||
| 294 | name = "deranged" | ||
| 295 | version = "0.3.11" | ||
| 296 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 297 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" | ||
| 298 | dependencies = [ | ||
| 299 | "powerfmt", | ||
| 300 | "serde", | ||
| 301 | ] | ||
| 302 | |||
| 303 | [[package]] | ||
| 304 | name = "digest" | ||
| 305 | version = "0.10.7" | ||
| 306 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 307 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" | ||
| 308 | dependencies = [ | ||
| 309 | "block-buffer", | ||
| 310 | "crypto-common", | ||
| 311 | "subtle", | ||
| 312 | ] | ||
| 313 | |||
| 314 | [[package]] | ||
| 315 | name = "dirs" | ||
| 316 | version = "4.0.0" | ||
| 317 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 318 | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" | ||
| 319 | dependencies = [ | ||
| 320 | "dirs-sys", | ||
| 321 | ] | ||
| 322 | |||
| 323 | [[package]] | ||
| 324 | name = "dirs-sys" | ||
| 325 | version = "0.3.7" | ||
| 326 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 327 | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" | ||
| 328 | dependencies = [ | ||
| 329 | "libc", | ||
| 330 | "redox_users", | ||
| 331 | "winapi", | ||
| 332 | ] | ||
| 333 | |||
| 334 | [[package]] | ||
| 335 | name = "dlv-list" | ||
| 336 | version = "0.3.0" | ||
| 337 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 338 | checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" | ||
| 339 | |||
| 340 | [[package]] | ||
| 341 | name = "encoding_rs" | ||
| 342 | version = "0.8.33" | ||
| 343 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 344 | checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" | ||
| 345 | dependencies = [ | ||
| 346 | "cfg-if", | ||
| 347 | ] | ||
| 348 | |||
| 349 | [[package]] | ||
| 350 | name = "equivalent" | ||
| 351 | version = "1.0.1" | ||
| 352 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 353 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" | ||
| 354 | |||
| 355 | [[package]] | ||
| 356 | name = "errno" | ||
| 357 | version = "0.3.8" | ||
| 358 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 359 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" | ||
| 360 | dependencies = [ | ||
| 361 | "libc", | ||
| 362 | "windows-sys 0.52.0", | ||
| 363 | ] | ||
| 364 | |||
| 365 | [[package]] | ||
| 366 | name = "fastrand" | ||
| 367 | version = "2.0.1" | ||
| 368 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 369 | checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" | ||
| 370 | |||
| 371 | [[package]] | ||
| 372 | name = "fnv" | ||
| 373 | version = "1.0.7" | ||
| 374 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 375 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" | ||
| 376 | |||
| 377 | [[package]] | ||
| 378 | name = "foreign-types" | ||
| 379 | version = "0.3.2" | ||
| 380 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 381 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" | ||
| 382 | dependencies = [ | ||
| 383 | "foreign-types-shared", | ||
| 384 | ] | ||
| 385 | |||
| 386 | [[package]] | ||
| 387 | name = "foreign-types-shared" | ||
| 388 | version = "0.1.1" | ||
| 389 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 390 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" | ||
| 391 | |||
| 392 | [[package]] | ||
| 393 | name = "form_urlencoded" | ||
| 394 | version = "1.2.1" | ||
| 395 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 396 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" | ||
| 397 | dependencies = [ | ||
| 398 | "percent-encoding", | ||
| 399 | ] | ||
| 400 | |||
| 401 | [[package]] | ||
| 402 | name = "futures" | ||
| 403 | version = "0.3.30" | ||
| 404 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 405 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" | ||
| 406 | dependencies = [ | ||
| 407 | "futures-channel", | ||
| 408 | "futures-core", | ||
| 409 | "futures-executor", | ||
| 410 | "futures-io", | ||
| 411 | "futures-sink", | ||
| 412 | "futures-task", | ||
| 413 | "futures-util", | ||
| 414 | ] | ||
| 415 | |||
| 416 | [[package]] | ||
| 417 | name = "futures-channel" | ||
| 418 | version = "0.3.30" | ||
| 419 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 420 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" | ||
| 421 | dependencies = [ | ||
| 422 | "futures-core", | ||
| 423 | "futures-sink", | ||
| 424 | ] | ||
| 425 | |||
| 426 | [[package]] | ||
| 427 | name = "futures-core" | ||
| 428 | version = "0.3.30" | ||
| 429 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 430 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" | ||
| 431 | |||
| 432 | [[package]] | ||
| 433 | name = "futures-executor" | ||
| 434 | version = "0.3.30" | ||
| 435 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 436 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" | ||
| 437 | dependencies = [ | ||
| 438 | "futures-core", | ||
| 439 | "futures-task", | ||
| 440 | "futures-util", | ||
| 441 | ] | ||
| 442 | |||
| 443 | [[package]] | ||
| 444 | name = "futures-io" | ||
| 445 | version = "0.3.30" | ||
| 446 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 447 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" | ||
| 448 | |||
| 449 | [[package]] | ||
| 450 | name = "futures-macro" | ||
| 451 | version = "0.3.30" | ||
| 452 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 453 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" | ||
| 454 | dependencies = [ | ||
| 455 | "proc-macro2", | ||
| 456 | "quote", | ||
| 457 | "syn 2.0.48", | ||
| 458 | ] | ||
| 459 | |||
| 460 | [[package]] | ||
| 461 | name = "futures-sink" | ||
| 462 | version = "0.3.30" | ||
| 463 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 464 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" | ||
| 465 | |||
| 466 | [[package]] | ||
| 467 | name = "futures-task" | ||
| 468 | version = "0.3.30" | ||
| 469 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 470 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" | ||
| 471 | |||
| 472 | [[package]] | ||
| 473 | name = "futures-util" | ||
| 474 | version = "0.3.30" | ||
| 475 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 476 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" | ||
| 477 | dependencies = [ | ||
| 478 | "futures-channel", | ||
| 479 | "futures-core", | ||
| 480 | "futures-io", | ||
| 481 | "futures-macro", | ||
| 482 | "futures-sink", | ||
| 483 | "futures-task", | ||
| 484 | "memchr", | ||
| 485 | "pin-project-lite", | ||
| 486 | "pin-utils", | ||
| 487 | "slab", | ||
| 488 | ] | ||
| 489 | |||
| 490 | [[package]] | ||
| 491 | name = "generic-array" | ||
| 492 | version = "0.14.7" | ||
| 493 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 494 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" | ||
| 495 | dependencies = [ | ||
| 496 | "typenum", | ||
| 497 | "version_check", | ||
| 498 | ] | ||
| 499 | |||
| 500 | [[package]] | ||
| 501 | name = "getrandom" | ||
| 502 | version = "0.2.12" | ||
| 503 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 504 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" | ||
| 505 | dependencies = [ | ||
| 506 | "cfg-if", | ||
| 507 | "libc", | ||
| 508 | "wasi", | ||
| 509 | ] | ||
| 510 | |||
| 511 | [[package]] | ||
| 512 | name = "gimli" | ||
| 513 | version = "0.28.1" | ||
| 514 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 515 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" | ||
| 516 | |||
| 517 | [[package]] | ||
| 518 | name = "git-lfs-authenticate" | ||
| 519 | version = "0.1.0" | ||
| 520 | dependencies = [ | ||
| 521 | "chrono", | ||
| 522 | "common", | ||
| 523 | ] | ||
| 524 | |||
| 525 | [[package]] | ||
| 526 | name = "h2" | ||
| 527 | version = "0.3.24" | ||
| 528 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 529 | checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" | ||
| 530 | dependencies = [ | ||
| 531 | "bytes", | ||
| 532 | "fnv", | ||
| 533 | "futures-core", | ||
| 534 | "futures-sink", | ||
| 535 | "futures-util", | ||
| 536 | "http 0.2.11", | ||
| 537 | "indexmap", | ||
| 538 | "slab", | ||
| 539 | "tokio", | ||
| 540 | "tokio-util", | ||
| 541 | "tracing", | ||
| 542 | ] | ||
| 543 | |||
| 544 | [[package]] | ||
| 545 | name = "h2" | ||
| 546 | version = "0.4.2" | ||
| 547 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 548 | checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943" | ||
| 549 | dependencies = [ | ||
| 550 | "bytes", | ||
| 551 | "fnv", | ||
| 552 | "futures-core", | ||
| 553 | "futures-sink", | ||
| 554 | "futures-util", | ||
| 555 | "http 1.0.0", | ||
| 556 | "indexmap", | ||
| 557 | "slab", | ||
| 558 | "tokio", | ||
| 559 | "tokio-util", | ||
| 560 | "tracing", | ||
| 561 | ] | ||
| 562 | |||
| 563 | [[package]] | ||
| 564 | name = "hashbrown" | ||
| 565 | version = "0.12.3" | ||
| 566 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 567 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" | ||
| 568 | dependencies = [ | ||
| 569 | "ahash", | ||
| 570 | ] | ||
| 571 | |||
| 572 | [[package]] | ||
| 573 | name = "hashbrown" | ||
| 574 | version = "0.14.3" | ||
| 575 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 576 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" | ||
| 577 | |||
| 578 | [[package]] | ||
| 579 | name = "hermit-abi" | ||
| 580 | version = "0.3.3" | ||
| 581 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 582 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" | ||
| 583 | |||
| 584 | [[package]] | ||
| 585 | name = "hex" | ||
| 586 | version = "0.4.3" | ||
| 587 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 588 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" | ||
| 589 | |||
| 590 | [[package]] | ||
| 591 | name = "hmac" | ||
| 592 | version = "0.12.1" | ||
| 593 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 594 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" | ||
| 595 | dependencies = [ | ||
| 596 | "digest", | ||
| 597 | ] | ||
| 598 | |||
| 599 | [[package]] | ||
| 600 | name = "hmac-sha256" | ||
| 601 | version = "1.1.7" | ||
| 602 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 603 | checksum = "3688e69b38018fec1557254f64c8dc2cc8ec502890182f395dbb0aa997aa5735" | ||
| 604 | |||
| 605 | [[package]] | ||
| 606 | name = "http" | ||
| 607 | version = "0.2.11" | ||
| 608 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 609 | checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" | ||
| 610 | dependencies = [ | ||
| 611 | "bytes", | ||
| 612 | "fnv", | ||
| 613 | "itoa", | ||
| 614 | ] | ||
| 615 | |||
| 616 | [[package]] | ||
| 617 | name = "http" | ||
| 618 | version = "1.0.0" | ||
| 619 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 620 | checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" | ||
| 621 | dependencies = [ | ||
| 622 | "bytes", | ||
| 623 | "fnv", | ||
| 624 | "itoa", | ||
| 625 | ] | ||
| 626 | |||
| 627 | [[package]] | ||
| 628 | name = "http-body" | ||
| 629 | version = "0.4.6" | ||
| 630 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 631 | checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" | ||
| 632 | dependencies = [ | ||
| 633 | "bytes", | ||
| 634 | "http 0.2.11", | ||
| 635 | "pin-project-lite", | ||
| 636 | ] | ||
| 637 | |||
| 638 | [[package]] | ||
| 639 | name = "http-body" | ||
| 640 | version = "1.0.0" | ||
| 641 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 642 | checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" | ||
| 643 | dependencies = [ | ||
| 644 | "bytes", | ||
| 645 | "http 1.0.0", | ||
| 646 | ] | ||
| 647 | |||
| 648 | [[package]] | ||
| 649 | name = "http-body-util" | ||
| 650 | version = "0.1.0" | ||
| 651 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 652 | checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" | ||
| 653 | dependencies = [ | ||
| 654 | "bytes", | ||
| 655 | "futures-util", | ||
| 656 | "http 1.0.0", | ||
| 657 | "http-body 1.0.0", | ||
| 658 | "pin-project-lite", | ||
| 659 | ] | ||
| 660 | |||
| 661 | [[package]] | ||
| 662 | name = "httparse" | ||
| 663 | version = "1.8.0" | ||
| 664 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 665 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" | ||
| 666 | |||
| 667 | [[package]] | ||
| 668 | name = "httpdate" | ||
| 669 | version = "1.0.3" | ||
| 670 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 671 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" | ||
| 672 | |||
| 673 | [[package]] | ||
| 674 | name = "hyper" | ||
| 675 | version = "0.14.28" | ||
| 676 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 677 | checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" | ||
| 678 | dependencies = [ | ||
| 679 | "bytes", | ||
| 680 | "futures-channel", | ||
| 681 | "futures-core", | ||
| 682 | "futures-util", | ||
| 683 | "h2 0.3.24", | ||
| 684 | "http 0.2.11", | ||
| 685 | "http-body 0.4.6", | ||
| 686 | "httparse", | ||
| 687 | "httpdate", | ||
| 688 | "itoa", | ||
| 689 | "pin-project-lite", | ||
| 690 | "socket2", | ||
| 691 | "tokio", | ||
| 692 | "tower-service", | ||
| 693 | "tracing", | ||
| 694 | "want", | ||
| 695 | ] | ||
| 696 | |||
| 697 | [[package]] | ||
| 698 | name = "hyper" | ||
| 699 | version = "1.1.0" | ||
| 700 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 701 | checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" | ||
| 702 | dependencies = [ | ||
| 703 | "bytes", | ||
| 704 | "futures-channel", | ||
| 705 | "futures-util", | ||
| 706 | "h2 0.4.2", | ||
| 707 | "http 1.0.0", | ||
| 708 | "http-body 1.0.0", | ||
| 709 | "httparse", | ||
| 710 | "httpdate", | ||
| 711 | "itoa", | ||
| 712 | "pin-project-lite", | ||
| 713 | "tokio", | ||
| 714 | ] | ||
| 715 | |||
| 716 | [[package]] | ||
| 717 | name = "hyper-tls" | ||
| 718 | version = "0.5.0" | ||
| 719 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 720 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" | ||
| 721 | dependencies = [ | ||
| 722 | "bytes", | ||
| 723 | "hyper 0.14.28", | ||
| 724 | "native-tls", | ||
| 725 | "tokio", | ||
| 726 | "tokio-native-tls", | ||
| 727 | ] | ||
| 728 | |||
| 729 | [[package]] | ||
| 730 | name = "hyper-util" | ||
| 731 | version = "0.1.2" | ||
| 732 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 733 | checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" | ||
| 734 | dependencies = [ | ||
| 735 | "bytes", | ||
| 736 | "futures-channel", | ||
| 737 | "futures-util", | ||
| 738 | "http 1.0.0", | ||
| 739 | "http-body 1.0.0", | ||
| 740 | "hyper 1.1.0", | ||
| 741 | "pin-project-lite", | ||
| 742 | "socket2", | ||
| 743 | "tokio", | ||
| 744 | "tracing", | ||
| 745 | ] | ||
| 746 | |||
| 747 | [[package]] | ||
| 748 | name = "iana-time-zone" | ||
| 749 | version = "0.1.59" | ||
| 750 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 751 | checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" | ||
| 752 | dependencies = [ | ||
| 753 | "android_system_properties", | ||
| 754 | "core-foundation-sys", | ||
| 755 | "iana-time-zone-haiku", | ||
| 756 | "js-sys", | ||
| 757 | "wasm-bindgen", | ||
| 758 | "windows-core", | ||
| 759 | ] | ||
| 760 | |||
| 761 | [[package]] | ||
| 762 | name = "iana-time-zone-haiku" | ||
| 763 | version = "0.1.2" | ||
| 764 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 765 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" | ||
| 766 | dependencies = [ | ||
| 767 | "cc", | ||
| 768 | ] | ||
| 769 | |||
| 770 | [[package]] | ||
| 771 | name = "idna" | ||
| 772 | version = "0.5.0" | ||
| 773 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 774 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" | ||
| 775 | dependencies = [ | ||
| 776 | "unicode-bidi", | ||
| 777 | "unicode-normalization", | ||
| 778 | ] | ||
| 779 | |||
| 780 | [[package]] | ||
| 781 | name = "indexmap" | ||
| 782 | version = "2.1.0" | ||
| 783 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 784 | checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" | ||
| 785 | dependencies = [ | ||
| 786 | "equivalent", | ||
| 787 | "hashbrown 0.14.3", | ||
| 788 | ] | ||
| 789 | |||
| 790 | [[package]] | ||
| 791 | name = "ipnet" | ||
| 792 | version = "2.9.0" | ||
| 793 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 794 | checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" | ||
| 795 | |||
| 796 | [[package]] | ||
| 797 | name = "itoa" | ||
| 798 | version = "1.0.10" | ||
| 799 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 800 | checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" | ||
| 801 | |||
| 802 | [[package]] | ||
| 803 | name = "js-sys" | ||
| 804 | version = "0.3.67" | ||
| 805 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 806 | checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" | ||
| 807 | dependencies = [ | ||
| 808 | "wasm-bindgen", | ||
| 809 | ] | ||
| 810 | |||
| 811 | [[package]] | ||
| 812 | name = "lazy_static" | ||
| 813 | version = "1.4.0" | ||
| 814 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 815 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | ||
| 816 | |||
| 817 | [[package]] | ||
| 818 | name = "libc" | ||
| 819 | version = "0.2.152" | ||
| 820 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 821 | checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" | ||
| 822 | |||
| 823 | [[package]] | ||
| 824 | name = "libredox" | ||
| 825 | version = "0.0.1" | ||
| 826 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 827 | checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" | ||
| 828 | dependencies = [ | ||
| 829 | "bitflags 2.4.2", | ||
| 830 | "libc", | ||
| 831 | "redox_syscall", | ||
| 832 | ] | ||
| 833 | |||
| 834 | [[package]] | ||
| 835 | name = "linux-raw-sys" | ||
| 836 | version = "0.4.13" | ||
| 837 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 838 | checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" | ||
| 839 | |||
| 840 | [[package]] | ||
| 841 | name = "lock_api" | ||
| 842 | version = "0.4.11" | ||
| 843 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 844 | checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" | ||
| 845 | dependencies = [ | ||
| 846 | "autocfg", | ||
| 847 | "scopeguard", | ||
| 848 | ] | ||
| 849 | |||
| 850 | [[package]] | ||
| 851 | name = "log" | ||
| 852 | version = "0.4.20" | ||
| 853 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 854 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" | ||
| 855 | |||
| 856 | [[package]] | ||
| 857 | name = "matchit" | ||
| 858 | version = "0.7.3" | ||
| 859 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 860 | checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" | ||
| 861 | |||
| 862 | [[package]] | ||
| 863 | name = "maybe-async" | ||
| 864 | version = "0.2.7" | ||
| 865 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 866 | checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" | ||
| 867 | dependencies = [ | ||
| 868 | "proc-macro2", | ||
| 869 | "quote", | ||
| 870 | "syn 1.0.109", | ||
| 871 | ] | ||
| 872 | |||
| 873 | [[package]] | ||
| 874 | name = "md5" | ||
| 875 | version = "0.7.0" | ||
| 876 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 877 | checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" | ||
| 878 | |||
| 879 | [[package]] | ||
| 880 | name = "memchr" | ||
| 881 | version = "2.7.1" | ||
| 882 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 883 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" | ||
| 884 | |||
| 885 | [[package]] | ||
| 886 | name = "mime" | ||
| 887 | version = "0.3.17" | ||
| 888 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 889 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" | ||
| 890 | |||
| 891 | [[package]] | ||
| 892 | name = "minidom" | ||
| 893 | version = "0.15.2" | ||
| 894 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 895 | checksum = "f45614075738ce1b77a1768912a60c0227525971b03e09122a05b8a34a2a6278" | ||
| 896 | dependencies = [ | ||
| 897 | "rxml", | ||
| 898 | ] | ||
| 899 | |||
| 900 | [[package]] | ||
| 901 | name = "miniz_oxide" | ||
| 902 | version = "0.7.1" | ||
| 903 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 904 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" | ||
| 905 | dependencies = [ | ||
| 906 | "adler", | ||
| 907 | ] | ||
| 908 | |||
| 909 | [[package]] | ||
| 910 | name = "mio" | ||
| 911 | version = "0.8.10" | ||
| 912 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 913 | checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" | ||
| 914 | dependencies = [ | ||
| 915 | "libc", | ||
| 916 | "wasi", | ||
| 917 | "windows-sys 0.48.0", | ||
| 918 | ] | ||
| 919 | |||
| 920 | [[package]] | ||
| 921 | name = "native-tls" | ||
| 922 | version = "0.2.11" | ||
| 923 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 924 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" | ||
| 925 | dependencies = [ | ||
| 926 | "lazy_static", | ||
| 927 | "libc", | ||
| 928 | "log", | ||
| 929 | "openssl", | ||
| 930 | "openssl-probe", | ||
| 931 | "openssl-sys", | ||
| 932 | "schannel", | ||
| 933 | "security-framework", | ||
| 934 | "security-framework-sys", | ||
| 935 | "tempfile", | ||
| 936 | ] | ||
| 937 | |||
| 938 | [[package]] | ||
| 939 | name = "num-traits" | ||
| 940 | version = "0.2.17" | ||
| 941 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 942 | checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" | ||
| 943 | dependencies = [ | ||
| 944 | "autocfg", | ||
| 945 | ] | ||
| 946 | |||
| 947 | [[package]] | ||
| 948 | name = "num_cpus" | ||
| 949 | version = "1.16.0" | ||
| 950 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 951 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" | ||
| 952 | dependencies = [ | ||
| 953 | "hermit-abi", | ||
| 954 | "libc", | ||
| 955 | ] | ||
| 956 | |||
| 957 | [[package]] | ||
| 958 | name = "object" | ||
| 959 | version = "0.32.2" | ||
| 960 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 961 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" | ||
| 962 | dependencies = [ | ||
| 963 | "memchr", | ||
| 964 | ] | ||
| 965 | |||
| 966 | [[package]] | ||
| 967 | name = "once_cell" | ||
| 968 | version = "1.19.0" | ||
| 969 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 970 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" | ||
| 971 | |||
| 972 | [[package]] | ||
| 973 | name = "openssl" | ||
| 974 | version = "0.10.62" | ||
| 975 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 976 | checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" | ||
| 977 | dependencies = [ | ||
| 978 | "bitflags 2.4.2", | ||
| 979 | "cfg-if", | ||
| 980 | "foreign-types", | ||
| 981 | "libc", | ||
| 982 | "once_cell", | ||
| 983 | "openssl-macros", | ||
| 984 | "openssl-sys", | ||
| 985 | ] | ||
| 986 | |||
| 987 | [[package]] | ||
| 988 | name = "openssl-macros" | ||
| 989 | version = "0.1.1" | ||
| 990 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 991 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" | ||
| 992 | dependencies = [ | ||
| 993 | "proc-macro2", | ||
| 994 | "quote", | ||
| 995 | "syn 2.0.48", | ||
| 996 | ] | ||
| 997 | |||
| 998 | [[package]] | ||
| 999 | name = "openssl-probe" | ||
| 1000 | version = "0.1.5" | ||
| 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1002 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" | ||
| 1003 | |||
| 1004 | [[package]] | ||
| 1005 | name = "openssl-sys" | ||
| 1006 | version = "0.9.98" | ||
| 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1008 | checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" | ||
| 1009 | dependencies = [ | ||
| 1010 | "cc", | ||
| 1011 | "libc", | ||
| 1012 | "pkg-config", | ||
| 1013 | "vcpkg", | ||
| 1014 | ] | ||
| 1015 | |||
| 1016 | [[package]] | ||
| 1017 | name = "ordered-multimap" | ||
| 1018 | version = "0.4.3" | ||
| 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1020 | checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" | ||
| 1021 | dependencies = [ | ||
| 1022 | "dlv-list", | ||
| 1023 | "hashbrown 0.12.3", | ||
| 1024 | ] | ||
| 1025 | |||
| 1026 | [[package]] | ||
| 1027 | name = "parking_lot" | ||
| 1028 | version = "0.12.1" | ||
| 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1030 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" | ||
| 1031 | dependencies = [ | ||
| 1032 | "lock_api", | ||
| 1033 | "parking_lot_core", | ||
| 1034 | ] | ||
| 1035 | |||
| 1036 | [[package]] | ||
| 1037 | name = "parking_lot_core" | ||
| 1038 | version = "0.9.9" | ||
| 1039 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1040 | checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" | ||
| 1041 | dependencies = [ | ||
| 1042 | "cfg-if", | ||
| 1043 | "libc", | ||
| 1044 | "redox_syscall", | ||
| 1045 | "smallvec", | ||
| 1046 | "windows-targets 0.48.5", | ||
| 1047 | ] | ||
| 1048 | |||
| 1049 | [[package]] | ||
| 1050 | name = "percent-encoding" | ||
| 1051 | version = "2.3.1" | ||
| 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1053 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" | ||
| 1054 | |||
| 1055 | [[package]] | ||
| 1056 | name = "pin-project" | ||
| 1057 | version = "1.1.3" | ||
| 1058 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1059 | checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" | ||
| 1060 | dependencies = [ | ||
| 1061 | "pin-project-internal", | ||
| 1062 | ] | ||
| 1063 | |||
| 1064 | [[package]] | ||
| 1065 | name = "pin-project-internal" | ||
| 1066 | version = "1.1.3" | ||
| 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1068 | checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" | ||
| 1069 | dependencies = [ | ||
| 1070 | "proc-macro2", | ||
| 1071 | "quote", | ||
| 1072 | "syn 2.0.48", | ||
| 1073 | ] | ||
| 1074 | |||
| 1075 | [[package]] | ||
| 1076 | name = "pin-project-lite" | ||
| 1077 | version = "0.2.13" | ||
| 1078 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1079 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" | ||
| 1080 | |||
| 1081 | [[package]] | ||
| 1082 | name = "pin-utils" | ||
| 1083 | version = "0.1.0" | ||
| 1084 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1085 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" | ||
| 1086 | |||
| 1087 | [[package]] | ||
| 1088 | name = "pkg-config" | ||
| 1089 | version = "0.3.29" | ||
| 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1091 | checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" | ||
| 1092 | |||
| 1093 | [[package]] | ||
| 1094 | name = "powerfmt" | ||
| 1095 | version = "0.2.0" | ||
| 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1097 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" | ||
| 1098 | |||
| 1099 | [[package]] | ||
| 1100 | name = "proc-macro2" | ||
| 1101 | version = "1.0.76" | ||
| 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1103 | checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" | ||
| 1104 | dependencies = [ | ||
| 1105 | "unicode-ident", | ||
| 1106 | ] | ||
| 1107 | |||
| 1108 | [[package]] | ||
| 1109 | name = "quick-xml" | ||
| 1110 | version = "0.26.0" | ||
| 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1112 | checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" | ||
| 1113 | dependencies = [ | ||
| 1114 | "memchr", | ||
| 1115 | "serde", | ||
| 1116 | ] | ||
| 1117 | |||
| 1118 | [[package]] | ||
| 1119 | name = "quote" | ||
| 1120 | version = "1.0.35" | ||
| 1121 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1122 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" | ||
| 1123 | dependencies = [ | ||
| 1124 | "proc-macro2", | ||
| 1125 | ] | ||
| 1126 | |||
| 1127 | [[package]] | ||
| 1128 | name = "redox_syscall" | ||
| 1129 | version = "0.4.1" | ||
| 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1131 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" | ||
| 1132 | dependencies = [ | ||
| 1133 | "bitflags 1.3.2", | ||
| 1134 | ] | ||
| 1135 | |||
| 1136 | [[package]] | ||
| 1137 | name = "redox_users" | ||
| 1138 | version = "0.4.4" | ||
| 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1140 | checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" | ||
| 1141 | dependencies = [ | ||
| 1142 | "getrandom", | ||
| 1143 | "libredox", | ||
| 1144 | "thiserror", | ||
| 1145 | ] | ||
| 1146 | |||
| 1147 | [[package]] | ||
| 1148 | name = "reqwest" | ||
| 1149 | version = "0.11.23" | ||
| 1150 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1151 | checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" | ||
| 1152 | dependencies = [ | ||
| 1153 | "base64 0.21.7", | ||
| 1154 | "bytes", | ||
| 1155 | "encoding_rs", | ||
| 1156 | "futures-core", | ||
| 1157 | "futures-util", | ||
| 1158 | "h2 0.3.24", | ||
| 1159 | "http 0.2.11", | ||
| 1160 | "http-body 0.4.6", | ||
| 1161 | "hyper 0.14.28", | ||
| 1162 | "hyper-tls", | ||
| 1163 | "ipnet", | ||
| 1164 | "js-sys", | ||
| 1165 | "log", | ||
| 1166 | "mime", | ||
| 1167 | "native-tls", | ||
| 1168 | "once_cell", | ||
| 1169 | "percent-encoding", | ||
| 1170 | "pin-project-lite", | ||
| 1171 | "serde", | ||
| 1172 | "serde_json", | ||
| 1173 | "serde_urlencoded", | ||
| 1174 | "system-configuration", | ||
| 1175 | "tokio", | ||
| 1176 | "tokio-native-tls", | ||
| 1177 | "tokio-util", | ||
| 1178 | "tower-service", | ||
| 1179 | "url", | ||
| 1180 | "wasm-bindgen", | ||
| 1181 | "wasm-bindgen-futures", | ||
| 1182 | "wasm-streams", | ||
| 1183 | "web-sys", | ||
| 1184 | "winreg", | ||
| 1185 | ] | ||
| 1186 | |||
| 1187 | [[package]] | ||
| 1188 | name = "rust-ini" | ||
| 1189 | version = "0.18.0" | ||
| 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1191 | checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" | ||
| 1192 | dependencies = [ | ||
| 1193 | "cfg-if", | ||
| 1194 | "ordered-multimap", | ||
| 1195 | ] | ||
| 1196 | |||
| 1197 | [[package]] | ||
| 1198 | name = "rust-s3" | ||
| 1199 | version = "0.33.0" | ||
| 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1201 | checksum = "1b2ac5ff6acfbe74226fa701b5ef793aaa054055c13ebb7060ad36942956e027" | ||
| 1202 | dependencies = [ | ||
| 1203 | "async-trait", | ||
| 1204 | "aws-creds", | ||
| 1205 | "aws-region", | ||
| 1206 | "base64 0.13.1", | ||
| 1207 | "bytes", | ||
| 1208 | "cfg-if", | ||
| 1209 | "futures", | ||
| 1210 | "hex", | ||
| 1211 | "hmac", | ||
| 1212 | "http 0.2.11", | ||
| 1213 | "log", | ||
| 1214 | "maybe-async", | ||
| 1215 | "md5", | ||
| 1216 | "minidom", | ||
| 1217 | "percent-encoding", | ||
| 1218 | "quick-xml", | ||
| 1219 | "reqwest", | ||
| 1220 | "serde", | ||
| 1221 | "serde_derive", | ||
| 1222 | "sha2", | ||
| 1223 | "thiserror", | ||
| 1224 | "time", | ||
| 1225 | "tokio", | ||
| 1226 | "tokio-stream", | ||
| 1227 | "url", | ||
| 1228 | ] | ||
| 1229 | |||
| 1230 | [[package]] | ||
| 1231 | name = "rustc-demangle" | ||
| 1232 | version = "0.1.23" | ||
| 1233 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1234 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" | ||
| 1235 | |||
| 1236 | [[package]] | ||
| 1237 | name = "rustix" | ||
| 1238 | version = "0.38.30" | ||
| 1239 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1240 | checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" | ||
| 1241 | dependencies = [ | ||
| 1242 | "bitflags 2.4.2", | ||
| 1243 | "errno", | ||
| 1244 | "libc", | ||
| 1245 | "linux-raw-sys", | ||
| 1246 | "windows-sys 0.52.0", | ||
| 1247 | ] | ||
| 1248 | |||
| 1249 | [[package]] | ||
| 1250 | name = "rustversion" | ||
| 1251 | version = "1.0.14" | ||
| 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1253 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" | ||
| 1254 | |||
| 1255 | [[package]] | ||
| 1256 | name = "rxml" | ||
| 1257 | version = "0.9.1" | ||
| 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1259 | checksum = "a98f186c7a2f3abbffb802984b7f1dfd65dac8be1aafdaabbca4137f53f0dff7" | ||
| 1260 | dependencies = [ | ||
| 1261 | "bytes", | ||
| 1262 | "rxml_validation", | ||
| 1263 | "smartstring", | ||
| 1264 | ] | ||
| 1265 | |||
| 1266 | [[package]] | ||
| 1267 | name = "rxml_validation" | ||
| 1268 | version = "0.9.1" | ||
| 1269 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1270 | checksum = "22a197350ece202f19a166d1ad6d9d6de145e1d2a8ef47db299abe164dbd7530" | ||
| 1271 | |||
| 1272 | [[package]] | ||
| 1273 | name = "ryu" | ||
| 1274 | version = "1.0.16" | ||
| 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1276 | checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" | ||
| 1277 | |||
| 1278 | [[package]] | ||
| 1279 | name = "schannel" | ||
| 1280 | version = "0.1.23" | ||
| 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1282 | checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" | ||
| 1283 | dependencies = [ | ||
| 1284 | "windows-sys 0.52.0", | ||
| 1285 | ] | ||
| 1286 | |||
| 1287 | [[package]] | ||
| 1288 | name = "scopeguard" | ||
| 1289 | version = "1.2.0" | ||
| 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1291 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" | ||
| 1292 | |||
| 1293 | [[package]] | ||
| 1294 | name = "security-framework" | ||
| 1295 | version = "2.9.2" | ||
| 1296 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1297 | checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" | ||
| 1298 | dependencies = [ | ||
| 1299 | "bitflags 1.3.2", | ||
| 1300 | "core-foundation", | ||
| 1301 | "core-foundation-sys", | ||
| 1302 | "libc", | ||
| 1303 | "security-framework-sys", | ||
| 1304 | ] | ||
| 1305 | |||
| 1306 | [[package]] | ||
| 1307 | name = "security-framework-sys" | ||
| 1308 | version = "2.9.1" | ||
| 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1310 | checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" | ||
| 1311 | dependencies = [ | ||
| 1312 | "core-foundation-sys", | ||
| 1313 | "libc", | ||
| 1314 | ] | ||
| 1315 | |||
| 1316 | [[package]] | ||
| 1317 | name = "serde" | ||
| 1318 | version = "1.0.195" | ||
| 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1320 | checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" | ||
| 1321 | dependencies = [ | ||
| 1322 | "serde_derive", | ||
| 1323 | ] | ||
| 1324 | |||
| 1325 | [[package]] | ||
| 1326 | name = "serde_derive" | ||
| 1327 | version = "1.0.195" | ||
| 1328 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1329 | checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" | ||
| 1330 | dependencies = [ | ||
| 1331 | "proc-macro2", | ||
| 1332 | "quote", | ||
| 1333 | "syn 2.0.48", | ||
| 1334 | ] | ||
| 1335 | |||
| 1336 | [[package]] | ||
| 1337 | name = "serde_json" | ||
| 1338 | version = "1.0.111" | ||
| 1339 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1340 | checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" | ||
| 1341 | dependencies = [ | ||
| 1342 | "itoa", | ||
| 1343 | "ryu", | ||
| 1344 | "serde", | ||
| 1345 | ] | ||
| 1346 | |||
| 1347 | [[package]] | ||
| 1348 | name = "serde_path_to_error" | ||
| 1349 | version = "0.1.15" | ||
| 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1351 | checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" | ||
| 1352 | dependencies = [ | ||
| 1353 | "itoa", | ||
| 1354 | "serde", | ||
| 1355 | ] | ||
| 1356 | |||
| 1357 | [[package]] | ||
| 1358 | name = "serde_urlencoded" | ||
| 1359 | version = "0.7.1" | ||
| 1360 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1361 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" | ||
| 1362 | dependencies = [ | ||
| 1363 | "form_urlencoded", | ||
| 1364 | "itoa", | ||
| 1365 | "ryu", | ||
| 1366 | "serde", | ||
| 1367 | ] | ||
| 1368 | |||
| 1369 | [[package]] | ||
| 1370 | name = "server" | ||
| 1371 | version = "0.1.0" | ||
| 1372 | dependencies = [ | ||
| 1373 | "aws-creds", | ||
| 1374 | "axum", | ||
| 1375 | "chrono", | ||
| 1376 | "common", | ||
| 1377 | "mime", | ||
| 1378 | "rust-s3", | ||
| 1379 | "serde", | ||
| 1380 | "tokio", | ||
| 1381 | "tower-service", | ||
| 1382 | ] | ||
| 1383 | |||
| 1384 | [[package]] | ||
| 1385 | name = "sha2" | ||
| 1386 | version = "0.10.8" | ||
| 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1388 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" | ||
| 1389 | dependencies = [ | ||
| 1390 | "cfg-if", | ||
| 1391 | "cpufeatures", | ||
| 1392 | "digest", | ||
| 1393 | ] | ||
| 1394 | |||
| 1395 | [[package]] | ||
| 1396 | name = "signal-hook-registry" | ||
| 1397 | version = "1.4.1" | ||
| 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1399 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" | ||
| 1400 | dependencies = [ | ||
| 1401 | "libc", | ||
| 1402 | ] | ||
| 1403 | |||
| 1404 | [[package]] | ||
| 1405 | name = "slab" | ||
| 1406 | version = "0.4.9" | ||
| 1407 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1408 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" | ||
| 1409 | dependencies = [ | ||
| 1410 | "autocfg", | ||
| 1411 | ] | ||
| 1412 | |||
| 1413 | [[package]] | ||
| 1414 | name = "smallvec" | ||
| 1415 | version = "1.11.2" | ||
| 1416 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1417 | checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" | ||
| 1418 | |||
| 1419 | [[package]] | ||
| 1420 | name = "smartstring" | ||
| 1421 | version = "1.0.1" | ||
| 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1423 | checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" | ||
| 1424 | dependencies = [ | ||
| 1425 | "autocfg", | ||
| 1426 | "static_assertions", | ||
| 1427 | "version_check", | ||
| 1428 | ] | ||
| 1429 | |||
| 1430 | [[package]] | ||
| 1431 | name = "socket2" | ||
| 1432 | version = "0.5.5" | ||
| 1433 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1434 | checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" | ||
| 1435 | dependencies = [ | ||
| 1436 | "libc", | ||
| 1437 | "windows-sys 0.48.0", | ||
| 1438 | ] | ||
| 1439 | |||
| 1440 | [[package]] | ||
| 1441 | name = "static_assertions" | ||
| 1442 | version = "1.1.0" | ||
| 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1444 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" | ||
| 1445 | |||
| 1446 | [[package]] | ||
| 1447 | name = "subtle" | ||
| 1448 | version = "2.5.0" | ||
| 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1450 | checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" | ||
| 1451 | |||
| 1452 | [[package]] | ||
| 1453 | name = "syn" | ||
| 1454 | version = "1.0.109" | ||
| 1455 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1456 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" | ||
| 1457 | dependencies = [ | ||
| 1458 | "proc-macro2", | ||
| 1459 | "quote", | ||
| 1460 | "unicode-ident", | ||
| 1461 | ] | ||
| 1462 | |||
| 1463 | [[package]] | ||
| 1464 | name = "syn" | ||
| 1465 | version = "2.0.48" | ||
| 1466 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1467 | checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" | ||
| 1468 | dependencies = [ | ||
| 1469 | "proc-macro2", | ||
| 1470 | "quote", | ||
| 1471 | "unicode-ident", | ||
| 1472 | ] | ||
| 1473 | |||
| 1474 | [[package]] | ||
| 1475 | name = "sync_wrapper" | ||
| 1476 | version = "0.1.2" | ||
| 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1478 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" | ||
| 1479 | |||
| 1480 | [[package]] | ||
| 1481 | name = "system-configuration" | ||
| 1482 | version = "0.5.1" | ||
| 1483 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1484 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" | ||
| 1485 | dependencies = [ | ||
| 1486 | "bitflags 1.3.2", | ||
| 1487 | "core-foundation", | ||
| 1488 | "system-configuration-sys", | ||
| 1489 | ] | ||
| 1490 | |||
| 1491 | [[package]] | ||
| 1492 | name = "system-configuration-sys" | ||
| 1493 | version = "0.5.0" | ||
| 1494 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1495 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" | ||
| 1496 | dependencies = [ | ||
| 1497 | "core-foundation-sys", | ||
| 1498 | "libc", | ||
| 1499 | ] | ||
| 1500 | |||
| 1501 | [[package]] | ||
| 1502 | name = "tempfile" | ||
| 1503 | version = "3.9.0" | ||
| 1504 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1505 | checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" | ||
| 1506 | dependencies = [ | ||
| 1507 | "cfg-if", | ||
| 1508 | "fastrand", | ||
| 1509 | "redox_syscall", | ||
| 1510 | "rustix", | ||
| 1511 | "windows-sys 0.52.0", | ||
| 1512 | ] | ||
| 1513 | |||
| 1514 | [[package]] | ||
| 1515 | name = "thiserror" | ||
| 1516 | version = "1.0.56" | ||
| 1517 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1518 | checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" | ||
| 1519 | dependencies = [ | ||
| 1520 | "thiserror-impl", | ||
| 1521 | ] | ||
| 1522 | |||
| 1523 | [[package]] | ||
| 1524 | name = "thiserror-impl" | ||
| 1525 | version = "1.0.56" | ||
| 1526 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1527 | checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" | ||
| 1528 | dependencies = [ | ||
| 1529 | "proc-macro2", | ||
| 1530 | "quote", | ||
| 1531 | "syn 2.0.48", | ||
| 1532 | ] | ||
| 1533 | |||
| 1534 | [[package]] | ||
| 1535 | name = "time" | ||
| 1536 | version = "0.3.31" | ||
| 1537 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1538 | checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" | ||
| 1539 | dependencies = [ | ||
| 1540 | "deranged", | ||
| 1541 | "itoa", | ||
| 1542 | "powerfmt", | ||
| 1543 | "serde", | ||
| 1544 | "time-core", | ||
| 1545 | "time-macros", | ||
| 1546 | ] | ||
| 1547 | |||
| 1548 | [[package]] | ||
| 1549 | name = "time-core" | ||
| 1550 | version = "0.1.2" | ||
| 1551 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1552 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" | ||
| 1553 | |||
| 1554 | [[package]] | ||
| 1555 | name = "time-macros" | ||
| 1556 | version = "0.2.16" | ||
| 1557 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1558 | checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" | ||
| 1559 | dependencies = [ | ||
| 1560 | "time-core", | ||
| 1561 | ] | ||
| 1562 | |||
| 1563 | [[package]] | ||
| 1564 | name = "tinyvec" | ||
| 1565 | version = "1.6.0" | ||
| 1566 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1567 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" | ||
| 1568 | dependencies = [ | ||
| 1569 | "tinyvec_macros", | ||
| 1570 | ] | ||
| 1571 | |||
| 1572 | [[package]] | ||
| 1573 | name = "tinyvec_macros" | ||
| 1574 | version = "0.1.1" | ||
| 1575 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1576 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" | ||
| 1577 | |||
| 1578 | [[package]] | ||
| 1579 | name = "tokio" | ||
| 1580 | version = "1.35.1" | ||
| 1581 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1582 | checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" | ||
| 1583 | dependencies = [ | ||
| 1584 | "backtrace", | ||
| 1585 | "bytes", | ||
| 1586 | "libc", | ||
| 1587 | "mio", | ||
| 1588 | "num_cpus", | ||
| 1589 | "parking_lot", | ||
| 1590 | "pin-project-lite", | ||
| 1591 | "signal-hook-registry", | ||
| 1592 | "socket2", | ||
| 1593 | "tokio-macros", | ||
| 1594 | "windows-sys 0.48.0", | ||
| 1595 | ] | ||
| 1596 | |||
| 1597 | [[package]] | ||
| 1598 | name = "tokio-macros" | ||
| 1599 | version = "2.2.0" | ||
| 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1601 | checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" | ||
| 1602 | dependencies = [ | ||
| 1603 | "proc-macro2", | ||
| 1604 | "quote", | ||
| 1605 | "syn 2.0.48", | ||
| 1606 | ] | ||
| 1607 | |||
| 1608 | [[package]] | ||
| 1609 | name = "tokio-native-tls" | ||
| 1610 | version = "0.3.1" | ||
| 1611 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1612 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" | ||
| 1613 | dependencies = [ | ||
| 1614 | "native-tls", | ||
| 1615 | "tokio", | ||
| 1616 | ] | ||
| 1617 | |||
| 1618 | [[package]] | ||
| 1619 | name = "tokio-stream" | ||
| 1620 | version = "0.1.14" | ||
| 1621 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1622 | checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" | ||
| 1623 | dependencies = [ | ||
| 1624 | "futures-core", | ||
| 1625 | "pin-project-lite", | ||
| 1626 | "tokio", | ||
| 1627 | ] | ||
| 1628 | |||
| 1629 | [[package]] | ||
| 1630 | name = "tokio-util" | ||
| 1631 | version = "0.7.10" | ||
| 1632 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1633 | checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" | ||
| 1634 | dependencies = [ | ||
| 1635 | "bytes", | ||
| 1636 | "futures-core", | ||
| 1637 | "futures-sink", | ||
| 1638 | "pin-project-lite", | ||
| 1639 | "tokio", | ||
| 1640 | "tracing", | ||
| 1641 | ] | ||
| 1642 | |||
| 1643 | [[package]] | ||
| 1644 | name = "tower" | ||
| 1645 | version = "0.4.13" | ||
| 1646 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1647 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" | ||
| 1648 | dependencies = [ | ||
| 1649 | "futures-core", | ||
| 1650 | "futures-util", | ||
| 1651 | "pin-project", | ||
| 1652 | "pin-project-lite", | ||
| 1653 | "tokio", | ||
| 1654 | "tower-layer", | ||
| 1655 | "tower-service", | ||
| 1656 | "tracing", | ||
| 1657 | ] | ||
| 1658 | |||
| 1659 | [[package]] | ||
| 1660 | name = "tower-layer" | ||
| 1661 | version = "0.3.2" | ||
| 1662 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1663 | checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" | ||
| 1664 | |||
| 1665 | [[package]] | ||
| 1666 | name = "tower-service" | ||
| 1667 | version = "0.3.2" | ||
| 1668 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1669 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" | ||
| 1670 | |||
| 1671 | [[package]] | ||
| 1672 | name = "tracing" | ||
| 1673 | version = "0.1.40" | ||
| 1674 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1675 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" | ||
| 1676 | dependencies = [ | ||
| 1677 | "log", | ||
| 1678 | "pin-project-lite", | ||
| 1679 | "tracing-core", | ||
| 1680 | ] | ||
| 1681 | |||
| 1682 | [[package]] | ||
| 1683 | name = "tracing-core" | ||
| 1684 | version = "0.1.32" | ||
| 1685 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1686 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" | ||
| 1687 | dependencies = [ | ||
| 1688 | "once_cell", | ||
| 1689 | ] | ||
| 1690 | |||
| 1691 | [[package]] | ||
| 1692 | name = "try-lock" | ||
| 1693 | version = "0.2.5" | ||
| 1694 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1695 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" | ||
| 1696 | |||
| 1697 | [[package]] | ||
| 1698 | name = "typenum" | ||
| 1699 | version = "1.17.0" | ||
| 1700 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1701 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" | ||
| 1702 | |||
| 1703 | [[package]] | ||
| 1704 | name = "unicode-bidi" | ||
| 1705 | version = "0.3.15" | ||
| 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1707 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" | ||
| 1708 | |||
| 1709 | [[package]] | ||
| 1710 | name = "unicode-ident" | ||
| 1711 | version = "1.0.12" | ||
| 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1713 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" | ||
| 1714 | |||
| 1715 | [[package]] | ||
| 1716 | name = "unicode-normalization" | ||
| 1717 | version = "0.1.22" | ||
| 1718 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1719 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" | ||
| 1720 | dependencies = [ | ||
| 1721 | "tinyvec", | ||
| 1722 | ] | ||
| 1723 | |||
| 1724 | [[package]] | ||
| 1725 | name = "url" | ||
| 1726 | version = "2.5.0" | ||
| 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1728 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" | ||
| 1729 | dependencies = [ | ||
| 1730 | "form_urlencoded", | ||
| 1731 | "idna", | ||
| 1732 | "percent-encoding", | ||
| 1733 | ] | ||
| 1734 | |||
| 1735 | [[package]] | ||
| 1736 | name = "vcpkg" | ||
| 1737 | version = "0.2.15" | ||
| 1738 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1739 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" | ||
| 1740 | |||
| 1741 | [[package]] | ||
| 1742 | name = "version_check" | ||
| 1743 | version = "0.9.4" | ||
| 1744 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1745 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" | ||
| 1746 | |||
| 1747 | [[package]] | ||
| 1748 | name = "want" | ||
| 1749 | version = "0.3.1" | ||
| 1750 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1751 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" | ||
| 1752 | dependencies = [ | ||
| 1753 | "try-lock", | ||
| 1754 | ] | ||
| 1755 | |||
| 1756 | [[package]] | ||
| 1757 | name = "wasi" | ||
| 1758 | version = "0.11.0+wasi-snapshot-preview1" | ||
| 1759 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1760 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" | ||
| 1761 | |||
| 1762 | [[package]] | ||
| 1763 | name = "wasm-bindgen" | ||
| 1764 | version = "0.2.90" | ||
| 1765 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1766 | checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" | ||
| 1767 | dependencies = [ | ||
| 1768 | "cfg-if", | ||
| 1769 | "wasm-bindgen-macro", | ||
| 1770 | ] | ||
| 1771 | |||
| 1772 | [[package]] | ||
| 1773 | name = "wasm-bindgen-backend" | ||
| 1774 | version = "0.2.90" | ||
| 1775 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1776 | checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" | ||
| 1777 | dependencies = [ | ||
| 1778 | "bumpalo", | ||
| 1779 | "log", | ||
| 1780 | "once_cell", | ||
| 1781 | "proc-macro2", | ||
| 1782 | "quote", | ||
| 1783 | "syn 2.0.48", | ||
| 1784 | "wasm-bindgen-shared", | ||
| 1785 | ] | ||
| 1786 | |||
| 1787 | [[package]] | ||
| 1788 | name = "wasm-bindgen-futures" | ||
| 1789 | version = "0.4.40" | ||
| 1790 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1791 | checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" | ||
| 1792 | dependencies = [ | ||
| 1793 | "cfg-if", | ||
| 1794 | "js-sys", | ||
| 1795 | "wasm-bindgen", | ||
| 1796 | "web-sys", | ||
| 1797 | ] | ||
| 1798 | |||
| 1799 | [[package]] | ||
| 1800 | name = "wasm-bindgen-macro" | ||
| 1801 | version = "0.2.90" | ||
| 1802 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1803 | checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" | ||
| 1804 | dependencies = [ | ||
| 1805 | "quote", | ||
| 1806 | "wasm-bindgen-macro-support", | ||
| 1807 | ] | ||
| 1808 | |||
| 1809 | [[package]] | ||
| 1810 | name = "wasm-bindgen-macro-support" | ||
| 1811 | version = "0.2.90" | ||
| 1812 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1813 | checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" | ||
| 1814 | dependencies = [ | ||
| 1815 | "proc-macro2", | ||
| 1816 | "quote", | ||
| 1817 | "syn 2.0.48", | ||
| 1818 | "wasm-bindgen-backend", | ||
| 1819 | "wasm-bindgen-shared", | ||
| 1820 | ] | ||
| 1821 | |||
| 1822 | [[package]] | ||
| 1823 | name = "wasm-bindgen-shared" | ||
| 1824 | version = "0.2.90" | ||
| 1825 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1826 | checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" | ||
| 1827 | |||
| 1828 | [[package]] | ||
| 1829 | name = "wasm-streams" | ||
| 1830 | version = "0.3.0" | ||
| 1831 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1832 | checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" | ||
| 1833 | dependencies = [ | ||
| 1834 | "futures-util", | ||
| 1835 | "js-sys", | ||
| 1836 | "wasm-bindgen", | ||
| 1837 | "wasm-bindgen-futures", | ||
| 1838 | "web-sys", | ||
| 1839 | ] | ||
| 1840 | |||
| 1841 | [[package]] | ||
| 1842 | name = "web-sys" | ||
| 1843 | version = "0.3.67" | ||
| 1844 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1845 | checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" | ||
| 1846 | dependencies = [ | ||
| 1847 | "js-sys", | ||
| 1848 | "wasm-bindgen", | ||
| 1849 | ] | ||
| 1850 | |||
| 1851 | [[package]] | ||
| 1852 | name = "winapi" | ||
| 1853 | version = "0.3.9" | ||
| 1854 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1855 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" | ||
| 1856 | dependencies = [ | ||
| 1857 | "winapi-i686-pc-windows-gnu", | ||
| 1858 | "winapi-x86_64-pc-windows-gnu", | ||
| 1859 | ] | ||
| 1860 | |||
| 1861 | [[package]] | ||
| 1862 | name = "winapi-i686-pc-windows-gnu" | ||
| 1863 | version = "0.4.0" | ||
| 1864 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1865 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | ||
| 1866 | |||
| 1867 | [[package]] | ||
| 1868 | name = "winapi-x86_64-pc-windows-gnu" | ||
| 1869 | version = "0.4.0" | ||
| 1870 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1871 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" | ||
| 1872 | |||
| 1873 | [[package]] | ||
| 1874 | name = "windows-core" | ||
| 1875 | version = "0.52.0" | ||
| 1876 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1877 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" | ||
| 1878 | dependencies = [ | ||
| 1879 | "windows-targets 0.52.0", | ||
| 1880 | ] | ||
| 1881 | |||
| 1882 | [[package]] | ||
| 1883 | name = "windows-sys" | ||
| 1884 | version = "0.48.0" | ||
| 1885 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1886 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" | ||
| 1887 | dependencies = [ | ||
| 1888 | "windows-targets 0.48.5", | ||
| 1889 | ] | ||
| 1890 | |||
| 1891 | [[package]] | ||
| 1892 | name = "windows-sys" | ||
| 1893 | version = "0.52.0" | ||
| 1894 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1895 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" | ||
| 1896 | dependencies = [ | ||
| 1897 | "windows-targets 0.52.0", | ||
| 1898 | ] | ||
| 1899 | |||
| 1900 | [[package]] | ||
| 1901 | name = "windows-targets" | ||
| 1902 | version = "0.48.5" | ||
| 1903 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1904 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" | ||
| 1905 | dependencies = [ | ||
| 1906 | "windows_aarch64_gnullvm 0.48.5", | ||
| 1907 | "windows_aarch64_msvc 0.48.5", | ||
| 1908 | "windows_i686_gnu 0.48.5", | ||
| 1909 | "windows_i686_msvc 0.48.5", | ||
| 1910 | "windows_x86_64_gnu 0.48.5", | ||
| 1911 | "windows_x86_64_gnullvm 0.48.5", | ||
| 1912 | "windows_x86_64_msvc 0.48.5", | ||
| 1913 | ] | ||
| 1914 | |||
| 1915 | [[package]] | ||
| 1916 | name = "windows-targets" | ||
| 1917 | version = "0.52.0" | ||
| 1918 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1919 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" | ||
| 1920 | dependencies = [ | ||
| 1921 | "windows_aarch64_gnullvm 0.52.0", | ||
| 1922 | "windows_aarch64_msvc 0.52.0", | ||
| 1923 | "windows_i686_gnu 0.52.0", | ||
| 1924 | "windows_i686_msvc 0.52.0", | ||
| 1925 | "windows_x86_64_gnu 0.52.0", | ||
| 1926 | "windows_x86_64_gnullvm 0.52.0", | ||
| 1927 | "windows_x86_64_msvc 0.52.0", | ||
| 1928 | ] | ||
| 1929 | |||
| 1930 | [[package]] | ||
| 1931 | name = "windows_aarch64_gnullvm" | ||
| 1932 | version = "0.48.5" | ||
| 1933 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1934 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" | ||
| 1935 | |||
| 1936 | [[package]] | ||
| 1937 | name = "windows_aarch64_gnullvm" | ||
| 1938 | version = "0.52.0" | ||
| 1939 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1940 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" | ||
| 1941 | |||
| 1942 | [[package]] | ||
| 1943 | name = "windows_aarch64_msvc" | ||
| 1944 | version = "0.48.5" | ||
| 1945 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1946 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" | ||
| 1947 | |||
| 1948 | [[package]] | ||
| 1949 | name = "windows_aarch64_msvc" | ||
| 1950 | version = "0.52.0" | ||
| 1951 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1952 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" | ||
| 1953 | |||
| 1954 | [[package]] | ||
| 1955 | name = "windows_i686_gnu" | ||
| 1956 | version = "0.48.5" | ||
| 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1958 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" | ||
| 1959 | |||
| 1960 | [[package]] | ||
| 1961 | name = "windows_i686_gnu" | ||
| 1962 | version = "0.52.0" | ||
| 1963 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1964 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" | ||
| 1965 | |||
| 1966 | [[package]] | ||
| 1967 | name = "windows_i686_msvc" | ||
| 1968 | version = "0.48.5" | ||
| 1969 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1970 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" | ||
| 1971 | |||
| 1972 | [[package]] | ||
| 1973 | name = "windows_i686_msvc" | ||
| 1974 | version = "0.52.0" | ||
| 1975 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1976 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" | ||
| 1977 | |||
| 1978 | [[package]] | ||
| 1979 | name = "windows_x86_64_gnu" | ||
| 1980 | version = "0.48.5" | ||
| 1981 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1982 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" | ||
| 1983 | |||
| 1984 | [[package]] | ||
| 1985 | name = "windows_x86_64_gnu" | ||
| 1986 | version = "0.52.0" | ||
| 1987 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1988 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" | ||
| 1989 | |||
| 1990 | [[package]] | ||
| 1991 | name = "windows_x86_64_gnullvm" | ||
| 1992 | version = "0.48.5" | ||
| 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 1994 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" | ||
| 1995 | |||
| 1996 | [[package]] | ||
| 1997 | name = "windows_x86_64_gnullvm" | ||
| 1998 | version = "0.52.0" | ||
| 1999 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2000 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" | ||
| 2001 | |||
| 2002 | [[package]] | ||
| 2003 | name = "windows_x86_64_msvc" | ||
| 2004 | version = "0.48.5" | ||
| 2005 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2006 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" | ||
| 2007 | |||
| 2008 | [[package]] | ||
| 2009 | name = "windows_x86_64_msvc" | ||
| 2010 | version = "0.52.0" | ||
| 2011 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2012 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" | ||
| 2013 | |||
| 2014 | [[package]] | ||
| 2015 | name = "winreg" | ||
| 2016 | version = "0.50.0" | ||
| 2017 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2018 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" | ||
| 2019 | dependencies = [ | ||
| 2020 | "cfg-if", | ||
| 2021 | "windows-sys 0.48.0", | ||
| 2022 | ] | ||
diff --git a/rs/Cargo.toml b/rs/Cargo.toml new file mode 100644 index 0000000..ec75eb3 --- /dev/null +++ b/rs/Cargo.toml | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | [workspace] | ||
| 2 | resolver = "2" | ||
| 3 | members = [ | ||
| 4 | "common", | ||
| 5 | "git-lfs-authenticate", | ||
| 6 | "server", | ||
| 7 | ] | ||
diff --git a/rs/common/Cargo.toml b/rs/common/Cargo.toml new file mode 100644 index 0000000..20d9bdd --- /dev/null +++ b/rs/common/Cargo.toml | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | [package] | ||
| 2 | name = "common" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | |||
| 6 | [dependencies] | ||
| 7 | chrono = "0.4" | ||
| 8 | hmac-sha256 = "1.1" | ||
| 9 | subtle = "2.5" | ||
| 10 | serde = { version = "1", features = ["derive"] } | ||
diff --git a/rs/common/src/lib.rs b/rs/common/src/lib.rs new file mode 100644 index 0000000..aafe7f1 --- /dev/null +++ b/rs/common/src/lib.rs | |||
| @@ -0,0 +1,337 @@ | |||
| 1 | use chrono::{DateTime, Utc}; | ||
| 2 | use serde::de; | ||
| 3 | use serde::{Deserialize, Serialize}; | ||
| 4 | use std::fmt::Write; | ||
| 5 | use std::ops; | ||
| 6 | use std::{fmt, str::FromStr}; | ||
| 7 | use subtle::ConstantTimeEq; | ||
| 8 | |||
| 9 | #[derive(Debug, Eq, PartialEq, Copy, Clone, Serialize, Deserialize)] | ||
| 10 | #[repr(u8)] | ||
| 11 | pub enum Operation { | ||
| 12 | #[serde(rename = "download")] | ||
| 13 | Download = 1, | ||
| 14 | #[serde(rename = "upload")] | ||
| 15 | Upload = 2, | ||
| 16 | } | ||
| 17 | |||
| 18 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | ||
| 19 | pub struct ParseOperationError; | ||
| 20 | |||
| 21 | impl fmt::Display for ParseOperationError { | ||
| 22 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 23 | write!(f, "operation should be 'download' or 'upload'") | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | impl FromStr for Operation { | ||
| 28 | type Err = ParseOperationError; | ||
| 29 | |||
| 30 | fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
| 31 | match s { | ||
| 32 | "upload" => Ok(Self::Upload), | ||
| 33 | "download" => Ok(Self::Download), | ||
| 34 | _ => Err(ParseOperationError), | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | #[repr(u8)] | ||
| 40 | pub enum AuthType { | ||
| 41 | GitLfsAuthenticate = 1, | ||
| 42 | } | ||
| 43 | |||
| 44 | /// None means out of range. | ||
| 45 | fn decode_nibble(c: u8) -> Option<u8> { | ||
| 46 | if c.is_ascii_digit() { | ||
| 47 | Some(c - b'0') | ||
| 48 | } else if (b'a'..=b'f').contains(&c) { | ||
| 49 | Some(c - b'a' + 10) | ||
| 50 | } else if (b'A'..=b'F').contains(&c) { | ||
| 51 | Some(c - b'A' + 10) | ||
| 52 | } else { | ||
| 53 | None | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] | ||
| 58 | pub struct HexByte(pub u8); | ||
| 59 | |||
| 60 | impl<'de> Deserialize<'de> for HexByte { | ||
| 61 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
| 62 | where | ||
| 63 | D: serde::Deserializer<'de>, | ||
| 64 | { | ||
| 65 | let str = <&str>::deserialize(deserializer)?; | ||
| 66 | let &[b1, b2] = str.as_bytes() else { | ||
| 67 | return Err(de::Error::invalid_length( | ||
| 68 | str.len(), | ||
| 69 | &"two hexadecimal characters", | ||
| 70 | )); | ||
| 71 | }; | ||
| 72 | let (Some(b1), Some(b2)) = (decode_nibble(b1), decode_nibble(b2)) else { | ||
| 73 | return Err(de::Error::invalid_value( | ||
| 74 | de::Unexpected::Str(str), | ||
| 75 | &"two hexadecimal characters", | ||
| 76 | )); | ||
| 77 | }; | ||
| 78 | Ok(HexByte((b1 << 4) | b2)) | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | impl fmt::Display for HexByte { | ||
| 83 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 84 | let &HexByte(b) = self; | ||
| 85 | HexFmt(&[b]).fmt(f) | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | ||
| 90 | pub enum ParseHexError { | ||
| 91 | UnevenNibbles, | ||
| 92 | InvalidCharacter, | ||
| 93 | TooShort, | ||
| 94 | TooLong, | ||
| 95 | } | ||
| 96 | |||
| 97 | impl fmt::Display for ParseHexError { | ||
| 98 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| 99 | match self { | ||
| 100 | Self::UnevenNibbles => { | ||
| 101 | write!(f, "uneven amount of nibbles (chars in range [a-zA-Z0-9])") | ||
| 102 | } | ||
| 103 | Self::InvalidCharacter => write!(f, "non-hex character encountered"), | ||
| 104 | Self::TooShort => write!(f, "unexpected end of hex sequence"), | ||
| 105 | Self::TooLong => write!(f, "longer hex sequence than expected"), | ||
| 106 | } | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | #[derive(Debug)] | ||
| 111 | pub enum ReadHexError { | ||
| 112 | Io(std::io::Error), | ||
| 113 | Format(ParseHexError), | ||
| 114 | } | ||
| 115 | |||
| 116 | impl fmt::Display for ReadHexError { | ||
| 117 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 118 | match self { | ||
| 119 | Self::Io(e) => e.fmt(f), | ||
| 120 | Self::Format(e) => e.fmt(f), | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | fn parse_hex_exact(value: &str, buf: &mut [u8]) -> Result<(), ParseHexError> { | ||
| 126 | if value.bytes().len() % 2 == 1 { | ||
| 127 | return Err(ParseHexError::UnevenNibbles); | ||
| 128 | } | ||
| 129 | if value.bytes().len() < 2 * buf.len() { | ||
| 130 | return Err(ParseHexError::TooShort); | ||
| 131 | } | ||
| 132 | if value.bytes().len() > 2 * buf.len() { | ||
| 133 | return Err(ParseHexError::TooLong); | ||
| 134 | } | ||
| 135 | for (i, c) in value.bytes().enumerate() { | ||
| 136 | if let Some(b) = decode_nibble(c) { | ||
| 137 | if i % 2 == 0 { | ||
| 138 | buf[i / 2] |= b; | ||
| 139 | } else { | ||
| 140 | buf[i / 2] = b << 4; | ||
| 141 | } | ||
| 142 | } else { | ||
| 143 | return Err(ParseHexError::InvalidCharacter); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | Ok(()) | ||
| 147 | } | ||
| 148 | |||
| 149 | pub struct SafeByteArray<const N: usize> { | ||
| 150 | inner: [u8; N], | ||
| 151 | } | ||
| 152 | |||
| 153 | impl<const N: usize> SafeByteArray<N> { | ||
| 154 | pub fn new() -> Self { | ||
| 155 | Self { inner: [0; N] } | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | impl<const N: usize> AsRef<[u8]> for SafeByteArray<N> { | ||
| 160 | fn as_ref(&self) -> &[u8] { | ||
| 161 | &self.inner | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | impl<const N: usize> AsMut<[u8]> for SafeByteArray<N> { | ||
| 166 | fn as_mut(&mut self) -> &mut [u8] { | ||
| 167 | &mut self.inner | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | impl<const N: usize> Drop for SafeByteArray<N> { | ||
| 172 | fn drop(&mut self) { | ||
| 173 | self.inner.fill(0) | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | impl<const N: usize> FromStr for SafeByteArray<N> { | ||
| 178 | type Err = ParseHexError; | ||
| 179 | |||
| 180 | fn from_str(value: &str) -> Result<Self, Self::Err> { | ||
| 181 | let mut sba = Self { inner: [0u8; N] }; | ||
| 182 | parse_hex_exact(value, &mut sba.inner)?; | ||
| 183 | Ok(sba) | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | pub struct Claims<'a> { | ||
| 188 | pub auth_type: AuthType, | ||
| 189 | pub repo_path: &'a str, | ||
| 190 | pub operation: Operation, | ||
| 191 | pub expires_at: DateTime<Utc>, | ||
| 192 | } | ||
| 193 | |||
| 194 | /// Returns None if the claims are invalid. Repo path length may be no more than 100 bytes. | ||
| 195 | pub fn generate_tag(claims: Claims, key: impl AsRef<[u8]>) -> Option<Digest<32>> { | ||
| 196 | if claims.repo_path.len() > 100 { | ||
| 197 | return None; | ||
| 198 | } | ||
| 199 | |||
| 200 | let mut hmac = hmac_sha256::HMAC::new(key); | ||
| 201 | hmac.update([claims.auth_type as u8]); | ||
| 202 | hmac.update([claims.repo_path.len() as u8]); | ||
| 203 | hmac.update(claims.repo_path.as_bytes()); | ||
| 204 | hmac.update([claims.operation as u8]); | ||
| 205 | hmac.update(claims.expires_at.timestamp().to_be_bytes()); | ||
| 206 | Some(hmac.finalize().into()) | ||
| 207 | } | ||
| 208 | |||
| 209 | pub struct HexFmt<B: AsRef<[u8]>>(pub B); | ||
| 210 | |||
| 211 | impl<B: AsRef<[u8]>> fmt::Display for HexFmt<B> { | ||
| 212 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 213 | let HexFmt(buf) = self; | ||
| 214 | for b in buf.as_ref() { | ||
| 215 | let (high, low) = (b >> 4, b & 0xF); | ||
| 216 | let highc = if high < 10 { b'0' + high } else { b'a' + high }; | ||
| 217 | let lowc = if low < 10 { b'0' + low } else { b'a' + low }; | ||
| 218 | f.write_char(highc as char)?; | ||
| 219 | f.write_char(lowc as char)?; | ||
| 220 | } | ||
| 221 | Ok(()) | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | pub struct EscJsonFmt<'a>(pub &'a str); | ||
| 226 | |||
| 227 | impl<'a> fmt::Display for EscJsonFmt<'a> { | ||
| 228 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 229 | let EscJsonFmt(buf) = self; | ||
| 230 | for c in buf.chars() { | ||
| 231 | match c { | ||
| 232 | '"' => f.write_str("\\\"")?, // quote | ||
| 233 | '\\' => f.write_str("\\\\")?, // backslash | ||
| 234 | '\x08' => f.write_str("\\b")?, // backspace | ||
| 235 | '\x0C' => f.write_str("\\f")?, // form feed | ||
| 236 | '\n' => f.write_str("\\n")?, // line feed | ||
| 237 | '\r' => f.write_str("\\r")?, // carriage return | ||
| 238 | '\t' => f.write_str("\\t")?, // horizontal tab | ||
| 239 | _ => f.write_char(c)?, | ||
| 240 | }; | ||
| 241 | } | ||
| 242 | Ok(()) | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | #[derive(Debug, Copy, Clone)] | ||
| 247 | pub struct Digest<const N: usize> { | ||
| 248 | inner: [u8; N], | ||
| 249 | } | ||
| 250 | |||
| 251 | impl<const N: usize> ops::Index<usize> for Digest<N> { | ||
| 252 | type Output = u8; | ||
| 253 | |||
| 254 | fn index(&self, index: usize) -> &Self::Output { | ||
| 255 | &self.inner[index] | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | impl<const N: usize> Digest<N> { | ||
| 260 | pub fn as_bytes(&self) -> &[u8; N] { | ||
| 261 | &self.inner | ||
| 262 | } | ||
| 263 | } | ||
| 264 | |||
| 265 | impl<const N: usize> fmt::Display for Digest<N> { | ||
| 266 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 267 | HexFmt(&self.inner).fmt(f) | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | impl<const N: usize> Digest<N> { | ||
| 272 | pub fn new(data: [u8; N]) -> Self { | ||
| 273 | Self { inner: data } | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | impl<const N: usize> From<[u8; N]> for Digest<N> { | ||
| 278 | fn from(value: [u8; N]) -> Self { | ||
| 279 | Self::new(value) | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | impl<const N: usize> Into<[u8; N]> for Digest<N> { | ||
| 284 | fn into(self) -> [u8; N] { | ||
| 285 | self.inner | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | impl<const N: usize> FromStr for Digest<N> { | ||
| 290 | type Err = ParseHexError; | ||
| 291 | |||
| 292 | fn from_str(value: &str) -> Result<Self, Self::Err> { | ||
| 293 | let mut buf = [0u8; N]; | ||
| 294 | parse_hex_exact(value, &mut buf)?; | ||
| 295 | Ok(buf.into()) | ||
| 296 | } | ||
| 297 | } | ||
| 298 | |||
| 299 | impl<const N: usize> ConstantTimeEq for Digest<N> { | ||
| 300 | fn ct_eq(&self, other: &Self) -> subtle::Choice { | ||
| 301 | self.inner.ct_eq(&other.inner) | ||
| 302 | } | ||
| 303 | } | ||
| 304 | |||
| 305 | impl<const N: usize> PartialEq for Digest<N> { | ||
| 306 | fn eq(&self, other: &Self) -> bool { | ||
| 307 | self.ct_eq(&other).into() | ||
| 308 | } | ||
| 309 | } | ||
| 310 | |||
| 311 | impl<const N: usize> Eq for Digest<N> {} | ||
| 312 | |||
| 313 | impl<'de, const N: usize> Deserialize<'de> for Digest<N> { | ||
| 314 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
| 315 | where | ||
| 316 | D: serde::Deserializer<'de>, | ||
| 317 | { | ||
| 318 | let hex = <&str>::deserialize(deserializer)?; | ||
| 319 | Digest::from_str(hex).map_err(de::Error::custom) | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | impl<const N: usize> Serialize for Digest<N> { | ||
| 324 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> | ||
| 325 | where | ||
| 326 | S: serde::Serializer, | ||
| 327 | { | ||
| 328 | serializer.serialize_str(&format!("{self}")) | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | pub type Key = SafeByteArray<64>; | ||
| 333 | |||
| 334 | pub fn load_key(path: &str) -> Result<Key, ReadHexError> { | ||
| 335 | let key_str = std::fs::read_to_string(path).map_err(ReadHexError::Io)?; | ||
| 336 | key_str.trim().parse().map_err(ReadHexError::Format) | ||
| 337 | } | ||
diff --git a/rs/git-lfs-authenticate/Cargo.toml b/rs/git-lfs-authenticate/Cargo.toml new file mode 100644 index 0000000..217250f --- /dev/null +++ b/rs/git-lfs-authenticate/Cargo.toml | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | [package] | ||
| 2 | name = "git-lfs-authenticate" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | |||
| 6 | [dependencies] | ||
| 7 | chrono = "0.4" | ||
| 8 | common = { path = "../common" } | ||
diff --git a/rs/git-lfs-authenticate/src/main.rs b/rs/git-lfs-authenticate/src/main.rs new file mode 100644 index 0000000..76f2edd --- /dev/null +++ b/rs/git-lfs-authenticate/src/main.rs | |||
| @@ -0,0 +1,239 @@ | |||
| 1 | use std::{fmt, process::ExitCode, time::Duration}; | ||
| 2 | |||
| 3 | use chrono::Utc; | ||
| 4 | use common::{Operation, ParseOperationError}; | ||
| 5 | |||
| 6 | fn help() { | ||
| 7 | eprintln!("Usage: git-lfs-authenticate <REPO> upload/download"); | ||
| 8 | } | ||
| 9 | |||
| 10 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | ||
| 11 | enum RepoNameError { | ||
| 12 | TooLong, | ||
| 13 | UnresolvedPath, | ||
| 14 | AbsolutePath, | ||
| 15 | MissingGitSuffix, | ||
| 16 | } | ||
| 17 | |||
| 18 | impl fmt::Display for RepoNameError { | ||
| 19 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 20 | match self { | ||
| 21 | Self::TooLong => write!(f, "too long (more than 100 characters)"), | ||
| 22 | Self::UnresolvedPath => { | ||
| 23 | write!(f, "contains path one or more path elements '.' and '..'") | ||
| 24 | } | ||
| 25 | Self::AbsolutePath => { | ||
| 26 | write!(f, "starts with '/', which is not allowed") | ||
| 27 | } | ||
| 28 | Self::MissingGitSuffix => write!(f, "misses '.git' suffix"), | ||
| 29 | } | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | // Using `Result<(), E>` here instead of `Option<E>` because `None` typically signifies some error | ||
| 34 | // state with no further details provided. If we were to return an `Option` type, the user would | ||
| 35 | // have to first transform it into a `Result` type in order to use the `?` operator, meaning that | ||
| 36 | // they would have to the following operation to get the type into the right shape: | ||
| 37 | // `validate_repo_path(path).map_or(Ok(()), Err)`. That would not be very ergonomic. | ||
| 38 | fn validate_repo_path(path: &str) -> Result<(), RepoNameError> { | ||
| 39 | if path.len() > 100 { | ||
| 40 | return Err(RepoNameError::TooLong); | ||
| 41 | } | ||
| 42 | if path.contains("//") | ||
| 43 | || path.contains("/./") | ||
| 44 | || path.contains("/../") | ||
| 45 | || path.starts_with("./") | ||
| 46 | || path.starts_with("../") | ||
| 47 | { | ||
| 48 | return Err(RepoNameError::UnresolvedPath); | ||
| 49 | } | ||
| 50 | if path.starts_with('/') { | ||
| 51 | return Err(RepoNameError::AbsolutePath); | ||
| 52 | } | ||
| 53 | if !path.ends_with(".git") { | ||
| 54 | return Err(RepoNameError::MissingGitSuffix); | ||
| 55 | } | ||
| 56 | Ok(()) | ||
| 57 | } | ||
| 58 | |||
| 59 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | ||
| 60 | enum ParseCmdlineError { | ||
| 61 | UnknownOperation(ParseOperationError), | ||
| 62 | InvalidRepoName(RepoNameError), | ||
| 63 | UnexpectedArgCount(ArgCountError), | ||
| 64 | } | ||
| 65 | |||
| 66 | impl From<RepoNameError> for ParseCmdlineError { | ||
| 67 | fn from(value: RepoNameError) -> Self { | ||
| 68 | Self::InvalidRepoName(value) | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | impl From<ParseOperationError> for ParseCmdlineError { | ||
| 73 | fn from(value: ParseOperationError) -> Self { | ||
| 74 | Self::UnknownOperation(value) | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | impl From<ArgCountError> for ParseCmdlineError { | ||
| 79 | fn from(value: ArgCountError) -> Self { | ||
| 80 | Self::UnexpectedArgCount(value) | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | impl fmt::Display for ParseCmdlineError { | ||
| 85 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 86 | match self { | ||
| 87 | Self::UnknownOperation(e) => write!(f, "unknown operation: {e}"), | ||
| 88 | Self::InvalidRepoName(e) => write!(f, "invalid repository name: {e}"), | ||
| 89 | Self::UnexpectedArgCount(e) => e.fmt(f), | ||
| 90 | } | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | ||
| 95 | struct ArgCountError { | ||
| 96 | provided: usize, | ||
| 97 | expected: usize, | ||
| 98 | } | ||
| 99 | |||
| 100 | impl fmt::Display for ArgCountError { | ||
| 101 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
| 102 | write!( | ||
| 103 | f, | ||
| 104 | "got {} argument(s), expected {}", | ||
| 105 | self.provided, self.expected | ||
| 106 | ) | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | fn get_cmdline_args<const N: usize>() -> Result<[String; N], ArgCountError> { | ||
| 111 | let args = std::env::args(); | ||
| 112 | if args.len() - 1 != N { | ||
| 113 | return Err(ArgCountError { | ||
| 114 | provided: args.len() - 1, | ||
| 115 | expected: N, | ||
| 116 | }); | ||
| 117 | } | ||
| 118 | |||
| 119 | // Does not allocate. | ||
| 120 | const EMPTY_STRING: String = String::new(); | ||
| 121 | let mut values = [EMPTY_STRING; N]; | ||
| 122 | |||
| 123 | // Skip the first element; we do not care about the program name. | ||
| 124 | for (i, arg) in args.skip(1).enumerate() { | ||
| 125 | values[i] = arg | ||
| 126 | } | ||
| 127 | Ok(values) | ||
| 128 | } | ||
| 129 | |||
| 130 | fn parse_cmdline() -> Result<(String, Operation), ParseCmdlineError> { | ||
| 131 | let [repo_path, op_str] = get_cmdline_args::<2>()?; | ||
| 132 | let op: Operation = op_str.parse()?; | ||
| 133 | validate_repo_path(&repo_path)?; | ||
| 134 | Ok((repo_path.to_string(), op)) | ||
| 135 | } | ||
| 136 | |||
| 137 | fn repo_exists(name: &str) -> bool { | ||
| 138 | match std::fs::metadata(name) { | ||
| 139 | Ok(metadata) => metadata.is_dir(), | ||
| 140 | _ => false, | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | struct Config { | ||
| 145 | href_base: String, | ||
| 146 | key_path: String, | ||
| 147 | } | ||
| 148 | |||
| 149 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | ||
| 150 | enum LoadConfigError { | ||
| 151 | BaseUrlMissing, | ||
| 152 | BaseUrlSlashSuffixMissing, | ||
| 153 | KeyPathMissing, | ||
| 154 | } | ||
| 155 | |||
| 156 | impl fmt::Display for LoadConfigError { | ||
| 157 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| 158 | match self { | ||
| 159 | Self::BaseUrlMissing => write!(f, "base URL not provided"), | ||
| 160 | Self::BaseUrlSlashSuffixMissing => write!(f, "base URL does not end with slash"), | ||
| 161 | Self::KeyPathMissing => write!(f, "key path not provided"), | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | fn load_config() -> Result<Config, LoadConfigError> { | ||
| 167 | let Ok(href_base) = std::env::var("GITOLFS3_HREF_BASE") else { | ||
| 168 | return Err(LoadConfigError::BaseUrlMissing); | ||
| 169 | }; | ||
| 170 | if !href_base.ends_with('/') { | ||
| 171 | return Err(LoadConfigError::BaseUrlSlashSuffixMissing); | ||
| 172 | } | ||
| 173 | let Ok(key_path) = std::env::var("GITOLFS3_KEY_PATH") else { | ||
| 174 | return Err(LoadConfigError::KeyPathMissing); | ||
| 175 | }; | ||
| 176 | Ok(Config { | ||
| 177 | href_base, | ||
| 178 | key_path, | ||
| 179 | }) | ||
| 180 | } | ||
| 181 | |||
| 182 | fn main() -> ExitCode { | ||
| 183 | let config = match load_config() { | ||
| 184 | Ok(config) => config, | ||
| 185 | Err(e) => { | ||
| 186 | eprintln!("Failed to load config: {e}"); | ||
| 187 | return ExitCode::FAILURE; | ||
| 188 | } | ||
| 189 | }; | ||
| 190 | let key = match common::load_key(&config.key_path) { | ||
| 191 | Ok(key) => key, | ||
| 192 | Err(e) => { | ||
| 193 | eprintln!("Failed to load key: {e}"); | ||
| 194 | return ExitCode::FAILURE; | ||
| 195 | } | ||
| 196 | }; | ||
| 197 | |||
| 198 | let (repo_name, op) = match parse_cmdline() { | ||
| 199 | Ok(args) => args, | ||
| 200 | Err(e) => { | ||
| 201 | eprintln!("Error: {e}\n"); | ||
| 202 | help(); | ||
| 203 | // Exit code 2 signifies bad usage of CLI. | ||
| 204 | return ExitCode::from(2); | ||
| 205 | } | ||
| 206 | }; | ||
| 207 | |||
| 208 | if !repo_exists(&repo_name) { | ||
| 209 | eprintln!("Error: repository does not exist"); | ||
| 210 | return ExitCode::FAILURE; | ||
| 211 | } | ||
| 212 | |||
| 213 | let expires_in = Duration::from_secs(5 * 60); | ||
| 214 | let expires_at = Utc::now() + expires_in; | ||
| 215 | |||
| 216 | let Some(tag) = common::generate_tag( | ||
| 217 | common::Claims { | ||
| 218 | auth_type: common::AuthType::GitLfsAuthenticate, | ||
| 219 | repo_path: &repo_name, | ||
| 220 | expires_at, | ||
| 221 | operation: op, | ||
| 222 | }, | ||
| 223 | key, | ||
| 224 | ) else { | ||
| 225 | eprintln!("Failed to generate validation tag"); | ||
| 226 | return ExitCode::FAILURE; | ||
| 227 | }; | ||
| 228 | |||
| 229 | println!( | ||
| 230 | "{{\"header\":{{\"Authorization\":\"Gitolfs3-Hmac-Sha256 {tag}\"}},\ | ||
| 231 | \"expires_at\":\"{}\",\"href\":\"{}{}/info/lfs?p=1&te={}\"}}", | ||
| 232 | common::EscJsonFmt(&expires_at.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)), | ||
| 233 | common::EscJsonFmt(&config.href_base), | ||
| 234 | common::EscJsonFmt(&repo_name), | ||
| 235 | expires_at.timestamp() | ||
| 236 | ); | ||
| 237 | |||
| 238 | ExitCode::SUCCESS | ||
| 239 | } | ||
diff --git a/rs/server/Cargo.toml b/rs/server/Cargo.toml new file mode 100644 index 0000000..ac571af --- /dev/null +++ b/rs/server/Cargo.toml | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | [package] | ||
| 2 | name = "server" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2021" | ||
| 5 | |||
| 6 | [dependencies] | ||
| 7 | axum = "0.7" | ||
| 8 | aws-creds = "0.34" | ||
| 9 | chrono = { version = "0.4", features = ["serde"] } | ||
| 10 | common = { path = "../common" } | ||
| 11 | mime = "0.3" | ||
| 12 | rust-s3 = "0.33" | ||
| 13 | serde = { version = "1", features = ["derive"] } | ||
| 14 | tokio = { version = "1.35", features = ["full"] } | ||
| 15 | tower-service = "0.3" | ||
diff --git a/rs/server/src/main.rs b/rs/server/src/main.rs new file mode 100644 index 0000000..8fe1d16 --- /dev/null +++ b/rs/server/src/main.rs | |||
| @@ -0,0 +1,347 @@ | |||
| 1 | use std::collections::HashMap; | ||
| 2 | |||
| 3 | use awscreds::Credentials; | ||
| 4 | use axum::extract::rejection; | ||
| 5 | use axum::extract::FromRequest; | ||
| 6 | use axum::extract::Path; | ||
| 7 | use axum::http::header; | ||
| 8 | use axum::http::HeaderMap; | ||
| 9 | use axum::http::HeaderValue; | ||
| 10 | use axum::response::Response; | ||
| 11 | use axum::Json; | ||
| 12 | use chrono::DateTime; | ||
| 13 | use chrono::Utc; | ||
| 14 | use common::HexByte; | ||
| 15 | use common::Operation; | ||
| 16 | use s3::Bucket; | ||
| 17 | use serde::de; | ||
| 18 | use serde::de::DeserializeOwned; | ||
| 19 | use serde::Deserialize; | ||
| 20 | use serde::Serialize; | ||
| 21 | use tower_service::Service; | ||
| 22 | |||
| 23 | use axum::{ | ||
| 24 | async_trait, | ||
| 25 | extract::{FromRequestParts, OriginalUri, Request}, | ||
| 26 | http::{request::Parts, StatusCode, Uri}, | ||
| 27 | response::IntoResponse, | ||
| 28 | routing::{any, get, post, put}, | ||
| 29 | Extension, Router, | ||
| 30 | }; | ||
| 31 | |||
| 32 | #[derive(Clone)] | ||
| 33 | struct RepositoryName(String); | ||
| 34 | |||
| 35 | struct RepositoryNameRejection; | ||
| 36 | |||
| 37 | impl IntoResponse for RepositoryNameRejection { | ||
| 38 | fn into_response(self) -> Response { | ||
| 39 | (StatusCode::INTERNAL_SERVER_ERROR, "Missing repository name").into_response() | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | #[async_trait] | ||
| 44 | impl<S: Send + Sync> FromRequestParts<S> for RepositoryName { | ||
| 45 | type Rejection = RepositoryNameRejection; | ||
| 46 | |||
| 47 | async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { | ||
| 48 | let Ok(Extension(repo_name)) = Extension::<Self>::from_request_parts(parts, state).await | ||
| 49 | else { | ||
| 50 | return Err(RepositoryNameRejection); | ||
| 51 | }; | ||
| 52 | Ok(repo_name) | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | #[tokio::main] | ||
| 57 | async fn main() { | ||
| 58 | // run our app with hyper, listening globally on port 3000 | ||
| 59 | let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); | ||
| 60 | let mut app = Router::new() | ||
| 61 | .route("/batch", post(batch)) | ||
| 62 | .route("/:oid0/:oid1/:oid", get(obj_download)) | ||
| 63 | .route("/:oid0/:oid1/:oid", put(obj_upload)); | ||
| 64 | axum::serve( | ||
| 65 | listener, | ||
| 66 | any(|mut req: Request| async move { | ||
| 67 | let uri = req.uri(); | ||
| 68 | let original_uri = OriginalUri(uri.clone()); | ||
| 69 | |||
| 70 | let path_and_query = uri.path_and_query().unwrap(); | ||
| 71 | let Some((repo, path)) = path_and_query.path().split_once("/info/lfs/objects") else { | ||
| 72 | return Ok(StatusCode::NOT_FOUND.into_response()); | ||
| 73 | }; | ||
| 74 | let repo = repo | ||
| 75 | .trim_start_matches('/') | ||
| 76 | .trim_end_matches('/') | ||
| 77 | .to_string(); | ||
| 78 | if !path.starts_with("/") || !repo.ends_with(".git") { | ||
| 79 | return Ok(StatusCode::NOT_FOUND.into_response()); | ||
| 80 | } | ||
| 81 | |||
| 82 | let mut parts = uri.clone().into_parts(); | ||
| 83 | parts.path_and_query = match path_and_query.query() { | ||
| 84 | None => path.try_into().ok(), | ||
| 85 | Some(q) => format!("{path}?{q}").try_into().ok(), | ||
| 86 | }; | ||
| 87 | let new_uri = Uri::from_parts(parts).unwrap(); | ||
| 88 | |||
| 89 | *req.uri_mut() = new_uri; | ||
| 90 | req.extensions_mut().insert(original_uri); | ||
| 91 | req.extensions_mut().insert(RepositoryName(repo)); | ||
| 92 | |||
| 93 | app.call(req).await | ||
| 94 | }), | ||
| 95 | ) | ||
| 96 | .await | ||
| 97 | .unwrap(); | ||
| 98 | } | ||
| 99 | |||
| 100 | #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)] | ||
| 101 | enum TransferAdapter { | ||
| 102 | #[serde(rename = "basic")] | ||
| 103 | Basic, | ||
| 104 | } | ||
| 105 | |||
| 106 | #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)] | ||
| 107 | enum HashAlgo { | ||
| 108 | #[serde(rename = "sha256")] | ||
| 109 | Sha256, | ||
| 110 | } | ||
| 111 | |||
| 112 | impl Default for HashAlgo { | ||
| 113 | fn default() -> Self { | ||
| 114 | Self::Sha256 | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | type Oid = common::Digest<32>; | ||
| 119 | |||
| 120 | #[derive(Debug, Deserialize, Clone)] | ||
| 121 | struct BatchRequestObject { | ||
| 122 | oid: Oid, | ||
| 123 | size: i64, | ||
| 124 | } | ||
| 125 | |||
| 126 | #[derive(Debug, Serialize, Deserialize, Clone)] | ||
| 127 | struct BatchRef { | ||
| 128 | name: String, | ||
| 129 | } | ||
| 130 | |||
| 131 | fn default_transfers() -> Vec<TransferAdapter> { | ||
| 132 | vec![TransferAdapter::Basic] | ||
| 133 | } | ||
| 134 | |||
| 135 | #[derive(Deserialize)] | ||
| 136 | struct BatchRequest { | ||
| 137 | operation: common::Operation, | ||
| 138 | #[serde(default = "default_transfers")] | ||
| 139 | transfers: Vec<TransferAdapter>, | ||
| 140 | #[serde(rename = "ref")] | ||
| 141 | reference: Option<BatchRef>, | ||
| 142 | objects: Vec<BatchRequestObject>, | ||
| 143 | #[serde(default)] | ||
| 144 | hash_algo: HashAlgo, | ||
| 145 | } | ||
| 146 | |||
| 147 | #[derive(Clone)] | ||
| 148 | struct GitLfsJson<T>(Json<T>); | ||
| 149 | |||
| 150 | const LFS_MIME: &'static str = "application/vnd.git-lfs+json"; | ||
| 151 | |||
| 152 | enum GitLfsJsonRejection { | ||
| 153 | Json(rejection::JsonRejection), | ||
| 154 | MissingGitLfsJsonContentType, | ||
| 155 | } | ||
| 156 | |||
| 157 | impl IntoResponse for GitLfsJsonRejection { | ||
| 158 | fn into_response(self) -> Response { | ||
| 159 | ( | ||
| 160 | StatusCode::UNSUPPORTED_MEDIA_TYPE, | ||
| 161 | format!("Expected request with `Content-Type: {LFS_MIME}`"), | ||
| 162 | ) | ||
| 163 | .into_response() | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | fn is_git_lfs_json_mimetype(mimetype: &str) -> bool { | ||
| 168 | let Ok(mime) = mimetype.parse::<mime::Mime>() else { | ||
| 169 | return false; | ||
| 170 | }; | ||
| 171 | if mime.type_() != mime::APPLICATION | ||
| 172 | || mime.subtype() != "vnd.git-lfs" | ||
| 173 | || mime.suffix() != Some(mime::JSON) | ||
| 174 | { | ||
| 175 | return false; | ||
| 176 | } | ||
| 177 | match mime.get_param(mime::CHARSET) { | ||
| 178 | Some(mime::UTF_8) | None => true, | ||
| 179 | Some(_) => false, | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | fn has_git_lfs_json_content_type(req: &Request) -> bool { | ||
| 184 | let Some(content_type) = req.headers().get(header::CONTENT_TYPE) else { | ||
| 185 | return false; | ||
| 186 | }; | ||
| 187 | let Ok(content_type) = content_type.to_str() else { | ||
| 188 | return false; | ||
| 189 | }; | ||
| 190 | return is_git_lfs_json_mimetype(content_type); | ||
| 191 | } | ||
| 192 | |||
| 193 | #[async_trait] | ||
| 194 | impl<T, S> FromRequest<S> for GitLfsJson<T> | ||
| 195 | where | ||
| 196 | T: DeserializeOwned, | ||
| 197 | S: Send + Sync, | ||
| 198 | { | ||
| 199 | type Rejection = GitLfsJsonRejection; | ||
| 200 | |||
| 201 | async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> { | ||
| 202 | if !has_git_lfs_json_content_type(&req) { | ||
| 203 | return Err(GitLfsJsonRejection::MissingGitLfsJsonContentType); | ||
| 204 | } | ||
| 205 | Json::<T>::from_request(req, state) | ||
| 206 | .await | ||
| 207 | .map(GitLfsJson) | ||
| 208 | .map_err(GitLfsJsonRejection::Json) | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | impl<T: Serialize> IntoResponse for GitLfsJson<T> { | ||
| 213 | fn into_response(self) -> Response { | ||
| 214 | let GitLfsJson(json) = self; | ||
| 215 | let mut resp = json.into_response(); | ||
| 216 | resp.headers_mut().insert( | ||
| 217 | header::CONTENT_TYPE, | ||
| 218 | HeaderValue::from_static("application/vnd.git-lfs+json"), | ||
| 219 | ); | ||
| 220 | resp | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | #[derive(Debug, Serialize, Clone)] | ||
| 225 | struct BatchResponseObjectAction { | ||
| 226 | href: String, | ||
| 227 | #[serde(skip_serializing_if = "HashMap::is_empty")] | ||
| 228 | header: HashMap<String, String>, | ||
| 229 | expires_at: DateTime<Utc>, | ||
| 230 | } | ||
| 231 | |||
| 232 | #[derive(Debug, Serialize, Clone)] | ||
| 233 | struct BatchResponseObjectActions { | ||
| 234 | #[serde(skip_serializing_if = "Option::is_none")] | ||
| 235 | upload: Option<BatchResponseObjectAction>, | ||
| 236 | #[serde(skip_serializing_if = "Option::is_none")] | ||
| 237 | download: Option<BatchResponseObjectAction>, | ||
| 238 | #[serde(skip_serializing_if = "Option::is_none")] | ||
| 239 | verify: Option<BatchResponseObjectAction>, | ||
| 240 | } | ||
| 241 | |||
| 242 | #[derive(Debug, Serialize, Clone)] | ||
| 243 | struct BatchResponseObject { | ||
| 244 | oid: Oid, | ||
| 245 | size: i64, | ||
| 246 | #[serde(skip_serializing_if = "Option::is_none")] | ||
| 247 | authenticated: Option<bool>, | ||
| 248 | } | ||
| 249 | |||
| 250 | #[derive(Debug, Serialize, Clone)] | ||
| 251 | struct BatchResponse { | ||
| 252 | transfer: TransferAdapter, | ||
| 253 | objects: Vec<BatchResponseObject>, | ||
| 254 | hash_algo: HashAlgo, | ||
| 255 | } | ||
| 256 | |||
| 257 | //fn handle_download_object(repo: &str, obj: &BatchRequestObject) { | ||
| 258 | // let (oid0, oid1) = (HexByte(obj.oid[0]), HexByte(obj.oid[1])); | ||
| 259 | // let full_path = format!("{repo}/lfs/objects/{}/{}/{}", oid0, oid1, obj.oid); | ||
| 260 | // | ||
| 261 | // let bucket_anme = "asdfasdf"; | ||
| 262 | // let region = s3::Region::Custom { | ||
| 263 | // region: "nl-ams".to_string(), | ||
| 264 | // endpoint: "rg.nl-ams.swc.cloud".to_string() | ||
| 265 | // }; | ||
| 266 | // let credentials = Credentials::new(None, None, None, None, None).unwrap(); | ||
| 267 | // let bucket = Bucket::new(bucket_anme, region, credentials).unwrap(); | ||
| 268 | //} | ||
| 269 | |||
| 270 | async fn batch( | ||
| 271 | header: HeaderMap, | ||
| 272 | RepositoryName(repo): RepositoryName, | ||
| 273 | GitLfsJson(Json(payload)): GitLfsJson<BatchRequest>, | ||
| 274 | ) -> Response { | ||
| 275 | if !header | ||
| 276 | .get_all("Accept") | ||
| 277 | .iter() | ||
| 278 | .filter_map(|v| v.to_str().ok()) | ||
| 279 | .any(is_git_lfs_json_mimetype) | ||
| 280 | { | ||
| 281 | return ( | ||
| 282 | StatusCode::NOT_ACCEPTABLE, | ||
| 283 | format!("Expected `{LFS_MIME}` (with UTF-8 charset) in list of acceptable response media types"), | ||
| 284 | ).into_response(); | ||
| 285 | } | ||
| 286 | |||
| 287 | if payload.hash_algo != HashAlgo::Sha256 { | ||
| 288 | return ( | ||
| 289 | StatusCode::CONFLICT, | ||
| 290 | "Unsupported hashing algorithm speicifed", | ||
| 291 | ) | ||
| 292 | .into_response(); | ||
| 293 | } | ||
| 294 | if !payload.transfers.is_empty() && !payload.transfers.contains(&TransferAdapter::Basic) { | ||
| 295 | return ( | ||
| 296 | StatusCode::CONFLICT, | ||
| 297 | "Unsupported transfer adapter specified (supported: basic)", | ||
| 298 | ) | ||
| 299 | .into_response(); | ||
| 300 | } | ||
| 301 | |||
| 302 | let resp: BatchResponse; | ||
| 303 | for obj in payload.objects { | ||
| 304 | // match payload.operation { | ||
| 305 | // Operation::Download => resp.objects.push(handle_download_object(repo, obj));, | ||
| 306 | // Operation::Upload => resp.objects.push(handle_upload_object(repo, obj)), | ||
| 307 | // }; | ||
| 308 | } | ||
| 309 | |||
| 310 | format!("hi from {repo}\n").into_response() | ||
| 311 | } | ||
| 312 | |||
| 313 | #[derive(Deserialize, Copy, Clone)] | ||
| 314 | #[serde(remote = "Self")] | ||
| 315 | struct FileParams { | ||
| 316 | oid0: HexByte, | ||
| 317 | oid1: HexByte, | ||
| 318 | oid: Oid, | ||
| 319 | } | ||
| 320 | |||
| 321 | impl<'de> Deserialize<'de> for FileParams { | ||
| 322 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
| 323 | where | ||
| 324 | D: serde::Deserializer<'de>, | ||
| 325 | { | ||
| 326 | let unchecked @ FileParams { | ||
| 327 | oid0: HexByte(oid0), | ||
| 328 | oid1: HexByte(oid1), | ||
| 329 | oid, | ||
| 330 | } = FileParams::deserialize(deserializer)?; | ||
| 331 | if oid0 != oid.as_bytes()[0] { | ||
| 332 | return Err(de::Error::custom( | ||
| 333 | "first OID path part does not match first byte of full OID", | ||
| 334 | )); | ||
| 335 | } | ||
| 336 | if oid1 != oid.as_bytes()[1] { | ||
| 337 | return Err(de::Error::custom( | ||
| 338 | "second OID path part does not match first byte of full OID", | ||
| 339 | )); | ||
| 340 | } | ||
| 341 | Ok(unchecked) | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | async fn obj_download(Path(FileParams { oid0, oid1, oid }): Path<FileParams>) {} | ||
| 346 | |||
| 347 | async fn obj_upload(Path(FileParams { oid0, oid1, oid }): Path<FileParams>) {} | ||