Author: Jason White [github@jasonwhite.io]
Committer: GitHub [noreply@github.com] Sun, 13 Sep 2020 17:46:35 +0000
Hash: 116ee717c5b877df6c47dae7711d4394489c3767
Timestamp: Sun, 13 Sep 2020 17:46:35 +0000 (4 years ago)

+1741 -1679 +/-18 browse
Use async-await syntax (#18)
Use async-await syntax (#18)

1diff --git a/Cargo.lock b/Cargo.lock
2index 11e4288..20cdf4f 100644
3--- a/Cargo.lock
4+++ b/Cargo.lock
5 @@ -66,42 +66,52 @@ dependencies = [
6 "askama_escape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
7 "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
8 "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
9- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
10- "serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
11+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
12+ "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
13 "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
14 ]
15
16 [[package]]
17+ name = "async-trait"
18+ version = "0.1.40"
19+ source = "registry+https://github.com/rust-lang/crates.io-index"
20+ dependencies = [
21+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
22+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
23+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
24+ ]
25+
26+ [[package]]
27 name = "atty"
28 version = "0.2.14"
29 source = "registry+https://github.com/rust-lang/crates.io-index"
30 dependencies = [
31- "hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
32- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
33+ "hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
34+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
35 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
36 ]
37
38 [[package]]
39 name = "autocfg"
40- version = "1.0.0"
41+ version = "1.0.1"
42 source = "registry+https://github.com/rust-lang/crates.io-index"
43
44 [[package]]
45- name = "base64"
46- version = "0.9.3"
47+ name = "backoff"
48+ version = "0.2.1"
49 source = "registry+https://github.com/rust-lang/crates.io-index"
50 dependencies = [
51- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
52- "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
53+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
54+ "instant 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
55+ "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
56+ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
57+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
58 ]
59
60 [[package]]
61- name = "base64"
62- version = "0.10.1"
63+ name = "base-x"
64+ version = "0.2.6"
65 source = "registry+https://github.com/rust-lang/crates.io-index"
66- dependencies = [
67- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
68- ]
69
70 [[package]]
71 name = "base64"
72 @@ -109,6 +119,11 @@ version = "0.11.0"
73 source = "registry+https://github.com/rust-lang/crates.io-index"
74
75 [[package]]
76+ name = "base64"
77+ version = "0.12.3"
78+ source = "registry+https://github.com/rust-lang/crates.io-index"
79+
80+ [[package]]
81 name = "bitflags"
82 version = "1.2.1"
83 source = "registry+https://github.com/rust-lang/crates.io-index"
84 @@ -125,11 +140,13 @@ dependencies = [
85
86 [[package]]
87 name = "block-buffer"
88- version = "0.3.3"
89+ version = "0.7.3"
90 source = "registry+https://github.com/rust-lang/crates.io-index"
91 dependencies = [
92- "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
93- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
94+ "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
95+ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
96+ "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
97+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
98 ]
99
100 [[package]]
101 @@ -137,12 +154,25 @@ name = "block-buffer"
102 version = "0.9.0"
103 source = "registry+https://github.com/rust-lang/crates.io-index"
104 dependencies = [
105- "generic-array 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
106+ "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
107+ ]
108+
109+ [[package]]
110+ name = "block-padding"
111+ version = "0.1.5"
112+ source = "registry+https://github.com/rust-lang/crates.io-index"
113+ dependencies = [
114+ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
115 ]
116
117 [[package]]
118+ name = "bumpalo"
119+ version = "3.4.0"
120+ source = "registry+https://github.com/rust-lang/crates.io-index"
121+
122+ [[package]]
123 name = "byte-tools"
124- version = "0.2.0"
125+ version = "0.3.1"
126 source = "registry+https://github.com/rust-lang/crates.io-index"
127
128 [[package]]
129 @@ -156,13 +186,17 @@ version = "0.4.12"
130 source = "registry+https://github.com/rust-lang/crates.io-index"
131 dependencies = [
132 "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
133- "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
134 "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
135 ]
136
137 [[package]]
138+ name = "bytes"
139+ version = "0.5.6"
140+ source = "registry+https://github.com/rust-lang/crates.io-index"
141+
142+ [[package]]
143 name = "cc"
144- version = "1.0.56"
145+ version = "1.0.59"
146 source = "registry+https://github.com/rust-lang/crates.io-index"
147
148 [[package]]
149 @@ -181,18 +215,18 @@ dependencies = [
150
151 [[package]]
152 name = "chrono"
153- version = "0.4.11"
154+ version = "0.4.15"
155 source = "registry+https://github.com/rust-lang/crates.io-index"
156 dependencies = [
157 "num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
158 "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
159- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
160- "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
161+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
162+ "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
163 ]
164
165 [[package]]
166 name = "clap"
167- version = "2.33.1"
168+ version = "2.33.3"
169 source = "registry+https://github.com/rust-lang/crates.io-index"
170 dependencies = [
171 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
172 @@ -213,109 +247,77 @@ dependencies = [
173 ]
174
175 [[package]]
176- name = "constant_time_eq"
177- version = "0.1.5"
178+ name = "const_fn"
179+ version = "0.4.2"
180 source = "registry+https://github.com/rust-lang/crates.io-index"
181
182 [[package]]
183- name = "cpuid-bool"
184- version = "0.1.0"
185+ name = "constant_time_eq"
186+ version = "0.1.5"
187 source = "registry+https://github.com/rust-lang/crates.io-index"
188
189 [[package]]
190- name = "crossbeam-deque"
191- version = "0.7.3"
192+ name = "core-foundation"
193+ version = "0.7.0"
194 source = "registry+https://github.com/rust-lang/crates.io-index"
195 dependencies = [
196- "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
197- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
198- "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
199+ "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
200+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
201 ]
202
203 [[package]]
204- name = "crossbeam-epoch"
205- version = "0.8.2"
206+ name = "core-foundation-sys"
207+ version = "0.7.0"
208 source = "registry+https://github.com/rust-lang/crates.io-index"
209- dependencies = [
210- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
211- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
212- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
213- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
214- "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
215- "memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
216- "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
217- ]
218
219 [[package]]
220- name = "crossbeam-queue"
221+ name = "cpuid-bool"
222 version = "0.1.2"
223 source = "registry+https://github.com/rust-lang/crates.io-index"
224- dependencies = [
225- "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
226- ]
227-
228- [[package]]
229- name = "crossbeam-queue"
230- version = "0.2.3"
231- source = "registry+https://github.com/rust-lang/crates.io-index"
232- dependencies = [
233- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
234- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
235- "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
236- ]
237-
238- [[package]]
239- name = "crossbeam-utils"
240- version = "0.6.6"
241- source = "registry+https://github.com/rust-lang/crates.io-index"
242- dependencies = [
243- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
244- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
245- ]
246
247 [[package]]
248 name = "crossbeam-utils"
249 version = "0.7.2"
250 source = "registry+https://github.com/rust-lang/crates.io-index"
251 dependencies = [
252- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
253+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
254 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
255 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
256 ]
257
258 [[package]]
259 name = "crypto-mac"
260- version = "0.5.2"
261+ version = "0.7.0"
262 source = "registry+https://github.com/rust-lang/crates.io-index"
263 dependencies = [
264- "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
265- "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
266+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
267+ "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
268 ]
269
270 [[package]]
271 name = "ct-logs"
272- version = "0.5.1"
273+ version = "0.6.0"
274 source = "registry+https://github.com/rust-lang/crates.io-index"
275 dependencies = [
276- "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
277+ "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
278 ]
279
280 [[package]]
281 name = "derive_more"
282- version = "0.99.9"
283+ version = "0.99.10"
284 source = "registry+https://github.com/rust-lang/crates.io-index"
285 dependencies = [
286- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
287+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
288 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
289- "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
290+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
291 ]
292
293 [[package]]
294 name = "digest"
295- version = "0.7.6"
296+ version = "0.8.1"
297 source = "registry+https://github.com/rust-lang/crates.io-index"
298 dependencies = [
299- "generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
300+ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
301 ]
302
303 [[package]]
304 @@ -323,22 +325,31 @@ name = "digest"
305 version = "0.9.0"
306 source = "registry+https://github.com/rust-lang/crates.io-index"
307 dependencies = [
308- "generic-array 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
309+ "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
310 ]
311
312 [[package]]
313 name = "dirs"
314- version = "1.0.5"
315+ version = "2.0.2"
316+ source = "registry+https://github.com/rust-lang/crates.io-index"
317+ dependencies = [
318+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
319+ "dirs-sys 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
320+ ]
321+
322+ [[package]]
323+ name = "dirs-sys"
324+ version = "0.3.5"
325 source = "registry+https://github.com/rust-lang/crates.io-index"
326 dependencies = [
327- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
328- "redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
329+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
330+ "redox_users 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
331 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
332 ]
333
334 [[package]]
335- name = "either"
336- version = "1.5.3"
337+ name = "discard"
338+ version = "1.0.4"
339 source = "registry+https://github.com/rust-lang/crates.io-index"
340
341 [[package]]
342 @@ -348,7 +359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
343 dependencies = [
344 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
345 "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
346- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
347+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
348 "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
349 "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
350 ]
351 @@ -364,11 +375,6 @@ version = "1.0.7"
352 source = "registry+https://github.com/rust-lang/crates.io-index"
353
354 [[package]]
355- name = "fuchsia-cprng"
356- version = "0.1.1"
357- source = "registry+https://github.com/rust-lang/crates.io-index"
358-
359- [[package]]
360 name = "fuchsia-zircon"
361 version = "0.3.3"
362 source = "registry+https://github.com/rust-lang/crates.io-index"
363 @@ -388,35 +394,95 @@ version = "0.1.29"
364 source = "registry+https://github.com/rust-lang/crates.io-index"
365
366 [[package]]
367- name = "futures-backoff"
368- version = "0.1.0"
369+ name = "futures"
370+ version = "0.3.5"
371 source = "registry+https://github.com/rust-lang/crates.io-index"
372 dependencies = [
373- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
374- "futures-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
375- "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
376+ "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
377+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
378+ "futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
379+ "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
380+ "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
381+ "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
382+ "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
383 ]
384
385 [[package]]
386- name = "futures-cpupool"
387- version = "0.1.8"
388+ name = "futures-channel"
389+ version = "0.3.5"
390 source = "registry+https://github.com/rust-lang/crates.io-index"
391 dependencies = [
392- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
393- "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
394+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
395+ "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
396 ]
397
398 [[package]]
399- name = "futures-timer"
400- version = "0.1.1"
401+ name = "futures-core"
402+ version = "0.3.5"
403+ source = "registry+https://github.com/rust-lang/crates.io-index"
404+
405+ [[package]]
406+ name = "futures-executor"
407+ version = "0.3.5"
408+ source = "registry+https://github.com/rust-lang/crates.io-index"
409+ dependencies = [
410+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
411+ "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
412+ "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
413+ ]
414+
415+ [[package]]
416+ name = "futures-io"
417+ version = "0.3.5"
418+ source = "registry+https://github.com/rust-lang/crates.io-index"
419+
420+ [[package]]
421+ name = "futures-macro"
422+ version = "0.3.5"
423+ source = "registry+https://github.com/rust-lang/crates.io-index"
424+ dependencies = [
425+ "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)",
426+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
427+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
428+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
429+ ]
430+
431+ [[package]]
432+ name = "futures-sink"
433+ version = "0.3.5"
434+ source = "registry+https://github.com/rust-lang/crates.io-index"
435+
436+ [[package]]
437+ name = "futures-task"
438+ version = "0.3.5"
439+ source = "registry+https://github.com/rust-lang/crates.io-index"
440+ dependencies = [
441+ "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
442+ ]
443+
444+ [[package]]
445+ name = "futures-util"
446+ version = "0.3.5"
447 source = "registry+https://github.com/rust-lang/crates.io-index"
448 dependencies = [
449 "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
450+ "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
451+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
452+ "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
453+ "futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
454+ "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
455+ "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
456+ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
457+ "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
458+ "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
459+ "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)",
460+ "proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
461+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
462 ]
463
464 [[package]]
465 name = "generic-array"
466- version = "0.9.0"
467+ version = "0.12.3"
468 source = "registry+https://github.com/rust-lang/crates.io-index"
469 dependencies = [
470 "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
471 @@ -424,7 +490,7 @@ dependencies = [
472
473 [[package]]
474 name = "generic-array"
475- version = "0.14.2"
476+ version = "0.14.4"
477 source = "registry+https://github.com/rust-lang/crates.io-index"
478 dependencies = [
479 "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
480 @@ -433,32 +499,38 @@ dependencies = [
481
482 [[package]]
483 name = "getrandom"
484- version = "0.1.14"
485+ version = "0.1.15"
486 source = "registry+https://github.com/rust-lang/crates.io-index"
487 dependencies = [
488 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
489- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
490+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
491 "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
492 ]
493
494 [[package]]
495 name = "h2"
496- version = "0.1.26"
497+ version = "0.2.6"
498 source = "registry+https://github.com/rust-lang/crates.io-index"
499 dependencies = [
500- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
501- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
502+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
503 "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
504- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
505- "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
506- "indexmap 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
507- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
508+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
509+ "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
510+ "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
511+ "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
512+ "indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
513 "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
514- "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
515- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
516+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
517+ "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
518+ "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
519 ]
520
521 [[package]]
522+ name = "hashbrown"
523+ version = "0.9.0"
524+ source = "registry+https://github.com/rust-lang/crates.io-index"
525+
526+ [[package]]
527 name = "heck"
528 version = "0.3.1"
529 source = "registry+https://github.com/rust-lang/crates.io-index"
530 @@ -468,10 +540,10 @@ dependencies = [
531
532 [[package]]
533 name = "hermit-abi"
534- version = "0.1.14"
535+ version = "0.1.15"
536 source = "registry+https://github.com/rust-lang/crates.io-index"
537 dependencies = [
538- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
539+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
540 ]
541
542 [[package]]
543 @@ -480,33 +552,36 @@ version = "0.3.2"
544 source = "registry+https://github.com/rust-lang/crates.io-index"
545
546 [[package]]
547+ name = "hex"
548+ version = "0.4.2"
549+ source = "registry+https://github.com/rust-lang/crates.io-index"
550+
551+ [[package]]
552 name = "hmac"
553- version = "0.5.0"
554+ version = "0.7.1"
555 source = "registry+https://github.com/rust-lang/crates.io-index"
556 dependencies = [
557- "crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
558- "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
559+ "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
560+ "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
561 ]
562
563 [[package]]
564 name = "http"
565- version = "0.1.21"
566+ version = "0.2.1"
567 source = "registry+https://github.com/rust-lang/crates.io-index"
568 dependencies = [
569- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
570+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
571 "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
572 "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
573 ]
574
575 [[package]]
576 name = "http-body"
577- version = "0.1.0"
578+ version = "0.3.1"
579 source = "registry+https://github.com/rust-lang/crates.io-index"
580 dependencies = [
581- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
582- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
583- "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
584- "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
585+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
586+ "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
587 ]
588
589 [[package]]
590 @@ -539,52 +614,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
591
592 [[package]]
593 name = "hyper"
594- version = "0.12.35"
595+ version = "0.13.7"
596 source = "registry+https://github.com/rust-lang/crates.io-index"
597 dependencies = [
598- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
599- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
600- "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
601- "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
602- "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
603- "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
604+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
605+ "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
606+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
607+ "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
608+ "h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
609+ "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
610+ "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
611 "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
612- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
613 "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
614- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
615- "net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
616- "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
617- "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
618- "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
619- "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
620- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
621- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
622- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
623- "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
624- "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
625- "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
626- "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
627+ "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
628+ "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
629+ "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
630+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
631+ "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
632+ "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
633+ "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
634 ]
635
636 [[package]]
637 name = "hyper-rustls"
638- version = "0.16.1"
639+ version = "0.20.0"
640 source = "registry+https://github.com/rust-lang/crates.io-index"
641 dependencies = [
642- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
643- "ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
644- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
645- "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)",
646- "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
647- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
648- "tokio-rustls 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
649- "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
650- "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
651+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
652+ "ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
653+ "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
654+ "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
655+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
656+ "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
657+ "rustls-native-certs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
658+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
659+ "tokio-rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
660+ "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)",
661 ]
662
663 [[package]]
664 name = "idna"
665- version = "0.1.5"
666+ version = "0.2.0"
667 source = "registry+https://github.com/rust-lang/crates.io-index"
668 dependencies = [
669 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
670 @@ -594,18 +664,24 @@ dependencies = [
671
672 [[package]]
673 name = "indexmap"
674- version = "1.4.0"
675+ version = "1.6.0"
676 source = "registry+https://github.com/rust-lang/crates.io-index"
677 dependencies = [
678- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
679+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
680+ "hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
681 ]
682
683 [[package]]
684+ name = "instant"
685+ version = "0.1.6"
686+ source = "registry+https://github.com/rust-lang/crates.io-index"
687+
688+ [[package]]
689 name = "iovec"
690 version = "0.1.4"
691 source = "registry+https://github.com/rust-lang/crates.io-index"
692 dependencies = [
693- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
694+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
695 ]
696
697 [[package]]
698 @@ -614,6 +690,14 @@ version = "0.4.6"
699 source = "registry+https://github.com/rust-lang/crates.io-index"
700
701 [[package]]
702+ name = "js-sys"
703+ version = "0.3.45"
704+ source = "registry+https://github.com/rust-lang/crates.io-index"
705+ dependencies = [
706+ "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
707+ ]
708+
709+ [[package]]
710 name = "kernel32-sys"
711 version = "0.2.2"
712 source = "registry+https://github.com/rust-lang/crates.io-index"
713 @@ -634,7 +718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
714
715 [[package]]
716 name = "libc"
717- version = "0.2.71"
718+ version = "0.2.77"
719 source = "registry+https://github.com/rust-lang/crates.io-index"
720
721 [[package]]
722 @@ -642,8 +726,8 @@ name = "linked-hash-map"
723 version = "0.5.3"
724 source = "registry+https://github.com/rust-lang/crates.io-index"
725 dependencies = [
726- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
727- "serde_test 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
728+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
729+ "serde_test 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
730 ]
731
732 [[package]]
733 @@ -656,7 +740,7 @@ dependencies = [
734
735 [[package]]
736 name = "log"
737- version = "0.4.8"
738+ version = "0.4.11"
739 source = "registry+https://github.com/rust-lang/crates.io-index"
740 dependencies = [
741 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
742 @@ -674,7 +758,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
743
744 [[package]]
745 name = "md5"
746- version = "0.3.8"
747+ version = "0.7.0"
748 source = "registry+https://github.com/rust-lang/crates.io-index"
749
750 [[package]]
751 @@ -683,14 +767,6 @@ version = "2.3.3"
752 source = "registry+https://github.com/rust-lang/crates.io-index"
753
754 [[package]]
755- name = "memoffset"
756- version = "0.5.4"
757- source = "registry+https://github.com/rust-lang/crates.io-index"
758- dependencies = [
759- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
760- ]
761-
762- [[package]]
763 name = "mio"
764 version = "0.6.22"
765 source = "registry+https://github.com/rust-lang/crates.io-index"
766 @@ -700,10 +776,10 @@ dependencies = [
767 "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
768 "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
769 "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
770- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
771- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
772+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
773+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
774 "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
775- "net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
776+ "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
777 "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
778 "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
779 ]
780 @@ -713,7 +789,7 @@ name = "mio-named-pipes"
781 version = "0.1.7"
782 source = "registry+https://github.com/rust-lang/crates.io-index"
783 dependencies = [
784- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
785+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
786 "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
787 "miow 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
788 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
789 @@ -725,7 +801,7 @@ version = "0.6.8"
790 source = "registry+https://github.com/rust-lang/crates.io-index"
791 dependencies = [
792 "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
793- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
794+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
795 "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
796 ]
797
798 @@ -735,7 +811,7 @@ version = "0.2.1"
799 source = "registry+https://github.com/rust-lang/crates.io-index"
800 dependencies = [
801 "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
802- "net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
803+ "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
804 "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
805 "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
806 ]
807 @@ -745,17 +821,17 @@ name = "miow"
808 version = "0.3.5"
809 source = "registry+https://github.com/rust-lang/crates.io-index"
810 dependencies = [
811- "socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
812+ "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
813 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
814 ]
815
816 [[package]]
817 name = "net2"
818- version = "0.2.34"
819+ version = "0.2.35"
820 source = "registry+https://github.com/rust-lang/crates.io-index"
821 dependencies = [
822 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
823- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
824+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
825 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
826 ]
827
828 @@ -773,7 +849,7 @@ name = "num-integer"
829 version = "0.1.43"
830 source = "registry+https://github.com/rust-lang/crates.io-index"
831 dependencies = [
832- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
833+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
834 "num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
835 ]
836
837 @@ -782,7 +858,7 @@ name = "num-traits"
838 version = "0.2.12"
839 source = "registry+https://github.com/rust-lang/crates.io-index"
840 dependencies = [
841- "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
842+ "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
843 ]
844
845 [[package]]
846 @@ -790,16 +866,31 @@ name = "num_cpus"
847 version = "1.13.0"
848 source = "registry+https://github.com/rust-lang/crates.io-index"
849 dependencies = [
850- "hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
851- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
852+ "hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
853+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
854 ]
855
856 [[package]]
857+ name = "once_cell"
858+ version = "1.4.1"
859+ source = "registry+https://github.com/rust-lang/crates.io-index"
860+
861+ [[package]]
862+ name = "opaque-debug"
863+ version = "0.2.3"
864+ source = "registry+https://github.com/rust-lang/crates.io-index"
865+
866+ [[package]]
867 name = "opaque-debug"
868 version = "0.3.0"
869 source = "registry+https://github.com/rust-lang/crates.io-index"
870
871 [[package]]
872+ name = "openssl-probe"
873+ version = "0.1.2"
874+ source = "registry+https://github.com/rust-lang/crates.io-index"
875+
876+ [[package]]
877 name = "parking_lot"
878 version = "0.9.0"
879 source = "registry+https://github.com/rust-lang/crates.io-index"
880 @@ -816,8 +907,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
881 dependencies = [
882 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
883 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
884- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
885- "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
886+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
887+ "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
888 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
889 "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
890 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
891 @@ -825,12 +916,40 @@ dependencies = [
892
893 [[package]]
894 name = "percent-encoding"
895- version = "1.0.1"
896+ version = "2.1.0"
897+ source = "registry+https://github.com/rust-lang/crates.io-index"
898+
899+ [[package]]
900+ name = "pin-project"
901+ version = "0.4.23"
902+ source = "registry+https://github.com/rust-lang/crates.io-index"
903+ dependencies = [
904+ "pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
905+ ]
906+
907+ [[package]]
908+ name = "pin-project-internal"
909+ version = "0.4.23"
910+ source = "registry+https://github.com/rust-lang/crates.io-index"
911+ dependencies = [
912+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
913+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
914+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
915+ ]
916+
917+ [[package]]
918+ name = "pin-project-lite"
919+ version = "0.1.7"
920+ source = "registry+https://github.com/rust-lang/crates.io-index"
921+
922+ [[package]]
923+ name = "pin-utils"
924+ version = "0.1.0"
925 source = "registry+https://github.com/rust-lang/crates.io-index"
926
927 [[package]]
928 name = "ppv-lite86"
929- version = "0.2.8"
930+ version = "0.2.9"
931 source = "registry+https://github.com/rust-lang/crates.io-index"
932
933 [[package]]
934 @@ -839,34 +958,42 @@ version = "0.4.0"
935 source = "registry+https://github.com/rust-lang/crates.io-index"
936 dependencies = [
937 "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
938- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
939+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
940 ]
941
942 [[package]]
943 name = "proc-macro-error"
944- version = "1.0.3"
945+ version = "1.0.4"
946 source = "registry+https://github.com/rust-lang/crates.io-index"
947 dependencies = [
948- "proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
949- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
950+ "proc-macro-error-attr 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
951+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
952 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
953- "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
954+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
955 "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
956 ]
957
958 [[package]]
959 name = "proc-macro-error-attr"
960- version = "1.0.3"
961+ version = "1.0.4"
962 source = "registry+https://github.com/rust-lang/crates.io-index"
963 dependencies = [
964- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
965+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
966 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
967- "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
968- "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
969 "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
970 ]
971
972 [[package]]
973+ name = "proc-macro-hack"
974+ version = "0.5.18"
975+ source = "registry+https://github.com/rust-lang/crates.io-index"
976+
977+ [[package]]
978+ name = "proc-macro-nested"
979+ version = "0.1.6"
980+ source = "registry+https://github.com/rust-lang/crates.io-index"
981+
982+ [[package]]
983 name = "proc-macro2"
984 version = "0.4.30"
985 source = "registry+https://github.com/rust-lang/crates.io-index"
986 @@ -876,7 +1003,7 @@ dependencies = [
987
988 [[package]]
989 name = "proc-macro2"
990- version = "1.0.18"
991+ version = "1.0.21"
992 source = "registry+https://github.com/rust-lang/crates.io-index"
993 dependencies = [
994 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
995 @@ -900,19 +1027,7 @@ name = "quote"
996 version = "1.0.7"
997 source = "registry+https://github.com/rust-lang/crates.io-index"
998 dependencies = [
999- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
1000- ]
1001-
1002- [[package]]
1003- name = "rand"
1004- version = "0.4.6"
1005- source = "registry+https://github.com/rust-lang/crates.io-index"
1006- dependencies = [
1007- "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1008- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1009- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1010- "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1011- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1012+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1013 ]
1014
1015 [[package]]
1016 @@ -920,8 +1035,8 @@ name = "rand"
1017 version = "0.7.3"
1018 source = "registry+https://github.com/rust-lang/crates.io-index"
1019 dependencies = [
1020- "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
1021- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1022+ "getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
1023+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1024 "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
1025 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1026 "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1027 @@ -932,29 +1047,16 @@ name = "rand_chacha"
1028 version = "0.2.2"
1029 source = "registry+https://github.com/rust-lang/crates.io-index"
1030 dependencies = [
1031- "ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
1032+ "ppv-lite86 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
1033 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
1034 ]
1035
1036 [[package]]
1037 name = "rand_core"
1038- version = "0.3.1"
1039- source = "registry+https://github.com/rust-lang/crates.io-index"
1040- dependencies = [
1041- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
1042- ]
1043-
1044- [[package]]
1045- name = "rand_core"
1046- version = "0.4.2"
1047- source = "registry+https://github.com/rust-lang/crates.io-index"
1048-
1049- [[package]]
1050- name = "rand_core"
1051 version = "0.5.1"
1052 source = "registry+https://github.com/rust-lang/crates.io-index"
1053 dependencies = [
1054- "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
1055+ "getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
1056 ]
1057
1058 [[package]]
1059 @@ -966,26 +1068,18 @@ dependencies = [
1060 ]
1061
1062 [[package]]
1063- name = "rdrand"
1064- version = "0.4.0"
1065- source = "registry+https://github.com/rust-lang/crates.io-index"
1066- dependencies = [
1067- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1068- ]
1069-
1070- [[package]]
1071 name = "redox_syscall"
1072- version = "0.1.56"
1073+ version = "0.1.57"
1074 source = "registry+https://github.com/rust-lang/crates.io-index"
1075
1076 [[package]]
1077 name = "redox_users"
1078- version = "0.3.4"
1079+ version = "0.3.5"
1080 source = "registry+https://github.com/rust-lang/crates.io-index"
1081 dependencies = [
1082- "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
1083- "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
1084- "rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1085+ "getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
1086+ "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
1087+ "rust-argon2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
1088 ]
1089
1090 [[package]]
1091 @@ -1006,14 +1100,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1092
1093 [[package]]
1094 name = "ring"
1095- version = "0.14.6"
1096+ version = "0.16.15"
1097 source = "registry+https://github.com/rust-lang/crates.io-index"
1098 dependencies = [
1099- "cc 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
1100- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1101- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1102+ "cc 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)",
1103+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1104+ "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
1105 "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1106- "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
1107+ "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1108+ "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
1109 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1110 ]
1111
1112 @@ -1022,96 +1117,124 @@ name = "rudolfs"
1113 version = "0.2.10"
1114 dependencies = [
1115 "askama 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
1116- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1117+ "async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
1118+ "backoff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1119+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1120 "chacha 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1121- "derive_more 0.99.9 (registry+https://github.com/rust-lang/crates.io-index)",
1122- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1123- "futures-backoff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1124- "generic-array 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)",
1125+ "derive_more 0.99.10 (registry+https://github.com/rust-lang/crates.io-index)",
1126+ "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1127+ "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
1128 "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
1129- "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
1130+ "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1131 "human-size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
1132 "humantime 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1133- "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)",
1134+ "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
1135 "linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
1136- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1137+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1138 "pretty_env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1139 "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
1140- "rusoto_core 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
1141- "rusoto_s3 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
1142- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1143- "serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
1144+ "rusoto_core 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
1145+ "rusoto_s3 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
1146+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1147+ "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
1148 "sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
1149- "structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
1150- "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
1151- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1152+ "structopt 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
1153+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
1154+ "tokio-compat 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
1155+ "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1156+ "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1157 "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
1158 ]
1159
1160 [[package]]
1161 name = "rusoto_core"
1162- version = "0.40.0"
1163+ version = "0.44.0"
1164 source = "registry+https://github.com/rust-lang/crates.io-index"
1165 dependencies = [
1166- "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
1167- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1168- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1169- "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
1170- "hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
1171- "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
1172- "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)",
1173- "hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
1174+ "async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
1175+ "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
1176+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1177+ "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1178+ "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1179+ "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1180+ "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
1181+ "hyper-rustls 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
1182 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1183- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1184- "md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
1185- "rusoto_credential 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
1186+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1187+ "md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1188+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1189+ "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
1190+ "rusoto_credential 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
1191+ "rusoto_signature 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
1192 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
1193- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1194- "serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1195- "serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
1196- "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1197- "time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
1198- "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
1199- "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
1200- "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1201- "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1202+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1203+ "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
1204+ "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
1205+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
1206+ "xml-rs 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
1207 ]
1208
1209 [[package]]
1210 name = "rusoto_credential"
1211- version = "0.40.0"
1212+ version = "0.44.0"
1213 source = "registry+https://github.com/rust-lang/crates.io-index"
1214 dependencies = [
1215- "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1216- "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1217- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1218- "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)",
1219+ "async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
1220+ "chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
1221+ "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1222+ "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1223+ "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
1224+ "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
1225 "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1226- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1227- "serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1228- "serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
1229+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1230+ "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
1231 "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1232- "tokio-process 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
1233- "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
1234+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
1235+ "zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1236 ]
1237
1238 [[package]]
1239 name = "rusoto_s3"
1240- version = "0.40.0"
1241+ version = "0.44.0"
1242 source = "registry+https://github.com/rust-lang/crates.io-index"
1243 dependencies = [
1244- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1245- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1246- "rusoto_core 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)",
1247- "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1248+ "async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
1249+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1250+ "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1251+ "rusoto_core 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
1252+ "xml-rs 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
1253+ ]
1254+
1255+ [[package]]
1256+ name = "rusoto_signature"
1257+ version = "0.44.0"
1258+ source = "registry+https://github.com/rust-lang/crates.io-index"
1259+ dependencies = [
1260+ "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
1261+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1262+ "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1263+ "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
1264+ "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1265+ "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1266+ "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
1267+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1268+ "md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1269+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1270+ "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
1271+ "rusoto_credential 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)",
1272+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
1273+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1274+ "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
1275+ "time 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
1276+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
1277 ]
1278
1279 [[package]]
1280 name = "rust-argon2"
1281- version = "0.7.0"
1282+ version = "0.8.2"
1283 source = "registry+https://github.com/rust-lang/crates.io-index"
1284 dependencies = [
1285- "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
1286+ "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
1287 "blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
1288 "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1289 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1290 @@ -1127,15 +1250,25 @@ dependencies = [
1291
1292 [[package]]
1293 name = "rustls"
1294- version = "0.15.2"
1295+ version = "0.17.0"
1296 source = "registry+https://github.com/rust-lang/crates.io-index"
1297 dependencies = [
1298- "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
1299- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1300- "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
1301- "sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
1302- "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
1303- "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
1304+ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
1305+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1306+ "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)",
1307+ "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
1308+ "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)",
1309+ ]
1310+
1311+ [[package]]
1312+ name = "rustls-native-certs"
1313+ version = "0.3.0"
1314+ source = "registry+https://github.com/rust-lang/crates.io-index"
1315+ dependencies = [
1316+ "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1317+ "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
1318+ "schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
1319+ "security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
1320 ]
1321
1322 [[package]]
1323 @@ -1144,9 +1277,13 @@ version = "1.0.5"
1324 source = "registry+https://github.com/rust-lang/crates.io-index"
1325
1326 [[package]]
1327- name = "safemem"
1328- version = "0.3.3"
1329+ name = "schannel"
1330+ version = "0.1.19"
1331 source = "registry+https://github.com/rust-lang/crates.io-index"
1332+ dependencies = [
1333+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1334+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1335+ ]
1336
1337 [[package]]
1338 name = "scopeguard"
1339 @@ -1155,11 +1292,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1340
1341 [[package]]
1342 name = "sct"
1343- version = "0.5.0"
1344+ version = "0.6.0"
1345 source = "registry+https://github.com/rust-lang/crates.io-index"
1346 dependencies = [
1347- "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
1348- "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
1349+ "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)",
1350+ "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
1351+ ]
1352+
1353+ [[package]]
1354+ name = "security-framework"
1355+ version = "0.4.4"
1356+ source = "registry+https://github.com/rust-lang/crates.io-index"
1357+ dependencies = [
1358+ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1359+ "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1360+ "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1361+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1362+ "security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
1363+ ]
1364+
1365+ [[package]]
1366+ name = "security-framework-sys"
1367+ version = "0.4.3"
1368+ source = "registry+https://github.com/rust-lang/crates.io-index"
1369+ dependencies = [
1370+ "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
1371+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1372 ]
1373
1374 [[package]]
1375 @@ -1177,49 +1335,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1376
1377 [[package]]
1378 name = "serde"
1379- version = "1.0.114"
1380+ version = "1.0.116"
1381 source = "registry+https://github.com/rust-lang/crates.io-index"
1382 dependencies = [
1383- "serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1384+ "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1385 ]
1386
1387 [[package]]
1388 name = "serde_derive"
1389- version = "1.0.114"
1390+ version = "1.0.116"
1391 source = "registry+https://github.com/rust-lang/crates.io-index"
1392 dependencies = [
1393- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
1394+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1395 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1396- "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
1397+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1398 ]
1399
1400 [[package]]
1401 name = "serde_json"
1402- version = "1.0.56"
1403+ version = "1.0.57"
1404 source = "registry+https://github.com/rust-lang/crates.io-index"
1405 dependencies = [
1406 "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1407 "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
1408- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1409+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1410 ]
1411
1412 [[package]]
1413 name = "serde_test"
1414- version = "1.0.114"
1415+ version = "1.0.116"
1416 source = "registry+https://github.com/rust-lang/crates.io-index"
1417 dependencies = [
1418- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1419+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1420 ]
1421
1422 [[package]]
1423+ name = "sha1"
1424+ version = "0.6.0"
1425+ source = "registry+https://github.com/rust-lang/crates.io-index"
1426+
1427+ [[package]]
1428 name = "sha2"
1429- version = "0.7.1"
1430+ version = "0.8.2"
1431 source = "registry+https://github.com/rust-lang/crates.io-index"
1432 dependencies = [
1433- "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
1434- "byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1435- "digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
1436+ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
1437+ "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
1438 "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1439+ "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
1440 ]
1441
1442 [[package]]
1443 @@ -1229,7 +1392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1444 dependencies = [
1445 "block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1446 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1447- "cpuid-bool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1448+ "cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1449 "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1450 "opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1451 ]
1452 @@ -1241,11 +1404,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1453
1454 [[package]]
1455 name = "signal-hook-registry"
1456- version = "1.2.0"
1457+ version = "1.2.1"
1458 source = "registry+https://github.com/rust-lang/crates.io-index"
1459 dependencies = [
1460 "arc-swap 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
1461- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1462+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1463 ]
1464
1465 [[package]]
1466 @@ -1263,12 +1426,12 @@ dependencies = [
1467
1468 [[package]]
1469 name = "socket2"
1470- version = "0.3.12"
1471+ version = "0.3.15"
1472 source = "registry+https://github.com/rust-lang/crates.io-index"
1473 dependencies = [
1474 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1475- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1476- "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
1477+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1478+ "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
1479 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1480 ]
1481
1482 @@ -1278,41 +1441,91 @@ version = "0.5.2"
1483 source = "registry+https://github.com/rust-lang/crates.io-index"
1484
1485 [[package]]
1486- name = "string"
1487- version = "0.2.1"
1488+ name = "standback"
1489+ version = "0.2.10"
1490 source = "registry+https://github.com/rust-lang/crates.io-index"
1491 dependencies = [
1492- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1493+ "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
1494+ ]
1495+
1496+ [[package]]
1497+ name = "stdweb"
1498+ version = "0.4.20"
1499+ source = "registry+https://github.com/rust-lang/crates.io-index"
1500+ dependencies = [
1501+ "discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
1502+ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
1503+ "stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
1504+ "stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
1505+ "stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1506+ "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
1507+ ]
1508+
1509+ [[package]]
1510+ name = "stdweb-derive"
1511+ version = "0.5.3"
1512+ source = "registry+https://github.com/rust-lang/crates.io-index"
1513+ dependencies = [
1514+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1515+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1516+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1517+ "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1518+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1519+ ]
1520+
1521+ [[package]]
1522+ name = "stdweb-internal-macros"
1523+ version = "0.2.9"
1524+ source = "registry+https://github.com/rust-lang/crates.io-index"
1525+ dependencies = [
1526+ "base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
1527+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1528+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1529+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1530+ "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1531+ "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
1532+ "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
1533+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1534 ]
1535
1536 [[package]]
1537+ name = "stdweb-internal-runtime"
1538+ version = "0.1.5"
1539+ source = "registry+https://github.com/rust-lang/crates.io-index"
1540+
1541+ [[package]]
1542 name = "strsim"
1543 version = "0.8.0"
1544 source = "registry+https://github.com/rust-lang/crates.io-index"
1545
1546 [[package]]
1547 name = "structopt"
1548- version = "0.3.15"
1549+ version = "0.3.17"
1550 source = "registry+https://github.com/rust-lang/crates.io-index"
1551 dependencies = [
1552- "clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
1553+ "clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)",
1554 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1555- "structopt-derive 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1556+ "structopt-derive 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
1557 ]
1558
1559 [[package]]
1560 name = "structopt-derive"
1561- version = "0.4.8"
1562+ version = "0.4.10"
1563 source = "registry+https://github.com/rust-lang/crates.io-index"
1564 dependencies = [
1565 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
1566- "proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
1567- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
1568+ "proc-macro-error 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
1569+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1570 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1571- "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
1572+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1573 ]
1574
1575 [[package]]
1576+ name = "subtle"
1577+ version = "1.0.0"
1578+ source = "registry+https://github.com/rust-lang/crates.io-index"
1579+
1580+ [[package]]
1581 name = "syn"
1582 version = "0.15.44"
1583 source = "registry+https://github.com/rust-lang/crates.io-index"
1584 @@ -1324,25 +1537,15 @@ dependencies = [
1585
1586 [[package]]
1587 name = "syn"
1588- version = "1.0.33"
1589+ version = "1.0.40"
1590 source = "registry+https://github.com/rust-lang/crates.io-index"
1591 dependencies = [
1592- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
1593+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1594 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1595 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1596 ]
1597
1598 [[package]]
1599- name = "syn-mid"
1600- version = "0.5.0"
1601- source = "registry+https://github.com/rust-lang/crates.io-index"
1602- dependencies = [
1603- "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
1604- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1605- "syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
1606- ]
1607-
1608- [[package]]
1609 name = "termcolor"
1610 version = "1.1.0"
1611 source = "registry+https://github.com/rust-lang/crates.io-index"
1612 @@ -1368,87 +1571,109 @@ dependencies = [
1613
1614 [[package]]
1615 name = "time"
1616- version = "0.1.43"
1617+ version = "0.1.44"
1618 source = "registry+https://github.com/rust-lang/crates.io-index"
1619 dependencies = [
1620- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1621+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1622+ "wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
1623 "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1624 ]
1625
1626 [[package]]
1627- name = "tinyvec"
1628- version = "0.3.3"
1629+ name = "time"
1630+ version = "0.2.19"
1631 source = "registry+https://github.com/rust-lang/crates.io-index"
1632+ dependencies = [
1633+ "const_fn 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
1634+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1635+ "standback 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
1636+ "stdweb 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
1637+ "time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1638+ "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
1639+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1640+ ]
1641
1642 [[package]]
1643- name = "tokio"
1644- version = "0.1.22"
1645+ name = "time-macros"
1646+ version = "0.1.0"
1647 source = "registry+https://github.com/rust-lang/crates.io-index"
1648 dependencies = [
1649- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1650- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1651- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1652- "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
1653- "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1654- "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1655- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1656- "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1657- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1658- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1659- "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
1660- "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
1661- "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
1662- "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
1663- "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
1664- "tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
1665+ "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)",
1666+ "time-macros-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1667 ]
1668
1669 [[package]]
1670- name = "tokio-buf"
1671+ name = "time-macros-impl"
1672 version = "0.1.1"
1673 source = "registry+https://github.com/rust-lang/crates.io-index"
1674 dependencies = [
1675- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1676- "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
1677- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1678+ "proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)",
1679+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1680+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1681+ "standback 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
1682+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1683 ]
1684
1685 [[package]]
1686- name = "tokio-codec"
1687- version = "0.1.2"
1688+ name = "tinyvec"
1689+ version = "0.3.4"
1690+ source = "registry+https://github.com/rust-lang/crates.io-index"
1691+
1692+ [[package]]
1693+ name = "tokio"
1694+ version = "0.2.22"
1695 source = "registry+https://github.com/rust-lang/crates.io-index"
1696 dependencies = [
1697- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1698- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1699- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1700+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1701+ "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1702+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1703+ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
1704+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1705+ "libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
1706+ "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
1707+ "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1708+ "mio-named-pipes 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1709+ "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
1710+ "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
1711+ "pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1712+ "signal-hook-registry 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
1713+ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
1714+ "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
1715+ "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1716 ]
1717
1718 [[package]]
1719- name = "tokio-current-thread"
1720- version = "0.1.7"
1721+ name = "tokio-compat"
1722+ version = "0.1.6"
1723 source = "registry+https://github.com/rust-lang/crates.io-index"
1724 dependencies = [
1725 "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1726+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1727+ "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1728+ "pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1729+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
1730+ "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1731 "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1732+ "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1733+ "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
1734 ]
1735
1736 [[package]]
1737- name = "tokio-executor"
1738- version = "0.1.10"
1739+ name = "tokio-current-thread"
1740+ version = "0.1.7"
1741 source = "registry+https://github.com/rust-lang/crates.io-index"
1742 dependencies = [
1743- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1744 "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1745+ "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1746 ]
1747
1748 [[package]]
1749- name = "tokio-fs"
1750- version = "0.1.7"
1751+ name = "tokio-executor"
1752+ version = "0.1.10"
1753 source = "registry+https://github.com/rust-lang/crates.io-index"
1754 dependencies = [
1755+ "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1756 "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1757- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1758- "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
1759 ]
1760
1761 [[package]]
1762 @@ -1458,25 +1683,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1763 dependencies = [
1764 "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1765 "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1766- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1767+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1768 ]
1769
1770 [[package]]
1771- name = "tokio-process"
1772+ name = "tokio-macros"
1773 version = "0.2.5"
1774 source = "registry+https://github.com/rust-lang/crates.io-index"
1775 dependencies = [
1776- "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1777- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1778- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1779- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1780- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1781- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1782- "mio-named-pipes 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1783- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1784- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1785- "tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
1786- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1787+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
1788+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
1789+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1790 ]
1791
1792 [[package]]
1793 @@ -1487,7 +1704,7 @@ dependencies = [
1794 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1795 "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1796 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1797- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1798+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1799 "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1800 "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
1801 "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
1802 @@ -1499,29 +1716,13 @@ dependencies = [
1803
1804 [[package]]
1805 name = "tokio-rustls"
1806- version = "0.9.4"
1807+ version = "0.13.1"
1808 source = "registry+https://github.com/rust-lang/crates.io-index"
1809 dependencies = [
1810- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1811- "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
1812- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1813- "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
1814- ]
1815-
1816- [[package]]
1817- name = "tokio-signal"
1818- version = "0.2.9"
1819- source = "registry+https://github.com/rust-lang/crates.io-index"
1820- dependencies = [
1821- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1822- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1823- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1824- "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
1825- "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1826- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1827- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1828- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1829- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
1830+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1831+ "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
1832+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
1833+ "webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)",
1834 ]
1835
1836 [[package]]
1837 @@ -1534,87 +1735,64 @@ dependencies = [
1838 ]
1839
1840 [[package]]
1841- name = "tokio-tcp"
1842- version = "0.1.4"
1843- source = "registry+https://github.com/rust-lang/crates.io-index"
1844- dependencies = [
1845- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1846- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1847- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
1848- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1849- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1850- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1851- ]
1852-
1853- [[package]]
1854- name = "tokio-threadpool"
1855- version = "0.1.18"
1856+ name = "tokio-timer"
1857+ version = "0.2.13"
1858 source = "registry+https://github.com/rust-lang/crates.io-index"
1859 dependencies = [
1860- "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
1861- "crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
1862 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1863 "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1864- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1865- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1866- "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
1867 "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
1868 "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1869 ]
1870
1871 [[package]]
1872- name = "tokio-timer"
1873- version = "0.2.13"
1874+ name = "tokio-util"
1875+ version = "0.3.1"
1876 source = "registry+https://github.com/rust-lang/crates.io-index"
1877 dependencies = [
1878- "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
1879- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1880- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
1881- "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1882+ "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1883+ "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1884+ "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1885+ "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
1886+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1887+ "pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
1888+ "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
1889 ]
1890
1891 [[package]]
1892- name = "tokio-udp"
1893- version = "0.1.6"
1894+ name = "toml"
1895+ version = "0.4.10"
1896 source = "registry+https://github.com/rust-lang/crates.io-index"
1897 dependencies = [
1898- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1899- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1900- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1901- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1902- "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1903- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1904- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1905+ "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
1906 ]
1907
1908 [[package]]
1909- name = "tokio-uds"
1910- version = "0.2.6"
1911+ name = "tower-service"
1912+ version = "0.3.0"
1913+ source = "registry+https://github.com/rust-lang/crates.io-index"
1914+
1915+ [[package]]
1916+ name = "tracing"
1917+ version = "0.1.19"
1918 source = "registry+https://github.com/rust-lang/crates.io-index"
1919 dependencies = [
1920- "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
1921- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1922- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
1923- "libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
1924- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1925- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
1926- "mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
1927- "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
1928- "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
1929- "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
1930+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
1931+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1932+ "tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
1933 ]
1934
1935 [[package]]
1936- name = "toml"
1937- version = "0.4.10"
1938+ name = "tracing-core"
1939+ version = "0.1.16"
1940 source = "registry+https://github.com/rust-lang/crates.io-index"
1941 dependencies = [
1942- "serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
1943+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1944 ]
1945
1946 [[package]]
1947 name = "try-lock"
1948- version = "0.2.2"
1949+ version = "0.2.3"
1950 source = "registry+https://github.com/rust-lang/crates.io-index"
1951
1952 [[package]]
1953 @@ -1635,7 +1813,7 @@ name = "unicode-normalization"
1954 version = "0.1.13"
1955 source = "registry+https://github.com/rust-lang/crates.io-index"
1956 dependencies = [
1957- "tinyvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
1958+ "tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
1959 ]
1960
1961 [[package]]
1962 @@ -1660,17 +1838,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1963
1964 [[package]]
1965 name = "untrusted"
1966- version = "0.6.2"
1967+ version = "0.7.1"
1968 source = "registry+https://github.com/rust-lang/crates.io-index"
1969
1970 [[package]]
1971 name = "url"
1972- version = "1.7.2"
1973+ version = "2.1.1"
1974 source = "registry+https://github.com/rust-lang/crates.io-index"
1975 dependencies = [
1976- "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
1977+ "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1978 "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
1979- "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1980+ "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1981 ]
1982
1983 [[package]]
1984 @@ -1698,12 +1876,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1985
1986 [[package]]
1987 name = "want"
1988- version = "0.2.0"
1989+ version = "0.3.0"
1990 source = "registry+https://github.com/rust-lang/crates.io-index"
1991 dependencies = [
1992- "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
1993- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
1994- "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
1995+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
1996+ "try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
1997 ]
1998
1999 [[package]]
2000 @@ -1712,21 +1889,75 @@ version = "0.9.0+wasi-snapshot-preview1"
2001 source = "registry+https://github.com/rust-lang/crates.io-index"
2002
2003 [[package]]
2004- name = "webpki"
2005- version = "0.19.1"
2006+ name = "wasi"
2007+ version = "0.10.0+wasi-snapshot-preview1"
2008+ source = "registry+https://github.com/rust-lang/crates.io-index"
2009+
2010+ [[package]]
2011+ name = "wasm-bindgen"
2012+ version = "0.2.68"
2013 source = "registry+https://github.com/rust-lang/crates.io-index"
2014 dependencies = [
2015- "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
2016- "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
2017+ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
2018+ "wasm-bindgen-macro 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
2019 ]
2020
2021 [[package]]
2022- name = "webpki-roots"
2023- version = "0.16.0"
2024+ name = "wasm-bindgen-backend"
2025+ version = "0.2.68"
2026 source = "registry+https://github.com/rust-lang/crates.io-index"
2027 dependencies = [
2028- "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
2029- "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
2030+ "bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
2031+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
2032+ "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
2033+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
2034+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
2035+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
2036+ "wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
2037+ ]
2038+
2039+ [[package]]
2040+ name = "wasm-bindgen-macro"
2041+ version = "0.2.68"
2042+ source = "registry+https://github.com/rust-lang/crates.io-index"
2043+ dependencies = [
2044+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
2045+ "wasm-bindgen-macro-support 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
2046+ ]
2047+
2048+ [[package]]
2049+ name = "wasm-bindgen-macro-support"
2050+ version = "0.2.68"
2051+ source = "registry+https://github.com/rust-lang/crates.io-index"
2052+ dependencies = [
2053+ "proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
2054+ "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
2055+ "syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
2056+ "wasm-bindgen-backend 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
2057+ "wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
2058+ ]
2059+
2060+ [[package]]
2061+ name = "wasm-bindgen-shared"
2062+ version = "0.2.68"
2063+ source = "registry+https://github.com/rust-lang/crates.io-index"
2064+
2065+ [[package]]
2066+ name = "web-sys"
2067+ version = "0.3.45"
2068+ source = "registry+https://github.com/rust-lang/crates.io-index"
2069+ dependencies = [
2070+ "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
2071+ "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
2072+ ]
2073+
2074+ [[package]]
2075+ name = "webpki"
2076+ version = "0.21.3"
2077+ source = "registry+https://github.com/rust-lang/crates.io-index"
2078+ dependencies = [
2079+ "ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)",
2080+ "untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
2081 ]
2082
2083 [[package]]
2084 @@ -1777,11 +2008,13 @@ dependencies = [
2085
2086 [[package]]
2087 name = "xml-rs"
2088- version = "0.7.0"
2089+ version = "0.8.3"
2090+ source = "registry+https://github.com/rust-lang/crates.io-index"
2091+
2092+ [[package]]
2093+ name = "zeroize"
2094+ version = "1.1.0"
2095 source = "registry+https://github.com/rust-lang/crates.io-index"
2096- dependencies = [
2097- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
2098- ]
2099
2100 [metadata]
2101 "checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
2102 @@ -1793,173 +2026,199 @@ dependencies = [
2103 "checksum askama_derive 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ee2fff0f22ad5d215cace1227cd036c28e81e26206763bb837b6d0e766c87d"
2104 "checksum askama_escape 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0de942230b5beedaa9e1d64df5b76fa1c97002e4c7982897be899cccf40621d"
2105 "checksum askama_shared 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6dfa6b6d254fd066a8bbed9a8f913123e3f701db89216ad4f0aff04ad87718c"
2106+ "checksum async-trait 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "687c230d85c0a52504709705fc8a53e4a692b83a2184f03dae73e38e1e93a783"
2107 "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
2108- "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
2109- "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
2110+ "checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
2111+ "checksum backoff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "721c249ab59cbc483ad4294c9ee2671835c1e43e9ffc277e6b4ecfef733cfdc5"
2112+ "checksum base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1"
2113 "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
2114- "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
2115+ "checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
2116 "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
2117 "checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a"
2118- "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
2119+ "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
2120 "checksum block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
2121- "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
2122+ "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
2123+ "checksum bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
2124+ "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
2125 "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
2126 "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
2127- "checksum cc 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)" = "77c1f1d60091c1b73e2b1f4560ab419204b178e625fa945ded7b660becd2bd46"
2128+ "checksum bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
2129+ "checksum cc 1.0.59 (registry+https://github.com/rust-lang/crates.io-index)" = "66120af515773fb005778dc07c261bd201ec8ce50bd6e7144c927753fe013381"
2130 "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
2131 "checksum chacha 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf3c081b5fba1e5615640aae998e0fbd10c24cbd897ee39ed754a77601a4862"
2132- "checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
2133- "checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
2134+ "checksum chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
2135+ "checksum clap 2.33.3 (registry+https://github.com/rust-lang/crates.io-index)" = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
2136 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
2137+ "checksum const_fn 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2"
2138 "checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
2139- "checksum cpuid-bool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d375c433320f6c5057ae04a04376eef4d04ce2801448cf8863a78da99107be4"
2140- "checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
2141- "checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
2142- "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
2143- "checksum crossbeam-queue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
2144- "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
2145+ "checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
2146+ "checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
2147+ "checksum cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
2148 "checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
2149- "checksum crypto-mac 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0999b4ff4d3446d4ddb19a63e9e00c1876e75cd7000d20e57a693b4b3f08d958"
2150- "checksum ct-logs 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b4660f8b07a560a88c02d76286edb9f0d5d64e495d2b0f233186155aa51be1f"
2151- "checksum derive_more 0.99.9 (registry+https://github.com/rust-lang/crates.io-index)" = "298998b1cf6b5b2c8a7b023dfd45821825ce3ba8a8af55c921a0e734e4653f76"
2152- "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
2153+ "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5"
2154+ "checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113"
2155+ "checksum derive_more 0.99.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba"
2156+ "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
2157 "checksum digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
2158- "checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901"
2159- "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
2160+ "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
2161+ "checksum dirs-sys 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
2162+ "checksum discard 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
2163 "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
2164 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
2165 "checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
2166- "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
2167 "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
2168 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
2169 "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
2170- "checksum futures-backoff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79f590345ee8cedf1f36068db74ca81c7e7bf753a3e59ea58b0826243a13971b"
2171- "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
2172- "checksum futures-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5cedfe9b6dc756220782cc1ba5bcb1fa091cdcba155e40d3556159c3db58043"
2173- "checksum generic-array 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ac746a5f3bbfdadd6106868134545e684693d54d9d44f6e9588a7d54af0bf980"
2174- "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
2175- "checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
2176- "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
2177+ "checksum futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
2178+ "checksum futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5"
2179+ "checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
2180+ "checksum futures-executor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314"
2181+ "checksum futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
2182+ "checksum futures-macro 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
2183+ "checksum futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
2184+ "checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
2185+ "checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
2186+ "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
2187+ "checksum generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
2188+ "checksum getrandom 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
2189+ "checksum h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
2190+ "checksum hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7"
2191 "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
2192- "checksum hermit-abi 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
2193+ "checksum hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
2194 "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
2195- "checksum hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44f3bdb08579d99d7dc761c0e266f13b5f2ab8c8c703b9fc9ef333cd8f48f55e"
2196- "checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0"
2197- "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
2198+ "checksum hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
2199+ "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
2200+ "checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
2201+ "checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
2202 "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
2203 "checksum human-size 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f90b9d206a509fdc5034ea8ffb4d6ca080dd61883cfa222c480cfcba8c570368"
2204 "checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
2205 "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
2206 "checksum humantime 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a"
2207- "checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6"
2208- "checksum hyper-rustls 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "15b66d1bd4864ef036adf2363409caa3acd63ebb4725957b66e621c8a36631a3"
2209- "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
2210- "checksum indexmap 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe"
2211+ "checksum hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb"
2212+ "checksum hyper-rustls 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac965ea399ec3a25ac7d13b8affd4b8f39325cca00858ddf5eb29b79e6b14b08"
2213+ "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
2214+ "checksum indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
2215+ "checksum instant 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5b141fdc7836c525d4d594027d318c84161ca17aaf8113ab1f81ab93ae897485"
2216 "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
2217 "checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
2218+ "checksum js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8"
2219 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
2220 "checksum keystream 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c33070833c9ee02266356de0c43f723152bd38bd96ddf52c82b3af10c9138b28"
2221 "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
2222- "checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
2223+ "checksum libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
2224 "checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
2225 "checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
2226- "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
2227+ "checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
2228 "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
2229 "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
2230- "checksum md5 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "79c56d6a0b07f9e19282511c83fc5b086364cbae4ba8c7d5f190c3d9b0425a48"
2231+ "checksum md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
2232 "checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
2233- "checksum memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
2234 "checksum mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)" = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
2235 "checksum mio-named-pipes 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
2236 "checksum mio-uds 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
2237 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
2238 "checksum miow 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"
2239- "checksum net2 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
2240+ "checksum net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
2241 "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
2242 "checksum num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
2243 "checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
2244 "checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
2245+ "checksum once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
2246+ "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
2247 "checksum opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
2248+ "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
2249 "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
2250 "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
2251- "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
2252- "checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
2253+ "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
2254+ "checksum pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa"
2255+ "checksum pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f"
2256+ "checksum pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
2257+ "checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
2258+ "checksum ppv-lite86 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
2259 "checksum pretty_env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
2260- "checksum proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
2261- "checksum proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
2262+ "checksum proc-macro-error 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
2263+ "checksum proc-macro-error-attr 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
2264+ "checksum proc-macro-hack 0.5.18 (registry+https://github.com/rust-lang/crates.io-index)" = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
2265+ "checksum proc-macro-nested 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
2266 "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
2267- "checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
2268+ "checksum proc-macro2 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c"
2269 "checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
2270 "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
2271 "checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
2272- "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
2273 "checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
2274 "checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
2275- "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
2276- "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
2277 "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
2278 "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
2279- "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
2280- "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
2281- "checksum redox_users 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
2282+ "checksum redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)" = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
2283+ "checksum redox_users 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
2284 "checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
2285 "checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
2286- "checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c"
2287- "checksum rusoto_core 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1a1069ba04874a485528d1602fab4569f2434a5547614428e2cc22b91bfb71"
2288- "checksum rusoto_credential 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d6cc3a602f01b9c5a04c8ed4ee281b789c5b2692d93202367c9b99ebc022ed"
2289- "checksum rusoto_s3 0.40.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4da6eac54781d2aac517a99f1d85d0d6a78674543f8d122d884628c1ff21b495"
2290- "checksum rust-argon2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017"
2291+ "checksum ring 0.16.15 (registry+https://github.com/rust-lang/crates.io-index)" = "952cd6b98c85bbc30efa1ba5783b8abf12fec8b3287ffa52605b9432313e34e4"
2292+ "checksum rusoto_core 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "841ca8f73e7498ba39146ab43acea906bbbb807d92ec0b7ea4b6293d2621f80d"
2293+ "checksum rusoto_credential 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60669ddc1bdbb83ce225593649d36b4c5f6bf9db47cc1ab3e81281abffc853f4"
2294+ "checksum rusoto_s3 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eebe039c71a8ab54ce6614e2967ef034bb3202f306e4025901f620cdfa5680c8"
2295+ "checksum rusoto_signature 0.44.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9eddff187ac18c5a91d9ccda9353f30cf531620dce437c4db661dfe2e23b2029"
2296+ "checksum rust-argon2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19"
2297 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
2298- "checksum rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f271e3552cd835fa28c541c34a7e8fdd8cdff09d77fe4eb8f6c42e87a11b096e"
2299+ "checksum rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
2300+ "checksum rustls-native-certs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5"
2301 "checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
2302- "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
2303+ "checksum schannel 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
2304 "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
2305- "checksum sct 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f5adf8fbd58e1b1b52699dc8bed2630faecb6d8c7bee77d009d6bbe4af569b9"
2306+ "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c"
2307+ "checksum security-framework 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535"
2308+ "checksum security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405"
2309 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
2310 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
2311- "checksum serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
2312- "checksum serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
2313- "checksum serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)" = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3"
2314- "checksum serde_test 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "f58190d074af17bd48118303db08afadbd506bc2ba511b4582cebd8f882a9b8d"
2315- "checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
2316+ "checksum serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
2317+ "checksum serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
2318+ "checksum serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)" = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
2319+ "checksum serde_test 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "923edec3f1ab4a2f489f384e117dc4f826fd977a9d189b28717cba8474dd5c6b"
2320+ "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
2321+ "checksum sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
2322 "checksum sha2 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1"
2323 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
2324- "checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41"
2325+ "checksum signal-hook-registry 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035"
2326 "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
2327 "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
2328- "checksum socket2 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
2329+ "checksum socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44"
2330 "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
2331- "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
2332+ "checksum standback 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "33a71ea1ea5f8747d1af1979bfb7e65c3a025a70609f04ceb78425bc5adad8e6"
2333+ "checksum stdweb 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5"
2334+ "checksum stdweb-derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
2335+ "checksum stdweb-internal-macros 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
2336+ "checksum stdweb-internal-runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
2337 "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
2338- "checksum structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
2339- "checksum structopt-derive 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
2340+ "checksum structopt 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc388d94ffabf39b5ed5fadddc40147cb21e605f53db6f8f36a625d27489ac5"
2341+ "checksum structopt-derive 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2513111825077552a6751dfad9e11ce0fba07d7276a3943a037d7e93e64c5f"
2342+ "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
2343 "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
2344- "checksum syn 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd"
2345- "checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
2346+ "checksum syn 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "963f7d3cc59b59b9325165add223142bbf1df27655d07789f109896d353d8350"
2347 "checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
2348 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
2349 "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
2350- "checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
2351- "checksum tinyvec 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed"
2352- "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
2353- "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46"
2354- "checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b"
2355+ "checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
2356+ "checksum time 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "80c1a1fd93112fc50b11c43a1def21f926be3c18884fad676ea879572da070a1"
2357+ "checksum time-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ae9b6e9f095bc105e183e3cd493d72579be3181ad4004fceb01adbe9eecab2d"
2358+ "checksum time-macros-impl 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
2359+ "checksum tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
2360+ "checksum tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
2361+ "checksum tokio-compat 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "107b625135aa7b9297dd2d99ccd6ca6ab124a5d1230778e159b9095adca4c722"
2362 "checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e"
2363 "checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
2364- "checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4"
2365 "checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
2366- "checksum tokio-process 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "382d90f43fa31caebe5d3bc6cfd854963394fff3b8cb59d5146607aaae7e7e43"
2367+ "checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
2368 "checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
2369- "checksum tokio-rustls 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "95a199832a67452c60bed18ed951d28d5755ff57b02b3d2d535d9f13a81ea6c9"
2370- "checksum tokio-signal 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c34c6e548f101053321cba3da7cbb87a610b85555884c41b07da2eb91aff12"
2371+ "checksum tokio-rustls 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "15cb62a0d2770787abc96e99c1cd98fcf17f94959f3af63ca85bdfb203f051b4"
2372 "checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee"
2373- "checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
2374- "checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89"
2375 "checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296"
2376- "checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82"
2377- "checksum tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798"
2378+ "checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
2379 "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
2380- "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
2381+ "checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
2382+ "checksum tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c"
2383+ "checksum tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a"
2384+ "checksum try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
2385 "checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
2386 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
2387 "checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
2388 @@ -1967,16 +2226,22 @@ dependencies = [
2389 "checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
2390 "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
2391 "checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
2392- "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
2393- "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
2394+ "checksum untrusted 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
2395+ "checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
2396 "checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
2397 "checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
2398 "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
2399 "checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
2400- "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
2401+ "checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
2402+ "checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
2403 "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
2404- "checksum webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f7e1cd7900a3a6b65a3e8780c51a3e6b59c0e2c55c6dc69578c288d69f7d082"
2405- "checksum webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c10fa4212003ba19a564f25cd8ab572c6791f99a03cc219c13ed35ccab00de0e"
2406+ "checksum wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
2407+ "checksum wasm-bindgen-backend 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68"
2408+ "checksum wasm-bindgen-macro 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038"
2409+ "checksum wasm-bindgen-macro-support 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
2410+ "checksum wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
2411+ "checksum web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d"
2412+ "checksum webpki 0.21.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ab146130f5f790d45f82aeeb09e55a256573373ec64409fc19a6fb82fb1032ae"
2413 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
2414 "checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
2415 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
2416 @@ -1984,4 +2249,5 @@ dependencies = [
2417 "checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
2418 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
2419 "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
2420- "checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2"
2421+ "checksum xml-rs 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"
2422+ "checksum zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3cbac2ed2ba24cc90f5e06485ac8c7c1e5449fe8911aef4d8877218af021a5b8"
2423 diff --git a/Cargo.toml b/Cargo.toml
2424index 31ab19e..6f06126 100644
2425--- a/Cargo.toml
2426+++ b/Cargo.toml
2427 @@ -16,36 +16,39 @@ license = "MIT"
2428
2429 [dependencies]
2430 askama = "0.8"
2431- bytes = "0.4"
2432+ async-trait = "0.1"
2433+ backoff = { version = "0.2", features = ["tokio"] }
2434+ bytes = "0.5"
2435 chacha = "0.3"
2436 derive_more = "0.99"
2437- futures = "0.1"
2438- futures-backoff = "0.1"
2439+ futures = "0.3"
2440 generic-array = "0.14"
2441 hex = "0.3"
2442- http = "0.1"
2443+ http = "0.2"
2444 human-size = "0.4"
2445 humantime = "2"
2446- hyper = "0.12"
2447+ hyper = "0.13"
2448 linked-hash-map = { version = "0.5", features = ["serde_impl"] }
2449 log = "0.4"
2450 pretty_env_logger = "0.4"
2451+ rand = { version = "0.7", optional = true }
2452 serde = { version = "1", features = ["derive"] }
2453 serde_json = "1"
2454 sha2 = "0.9"
2455 structopt = "0.3"
2456- tokio = "0.1"
2457- url = "1"
2458+ tokio = { version = "0.2", features = ["full"] }
2459+ tokio-compat = "0.1"
2460+ tokio-util = { version = "0.3", features = ["full"] }
2461+ url = "2"
2462 uuid = { version = "0.8", features = ["v4"] }
2463- rand = { version = "0.7", optional = true }
2464
2465 [dependencies.rusoto_core]
2466- version = "0.40"
2467+ version = "0.44"
2468 default_features = false
2469 features = ["rustls"]
2470
2471 [dependencies.rusoto_s3]
2472- version = "0.40"
2473+ version = "0.44"
2474 default_features = false
2475 features = ["rustls"]
2476
2477 diff --git a/src/app.rs b/src/app.rs
2478index a6629e6..d5f604a 100644
2479--- a/src/app.rs
2480+++ b/src/app.rs
2481 @@ -19,21 +19,44 @@
2482 // SOFTWARE.
2483 use std::fmt;
2484 use std::io;
2485- use std::sync::Arc;
2486+
2487+ use core::task::{Context, Poll};
2488
2489 use askama::Template;
2490 use futures::{
2491- future::{self, Either},
2492- Future, IntoFuture, Stream,
2493+ future::{self, BoxFuture},
2494+ stream::TryStreamExt,
2495 };
2496 use http::{self, header, StatusCode, Uri};
2497- use hyper::{self, service::Service, Chunk, Method, Request, Response};
2498+ use hyper::{self, service::Service, Body, Method, Request, Response};
2499+ use serde::{Deserialize, Serialize};
2500
2501 use crate::error::Error;
2502- use crate::hyperext::{into_request, Body, IntoResponse, RequestExt};
2503+ use crate::hyperext::RequestExt;
2504 use crate::lfs;
2505 use crate::storage::{LFSObject, Namespace, Storage, StorageKey};
2506
2507+ async fn from_json<T>(mut body: Body) -> Result<T, Error>
2508+ where
2509+ T: for<'de> Deserialize<'de>,
2510+ {
2511+ let mut buf = Vec::new();
2512+
2513+ while let Some(chunk) = body.try_next().await? {
2514+ buf.extend(chunk);
2515+ }
2516+
2517+ Ok(serde_json::from_slice(&buf)?)
2518+ }
2519+
2520+ fn into_json<T>(value: &T) -> Result<Body, Error>
2521+ where
2522+ T: Serialize,
2523+ {
2524+ let bytes = serde_json::to_vec_pretty(value)?;
2525+ Ok(bytes.into())
2526+ }
2527+
2528 #[derive(Template)]
2529 #[template(path = "index.html")]
2530 struct IndexTemplate<'a> {
2531 @@ -41,21 +64,9 @@ struct IndexTemplate<'a> {
2532 api: Uri,
2533 }
2534
2535- /// Shared state for all instances of the `App` service.
2536- pub struct State<S> {
2537- // Storage backend.
2538- storage: S,
2539- }
2540-
2541- impl<S> State<S> {
2542- pub fn new(storage: S) -> Self {
2543- State { storage }
2544- }
2545- }
2546-
2547 #[derive(Clone)]
2548 pub struct App<S> {
2549- state: Arc<State<S>>,
2550+ storage: S,
2551 }
2552
2553 impl<S> App<S>
2554 @@ -64,12 +75,12 @@ where
2555 S::Error: Into<Error> + 'static,
2556 Error: From<S::Error>,
2557 {
2558- pub fn new(state: Arc<State<S>>) -> Self {
2559- App { state }
2560+ pub fn new(storage: S) -> Self {
2561+ App { storage }
2562 }
2563
2564 /// Handles the index route.
2565- fn index(&mut self, req: Request<Body>) -> Result<Response<Body>, Error> {
2566+ fn index(req: Request<Body>) -> Result<Response<Body>, Error> {
2567 let template = IndexTemplate {
2568 title: "Rudolfs",
2569 api: req.base_uri().path_and_query("/api").build().unwrap(),
2570 @@ -81,20 +92,17 @@ where
2571 }
2572
2573 /// Generates a "404 not found" response.
2574- fn not_found(
2575- &mut self,
2576- _req: Request<Body>,
2577- ) -> Result<Response<Body>, Error> {
2578+ fn not_found(_req: Request<Body>) -> Result<Response<Body>, Error> {
2579 Ok(Response::builder()
2580 .status(StatusCode::NOT_FOUND)
2581 .body("Not found".into())?)
2582 }
2583
2584 /// Handles `/api` routes.
2585- fn api(
2586- &mut self,
2587+ async fn api(
2588+ storage: S,
2589 req: Request<Body>,
2590- ) -> impl Future<Item = Response<Body>, Error = Error> {
2591+ ) -> Result<Response<Body>, Error> {
2592 let mut parts = req.uri().path().split('/').filter(|s| !s.is_empty());
2593
2594 // Skip over the '/api' part.
2595 @@ -106,11 +114,9 @@ where
2596 Namespace::new(org.into(), project.into())
2597 }
2598 _ => {
2599- return Response::builder()
2600+ return Ok(Response::builder()
2601 .status(StatusCode::BAD_REQUEST)
2602- .body(Body::from("Missing org/project in URL"))
2603- .map_err(Into::into)
2604- .response();
2605+ .body(Body::from("Missing org/project in URL"))?)
2606 }
2607 };
2608
2609 @@ -121,69 +127,58 @@ where
2610 let oid = match oid {
2611 Some(oid) => oid,
2612 None => {
2613- return Response::builder()
2614+ return Ok(Response::builder()
2615 .status(StatusCode::BAD_REQUEST)
2616- .body(Body::from("Missing OID parameter."))
2617- .map_err(Into::into)
2618- .response();
2619+ .body(Body::from("Missing OID parameter."))?)
2620 }
2621 };
2622
2623 let key = StorageKey::new(namespace, oid);
2624
2625 match *req.method() {
2626- Method::GET => self.download(req, key).response(),
2627- Method::PUT => self.upload(req, key).response(),
2628- _ => self.not_found(req).response(),
2629+ Method::GET => Self::download(storage, req, key).await,
2630+ Method::PUT => Self::upload(storage, req, key).await,
2631+ _ => Self::not_found(req),
2632 }
2633 }
2634 Some("objects") => match (req.method(), parts.next()) {
2635 (&Method::POST, Some("batch")) => {
2636- self.batch(req, namespace).response()
2637+ Self::batch(storage, req, namespace).await
2638 }
2639 (&Method::POST, Some("verify")) => {
2640- self.verify(req, namespace).response()
2641+ Self::verify(storage, req, namespace).await
2642 }
2643- _ => self.not_found(req).response(),
2644+ _ => Self::not_found(req),
2645 },
2646- _ => self.not_found(req).response(),
2647+ _ => Self::not_found(req),
2648 }
2649 }
2650
2651 /// Downloads a single LFS object.
2652- fn download(
2653- &mut self,
2654+ async fn download(
2655+ storage: S,
2656 _req: Request<Body>,
2657 key: StorageKey,
2658- ) -> impl Future<Item = Response<Body>, Error = Error> {
2659- self.state.storage.get(&key).from_err::<Error>().and_then(
2660- move |object| -> Result<_, Error> {
2661- if let Some(object) = object {
2662- Response::builder()
2663- .status(StatusCode::OK)
2664- .header(
2665- header::CONTENT_TYPE,
2666- "application/octet-stream",
2667- )
2668- .header(header::CONTENT_LENGTH, object.len())
2669- .body(Body::wrap_stream(object.stream()))
2670- .map_err(Into::into)
2671- } else {
2672- Response::builder()
2673- .status(StatusCode::NOT_FOUND)
2674- .body(Body::empty())
2675- .map_err(Into::into)
2676- }
2677- },
2678- )
2679+ ) -> Result<Response<Body>, Error> {
2680+ if let Some(object) = storage.get(&key).await? {
2681+ Ok(Response::builder()
2682+ .status(StatusCode::OK)
2683+ .header(header::CONTENT_TYPE, "application/octet-stream")
2684+ .header(header::CONTENT_LENGTH, object.len())
2685+ .body(Body::wrap_stream(object.stream()))?)
2686+ } else {
2687+ Ok(Response::builder()
2688+ .status(StatusCode::NOT_FOUND)
2689+ .body(Body::empty())?)
2690+ }
2691 }
2692
2693 /// Uploads a single LFS object.
2694- fn upload(
2695- &mut self,
2696+ async fn upload(
2697+ storage: S,
2698 req: Request<Body>,
2699 key: StorageKey,
2700- ) -> <Self as Service>::Future {
2701+ ) -> Result<Response<Body>, Error> {
2702 let len = req
2703 .headers()
2704 .get("Content-Length")
2705 @@ -193,150 +188,105 @@ where
2706 let len = match len {
2707 Some(len) => len,
2708 None => {
2709- return Box::new(
2710- Response::builder()
2711- .status(StatusCode::BAD_REQUEST)
2712- .body(Body::from("Invalid Content-Length header."))
2713- .map_err(Into::into)
2714- .into_future(),
2715- );
2716+ return Response::builder()
2717+ .status(StatusCode::BAD_REQUEST)
2718+ .body(Body::from("Invalid Content-Length header."))
2719+ .map_err(Into::into);
2720 }
2721 };
2722
2723 // Verify the SHA256 of the uploaded object as it is being uploaded.
2724 let stream = req
2725 .into_body()
2726- .map(Chunk::into_bytes)
2727- .from_err::<Error>()
2728 .map_err(|e| io::Error::new(io::ErrorKind::Other, e));
2729
2730- let object = LFSObject::new(len, Box::new(stream));
2731-
2732- Box::new(
2733- self.state
2734- .storage
2735- .put(key, object)
2736- .from_err::<Error>()
2737- .and_then(|_| {
2738- Response::builder()
2739- .status(StatusCode::OK)
2740- .body(Body::empty())
2741- .map_err(Into::into)
2742- }),
2743- )
2744+ let object = LFSObject::new(len, Box::pin(stream));
2745+
2746+ storage.put(key, object).await?;
2747+
2748+ Ok(Response::builder()
2749+ .status(StatusCode::OK)
2750+ .body(Body::empty())?)
2751 }
2752
2753 /// Verifies that an LFS object exists on the server.
2754- fn verify(
2755- &mut self,
2756+ async fn verify(
2757+ storage: S,
2758 req: Request<Body>,
2759 namespace: Namespace,
2760- ) -> impl Future<Item = Response<Body>, Error = Error> {
2761- let state = self.state.clone();
2762-
2763- req.into_body()
2764- .into_json()
2765- .and_then(move |val: lfs::VerifyRequest| {
2766- let key = StorageKey::new(namespace, val.oid);
2767-
2768- state.storage.size(&key).from_err::<Error>().and_then(
2769- move |size| {
2770- if let Some(size) = size {
2771- if size == val.size {
2772- return Response::builder()
2773- .status(StatusCode::OK)
2774- .body(Body::empty())
2775- .map_err(Into::into);
2776- }
2777- }
2778-
2779- // Object doesn't exist or the size is incorrect.
2780- Response::builder()
2781- .status(StatusCode::NOT_FOUND)
2782- .body(Body::empty())
2783- .map_err(Into::into)
2784- },
2785- )
2786- })
2787+ ) -> Result<Response<Body>, Error> {
2788+ let val: lfs::VerifyRequest = from_json(req.into_body()).await?;
2789+ let key = StorageKey::new(namespace, val.oid);
2790+
2791+ if let Some(size) = storage.size(&key).await? {
2792+ if size == val.size {
2793+ return Ok(Response::builder()
2794+ .status(StatusCode::OK)
2795+ .body(Body::empty())?);
2796+ }
2797+ }
2798+
2799+ // Object doesn't exist or the size is incorrect.
2800+ Ok(Response::builder()
2801+ .status(StatusCode::NOT_FOUND)
2802+ .body(Body::empty())?)
2803 }
2804
2805 /// Batch API endpoint for the Git LFS server spec.
2806 ///
2807 /// See also:
2808 /// https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
2809- fn batch(
2810- &mut self,
2811+ async fn batch(
2812+ storage: S,
2813 req: Request<Body>,
2814 namespace: Namespace,
2815- ) -> impl Future<Item = Response<Body>, Error = Error> {
2816+ ) -> Result<Response<Body>, Error> {
2817 // Get the host name and scheme.
2818 let uri = req.base_uri().path_and_query("/").build().unwrap();
2819
2820- let state = self.state.clone();
2821-
2822- req.into_body().into_json().then(
2823- move |result: Result<lfs::BatchRequest, _>| {
2824- match result {
2825- Ok(val) => {
2826- let operation = val.operation;
2827-
2828- // For each object, check if it exists in the storage
2829- // backend.
2830- let objects =
2831- val.objects.into_iter().map(move |object| {
2832- let uri = uri.clone();
2833-
2834- let key = StorageKey::new(
2835- namespace.clone(),
2836- object.oid,
2837- );
2838-
2839- state.storage.size(&key).then(move |size| {
2840- let (namespace, _) = key.into_parts();
2841- Ok(basic_response(
2842- uri, object, operation, size, namespace,
2843- ))
2844- })
2845- });
2846-
2847- Either::A(
2848- future::join_all(objects)
2849- .from_err::<Error>()
2850- .and_then(|objects| {
2851- let response = lfs::BatchResponse {
2852- transfer: Some(lfs::Transfer::Basic),
2853- objects,
2854- };
2855-
2856- Response::builder()
2857- .status(StatusCode::OK)
2858- .header(
2859- header::CONTENT_TYPE,
2860- "application/json",
2861- )
2862- .body(Body::json(&response)?)
2863- .map_err(Into::into)
2864- }),
2865- )
2866- }
2867- Err(err) => {
2868- let response = lfs::BatchResponseError {
2869- message: err.to_string(),
2870- documentation_url: None,
2871- request_id: None,
2872- };
2873-
2874- Either::B(
2875- Response::builder()
2876- .status(StatusCode::BAD_REQUEST)
2877- .body(Body::json(&response).unwrap())
2878- .map_err(Into::into)
2879- .into_future(),
2880- )
2881+ match from_json::<lfs::BatchRequest>(req.into_body()).await {
2882+ Ok(val) => {
2883+ let operation = val.operation;
2884+
2885+ // For each object, check if it exists in the storage
2886+ // backend.
2887+ let objects = val.objects.into_iter().map(|object| {
2888+ let uri = uri.clone();
2889+ let key = StorageKey::new(namespace.clone(), object.oid);
2890+
2891+ async {
2892+ let size = storage.size(&key).await;
2893+
2894+ let (namespace, _) = key.into_parts();
2895+ Ok(basic_response(
2896+ uri, object, operation, size, namespace,
2897+ ))
2898 }
2899- }
2900- },
2901- )
2902+ });
2903+
2904+ let objects = future::try_join_all(objects).await?;
2905+ let response = lfs::BatchResponse {
2906+ transfer: Some(lfs::Transfer::Basic),
2907+ objects,
2908+ };
2909+
2910+ Ok(Response::builder()
2911+ .status(StatusCode::OK)
2912+ .header(header::CONTENT_TYPE, "application/json")
2913+ .body(into_json(&response)?)?)
2914+ }
2915+ Err(err) => {
2916+ let response = lfs::BatchResponseError {
2917+ message: err.to_string(),
2918+ documentation_url: None,
2919+ request_id: None,
2920+ };
2921+
2922+ Ok(Response::builder()
2923+ .status(StatusCode::BAD_REQUEST)
2924+ .body(into_json(&response).unwrap())?)
2925+ }
2926+ }
2927 }
2928 }
2929
2930 @@ -423,7 +373,7 @@ where
2931 authenticated: Some(true),
2932 actions: Some(lfs::Actions {
2933 download: None,
2934- upload: Some(action.clone()),
2935+ upload: Some(action),
2936 verify: Some(lfs::Action {
2937 href: format!(
2938 "{}api/{}/objects/verify",
2939 @@ -467,32 +417,30 @@ where
2940 }
2941 }
2942
2943- impl<S> Service for App<S>
2944+ impl<S> Service<Request<Body>> for App<S>
2945 where
2946- S: Storage + Send + Sync + 'static,
2947+ S: Storage + Clone + Send + Sync + 'static,
2948 S::Error: Into<Error> + 'static,
2949 Error: From<S::Error>,
2950 {
2951- type ReqBody = hyper::Body;
2952- type ResBody = Body;
2953+ type Response = Response<Body>;
2954 type Error = Error;
2955- type Future = Box<dyn Future<Item = Response<Body>, Error = Error> + Send>;
2956+ type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
2957
2958- fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
2959- let req = into_request(req);
2960+ fn poll_ready(
2961+ &mut self,
2962+ _cx: &mut Context,
2963+ ) -> Poll<Result<(), Self::Error>> {
2964+ Poll::Ready(Ok(()))
2965+ }
2966
2967+ fn call(&mut self, req: Request<Body>) -> Self::Future {
2968 if req.uri().path() == "/" {
2969- return self.index(req).response();
2970+ Box::pin(future::ready(Self::index(req)))
2971+ } else if req.uri().path().starts_with("/api/") {
2972+ Box::pin(Self::api(self.storage.clone(), req))
2973+ } else {
2974+ Box::pin(future::ready(Self::not_found(req)))
2975 }
2976-
2977- if req.uri().path().starts_with("/api/") {
2978- return self.api(req).response();
2979- }
2980-
2981- Response::builder()
2982- .status(StatusCode::NOT_FOUND)
2983- .body(Body::empty())
2984- .map_err(Into::into)
2985- .response()
2986 }
2987 }
2988 diff --git a/src/error.rs b/src/error.rs
2989index ee5e27d..23f4229 100644
2990--- a/src/error.rs
2991+++ b/src/error.rs
2992 @@ -19,11 +19,7 @@
2993 // SOFTWARE.
2994 use std::io;
2995
2996- use askama;
2997 use derive_more::{Display, From};
2998- use http;
2999- use hyper;
3000- use serde_json;
3001
3002 use crate::sha256::{Sha256Error, Sha256VerifyError};
3003 use crate::storage::{self, Storage};
3004 diff --git a/src/hyperext.rs b/src/hyperext.rs
3005index c3d3f7c..529998d 100644
3006--- a/src/hyperext.rs
3007+++ b/src/hyperext.rs
3008 @@ -17,171 +17,10 @@
3009 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3010 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3011 // SOFTWARE.
3012- use std::ops::Deref;
3013+ use std::convert::TryFrom;
3014
3015- use derive_more::From;
3016- use futures::{Future, IntoFuture, Poll, Stream};
3017 use http::uri::{self, Authority, Scheme, Uri};
3018- use hyper::{
3019- body::{Payload, Sender},
3020- Body as HBody, Chunk, HeaderMap, Request, Response,
3021- };
3022- use serde::{Deserialize, Serialize};
3023-
3024- use crate::error::Error;
3025-
3026- #[derive(Debug, Default, From)]
3027- pub struct Body(HBody);
3028-
3029- impl Body {
3030- pub fn empty() -> Self {
3031- HBody::empty().into()
3032- }
3033-
3034- #[allow(unused)]
3035- pub fn channel() -> (Sender, Self) {
3036- let (sender, body) = HBody::channel();
3037- (sender, body.into())
3038- }
3039-
3040- /// Deserializes the body as json. Returns a future of the deserialized
3041- /// json.
3042- pub fn into_json<T>(self) -> impl Future<Item = T, Error = Error>
3043- where
3044- T: for<'de> Deserialize<'de>,
3045- {
3046- self.concat2()
3047- .from_err::<Error>()
3048- .and_then(|body| Ok(serde_json::from_slice(&body)?))
3049- .from_err()
3050- }
3051-
3052- /// Serialize a value to JSON.
3053- pub fn json<T>(value: &T) -> Result<Self, Error>
3054- where
3055- T: Serialize,
3056- {
3057- let body: HBody = serde_json::to_vec_pretty(&value)?.into();
3058- Ok(body.into())
3059- }
3060-
3061- pub fn wrap_stream<S>(stream: S) -> Self
3062- where
3063- S: Stream + Send + 'static,
3064- S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
3065- Chunk: From<S::Item>,
3066- {
3067- Body(HBody::wrap_stream(stream))
3068- }
3069- }
3070-
3071- impl Into<HBody> for Body {
3072- fn into(self) -> HBody {
3073- self.0
3074- }
3075- }
3076-
3077- impl From<String> for Body {
3078- fn from(s: String) -> Self {
3079- Body(s.into())
3080- }
3081- }
3082-
3083- impl From<&'static str> for Body {
3084- fn from(slice: &'static str) -> Self {
3085- Body(slice.into())
3086- }
3087- }
3088-
3089- type ChunkedStream = Box<
3090- dyn Stream<
3091- Item = Chunk,
3092- Error = Box<dyn std::error::Error + 'static + Sync + Send>,
3093- >
3094- + 'static
3095- + Send,
3096- >;
3097-
3098- impl From<ChunkedStream> for Body {
3099- fn from(stream: ChunkedStream) -> Self {
3100- Body(stream.into())
3101- }
3102- }
3103-
3104- impl Deref for Body {
3105- type Target = HBody;
3106-
3107- fn deref(&self) -> &Self::Target {
3108- &self.0
3109- }
3110- }
3111-
3112- impl Stream for Body {
3113- type Item = <HBody as Stream>::Item;
3114- type Error = <HBody as Stream>::Error;
3115-
3116- fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
3117- self.0.poll()
3118- }
3119- }
3120-
3121- impl Payload for Body {
3122- type Data = <HBody as Payload>::Data;
3123- type Error = <HBody as Payload>::Error;
3124-
3125- fn poll_data(&mut self) -> Poll<Option<Self::Data>, Self::Error> {
3126- <HBody as Payload>::poll_data(&mut self.0)
3127- }
3128-
3129- fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, Self::Error> {
3130- <HBody as Payload>::poll_trailers(&mut self.0)
3131- }
3132-
3133- fn is_end_stream(&self) -> bool {
3134- <HBody as Payload>::is_end_stream(&self.0)
3135- }
3136-
3137- fn content_length(&self) -> Option<u64> {
3138- <HBody as Payload>::content_length(&self.0)
3139- }
3140- }
3141-
3142- type BoxResponse<T> = Box<dyn Future<Item = Response<T>, Error = Error> + Send>;
3143-
3144- pub trait IntoResponse<T> {
3145- /// Convert something into a response.
3146- fn response(self) -> BoxResponse<T>;
3147- }
3148-
3149- impl<F, T, U> IntoResponse<U> for F
3150- where
3151- F: IntoFuture<Item = Response<T>, Error = Error>,
3152- F::Future: Send + 'static,
3153- T: Into<U>,
3154- {
3155- fn response(self) -> BoxResponse<U> {
3156- Box::new(
3157- self.into_future()
3158- .map(move |r| -> Response<U> { into_response(r) }),
3159- )
3160- }
3161- }
3162-
3163- pub fn into_request<T, U>(req: Request<T>) -> Request<U>
3164- where
3165- T: Into<U>,
3166- {
3167- let (parts, body) = req.into_parts();
3168- Request::from_parts(parts, body.into())
3169- }
3170-
3171- fn into_response<T, U>(res: Response<T>) -> Response<U>
3172- where
3173- T: Into<U>,
3174- {
3175- let (parts, body) = res.into_parts();
3176- Response::from_parts(parts, body.into())
3177- }
3178+ use hyper::Request;
3179
3180 pub trait RequestExt {
3181 /// Gets the scheme based on the headers in the request.
3182 @@ -197,13 +36,12 @@ pub trait RequestExt {
3183 fn authority(&self) -> Option<Authority>;
3184
3185 fn base_uri(&self) -> uri::Builder {
3186- let mut builder = Uri::builder();
3187- builder.scheme(self.scheme().unwrap_or(Scheme::HTTP));
3188- builder.authority(
3189- self.authority()
3190- .unwrap_or_else(|| Authority::from_static("localhost")),
3191- );
3192- builder
3193+ Uri::builder()
3194+ .scheme(self.scheme().unwrap_or(Scheme::HTTP))
3195+ .authority(
3196+ self.authority()
3197+ .unwrap_or_else(|| Authority::from_static("localhost")),
3198+ )
3199 }
3200 }
3201
3202 @@ -212,9 +50,7 @@ impl<B> RequestExt for Request<B> {
3203 self.headers()
3204 .get("X-Forwarded-Proto")
3205 .or_else(|| self.headers().get(":scheme"))
3206- .and_then(|scheme| {
3207- Scheme::from_shared(scheme.as_bytes().into()).ok()
3208- })
3209+ .and_then(|scheme| Scheme::try_from(scheme.as_bytes()).ok())
3210 }
3211
3212 fn authority(&self) -> Option<Authority> {
3213 @@ -222,7 +58,7 @@ impl<B> RequestExt for Request<B> {
3214 .get(":authority")
3215 .or_else(|| self.headers().get("Host"))
3216 .and_then(|authority| {
3217- Authority::from_shared(authority.as_bytes().into()).ok()
3218+ Authority::try_from(authority.as_bytes()).ok()
3219 })
3220 }
3221 }
3222 diff --git a/src/logger.rs b/src/logger.rs
3223index cfb85b3..0aca513 100644
3224--- a/src/logger.rs
3225+++ b/src/logger.rs
3226 @@ -17,14 +17,15 @@
3227 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3228 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3229 // SOFTWARE.
3230+ use core::task::{Context, Poll};
3231+
3232 use std::fmt;
3233 use std::net::SocketAddr;
3234 use std::time::Instant;
3235
3236- use futures::Future;
3237+ use futures::future::{BoxFuture, FutureExt};
3238 use humantime::format_duration;
3239- use hyper::{service::Service, Request, Response};
3240- use log;
3241+ use hyper::{service::Service, Body, Request, Response};
3242
3243 /// Wraps a service to provide logging on both the request and the response.
3244 pub struct Logger<S> {
3245 @@ -41,30 +42,32 @@ impl<S> Logger<S> {
3246 }
3247 }
3248
3249- impl<S> Service for Logger<S>
3250+ impl<S> Service<Request<Body>> for Logger<S>
3251 where
3252- S: Service,
3253+ S: Service<Request<Body>, Response = Response<Body>>,
3254 S::Future: Send + 'static,
3255 S::Error: fmt::Display + Send + 'static,
3256 {
3257- type ReqBody = S::ReqBody;
3258- type ResBody = S::ResBody;
3259+ type Response = S::Response;
3260 type Error = S::Error;
3261- type Future = Box<
3262- dyn Future<Item = Response<Self::ResBody>, Error = Self::Error> + Send,
3263- >;
3264+ type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;
3265+
3266+ fn poll_ready(
3267+ &mut self,
3268+ cx: &mut Context,
3269+ ) -> Poll<Result<(), Self::Error>> {
3270+ self.service.poll_ready(cx)
3271+ }
3272
3273- fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future {
3274+ fn call(&mut self, req: Request<Body>) -> Self::Future {
3275 let method = req.method().clone();
3276 let uri = req.uri().clone();
3277 let remote_addr = self.remote_addr;
3278
3279 let start = Instant::now();
3280
3281- Box::new(self.service.call(req).then(move |response| {
3282- // TODO: Add a duration of how long it took to respond to the
3283- // request.
3284- match &response {
3285+ Box::pin(self.service.call(req).inspect(
3286+ move |response| match response {
3287 Ok(response) => log::info!(
3288 "[{}] {} {} - {} ({})",
3289 remote_addr.ip(),
3290 @@ -81,9 +84,7 @@ where
3291 err,
3292 format_duration(start.elapsed()),
3293 ),
3294- };
3295-
3296- response
3297- }))
3298+ },
3299+ ))
3300 }
3301 }
3302 diff --git a/src/lru.rs b/src/lru.rs
3303index 5744d97..5577086 100644
3304--- a/src/lru.rs
3305+++ b/src/lru.rs
3306 @@ -17,9 +17,11 @@
3307 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3308 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3309 // SOFTWARE.
3310+ use core::marker::Unpin;
3311+
3312 use std::hash::Hash;
3313
3314- use futures::{Future, Stream};
3315+ use futures::stream::{TryStream, TryStreamExt};
3316 use linked_hash_map::LinkedHashMap;
3317
3318 /// A least recently used (LRU) cache.
3319 @@ -54,18 +56,17 @@ where
3320 /// LRU information. Since the server shouldn't be restarted very often,
3321 /// this shouldn't be a problem in practice. Frequently used entries will
3322 /// naturally bubble back up to the top.
3323- pub fn from_stream<S>(
3324- stream: S,
3325- ) -> impl Future<Item = Self, Error = S::Error>
3326+ pub async fn from_stream<S>(mut stream: S) -> Result<Self, S::Error>
3327 where
3328- S: Stream<Item = (K, u64)>,
3329+ S: TryStream<Ok = (K, u64)> + Unpin,
3330 {
3331- stream
3332- .fold(Cache::new(), move |mut cache, (oid, len)| {
3333- cache.push(oid, len);
3334- Ok(cache)
3335- })
3336- .or_else(move |_err| Ok(Cache::new()))
3337+ let mut cache = Cache::new();
3338+
3339+ while let Some((oid, len)) = stream.try_next().await? {
3340+ cache.push(oid, len);
3341+ }
3342+
3343+ Ok(cache)
3344 }
3345
3346 /// Removes the least recently used item. Returns `None` if the cache is
3347 diff --git a/src/main.rs b/src/main.rs
3348index 17f5b29..e7abbdb 100644
3349--- a/src/main.rs
3350+++ b/src/main.rs
3351 @@ -27,19 +27,17 @@ mod sha256;
3352 mod storage;
3353 mod util;
3354
3355+ use std::convert::Infallible;
3356 use std::net::{SocketAddr, ToSocketAddrs};
3357 use std::path::PathBuf;
3358- use std::process::exit;
3359 use std::sync::Arc;
3360
3361- use futures::Future;
3362+ use futures::future::{self, TryFutureExt};
3363 use hex::FromHex;
3364 use hyper::{self, server::conn::AddrStream, service::make_service_fn, Server};
3365- use log;
3366- use pretty_env_logger;
3367 use structopt::StructOpt;
3368
3369- use crate::app::{App, State};
3370+ use crate::app::App;
3371 use crate::error::Error;
3372 use crate::logger::Logger;
3373 use crate::storage::{Cached, Disk, Encrypted, Retrying, Verify, S3};
3374 @@ -57,7 +55,7 @@ struct Args {
3375 #[structopt(long = "cache-dir")]
3376 cache_dir: PathBuf,
3377
3378- /// Logging level to use. By default, uses `info`.
3379+ /// Logging level to use.
3380 #[structopt(long = "log-level", default_value = "info")]
3381 log_level: log::LevelFilter,
3382
3383 @@ -80,7 +78,7 @@ struct Args {
3384 }
3385
3386 impl Args {
3387- fn main(self) -> Result<(), Box<dyn std::error::Error>> {
3388+ async fn main(self) -> Result<(), Box<dyn std::error::Error>> {
3389 // Initialize logging.
3390 let mut logger_builder = pretty_env_logger::formatted_timed_builder();
3391 logger_builder.filter_module("rudolfs", self.log_level);
3392 @@ -105,49 +103,39 @@ impl Args {
3393 self.max_cache_size.into::<human_size::Byte>().value() as u64;
3394 let key = self.key;
3395
3396- let mut rt = tokio::runtime::Runtime::new()?;
3397-
3398 // Initialize our storage backends.
3399 let disk = Disk::new(self.cache_dir).map_err(Error::from);
3400 let s3 = S3::new(self.s3_bucket, self.s3_prefix).map_err(Error::from);
3401- let storage = disk
3402- .join(s3)
3403- .and_then(move |(disk, s3)| {
3404- // Retry certain operations to S3 to make it more reliable.
3405- let s3 = Retrying::new(s3);
3406-
3407- // Add a little instability for testing purposes.
3408- #[cfg(feature = "faulty")]
3409- let s3 = Faulty::new(s3);
3410- #[cfg(feature = "faulty")]
3411- let disk = Faulty::new(disk);
3412-
3413- // Use the disk as a cache.
3414- Cached::new(max_cache_size, disk, s3).from_err()
3415- })
3416- .map(move |storage| {
3417- // Verify object SHA256s as they are uploaded and downloaded.
3418- Verify::new(Encrypted::new(key, storage))
3419- });
3420
3421 log::info!("Initializing storage...");
3422- let storage = rt.block_on(storage)?;
3423- log::info!("Successfully initialized storage.");
3424+ let (disk, s3) = future::try_join(disk, s3).await?;
3425
3426- // Initialize the shared state.
3427- let state = Arc::new(State::new(storage));
3428+ // Retry certain operations to S3 to make it more reliable.
3429+ let s3 = Retrying::new(s3);
3430
3431- // Create our service factory.
3432- let new_service =
3433- make_service_fn(move |socket: &AddrStream| -> Result<_, Error> {
3434- // Create our app.
3435- let service = App::new(state.clone());
3436+ // Add a little instability for testing purposes.
3437+ #[cfg(feature = "faulty")]
3438+ let s3 = Faulty::new(s3);
3439+ #[cfg(feature = "faulty")]
3440+ let disk = Faulty::new(disk);
3441+
3442+ // Use the disk as a cache.
3443+ let storage = Cached::new(max_cache_size, disk, s3).await?;
3444
3445- // Add logging middleware
3446- let service = Logger::new(socket.remote_addr(), service);
3447+ // Encrypt/decrypt and verify all incoming and outgoing data.
3448+ let storage = Arc::new(Verify::new(Encrypted::new(key, storage)));
3449+
3450+ // Create our service factory.
3451+ let new_service = make_service_fn(move |socket: &AddrStream| {
3452+ // Create our app.
3453+ let service = App::new(storage.clone());
3454
3455- Ok(service)
3456- });
3457+ // Add logging middleware
3458+ future::ok::<_, Infallible>(Logger::new(
3459+ socket.remote_addr(),
3460+ service,
3461+ ))
3462+ });
3463
3464 // Create the server.
3465 let server = Server::bind(&addr).serve(new_service);
3466 @@ -155,19 +143,20 @@ impl Args {
3467 log::info!("Listening on {}", server.local_addr());
3468
3469 // Run the server.
3470- rt.block_on_all(server)?;
3471+ server.await?;
3472
3473 Ok(())
3474 }
3475 }
3476
3477- fn main() {
3478- let exit_code = if let Err(err) = Args::from_args().main() {
3479+ #[tokio::main]
3480+ async fn main() {
3481+ let exit_code = if let Err(err) = Args::from_args().main().await {
3482 log::error!("{}", err);
3483 1
3484 } else {
3485 0
3486 };
3487
3488- exit(exit_code);
3489+ std::process::exit(exit_code);
3490 }
3491 diff --git a/src/sha256.rs b/src/sha256.rs
3492index 506651d..f46de9a 100644
3493--- a/src/sha256.rs
3494+++ b/src/sha256.rs
3495 @@ -17,11 +17,14 @@
3496 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3497 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3498 // SOFTWARE.
3499+ use core::pin::Pin;
3500+ use core::task::{Context, Poll};
3501+
3502 use std::fmt;
3503 use std::ops;
3504 use std::str::FromStr;
3505
3506- use futures::{try_ready, Async, Poll, Stream};
3507+ use futures::{ready, Stream};
3508 use hex::{FromHex, FromHexError, ToHex};
3509 use serde::{
3510 de::{self, Deserializer, Visitor},
3511 @@ -267,12 +270,7 @@ pub struct VerifyStream<S> {
3512 hasher: sha2::Sha256,
3513 }
3514
3515- impl<S> VerifyStream<S>
3516- where
3517- S: Stream,
3518- S::Item: AsRef<[u8]>,
3519- S::Error: From<Sha256VerifyError>,
3520- {
3521+ impl<S> VerifyStream<S> {
3522 pub fn new(stream: S, total: u64, expected: Sha256) -> Self {
3523 VerifyStream {
3524 stream,
3525 @@ -284,45 +282,48 @@ where
3526 }
3527 }
3528
3529- impl<S> Stream for VerifyStream<S>
3530+ impl<S, T, E> Stream for VerifyStream<S>
3531 where
3532- S: Stream,
3533- S::Item: AsRef<[u8]>,
3534- S::Error: From<Sha256VerifyError>,
3535+ S: Stream<Item = Result<T, E>> + Unpin,
3536+ T: AsRef<[u8]>,
3537+ E: From<Sha256VerifyError>,
3538 {
3539 type Item = S::Item;
3540- type Error = S::Error;
3541-
3542- fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
3543- let bytes = try_ready!(self.stream.poll());
3544
3545- match bytes {
3546- Some(bytes) => {
3547- self.len += bytes.as_ref().len() as u64;
3548-
3549- // Continuously hash the bytes as we receive them.
3550- self.hasher.update(bytes.as_ref());
3551-
3552- if self.len >= self.total {
3553- // This is the last chunk in the stream. Verify that the
3554- // digest matches.
3555- let found = Sha256::from(self.hasher.finalize_reset());
3556-
3557- if found == self.expected {
3558- Ok(Async::Ready(Some(bytes)))
3559+ fn poll_next(
3560+ mut self: Pin<&mut Self>,
3561+ cx: &mut Context,
3562+ ) -> Poll<Option<Self::Item>> {
3563+ match ready!(Stream::poll_next(Pin::new(&mut self.stream), cx)) {
3564+ Some(bytes) => match bytes {
3565+ Ok(bytes) => {
3566+ self.len += bytes.as_ref().len() as u64;
3567+
3568+ // Continuously hash the bytes as we receive them.
3569+ self.hasher.update(bytes.as_ref());
3570+
3571+ if self.len >= self.total {
3572+ // This is the last chunk in the stream. Verify that the
3573+ // digest matches.
3574+ let found = Sha256::from(self.hasher.finalize_reset());
3575+
3576+ if found == self.expected {
3577+ Poll::Ready(Some(Ok(bytes)))
3578+ } else {
3579+ Poll::Ready(Some(Err(E::from(Sha256VerifyError {
3580+ found,
3581+ expected: self.expected,
3582+ }))))
3583+ }
3584 } else {
3585- Err(Self::Error::from(Sha256VerifyError {
3586- found,
3587- expected: self.expected,
3588- }))
3589+ Poll::Ready(Some(Ok(bytes)))
3590 }
3591- } else {
3592- Ok(Async::Ready(Some(bytes)))
3593 }
3594- }
3595+ Err(err) => Poll::Ready(Some(Err(err))),
3596+ },
3597 None => {
3598 // End of stream.
3599- Ok(Async::Ready(None))
3600+ Poll::Ready(None)
3601 }
3602 }
3603 }
3604 diff --git a/src/storage/cached.rs b/src/storage/cached.rs
3605index fec2572..ecc76ce 100644
3606--- a/src/storage/cached.rs
3607+++ b/src/storage/cached.rs
3608 @@ -19,20 +19,21 @@
3609 // SOFTWARE.
3610 use std::fmt;
3611 use std::io;
3612- use std::sync::{Arc, Mutex};
3613+ use std::sync::Arc;
3614
3615+ use async_trait::async_trait;
3616 use bytes::Bytes;
3617 use futures::{
3618- future::{self, Either},
3619- stream,
3620- sync::oneshot,
3621- Future, Stream,
3622+ channel::oneshot,
3623+ future::{self, FutureExt, TryFutureExt},
3624+ stream::{StreamExt, TryStreamExt},
3625+ Future,
3626 };
3627- use tokio;
3628+ use tokio::{self, sync::Mutex};
3629
3630 use crate::lru;
3631
3632- use super::{LFSObject, Storage, StorageFuture, StorageKey, StorageStream};
3633+ use super::{LFSObject, Storage, StorageKey, StorageStream};
3634
3635 type Cache = lru::Cache<StorageKey>;
3636
3637 @@ -94,62 +95,64 @@ pub struct Backend<C, S> {
3638
3639 impl<C, S> Backend<C, S>
3640 where
3641- C: Storage,
3642+ C: Storage + Send + Sync,
3643 S: Storage,
3644 {
3645- pub fn new(
3646+ pub async fn new(
3647 max_size: u64,
3648 cache: C,
3649 storage: S,
3650- ) -> impl Future<Item = Self, Error = C::Error> {
3651- Cache::from_stream(cache.list()).and_then(move |mut lru| {
3652- let cache = Arc::new(cache);
3653-
3654- // Prune the cache. The maximum size setting may have changed
3655- // between server invocations. Thus, prune it down right away
3656- // instead of waiting for a client to do an upload.
3657- prune_cache(&mut lru, max_size, cache.clone()).map(move |count| {
3658- if count > 0 {
3659- log::info!("Pruned {} entries from the cache", count);
3660- }
3661+ ) -> Result<Self, C::Error> {
3662+ let lru = Arc::new(Mutex::new(Cache::from_stream(cache.list()).await?));
3663
3664- Backend {
3665- lru: Arc::new(Mutex::new(lru)),
3666- max_size,
3667- cache,
3668- storage: Arc::new(storage),
3669- }
3670- })
3671+ let cache = Arc::new(cache);
3672+
3673+ // Prune the cache. The maximum size setting may have changed
3674+ // between server invocations. Thus, prune it down right away
3675+ // instead of waiting for a client to do an upload.
3676+ let count = prune_cache(lru.clone(), max_size, cache.clone()).await?;
3677+
3678+ if count > 0 {
3679+ log::info!("Pruned {} entries from the cache", count);
3680+ }
3681+
3682+ Ok(Backend {
3683+ lru,
3684+ max_size,
3685+ cache,
3686+ storage: Arc::new(storage),
3687 })
3688 }
3689 }
3690
3691 /// Returns a future that prunes the least recently used entries that cause the
3692 /// storage to exceed the given maximum size.
3693- fn prune_cache<S>(
3694- lru: &mut Cache,
3695+ async fn prune_cache<S>(
3696+ lru: Arc<Mutex<Cache>>,
3697 max_size: u64,
3698 storage: Arc<S>,
3699- ) -> impl Future<Item = usize, Error = S::Error>
3700+ ) -> Result<usize, S::Error>
3701 where
3702- S: Storage,
3703+ S: Storage + Send + Sync,
3704 {
3705 if max_size == 0 {
3706 // The cache can have unlimited size.
3707- return Either::A(future::ok(0));
3708+ return Ok(0);
3709 }
3710
3711- let mut to_delete = Vec::new();
3712+ let mut deleted = 0;
3713+
3714+ let mut lru = lru.lock().await;
3715
3716 while lru.size() > max_size {
3717 if let Some((key, _)) = lru.pop() {
3718- to_delete.push(key);
3719+ log::debug!("Pruning '{}' from cache", key);
3720+ let _ = storage.delete(&key).await;
3721+ deleted += 1;
3722 }
3723 }
3724
3725- Either::B(stream::iter_ok(to_delete).fold(0, move |acc, key| {
3726- storage.delete(&key).map(move |()| acc + 1)
3727- }))
3728+ Ok(deleted)
3729 }
3730
3731 fn cache_and_prune<C>(
3732 @@ -158,34 +161,43 @@ fn cache_and_prune<C>(
3733 obj: LFSObject,
3734 lru: Arc<Mutex<Cache>>,
3735 max_size: u64,
3736- ) -> impl Future<Item = (), Error = C::Error>
3737+ ) -> impl Future<Output = Result<(), C::Error>>
3738 where
3739- C: Storage,
3740+ C: Storage + Send + Sync,
3741 {
3742- let len = obj.len();
3743+ async move {
3744+ let len = obj.len();
3745
3746- let oid = *key.oid();
3747+ let oid = *key.oid();
3748
3749- cache
3750- .put(key.clone(), obj)
3751- .and_then(move |()| {
3752- // Add the object info to our LRU cache once the download from
3753- // permanent storage is complete.
3754- let mut lru = lru.lock().unwrap();
3755+ log::debug!("Caching {}", oid);
3756+ cache.put(key.clone(), obj).await?;
3757+ log::debug!("Finished caching {}", oid);
3758+
3759+ // Add the object info to our LRU cache once the download from
3760+ // permanent storage is complete.
3761+ {
3762+ let mut lru = lru.lock().await;
3763 lru.push(key, len);
3764+ }
3765
3766- prune_cache(&mut lru, max_size, cache).map(move |count| {
3767+ match prune_cache(lru, max_size, cache).await {
3768+ Ok(count) => {
3769 if count > 0 {
3770 log::info!("Pruned {} entries from the cache", count);
3771 }
3772- })
3773- })
3774- .map_err(move |err| {
3775- log::error!("Error caching {} ({})", oid, err);
3776- err
3777- })
3778+
3779+ Ok(())
3780+ }
3781+ Err(err) => {
3782+ log::error!("Error caching {} ({})", oid, err);
3783+ Err(err)
3784+ }
3785+ }
3786+ }
3787 }
3788
3789+ #[async_trait]
3790 impl<C, S> Storage for Backend<C, S>
3791 where
3792 S: Storage + Send + Sync + 'static,
3793 @@ -197,111 +209,84 @@ where
3794
3795 /// Tries to query the cache first. If that fails, falls back to the
3796 /// permanent storage backend.
3797- fn get(
3798+ async fn get(
3799 &self,
3800 key: &StorageKey,
3801- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
3802+ ) -> Result<Option<LFSObject>, Self::Error> {
3803 // TODO: Keep stats on cache hits and misses. We can then display those
3804 // stats on a web page or send them to another service such as
3805 // Prometheus.
3806- if let Ok(mut lru) = self.lru.lock() {
3807- if lru.get_refresh(key).is_some() {
3808- // Cache hit!
3809- let storage = self.storage.clone();
3810- let lru2 = self.lru.clone();
3811-
3812- let key = key.clone();
3813-
3814- return Box::new(
3815- self.cache.get(&key).map_err(Error::from_cache).and_then(
3816- move |obj| match obj {
3817- Some(obj) => Either::A(future::ok(Some(obj))),
3818- None => {
3819- // If the cache doesn't actually have it, delete
3820- // the entry from our LRU. This can happen if
3821- // the cache is cleared out manually.
3822- let mut lru = lru2.lock().unwrap();
3823- lru.remove(&key);
3824-
3825- // Fall back to permanent storage. Note that
3826- // this won't actually cache the object. This
3827- // will be done next time the same object is
3828- // requested.
3829- Either::B(
3830- storage
3831- .get(&key)
3832- .map_err(Error::from_storage),
3833- )
3834- }
3835- },
3836- ),
3837- );
3838- }
3839+ if self.lru.lock().await.get_refresh(key).is_some() {
3840+ // Cache hit! (Probably)
3841+ let obj = self.cache.get(&key).await.map_err(Error::from_cache)?;
3842+
3843+ return match obj {
3844+ Some(obj) => Ok(Some(obj)),
3845+ None => {
3846+ // If the cache doesn't actually have it, delete the entry
3847+ // from our LRU. This can happen if the cache is cleared out
3848+ // manually.
3849+ let mut lru = self.lru.lock().await;
3850+ lru.remove(&key);
3851+
3852+ // Fall back to permanent storage. Note that this won't
3853+ // actually cache the object. This will be done next time
3854+ // the same object is requested.
3855+ self.storage.get(&key).await.map_err(Error::from_storage)
3856+ }
3857+ };
3858 }
3859
3860 // Cache miss. Get the object from permanent storage. If successful, we
3861- // to cache the resulting byte stream.
3862+ // need to cache the resulting byte stream.
3863 let lru = self.lru.clone();
3864 let max_size = self.max_size;
3865 let cache = self.cache.clone();
3866 let key = key.clone();
3867
3868- Box::new(
3869- self.storage
3870- .get(&key)
3871- .map_err(Error::from_storage)
3872- .and_then(move |obj| match obj {
3873- Some(obj) => {
3874- // Cache the returned LFS object.
3875- let (f, a, b) = obj.fanout();
3876-
3877- // Cache the object in the background. Whether or not
3878- // this succeeds shouldn't prevent the client from
3879- // getting the LFS object. For example, even if we run
3880- // out of disk space, the server should still continue
3881- // operating.
3882- let cache = cache_and_prune(
3883- cache,
3884- key.clone(),
3885- b,
3886- lru,
3887- max_size,
3888- )
3889+ let obj = self.storage.get(&key).await.map_err(Error::from_storage)?;
3890+
3891+ match obj {
3892+ Some(obj) => {
3893+ // Cache the returned LFS object.
3894+ let (f, a, b) = obj.fanout();
3895+
3896+ // Cache the object in the background. Whether or not this
3897+ // succeeds shouldn't prevent the client from getting the LFS
3898+ // object. For example, even if we run out of disk space, the
3899+ // server should still continue operating.
3900+ let cache =
3901+ cache_and_prune(cache, key.clone(), b, lru, max_size)
3902 .map_err(Error::from_cache);
3903
3904- tokio::spawn(
3905- f.map_err(Error::from_stream)
3906- .join(cache)
3907- .map(|((), ())| ())
3908- .map_err(move |err: Self::Error| {
3909- log::error!(
3910- "Error caching {} ({})",
3911- key,
3912- err
3913- );
3914- }),
3915- );
3916-
3917- // Send the object from permanent-storage.
3918- Either::A(future::ok(Some(a)))
3919- }
3920- None => {
3921- // The permanent storage also doesn't have it.
3922- //
3923- // Note that we cannot cache the non-existence of an
3924- // object because the storage backend might be shared by
3925- // multiple caches.
3926- Either::B(future::ok(None))
3927- }
3928- }),
3929- )
3930+ tokio::spawn(
3931+ future::try_join(f.map_err(Error::from_stream), cache)
3932+ .map_ok(|((), ())| ())
3933+ .map_err(move |err: Self::Error| {
3934+ log::error!("Error caching {} ({})", key, err);
3935+ }),
3936+ );
3937+
3938+ // Send the object from permanent-storage.
3939+ Ok(Some(a))
3940+ }
3941+ None => {
3942+ // The permanent storage also doesn't have it.
3943+ //
3944+ // Note that we cannot cache the non-existence of an object
3945+ // because the storage backend can be manipulated independently
3946+ // of the cache. There can also be multiple instances of caches
3947+ // per storage backend.
3948+ Ok(None)
3949+ }
3950+ }
3951 }
3952
3953- fn put(
3954+ async fn put(
3955 &self,
3956 key: StorageKey,
3957 value: LFSObject,
3958- ) -> StorageFuture<(), Self::Error> {
3959+ ) -> Result<(), Self::Error> {
3960 let lru = self.lru.clone();
3961 let max_size = self.max_size;
3962 let cache = self.cache.clone();
3963 @@ -320,8 +305,9 @@ where
3964 let store = self
3965 .storage
3966 .put(key.clone(), a)
3967- .map(move |()| {
3968+ .map_ok(move |()| {
3969 // Send a signal to the cache so that it can complete its write.
3970+ log::debug!("Received last chunk from server.");
3971 signal_sender.send(()).unwrap_or(())
3972 })
3973 .map_err(Error::from_storage);
3974 @@ -329,11 +315,11 @@ where
3975 let (len, stream) = b.into_parts();
3976
3977 // Add an empty chunk to the end of the stream whose only job is to
3978- // complete when it receives a signal that the upload completed to
3979- // permanent storage.
3980+ // complete when it receives a signal that the upload to permanent
3981+ // storage has completed.
3982 let stream = stream.chain(
3983 signal_receiver
3984- .map(|()| Bytes::new())
3985+ .map_ok(|()| Bytes::new())
3986 .map_err(|e| io::Error::new(io::ErrorKind::Other, e))
3987 .into_stream(),
3988 );
3989 @@ -341,58 +327,53 @@ where
3990 let cache = cache_and_prune(
3991 cache,
3992 key,
3993- LFSObject::new(len, Box::new(stream)),
3994+ LFSObject::new(len, Box::pin(stream)),
3995 lru,
3996 max_size,
3997 )
3998 .map_err(Error::from_cache);
3999
4000- Box::new(
4001- f.map_err(Error::from_stream)
4002- .join3(cache, store)
4003- .map(|(_, (), ())| ()),
4004- )
4005+ future::try_join3(f.map_err(Error::from_stream), cache, store).await?;
4006+
4007+ Ok(())
4008 }
4009
4010- fn size(
4011- &self,
4012- key: &StorageKey,
4013- ) -> StorageFuture<Option<u64>, Self::Error> {
4014+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
4015 // Get just the size of an object without perturbing the LRU ordering.
4016 // Only downloads or uploads need to perturb the LRU ordering.
4017- let lru = self.lru.lock().unwrap();
4018+ let lru = self.lru.lock().await;
4019 if let Some(size) = lru.get(key) {
4020 // Cache hit!
4021- Box::new(future::ok(Some(size)))
4022+ Ok(Some(size))
4023 } else {
4024 // Cache miss. Check permanent storage.
4025- Box::new(self.storage.size(key).map_err(Error::from_storage))
4026+ self.storage.size(key).await.map_err(Error::from_storage)
4027 }
4028 }
4029
4030 /// Deletes an item from the cache (not from permanent storage).
4031- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error> {
4032+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error> {
4033 // Only ever delete items from the cache. This may be called when
4034 // a corrupted object is detected.
4035- Box::new(self.cache.delete(key).map_err(Error::from_cache))
4036+ log::info!("Deleted {} from the cache", key);
4037+ self.cache.delete(key).await.map_err(Error::from_cache)
4038 }
4039
4040 /// Returns a stream of cached items.
4041 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error> {
4042 // TODO: Use the LRU instead to get this list.
4043- Box::new(self.cache.list().map_err(Error::from_cache))
4044+ Box::pin(self.cache.list().map_err(Error::from_cache))
4045 }
4046
4047 /// Returns the total size of the LRU cache (not the total size of the
4048 /// permanent storage).
4049- fn total_size(&self) -> Option<u64> {
4050- let lru = self.lru.lock().unwrap();
4051- Some(lru.size())
4052+ async fn total_size(&self) -> Option<u64> {
4053+ Some(self.lru.lock().await.size())
4054 }
4055
4056 /// Returns the maximum size of the LRU cache (not the maximum size of the
4057 /// permanent storage).
4058- fn max_size(&self) -> Option<u64> {
4059+ async fn max_size(&self) -> Option<u64> {
4060 if self.max_size == 0 {
4061 None
4062 } else {
4063 diff --git a/src/storage/disk.rs b/src/storage/disk.rs
4064index 9b24387..a6b3ae6 100644
4065--- a/src/storage/disk.rs
4066+++ b/src/storage/disk.rs
4067 @@ -18,25 +18,22 @@
4068 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4069 // SOFTWARE.
4070 use std::ffi::OsStr;
4071+ use std::fs::Metadata;
4072 use std::io;
4073 use std::path::PathBuf;
4074 use std::str::FromStr;
4075
4076+ use async_trait::async_trait;
4077 use bytes::{BufMut, Bytes, BytesMut};
4078 use futures::{
4079- future::{self, Either},
4080- Future, Stream,
4081- };
4082- use tokio::{
4083- self,
4084- codec::{Decoder, Encoder, Framed},
4085- fs,
4086+ future::{self, TryFutureExt},
4087+ stream::{StreamExt, TryStreamExt},
4088 };
4089+ use tokio::{self, fs};
4090+ use tokio_util::codec::{Decoder, Encoder, Framed};
4091 use uuid::Uuid;
4092
4093- use super::{
4094- LFSObject, Namespace, Storage, StorageFuture, StorageKey, StorageStream,
4095- };
4096+ use super::{LFSObject, Namespace, Storage, StorageKey, StorageStream};
4097 use crate::lfs::Oid;
4098 use crate::util::NamedTempFile;
4099
4100 @@ -45,9 +42,9 @@ pub struct Backend {
4101 }
4102
4103 impl Backend {
4104- pub fn new(root: PathBuf) -> impl Future<Item = Self, Error = io::Error> {
4105- // TODO: Clean out files in the "incomplete" folder.
4106- future::ok(Backend { root })
4107+ pub async fn new(root: PathBuf) -> Result<Self, io::Error> {
4108+ // TODO: Clean out files in the "incomplete" folder?
4109+ Ok(Backend { root })
4110 }
4111
4112 // Use sub directories in order to better utilize the file system's internal
4113 @@ -61,41 +58,38 @@ impl Backend {
4114 }
4115 }
4116
4117+ #[async_trait]
4118 impl Storage for Backend {
4119 type Error = io::Error;
4120
4121- fn get(
4122+ async fn get(
4123 &self,
4124 key: &StorageKey,
4125- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
4126- Box::new(
4127- fs::File::open(self.key_to_path(key))
4128- .and_then(fs::File::metadata)
4129- .then(move |result| {
4130- Ok(match result {
4131- Ok((file, metadata)) => {
4132- let stream = Framed::new(file, BytesCodec::new())
4133- .map(BytesMut::freeze);
4134-
4135- Some(LFSObject::new(
4136- metadata.len(),
4137- Box::new(stream),
4138- ))
4139- }
4140- Err(err) => match err.kind() {
4141- io::ErrorKind::NotFound => None,
4142- _ => return Err(err),
4143- },
4144- })
4145- }),
4146- )
4147+ ) -> Result<Option<LFSObject>, Self::Error> {
4148+ let file = match fs::File::open(self.key_to_path(key)).await {
4149+ Ok(file) => file,
4150+ Err(err) => {
4151+ if err.kind() == io::ErrorKind::NotFound {
4152+ return Ok(None);
4153+ } else {
4154+ return Err(err);
4155+ }
4156+ }
4157+ };
4158+
4159+ let metadata = file.metadata().await?;
4160+
4161+ let stream =
4162+ Framed::new(file, BytesCodec::new()).map_ok(BytesMut::freeze);
4163+
4164+ Ok(Some(LFSObject::new(metadata.len(), Box::pin(stream))))
4165 }
4166
4167- fn put(
4168+ async fn put(
4169 &self,
4170 key: StorageKey,
4171 value: LFSObject,
4172- ) -> StorageFuture<(), Self::Error> {
4173+ ) -> Result<(), Self::Error> {
4174 let path = self.key_to_path(&key);
4175 let dir = path.parent().unwrap().to_path_buf();
4176
4177 @@ -104,67 +98,57 @@ impl Storage for Backend {
4178 let incomplete = self.root.join("incomplete");
4179 let temp_path = incomplete.join(Uuid::new_v4().to_string());
4180
4181- Box::new(
4182- fs::create_dir_all(incomplete)
4183- .and_then(move |()| {
4184- // Note that when this is dropped, the file is deleted.
4185- // Thus, if anything goes wrong we are not left with
4186- // a temporary file laying around.
4187- NamedTempFile::new(temp_path)
4188- })
4189- .and_then(move |file| {
4190- stream.forward(Framed::new(file, BytesCodec::new()))
4191- })
4192- .and_then(move |(_, sink)| {
4193- let written = sink.codec().written();
4194- let file = sink.into_inner();
4195-
4196- if written != len {
4197- // If we didn't get a full object, we cannot save it to
4198- // disk. This can happen if we're using the disk as
4199- // a cache and there is an error in the middle of the
4200- // upload.
4201- Either::A(future::err(io::Error::new(
4202- io::ErrorKind::Other,
4203- "got incomplete object",
4204- )))
4205- } else {
4206- Either::B(
4207- fs::create_dir_all(dir)
4208- .and_then(move |()| file.persist(path))
4209- .map(|_| ()),
4210- )
4211- }
4212- }),
4213- )
4214+ fs::create_dir_all(incomplete).await?;
4215+
4216+ // Note that when this is dropped, the file is deleted. Thus, if
4217+ // anything goes wrong we are not left with a temporary file laying
4218+ // around.
4219+ let file = NamedTempFile::new(temp_path).await?;
4220+
4221+ let mut sink = Framed::new(file, BytesCodec::new());
4222+
4223+ stream.forward(&mut sink).await?;
4224+
4225+ let written = sink.codec().written();
4226+ let file = sink.into_inner();
4227+
4228+ if written != len {
4229+ // If we didn't get a full object, we cannot save it to disk. This
4230+ // can happen if we're using the disk as a cache and there is an
4231+ // error in the middle of the upload.
4232+ Err(io::Error::new(
4233+ io::ErrorKind::Other,
4234+ "got incomplete object",
4235+ ))
4236+ } else {
4237+ fs::create_dir_all(dir).await?;
4238+ file.persist(path).await?;
4239+ Ok(())
4240+ }
4241 }
4242
4243- fn size(
4244- &self,
4245- key: &StorageKey,
4246- ) -> StorageFuture<Option<u64>, Self::Error> {
4247+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
4248 let path = self.key_to_path(key);
4249
4250- Box::new(
4251- fs::metadata(path)
4252- .map(move |metadata| Some(metadata.len()))
4253- .or_else(move |err| match err.kind() {
4254- io::ErrorKind::NotFound => Ok(None),
4255- _ => Err(err),
4256- }),
4257- )
4258+ fs::metadata(path)
4259+ .await
4260+ .map(move |metadata| Some(metadata.len()))
4261+ .or_else(move |err| match err.kind() {
4262+ io::ErrorKind::NotFound => Ok(None),
4263+ _ => Err(err),
4264+ })
4265 }
4266
4267- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error> {
4268+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error> {
4269 // TODO: Attempt to delete the parent folder(s)? This would keep the
4270 // directory tree clean but it could also cause a race condition when
4271 // directories are created during `put` operations.
4272- Box::new(fs::remove_file(self.key_to_path(key)).or_else(move |err| {
4273- match err.kind() {
4274+ fs::remove_file(self.key_to_path(key))
4275+ .await
4276+ .or_else(move |err| match err.kind() {
4277 io::ErrorKind::NotFound => Ok(()),
4278 _ => Err(err),
4279- }
4280- }))
4281+ })
4282 }
4283
4284 /// Lists the objects that are on disk.
4285 @@ -189,41 +173,72 @@ impl Storage for Backend {
4286 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error> {
4287 let path = self.root.join("objects");
4288
4289- Box::new(
4290+ Box::pin(
4291 fs::read_dir(path)
4292- .flatten_stream()
4293- .map(move |entry| fs::read_dir(entry.path()).flatten_stream())
4294- .flatten()
4295- .map(move |entry| fs::read_dir(entry.path()).flatten_stream())
4296- .flatten()
4297- .map(move |entry| fs::read_dir(entry.path()).flatten_stream())
4298- .flatten()
4299- .map(move |entry| fs::read_dir(entry.path()).flatten_stream())
4300- .flatten()
4301- .and_then(move |entry| {
4302- let path = entry.path();
4303- future::poll_fn(move || entry.poll_metadata())
4304- .map(move |metadata| (path, metadata))
4305+ .try_flatten_stream()
4306+ .map_ok(move |entry| {
4307+ fs::read_dir(entry.path()).try_flatten_stream()
4308+ })
4309+ .try_flatten()
4310+ .map_ok(move |entry| {
4311+ fs::read_dir(entry.path()).try_flatten_stream()
4312+ })
4313+ .try_flatten()
4314+ .map_ok(move |entry| {
4315+ fs::read_dir(entry.path()).try_flatten_stream()
4316 })
4317- .filter_map(move |(path, metadata)| {
4318- // Extract the org and project names from the top two path
4319- // components.
4320- let project_path = path.parent()?.parent()?.parent()?;
4321+ .try_flatten()
4322+ .map_ok(move |entry| {
4323+ fs::read_dir(entry.path()).try_flatten_stream()
4324+ })
4325+ .try_flatten()
4326+ .filter(move |entry| {
4327+ // Filter out missing files and directories.
4328+ if let Err(err) = entry {
4329+ if err.kind() == io::ErrorKind::NotFound {
4330+ return future::ready(false);
4331+ }
4332+ }
4333+
4334+ future::ready(true)
4335+ })
4336+ .try_filter_map(move |entry| {
4337+ // Helper function to be able to use the ?-operator on
4338+ // `Option` types.
4339+ fn do_it(
4340+ path: PathBuf,
4341+ metadata: Metadata,
4342+ ) -> Option<(StorageKey, u64)> {
4343+ // Extract the org and project names from the top two
4344+ // path components.
4345+ let project_path = path.parent()?.parent()?.parent()?;
4346
4347- let project = project_path.file_name()?.to_str()?;
4348- let org = project_path.parent()?.file_name()?.to_str()?;
4349+ let project = project_path.file_name()?.to_str()?;
4350+ let org =
4351+ project_path.parent()?.file_name()?.to_str()?;
4352
4353- let namespace = Namespace::new(org.into(), project.into());
4354+ let namespace =
4355+ Namespace::new(org.into(), project.into());
4356
4357- let oid = path
4358- .file_name()
4359- .and_then(OsStr::to_str)
4360- .and_then(|s| Oid::from_str(s).ok())?;
4361+ let oid = path
4362+ .file_name()
4363+ .and_then(OsStr::to_str)
4364+ .and_then(|s| Oid::from_str(s).ok())?;
4365+
4366+ if metadata.is_file() {
4367+ Some((
4368+ StorageKey::new(namespace, oid),
4369+ metadata.len(),
4370+ ))
4371+ } else {
4372+ None
4373+ }
4374+ }
4375
4376- if metadata.is_file() {
4377- Some((StorageKey::new(namespace, oid), metadata.len()))
4378- } else {
4379- None
4380+ async move {
4381+ let path = entry.path();
4382+ let metadata = entry.metadata().await?;
4383+ Ok(do_it(path, metadata))
4384 }
4385 }),
4386 )
4387 @@ -262,8 +277,7 @@ impl Decoder for BytesCodec {
4388 }
4389 }
4390
4391- impl Encoder for BytesCodec {
4392- type Item = Bytes;
4393+ impl Encoder<Bytes> for BytesCodec {
4394 type Error = io::Error;
4395
4396 fn encode(
4397 diff --git a/src/storage/encrypt.rs b/src/storage/encrypt.rs
4398index 3845582..71dd0d5 100644
4399--- a/src/storage/encrypt.rs
4400+++ b/src/storage/encrypt.rs
4401 @@ -20,10 +20,11 @@
4402 use chacha::{ChaCha, KeyStream};
4403 use std::io;
4404
4405+ use async_trait::async_trait;
4406 use bytes::{Bytes, BytesMut};
4407- use futures::{Future, Stream};
4408+ use futures::{stream::StreamExt, Stream};
4409
4410- use super::{LFSObject, Storage, StorageFuture, StorageKey, StorageStream};
4411+ use super::{LFSObject, Storage, StorageKey, StorageStream};
4412
4413 /// A storage adaptor that encrypts/decrypts all data that passes through.
4414 pub struct Backend<S> {
4415 @@ -40,12 +41,12 @@ impl<S> Backend<S> {
4416 fn xor_stream<S>(
4417 mut chacha: ChaCha,
4418 stream: S,
4419- ) -> impl Stream<Item = Bytes, Error = io::Error>
4420+ ) -> impl Stream<Item = Result<Bytes, io::Error>>
4421 where
4422- S: Stream<Item = Bytes, Error = io::Error>,
4423+ S: Stream<Item = Result<Bytes, io::Error>>,
4424 {
4425- stream.and_then(move |bytes| {
4426- let mut bytes = BytesMut::from(bytes);
4427+ stream.map(move |bytes| {
4428+ let mut bytes = BytesMut::from(bytes?.as_ref());
4429
4430 chacha.xor_read(bytes.as_mut()).map_err(|_| {
4431 io::Error::new(
4432 @@ -58,6 +59,7 @@ where
4433 })
4434 }
4435
4436+ #[async_trait]
4437 impl<S> Storage for Backend<S>
4438 where
4439 S: Storage + Send + Sync + 'static,
4440 @@ -65,33 +67,27 @@ where
4441 {
4442 type Error = S::Error;
4443
4444- fn get(
4445+ async fn get(
4446 &self,
4447 key: &StorageKey,
4448- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
4449+ ) -> Result<Option<LFSObject>, Self::Error> {
4450 // Use the first part of the SHA256 as the nonce.
4451 let mut nonce: [u8; 24] = [0; 24];
4452 nonce.copy_from_slice(&key.oid().bytes()[0..24]);
4453
4454 let chacha = ChaCha::new_xchacha20(&self.key, &nonce);
4455
4456- Box::new(self.storage.get(key).and_then(move |obj| match obj {
4457- Some(obj) => {
4458- let (len, stream) = obj.into_parts();
4459- Ok(Some(LFSObject::new(
4460- len,
4461- Box::new(xor_stream(chacha, stream)),
4462- )))
4463- }
4464- None => Ok(None),
4465+ Ok(self.storage.get(key).await?.map(move |obj| {
4466+ let (len, stream) = obj.into_parts();
4467+ LFSObject::new(len, Box::pin(xor_stream(chacha, stream)))
4468 }))
4469 }
4470
4471- fn put(
4472+ async fn put(
4473 &self,
4474 key: StorageKey,
4475 value: LFSObject,
4476- ) -> StorageFuture<(), Self::Error> {
4477+ ) -> Result<(), Self::Error> {
4478 // Use the first part of the SHA256 as the nonce.
4479 let mut nonce: [u8; 24] = [0; 24];
4480 nonce.copy_from_slice(&key.oid().bytes()[0..24]);
4481 @@ -101,29 +97,28 @@ where
4482 let (len, stream) = value.into_parts();
4483 let stream = xor_stream(chacha, stream);
4484
4485- self.storage.put(key, LFSObject::new(len, Box::new(stream)))
4486+ self.storage
4487+ .put(key, LFSObject::new(len, Box::pin(stream)))
4488+ .await
4489 }
4490
4491- fn size(
4492- &self,
4493- key: &StorageKey,
4494- ) -> StorageFuture<Option<u64>, Self::Error> {
4495- self.storage.size(key)
4496+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
4497+ self.storage.size(key).await
4498 }
4499
4500- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error> {
4501- self.storage.delete(key)
4502+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error> {
4503+ self.storage.delete(key).await
4504 }
4505
4506 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error> {
4507 self.storage.list()
4508 }
4509
4510- fn total_size(&self) -> Option<u64> {
4511- self.storage.total_size()
4512+ async fn total_size(&self) -> Option<u64> {
4513+ self.storage.total_size().await
4514 }
4515
4516- fn max_size(&self) -> Option<u64> {
4517- self.storage.max_size()
4518+ async fn max_size(&self) -> Option<u64> {
4519+ self.storage.max_size().await
4520 }
4521 }
4522 diff --git a/src/storage/faulty.rs b/src/storage/faulty.rs
4523index 8f3e5b3..cc56e39 100644
4524--- a/src/storage/faulty.rs
4525+++ b/src/storage/faulty.rs
4526 @@ -19,11 +19,12 @@
4527 // SOFTWARE.
4528 use std::io;
4529
4530+ use async_trait::async_trait;
4531 use derive_more::{Display, From};
4532 use futures::{try_ready, Async, Future, Poll, Stream};
4533 use rand::{self, Rng};
4534
4535- use super::{LFSObject, Storage, StorageFuture, StorageKey, StorageStream};
4536+ use super::{LFSObject, Storage, StorageKey, StorageStream};
4537
4538 #[derive(Debug, Display, From)]
4539 enum Error {
4540 @@ -49,6 +50,7 @@ impl<S> Backend<S> {
4541 }
4542 }
4543
4544+ #[async_trait]
4545 impl<S> Storage for Backend<S>
4546 where
4547 S: Storage + Send + Sync + 'static,
4548 @@ -56,37 +58,34 @@ where
4549 {
4550 type Error = S::Error;
4551
4552- fn get(
4553+ async fn get(
4554 &self,
4555 key: &StorageKey,
4556- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
4557- Box::new(self.storage.get(key).map(move |obj| -> Option<_> {
4558+ ) -> Result<Option<LFSObject>, Self::Error> {
4559+ Box::pin(self.storage.get(key).map(move |obj| -> Option<_> {
4560 let (len, stream) = obj?.into_parts();
4561
4562- Some(LFSObject::new(len, Box::new(FaultyStream::new(stream))))
4563+ Some(LFSObject::new(len, Box::pin(FaultyStream::new(stream))))
4564 }))
4565 }
4566
4567- fn put(
4568+ async fn put(
4569 &self,
4570 key: StorageKey,
4571 value: LFSObject,
4572- ) -> StorageFuture<(), Self::Error> {
4573+ ) -> Result<(), Self::Error> {
4574 let (len, stream) = value.into_parts();
4575
4576 let stream = FaultyStream::new(stream);
4577
4578- self.storage.put(key, LFSObject::new(len, Box::new(stream)))
4579+ self.storage.put(key, LFSObject::new(len, Box::pin(stream)))
4580 }
4581
4582- fn size(
4583- &self,
4584- key: &StorageKey,
4585- ) -> StorageFuture<Option<u64>, Self::Error> {
4586+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
4587 self.storage.size(key)
4588 }
4589
4590- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error> {
4591+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error> {
4592 self.storage.delete(key)
4593 }
4594
4595 @@ -94,12 +93,12 @@ where
4596 self.storage.list()
4597 }
4598
4599- fn total_size(&self) -> Option<u64> {
4600- self.storage.total_size()
4601+ async fn total_size(&self) -> Option<u64> {
4602+ self.storage.total_size().await
4603 }
4604
4605- fn max_size(&self) -> Option<u64> {
4606- self.storage.max_size()
4607+ async fn max_size(&self) -> Option<u64> {
4608+ self.storage.max_size().await
4609 }
4610 }
4611
4612 diff --git a/src/storage/mod.rs b/src/storage/mod.rs
4613index 95c19a9..27039d7 100644
4614--- a/src/storage/mod.rs
4615+++ b/src/storage/mod.rs
4616 @@ -35,24 +35,31 @@ pub use retrying::Backend as Retrying;
4617 pub use s3::{Backend as S3, Error as S3Error};
4618 pub use verify::Backend as Verify;
4619
4620- use std::fmt;
4621+ use crate::lfs::Oid;
4622
4623- use bytes::Bytes;
4624+ use std::fmt;
4625 use std::io;
4626+ use std::pin::Pin;
4627+ use std::sync::Arc;
4628
4629- use crate::lfs::Oid;
4630- use futures::{sync::mpsc, Future, Sink, Stream};
4631+ use async_trait::async_trait;
4632+ use bytes::Bytes;
4633+ use futures::{
4634+ channel::mpsc,
4635+ sink::SinkExt,
4636+ stream::{BoxStream, Stream, StreamExt},
4637+ Future,
4638+ };
4639
4640 pub type S3DiskCache = Cached<Disk, S3>;
4641
4642- /// Future returned by storage operations.
4643- pub type StorageFuture<T, E> = Box<dyn Future<Item = T, Error = E> + Send>;
4644-
4645 /// Stream returned by storage operations.
4646- pub type StorageStream<T, E> = Box<dyn Stream<Item = T, Error = E> + Send>;
4647+ pub type StorageStream<T, E> = BoxStream<'static, Result<T, E>>;
4648
4649 /// The byte stream of an LFS object.
4650- pub type ByteStream = Box<dyn Stream<Item = Bytes, Error = io::Error> + Send>;
4651+ pub type ByteStream = Pin<
4652+ Box<dyn Stream<Item = Result<Bytes, io::Error>> + Send + Sync + 'static>,
4653+ >;
4654
4655 /// A namespace is used to categorize stored LFS objects. The storage
4656 /// implementation is free to ignore this. However, it can be useful when
4657 @@ -70,7 +77,7 @@ impl Namespace {
4658 }
4659
4660 #[allow(unused)]
4661- pub fn split(self) -> (String, String) {
4662+ pub fn into_parts(self) -> (String, String) {
4663 (self.org, self.project)
4664 }
4665
4666 @@ -153,64 +160,60 @@ impl LFSObject {
4667 /// to a client.
4668 pub fn fanout(
4669 self,
4670- ) -> (impl Future<Item = (), Error = io::Error>, Self, Self) {
4671+ ) -> (impl Future<Output = Result<(), io::Error>>, Self, Self) {
4672 let (len, stream) = self.into_parts();
4673
4674- let (sender_a, receiver_a) = mpsc::channel(0);
4675- let (sender_b, receiver_b) = mpsc::channel(0);
4676+ let (sender_a, receiver_a) = mpsc::channel::<Bytes>(0);
4677+ let (sender_b, receiver_b) = mpsc::channel::<Bytes>(0);
4678
4679 let sink = sender_a
4680 .fanout(sender_b)
4681 .sink_map_err(|e| io::Error::new(io::ErrorKind::Other, e));
4682
4683- let receiver_a = receiver_a.map_err(|()| {
4684- io::Error::new(io::ErrorKind::Other, "failed receiving byte stream")
4685- });
4686- let receiver_b = receiver_b.map_err(|()| {
4687- io::Error::new(io::ErrorKind::Other, "failed receiving byte stream")
4688- });
4689+ let receiver_a = receiver_a.map(|x| -> io::Result<_> { Ok(x) });
4690+ let receiver_b = receiver_b.map(|x| -> io::Result<_> { Ok(x) });
4691
4692- let f = stream.forward(sink).map(|_| ());
4693- let a = LFSObject::new(len, Box::new(receiver_a));
4694- let b = LFSObject::new(len, Box::new(receiver_b));
4695+ let f = stream.forward(sink);
4696+ let a = LFSObject::new(len, Box::pin(receiver_a));
4697+ let b = LFSObject::new(len, Box::pin(receiver_b));
4698
4699 (f, a, b)
4700 }
4701 }
4702
4703 /// Trait for abstracting away the storage medium.
4704+ #[async_trait]
4705 pub trait Storage {
4706 type Error: fmt::Display + Send;
4707
4708 /// Gets an entry from the storage medium.
4709- fn get(
4710+ async fn get(
4711 &self,
4712 key: &StorageKey,
4713- ) -> StorageFuture<Option<LFSObject>, Self::Error>;
4714+ ) -> Result<Option<LFSObject>, Self::Error>;
4715
4716 /// Sets an entry in the storage medium.
4717- fn put(
4718+ async fn put(
4719 &self,
4720 key: StorageKey,
4721 value: LFSObject,
4722- ) -> StorageFuture<(), Self::Error>;
4723+ ) -> Result<(), Self::Error>;
4724
4725 /// Gets the size of the object. Returns `None` if the object does not
4726 /// exist.
4727- fn size(&self, key: &StorageKey)
4728- -> StorageFuture<Option<u64>, Self::Error>;
4729+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error>;
4730
4731 /// Deletes an object.
4732 ///
4733 /// Permanent storage backends may choose to never delete objects, always
4734 /// returning success.
4735- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error>;
4736+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error>;
4737
4738 /// Returns a stream of all the object IDs in the storage medium.
4739 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error>;
4740
4741 /// Gets the total size of the storage, if known.
4742- fn total_size(&self) -> Option<u64> {
4743+ async fn total_size(&self) -> Option<u64> {
4744 None
4745 }
4746
4747 @@ -218,52 +221,57 @@ pub trait Storage {
4748 ///
4749 /// This should return `None` if the storage size is unbounded. This is only
4750 /// applicable to caches.
4751- fn max_size(&self) -> Option<u64> {
4752+ async fn max_size(&self) -> Option<u64> {
4753 None
4754 }
4755 }
4756
4757- impl<S> Storage for Box<S>
4758+ #[async_trait]
4759+ impl<S> Storage for Arc<S>
4760 where
4761- S: Storage + ?Sized,
4762+ S: Storage + Send + Sync,
4763 {
4764 type Error = S::Error;
4765
4766- fn get(
4767+ #[inline]
4768+ async fn get(
4769 &self,
4770 key: &StorageKey,
4771- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
4772- (**self).get(key)
4773+ ) -> Result<Option<LFSObject>, Self::Error> {
4774+ self.as_ref().get(key).await
4775 }
4776
4777- fn put(
4778+ #[inline]
4779+ async fn put(
4780 &self,
4781 key: StorageKey,
4782 value: LFSObject,
4783- ) -> StorageFuture<(), Self::Error> {
4784- (**self).put(key, value)
4785+ ) -> Result<(), Self::Error> {
4786+ self.as_ref().put(key, value).await
4787 }
4788
4789- fn size(
4790- &self,
4791- key: &StorageKey,
4792- ) -> StorageFuture<Option<u64>, Self::Error> {
4793- (**self).size(key)
4794+ #[inline]
4795+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
4796+ self.as_ref().size(key).await
4797 }
4798
4799- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error> {
4800- (**self).delete(key)
4801+ #[inline]
4802+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error> {
4803+ self.as_ref().delete(key).await
4804 }
4805
4806+ #[inline]
4807 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error> {
4808- (**self).list()
4809+ self.as_ref().list()
4810 }
4811
4812- fn total_size(&self) -> Option<u64> {
4813- (**self).total_size()
4814+ #[inline]
4815+ async fn total_size(&self) -> Option<u64> {
4816+ self.as_ref().total_size().await
4817 }
4818
4819- fn max_size(&self) -> Option<u64> {
4820- (**self).max_size()
4821+ #[inline]
4822+ async fn max_size(&self) -> Option<u64> {
4823+ self.as_ref().max_size().await
4824 }
4825 }
4826 diff --git a/src/storage/retrying.rs b/src/storage/retrying.rs
4827index 7bd1150..8dd9281 100644
4828--- a/src/storage/retrying.rs
4829+++ b/src/storage/retrying.rs
4830 @@ -19,9 +19,10 @@
4831 // SOFTWARE.
4832 use std::sync::Arc;
4833
4834- use futures_backoff::retry;
4835+ use async_trait::async_trait;
4836+ use backoff::{future::FutureOperation, ExponentialBackoff};
4837
4838- use super::{LFSObject, Storage, StorageFuture, StorageKey, StorageStream};
4839+ use super::{LFSObject, Storage, StorageKey, StorageStream};
4840
4841 /// Implements retries for certain operations.
4842 pub struct Backend<S> {
4843 @@ -36,6 +37,7 @@ impl<S> Backend<S> {
4844 }
4845 }
4846
4847+ #[async_trait]
4848 impl<S> Storage for Backend<S>
4849 where
4850 S: Storage + Send + Sync + 'static,
4851 @@ -43,45 +45,46 @@ where
4852 {
4853 type Error = S::Error;
4854
4855- fn get(
4856+ async fn get(
4857 &self,
4858 key: &StorageKey,
4859- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
4860- self.storage.get(key)
4861+ ) -> Result<Option<LFSObject>, Self::Error> {
4862+ // Due to their streaming nature, this can't be retried by the server.
4863+ // The client should retry this if it fails.
4864+ self.storage.get(key).await
4865 }
4866
4867- fn put(
4868+ async fn put(
4869 &self,
4870 key: StorageKey,
4871 value: LFSObject,
4872- ) -> StorageFuture<(), Self::Error> {
4873- self.storage.put(key, value)
4874+ ) -> Result<(), Self::Error> {
4875+ // Due to their streaming nature, this can't be retried by the server.
4876+ // The client should retry this if it fails.
4877+ self.storage.put(key, value).await
4878 }
4879
4880- fn size(
4881- &self,
4882- key: &StorageKey,
4883- ) -> StorageFuture<Option<u64>, Self::Error> {
4884- let key = key.clone();
4885- let storage = self.storage.clone();
4886- Box::new(retry(move || storage.size(&key)))
4887+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
4888+ (|| async { Ok(self.storage.size(&key).await?) })
4889+ .retry(ExponentialBackoff::default())
4890+ .await
4891 }
4892
4893- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error> {
4894- let key = key.clone();
4895- let storage = self.storage.clone();
4896- Box::new(retry(move || storage.delete(&key)))
4897+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error> {
4898+ (|| async { Ok(self.storage.delete(&key).await?) })
4899+ .retry(ExponentialBackoff::default())
4900+ .await
4901 }
4902
4903 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error> {
4904 self.storage.list()
4905 }
4906
4907- fn total_size(&self) -> Option<u64> {
4908- self.storage.total_size()
4909+ async fn total_size(&self) -> Option<u64> {
4910+ self.storage.total_size().await
4911 }
4912
4913- fn max_size(&self) -> Option<u64> {
4914- self.storage.max_size()
4915+ async fn max_size(&self) -> Option<u64> {
4916+ self.storage.max_size().await
4917 }
4918 }
4919 diff --git a/src/storage/s3.rs b/src/storage/s3.rs
4920index b28bac6..0b79336 100644
4921--- a/src/storage/s3.rs
4922+++ b/src/storage/s3.rs
4923 @@ -17,12 +17,12 @@
4924 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4925 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4926 // SOFTWARE.
4927+ use async_trait::async_trait;
4928+ use backoff::{future::FutureOperation, ExponentialBackoff};
4929 use bytes::Bytes;
4930 use derive_more::{Display, From};
4931- use futures::{future, stream, Future, Stream};
4932- use futures_backoff::retry;
4933+ use futures::{stream, stream::TryStreamExt};
4934 use http::StatusCode;
4935- use log;
4936 use rusoto_core::{Region, RusotoError};
4937 use rusoto_s3::{
4938 GetObjectError, GetObjectRequest, HeadBucketError, HeadBucketRequest,
4939 @@ -30,7 +30,7 @@ use rusoto_s3::{
4940 S3Client, StreamingBody, S3,
4941 };
4942
4943- use super::{LFSObject, Storage, StorageFuture, StorageKey, StorageStream};
4944+ use super::{LFSObject, Storage, StorageKey, StorageStream};
4945
4946 #[derive(Debug, From, Display)]
4947 pub enum Error {
4948 @@ -59,6 +59,20 @@ pub enum InitError {
4949 Other(String),
4950 }
4951
4952+ impl InitError {
4953+ /// Converts the initialization error into an backoff error. Useful for not
4954+ /// retrying certain errors.
4955+ pub fn into_backoff(self) -> backoff::Error<InitError> {
4956+ // Certain types of errors should never be retried.
4957+ match self {
4958+ InitError::Bucket | InitError::Credentials => {
4959+ backoff::Error::Permanent(self)
4960+ }
4961+ _ => backoff::Error::Transient(self),
4962+ }
4963+ }
4964+ }
4965+
4966 impl From<RusotoError<HeadBucketError>> for InitError {
4967 fn from(err: RusotoError<HeadBucketError>) -> Self {
4968 match err {
4969 @@ -96,67 +110,79 @@ pub struct Backend<C = S3Client> {
4970 }
4971
4972 impl Backend {
4973- pub fn new(
4974+ pub async fn new(
4975 bucket: String,
4976 mut prefix: String,
4977- ) -> impl Future<Item = Self, Error = Error> {
4978+ ) -> Result<Self, Error> {
4979 // Ensure the prefix doesn't end with a '/'.
4980 while prefix.ends_with('/') {
4981 prefix.pop();
4982 }
4983
4984- // If a custom endpoint is set, do not use the AWS default (us-east-1)
4985- // instead, check environment variables for a region name.
4986 let region = if let Ok(endpoint) = std::env::var("AWS_S3_ENDPOINT") {
4987- Region::Custom {
4988- name: std::env::var("AWS_DEFAULT_REGION")
4989- .or_else(|_| std::env::var("AWS_REGION"))
4990- .unwrap_or_else(|_| {
4991- log::warn!(
4992- "AWS_S3_ENDPOINT was set without \
4993- AWS_DEFAULT_REGION or AWS_REGION being set. \
4994- Defaulting to 'us-east-1', which probably \
4995- doesn't make sense with a custom endpoint."
4996- );
4997- String::from("us-east-1")
4998- }),
4999- endpoint,
5000- }
5001+ // If a custom endpoint is set, do not use the AWS default
5002+ // (us-east-1). Instead, check environment variables for a region
5003+ // name.
5004+ let name = std::env::var("AWS_DEFAULT_REGION")
5005+ .or_else(|_| std::env::var("AWS_REGION"))
5006+ .map_err(|_| {
5007+ InitError::Other(
5008+ "$AWS_S3_ENDPOINT was set without $AWS_DEFAULT_REGION \
5009+ or $AWS_REGION being set. Custom endpoints don't \
5010+ make sense without also setting a region."
5011+ .into(),
5012+ )
5013+ })?;
5014+
5015+ Region::Custom { name, endpoint }
5016 } else {
5017 Region::default()
5018 };
5019
5020- Backend::with_client(S3Client::new(region), bucket, prefix)
5021+ log::info!(
5022+ "Connecting to S3 bucket '{}' at region '{}'",
5023+ bucket,
5024+ region.name()
5025+ );
5026+
5027+ Backend::with_client(S3Client::new(region), bucket, prefix).await
5028 }
5029 }
5030
5031 impl<C> Backend<C> {
5032- pub fn with_client(
5033+ pub async fn with_client(
5034 client: C,
5035 bucket: String,
5036 prefix: String,
5037- ) -> impl Future<Item = Self, Error = Error>
5038+ ) -> Result<Self, Error>
5039 where
5040 C: S3 + Clone,
5041 {
5042 // Perform a HEAD operation to check that the bucket exists and that
5043- // our credentials work. This helps catch very common
5044- // errors early on application startup.
5045+ // our credentials work. This helps catch very common errors early on
5046+ // in application startup.
5047 let req = HeadBucketRequest {
5048 bucket: bucket.clone(),
5049 };
5050
5051 let c = client.clone();
5052
5053- retry(move || {
5054- c.head_bucket(req.clone()).map_err(|e| {
5055- log::error!("Failed to query S3 bucket ('{}'). Retrying...", e);
5056- e
5057- })
5058+ // We need to retry here so that any fake S3 services have a chance to
5059+ // start up alongside Rudolfs.
5060+ (|| async {
5061+ // Note that we don't retry certain failures, like credential or
5062+ // missing bucket errors. These are unlikely to be transient errors.
5063+ c.head_bucket(req.clone())
5064+ .await
5065+ .map_err(InitError::from)
5066+ .map_err(InitError::into_backoff)
5067 })
5068- .map_err(InitError::from)
5069- .from_err()
5070- .map(move |()| Backend {
5071+ .retry(ExponentialBackoff::default())
5072+ .await?;
5073+
5074+ log::info!("Successfully authorized with AWS");
5075+
5076+ Ok(Backend {
5077 client,
5078 bucket,
5079 prefix,
5080 @@ -168,16 +194,17 @@ impl<C> Backend<C> {
5081 }
5082 }
5083
5084+ #[async_trait]
5085 impl<C> Storage for Backend<C>
5086 where
5087- C: S3,
5088+ C: S3 + Send + Sync,
5089 {
5090 type Error = Error;
5091
5092- fn get(
5093+ async fn get(
5094 &self,
5095 key: &StorageKey,
5096- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
5097+ ) -> Result<Option<LFSObject>, Self::Error> {
5098 let request = GetObjectRequest {
5099 bucket: self.bucket.clone(),
5100 key: self.key_to_path(key),
5101 @@ -185,34 +212,21 @@ where
5102 ..Default::default()
5103 };
5104
5105- Box::new(
5106- self.client
5107- .get_object(request)
5108- .then(move |result| match result {
5109- Ok(object) => Ok(Some(LFSObject::new(
5110- object.content_length.unwrap() as u64,
5111- Box::new(object.body.unwrap().map(Bytes::from)),
5112- ))),
5113- Err(err) => {
5114- if let RusotoError::Service(
5115- GetObjectError::NoSuchKey(_),
5116- ) = &err
5117- {
5118- Ok(None)
5119- } else {
5120- Err(err)
5121- }
5122- }
5123- })
5124- .from_err(),
5125- )
5126+ Ok(match self.client.get_object(request).await {
5127+ Ok(object) => Ok(Some(LFSObject::new(
5128+ object.content_length.unwrap() as u64,
5129+ Box::pin(object.body.unwrap().map_ok(Bytes::from)),
5130+ ))),
5131+ Err(RusotoError::Service(GetObjectError::NoSuchKey(_))) => Ok(None),
5132+ Err(err) => Err(err),
5133+ }?)
5134 }
5135
5136- fn put(
5137+ async fn put(
5138 &self,
5139 key: StorageKey,
5140 value: LFSObject,
5141- ) -> StorageFuture<(), Self::Error> {
5142+ ) -> Result<(), Self::Error> {
5143 let (len, stream) = value.into_parts();
5144
5145 let request = PutObjectRequest {
5146 @@ -223,59 +237,43 @@ where
5147 ..Default::default()
5148 };
5149
5150- Box::new(self.client.put_object(request).map(|_| ()).from_err())
5151+ self.client.put_object(request).await?;
5152+
5153+ Ok(())
5154 }
5155
5156- fn size(
5157- &self,
5158- key: &StorageKey,
5159- ) -> StorageFuture<Option<u64>, Self::Error> {
5160+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
5161 let request = HeadObjectRequest {
5162 bucket: self.bucket.clone(),
5163 key: self.key_to_path(key),
5164 ..Default::default()
5165 };
5166
5167- Box::new(
5168- self.client
5169- .head_object(request)
5170- .then(|result| match result {
5171- Ok(object) => {
5172- Ok(Some(object.content_length.unwrap() as u64))
5173- }
5174- Err(err) => {
5175- match &err {
5176- RusotoError::Unknown(e) => {
5177- // There is a bug in Rusoto that causes it to
5178- // always return an "unknown" error when the key
5179- // does not exist. Thus we must check the error
5180- // code manually. See:
5181- // https://github.com/rusoto/rusoto/issues/716
5182- if e.status == 404 {
5183- Ok(None)
5184- } else {
5185- Err(err)
5186- }
5187- }
5188- RusotoError::Service(
5189- HeadObjectError::NoSuchKey(_),
5190- ) => Ok(None),
5191- _ => Err(err),
5192- }
5193- }
5194- })
5195- .from_err(),
5196- )
5197+ Ok(match self.client.head_object(request).await {
5198+ Ok(object) => Ok(Some(object.content_length.unwrap() as u64)),
5199+ Err(RusotoError::Unknown(e)) if e.status == 404 => {
5200+ // There is a bug in Rusoto that causes it to always return an
5201+ // "unknown" error when the key does not exist. Thus we must
5202+ // check the error code manually.
5203+ //
5204+ // See: https://github.com/rusoto/rusoto/issues/716
5205+ Ok(None)
5206+ }
5207+ Err(RusotoError::Service(HeadObjectError::NoSuchKey(_))) => {
5208+ Ok(None)
5209+ }
5210+ Err(err) => Err(err),
5211+ }?)
5212 }
5213
5214 /// This never deletes objects from S3 and always returns success. This may
5215 /// be changed in the future.
5216- fn delete(&self, _key: &StorageKey) -> StorageFuture<(), Self::Error> {
5217- Box::new(future::ok(()))
5218+ async fn delete(&self, _key: &StorageKey) -> Result<(), Self::Error> {
5219+ Ok(())
5220 }
5221
5222 /// Always returns an empty stream. This may be changed in the future.
5223 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error> {
5224- Box::new(stream::empty())
5225+ Box::pin(stream::empty())
5226 }
5227 }
5228 diff --git a/src/storage/verify.rs b/src/storage/verify.rs
5229index d278c10..4f4e85c 100644
5230--- a/src/storage/verify.rs
5231+++ b/src/storage/verify.rs
5232 @@ -20,15 +20,13 @@
5233 use std::io;
5234 use std::sync::Arc;
5235
5236+ use async_trait::async_trait;
5237 use derive_more::{Display, From};
5238- use futures::{
5239- future::{self, Either},
5240- Future, Stream,
5241- };
5242+ use futures::stream::TryStreamExt;
5243
5244 use crate::sha256::{Sha256VerifyError, VerifyStream};
5245
5246- use super::{LFSObject, Storage, StorageFuture, StorageKey, StorageStream};
5247+ use super::{LFSObject, Storage, StorageKey, StorageStream};
5248
5249 #[derive(Debug, Display, From)]
5250 enum Error {
5251 @@ -60,6 +58,7 @@ impl<S> Backend<S> {
5252 }
5253 }
5254
5255+ #[async_trait]
5256 impl<S> Storage for Backend<S>
5257 where
5258 S: Storage + Send + Sync + 'static,
5259 @@ -72,15 +71,11 @@ where
5260 /// from storage if it is corrupted. If storage backends are composed
5261 /// correctly, then it should only delete cache storage (not permanent
5262 /// storage).
5263- fn get(
5264+ async fn get(
5265 &self,
5266 key: &StorageKey,
5267- ) -> StorageFuture<Option<LFSObject>, Self::Error> {
5268- let key = key.clone();
5269-
5270- let storage = self.storage.clone();
5271-
5272- Box::new(self.storage.get(&key).map(move |obj| match obj {
5273+ ) -> Result<Option<LFSObject>, Self::Error> {
5274+ match self.storage.get(key).await? {
5275 Some(obj) => {
5276 let (len, stream) = obj.into_parts();
5277
5278 @@ -88,36 +83,48 @@ where
5279 stream.map_err(Error::from),
5280 len,
5281 *key.oid(),
5282- )
5283- .or_else(move |err| match err {
5284- Error::Verify(err) => {
5285- log::error!(
5286- "Deleting corrupted object {} ({})",
5287- key.oid(),
5288- err
5289- );
5290-
5291- Either::A(storage.delete(&key).then(|_| {
5292- Err(io::Error::new(
5293+ );
5294+
5295+ let key = key.clone();
5296+ let storage = self.storage.clone();
5297+
5298+ let stream = stream.map_err(move |err| {
5299+ match err {
5300+ Error::Verify(err) => {
5301+ log::error!(
5302+ "Found corrupted object {} ({})",
5303+ key.oid(),
5304+ err
5305+ );
5306+
5307+ let storage = storage.clone();
5308+ let key = key.clone();
5309+
5310+ // Delete the corrupted object from storage.
5311+ tokio::spawn(
5312+ async move { storage.delete(&key).await },
5313+ );
5314+
5315+ io::Error::new(
5316 io::ErrorKind::Other,
5317 "found corrupted object",
5318- ))
5319- }))
5320+ )
5321+ }
5322+ Error::Io(err) => err,
5323 }
5324- Error::Io(err) => Either::B(future::err(err)),
5325 });
5326
5327- Some(LFSObject::new(len, Box::new(stream)))
5328+ Ok(Some(LFSObject::new(len, Box::pin(stream))))
5329 }
5330- None => None,
5331- }))
5332+ None => Ok(None),
5333+ }
5334 }
5335
5336- fn put(
5337+ async fn put(
5338 &self,
5339 key: StorageKey,
5340 value: LFSObject,
5341- ) -> StorageFuture<(), Self::Error> {
5342+ ) -> Result<(), Self::Error> {
5343 let (len, stream) = value.into_parts();
5344
5345 let stream =
5346 @@ -129,29 +136,28 @@ where
5347 Error::Io(err) => io::Error::new(io::ErrorKind::Other, err),
5348 });
5349
5350- self.storage.put(key, LFSObject::new(len, Box::new(stream)))
5351+ self.storage
5352+ .put(key, LFSObject::new(len, Box::pin(stream)))
5353+ .await
5354 }
5355
5356- fn size(
5357- &self,
5358- key: &StorageKey,
5359- ) -> StorageFuture<Option<u64>, Self::Error> {
5360- self.storage.size(key)
5361+ async fn size(&self, key: &StorageKey) -> Result<Option<u64>, Self::Error> {
5362+ self.storage.size(key).await
5363 }
5364
5365- fn delete(&self, key: &StorageKey) -> StorageFuture<(), Self::Error> {
5366- self.storage.delete(key)
5367+ async fn delete(&self, key: &StorageKey) -> Result<(), Self::Error> {
5368+ self.storage.delete(key).await
5369 }
5370
5371 fn list(&self) -> StorageStream<(StorageKey, u64), Self::Error> {
5372 self.storage.list()
5373 }
5374
5375- fn total_size(&self) -> Option<u64> {
5376- self.storage.total_size()
5377+ async fn total_size(&self) -> Option<u64> {
5378+ self.storage.total_size().await
5379 }
5380
5381- fn max_size(&self) -> Option<u64> {
5382- self.storage.max_size()
5383+ async fn max_size(&self) -> Option<u64> {
5384+ self.storage.max_size().await
5385 }
5386 }
5387 diff --git a/src/util.rs b/src/util.rs
5388index 04a45fe..9b80790 100644
5389--- a/src/util.rs
5390+++ b/src/util.rs
5391 @@ -18,15 +18,16 @@
5392 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
5393 // SOFTWARE.
5394
5395- use std::io;
5396- use std::mem;
5397- use std::ops::Deref;
5398+ use core::mem;
5399+ use core::ops::Deref;
5400+ use core::pin::Pin;
5401+ use core::task::{Context, Poll};
5402+
5403 use std::path::{Path, PathBuf};
5404
5405- use futures::{Future, Poll};
5406 use tokio::{
5407 fs,
5408- io::{AsyncRead, AsyncWrite},
5409+ io::{self, AsyncRead, AsyncWrite},
5410 };
5411
5412 /// A temporary file path. When dropped, the file is deleted.
5413 @@ -35,16 +36,16 @@ pub struct TempPath(PathBuf);
5414
5415 impl TempPath {
5416 /// Renames the file without deleting it.
5417- pub fn persist<P: AsRef<Path>>(
5418+ pub async fn persist<P: AsRef<Path>>(
5419 mut self,
5420 new_path: P,
5421- ) -> impl Future<Item = (), Error = io::Error> {
5422+ ) -> Result<(), io::Error> {
5423 // Don't drop self. We want to avoid deleting the file here and also
5424 // avoid leaking memory.
5425 let path = mem::replace(&mut self.0, PathBuf::new());
5426 mem::forget(self);
5427
5428- fs::rename(path, new_path)
5429+ fs::rename(path, new_path).await
5430 }
5431 }
5432
5433 @@ -77,25 +78,26 @@ pub struct NamedTempFile {
5434 }
5435
5436 impl NamedTempFile {
5437- pub fn new<P>(temp_path: P) -> impl Future<Item = Self, Error = io::Error>
5438+ pub async fn new<P>(temp_path: P) -> Result<Self, io::Error>
5439 where
5440 P: AsRef<Path> + Send + 'static,
5441 {
5442 let path = TempPath(temp_path.as_ref().to_owned());
5443- fs::File::create(temp_path)
5444- .map(move |file| NamedTempFile { path, file })
5445+ let file = fs::File::create(temp_path).await?;
5446+ Ok(NamedTempFile { path, file })
5447 }
5448
5449 pub fn into_parts(self) -> (fs::File, TempPath) {
5450 (self.file, self.path)
5451 }
5452
5453- pub fn persist<P: AsRef<Path>>(
5454+ pub async fn persist<P: AsRef<Path>>(
5455 self,
5456 new_path: P,
5457- ) -> impl Future<Item = fs::File, Error = io::Error> {
5458+ ) -> Result<fs::File, io::Error> {
5459 let (file, path) = self.into_parts();
5460- path.persist(new_path).map(move |()| file)
5461+ path.persist(new_path).await?;
5462+ Ok(file)
5463 }
5464 }
5465
5466 @@ -117,33 +119,48 @@ impl AsMut<fs::File> for NamedTempFile {
5467 }
5468 }
5469
5470- impl io::Read for NamedTempFile {
5471- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
5472- self.file.read(buf)
5473+ impl AsyncRead for NamedTempFile {
5474+ #[inline]
5475+ fn poll_read(
5476+ mut self: Pin<&mut Self>,
5477+ cx: &mut Context,
5478+ buf: &mut [u8],
5479+ ) -> Poll<io::Result<usize>> {
5480+ Pin::new(&mut self.file).poll_read(cx, buf)
5481 }
5482- }
5483
5484- impl io::Write for NamedTempFile {
5485 #[inline]
5486- fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
5487- self.file.write(buf)
5488+ unsafe fn prepare_uninitialized_buffer(
5489+ &self,
5490+ buf: &mut [mem::MaybeUninit<u8>],
5491+ ) -> bool {
5492+ self.file.prepare_uninitialized_buffer(buf)
5493 }
5494+ }
5495
5496+ impl AsyncWrite for NamedTempFile {
5497 #[inline]
5498- fn flush(&mut self) -> io::Result<()> {
5499- self.file.flush()
5500+ fn poll_write(
5501+ mut self: Pin<&mut Self>,
5502+ cx: &mut Context,
5503+ buf: &[u8],
5504+ ) -> Poll<Result<usize, io::Error>> {
5505+ Pin::new(&mut self.file).poll_write(cx, buf)
5506 }
5507- }
5508
5509- impl AsyncRead for NamedTempFile {
5510 #[inline]
5511- unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool {
5512- self.file.prepare_uninitialized_buffer(buf)
5513+ fn poll_flush(
5514+ mut self: Pin<&mut Self>,
5515+ cx: &mut Context,
5516+ ) -> Poll<Result<(), io::Error>> {
5517+ Pin::new(&mut self.file).poll_flush(cx)
5518 }
5519- }
5520
5521- impl AsyncWrite for NamedTempFile {
5522- fn shutdown(&mut self) -> Poll<(), io::Error> {
5523- self.file.shutdown()
5524+ #[inline]
5525+ fn poll_shutdown(
5526+ mut self: Pin<&mut Self>,
5527+ cx: &mut Context,
5528+ ) -> Poll<Result<(), io::Error>> {
5529+ Pin::new(&mut self.file).poll_shutdown(cx)
5530 }
5531 }