##// END OF EJS Templates
rust: update all dependencies...
Raphaël Gomès -
r45090:d31d1c06 default
parent child Browse files
Show More
@@ -1,844 +1,727 b''
1 # This file is automatically @generated by Cargo.
1 # This file is automatically @generated by Cargo.
2 # It is not intended for manual editing.
2 # It is not intended for manual editing.
3 [[package]]
3 [[package]]
4 name = "aho-corasick"
4 name = "aho-corasick"
5 version = "0.7.10"
5 version = "0.7.10"
6 source = "registry+https://github.com/rust-lang/crates.io-index"
6 source = "registry+https://github.com/rust-lang/crates.io-index"
7 dependencies = [
7 dependencies = [
8 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
8 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
9 ]
9 ]
10
10
11 [[package]]
11 [[package]]
12 name = "ansi_term"
12 name = "ansi_term"
13 version = "0.11.0"
13 version = "0.11.0"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
15 dependencies = [
15 dependencies = [
16 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
16 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
17 ]
17 ]
18
18
19 [[package]]
19 [[package]]
20 name = "atty"
20 name = "atty"
21 version = "0.2.14"
21 version = "0.2.14"
22 source = "registry+https://github.com/rust-lang/crates.io-index"
22 source = "registry+https://github.com/rust-lang/crates.io-index"
23 dependencies = [
23 dependencies = [
24 "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
24 "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
25 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
25 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
26 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
26 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
27 ]
27 ]
28
28
29 [[package]]
29 [[package]]
30 name = "autocfg"
30 name = "autocfg"
31 version = "0.1.7"
32 source = "registry+https://github.com/rust-lang/crates.io-index"
33
34 [[package]]
35 name = "autocfg"
36 version = "1.0.0"
31 version = "1.0.0"
37 source = "registry+https://github.com/rust-lang/crates.io-index"
32 source = "registry+https://github.com/rust-lang/crates.io-index"
38
33
39 [[package]]
34 [[package]]
40 name = "bitflags"
35 name = "bitflags"
41 version = "1.2.1"
36 version = "1.2.1"
42 source = "registry+https://github.com/rust-lang/crates.io-index"
37 source = "registry+https://github.com/rust-lang/crates.io-index"
43
38
44 [[package]]
39 [[package]]
45 name = "byteorder"
40 name = "byteorder"
46 version = "1.3.4"
41 version = "1.3.4"
47 source = "registry+https://github.com/rust-lang/crates.io-index"
42 source = "registry+https://github.com/rust-lang/crates.io-index"
48
43
49 [[package]]
44 [[package]]
50 name = "cc"
45 name = "cc"
51 version = "1.0.50"
46 version = "1.0.50"
52 source = "registry+https://github.com/rust-lang/crates.io-index"
47 source = "registry+https://github.com/rust-lang/crates.io-index"
53
48
54 [[package]]
49 [[package]]
55 name = "cfg-if"
50 name = "cfg-if"
56 version = "0.1.10"
51 version = "0.1.10"
57 source = "registry+https://github.com/rust-lang/crates.io-index"
52 source = "registry+https://github.com/rust-lang/crates.io-index"
58
53
59 [[package]]
54 [[package]]
60 name = "chrono"
55 name = "chrono"
61 version = "0.4.11"
56 version = "0.4.11"
62 source = "registry+https://github.com/rust-lang/crates.io-index"
57 source = "registry+https://github.com/rust-lang/crates.io-index"
63 dependencies = [
58 dependencies = [
64 "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
59 "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
65 "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
60 "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
66 "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
61 "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
67 ]
62 ]
68
63
69 [[package]]
64 [[package]]
70 name = "clap"
65 name = "clap"
71 version = "2.33.0"
66 version = "2.33.0"
72 source = "registry+https://github.com/rust-lang/crates.io-index"
67 source = "registry+https://github.com/rust-lang/crates.io-index"
73 dependencies = [
68 dependencies = [
74 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
69 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
75 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
70 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
76 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
71 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
77 "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
72 "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
78 "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
73 "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
79 "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
74 "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
80 "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
75 "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
81 ]
76 ]
82
77
83 [[package]]
78 [[package]]
84 name = "cloudabi"
85 version = "0.0.3"
86 source = "registry+https://github.com/rust-lang/crates.io-index"
87 dependencies = [
88 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
89 ]
90
91 [[package]]
92 name = "colored"
79 name = "colored"
93 version = "1.9.3"
80 version = "1.9.3"
94 source = "registry+https://github.com/rust-lang/crates.io-index"
81 source = "registry+https://github.com/rust-lang/crates.io-index"
95 dependencies = [
82 dependencies = [
96 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
83 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
97 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
84 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
98 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
85 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
99 ]
86 ]
100
87
101 [[package]]
88 [[package]]
102 name = "cpython"
89 name = "cpython"
103 version = "0.4.1"
90 version = "0.4.1"
104 source = "registry+https://github.com/rust-lang/crates.io-index"
91 source = "registry+https://github.com/rust-lang/crates.io-index"
105 dependencies = [
92 dependencies = [
106 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
93 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
107 "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
94 "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
108 "python27-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
95 "python27-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
109 "python3-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
96 "python3-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
110 ]
97 ]
111
98
112 [[package]]
99 [[package]]
113 name = "crossbeam"
100 name = "crossbeam"
114 version = "0.7.3"
101 version = "0.7.3"
115 source = "registry+https://github.com/rust-lang/crates.io-index"
102 source = "registry+https://github.com/rust-lang/crates.io-index"
116 dependencies = [
103 dependencies = [
117 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
104 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
118 "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
105 "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
119 "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
106 "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
120 "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
107 "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
121 "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
108 "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
122 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
109 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
123 ]
110 ]
124
111
125 [[package]]
112 [[package]]
126 name = "crossbeam-channel"
113 name = "crossbeam-channel"
127 version = "0.4.2"
114 version = "0.4.2"
128 source = "registry+https://github.com/rust-lang/crates.io-index"
115 source = "registry+https://github.com/rust-lang/crates.io-index"
129 dependencies = [
116 dependencies = [
130 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
117 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
131 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
118 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
132 ]
119 ]
133
120
134 [[package]]
121 [[package]]
135 name = "crossbeam-deque"
122 name = "crossbeam-deque"
136 version = "0.7.3"
123 version = "0.7.3"
137 source = "registry+https://github.com/rust-lang/crates.io-index"
124 source = "registry+https://github.com/rust-lang/crates.io-index"
138 dependencies = [
125 dependencies = [
139 "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
126 "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
140 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
127 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
141 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
128 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
142 ]
129 ]
143
130
144 [[package]]
131 [[package]]
145 name = "crossbeam-epoch"
132 name = "crossbeam-epoch"
146 version = "0.8.2"
133 version = "0.8.2"
147 source = "registry+https://github.com/rust-lang/crates.io-index"
134 source = "registry+https://github.com/rust-lang/crates.io-index"
148 dependencies = [
135 dependencies = [
149 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
136 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
150 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
137 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
151 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
138 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
152 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
139 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
153 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
140 "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
154 "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
141 "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
155 "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
142 "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
156 ]
143 ]
157
144
158 [[package]]
145 [[package]]
159 name = "crossbeam-queue"
146 name = "crossbeam-queue"
160 version = "0.2.1"
147 version = "0.2.1"
161 source = "registry+https://github.com/rust-lang/crates.io-index"
148 source = "registry+https://github.com/rust-lang/crates.io-index"
162 dependencies = [
149 dependencies = [
163 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
150 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
164 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
151 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
165 ]
152 ]
166
153
167 [[package]]
154 [[package]]
168 name = "crossbeam-utils"
155 name = "crossbeam-utils"
169 version = "0.7.2"
156 version = "0.7.2"
170 source = "registry+https://github.com/rust-lang/crates.io-index"
157 source = "registry+https://github.com/rust-lang/crates.io-index"
171 dependencies = [
158 dependencies = [
172 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
159 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
173 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
160 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
174 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
161 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
175 ]
162 ]
176
163
177 [[package]]
164 [[package]]
178 name = "ctor"
165 name = "ctor"
179 version = "0.1.13"
166 version = "0.1.13"
180 source = "registry+https://github.com/rust-lang/crates.io-index"
167 source = "registry+https://github.com/rust-lang/crates.io-index"
181 dependencies = [
168 dependencies = [
182 "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
169 "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
183 "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
170 "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
184 ]
171 ]
185
172
186 [[package]]
173 [[package]]
187 name = "difference"
174 name = "difference"
188 version = "2.0.0"
175 version = "2.0.0"
189 source = "registry+https://github.com/rust-lang/crates.io-index"
176 source = "registry+https://github.com/rust-lang/crates.io-index"
190
177
191 [[package]]
178 [[package]]
192 name = "either"
179 name = "either"
193 version = "1.5.3"
180 version = "1.5.3"
194 source = "registry+https://github.com/rust-lang/crates.io-index"
181 source = "registry+https://github.com/rust-lang/crates.io-index"
195
182
196 [[package]]
183 [[package]]
197 name = "fuchsia-cprng"
198 version = "0.1.1"
199 source = "registry+https://github.com/rust-lang/crates.io-index"
200
201 [[package]]
202 name = "getrandom"
184 name = "getrandom"
203 version = "0.1.14"
185 version = "0.1.14"
204 source = "registry+https://github.com/rust-lang/crates.io-index"
186 source = "registry+https://github.com/rust-lang/crates.io-index"
205 dependencies = [
187 dependencies = [
206 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
188 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
207 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
189 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
208 "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
190 "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
209 ]
191 ]
210
192
211 [[package]]
193 [[package]]
212 name = "hermit-abi"
194 name = "hermit-abi"
213 version = "0.1.8"
195 version = "0.1.8"
214 source = "registry+https://github.com/rust-lang/crates.io-index"
196 source = "registry+https://github.com/rust-lang/crates.io-index"
215 dependencies = [
197 dependencies = [
216 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
198 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
217 ]
199 ]
218
200
219 [[package]]
201 [[package]]
220 name = "hex"
202 name = "hex"
221 version = "0.4.2"
203 version = "0.4.2"
222 source = "registry+https://github.com/rust-lang/crates.io-index"
204 source = "registry+https://github.com/rust-lang/crates.io-index"
223
205
224 [[package]]
206 [[package]]
225 name = "hg-core"
207 name = "hg-core"
226 version = "0.1.0"
208 version = "0.1.0"
227 dependencies = [
209 dependencies = [
228 "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
210 "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
229 "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
211 "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
230 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
212 "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
231 "crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
213 "crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
232 "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
214 "hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
233 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
215 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
234 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
216 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
235 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
217 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
236 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
218 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
237 "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
219 "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
238 "micro-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
220 "micro-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
239 "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
221 "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
240 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
222 "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
241 "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
223 "rand_distr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
224 "rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
242 "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
225 "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
243 "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
226 "regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
244 "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
227 "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
245 "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
228 "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
246 "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
229 "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
247 ]
230 ]
248
231
249 [[package]]
232 [[package]]
250 name = "hg-cpython"
233 name = "hg-cpython"
251 version = "0.1.0"
234 version = "0.1.0"
252 dependencies = [
235 dependencies = [
253 "cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
236 "cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
254 "hg-core 0.1.0",
237 "hg-core 0.1.0",
255 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
238 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
256 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
239 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
257 "simple_logger 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
240 "simple_logger 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
258 ]
241 ]
259
242
260 [[package]]
243 [[package]]
261 name = "lazy_static"
244 name = "lazy_static"
262 version = "1.4.0"
245 version = "1.4.0"
263 source = "registry+https://github.com/rust-lang/crates.io-index"
246 source = "registry+https://github.com/rust-lang/crates.io-index"
264
247
265 [[package]]
248 [[package]]
266 name = "libc"
249 name = "libc"
267 version = "0.2.67"
250 version = "0.2.67"
268 source = "registry+https://github.com/rust-lang/crates.io-index"
251 source = "registry+https://github.com/rust-lang/crates.io-index"
269
252
270 [[package]]
253 [[package]]
271 name = "log"
254 name = "log"
272 version = "0.4.8"
255 version = "0.4.8"
273 source = "registry+https://github.com/rust-lang/crates.io-index"
256 source = "registry+https://github.com/rust-lang/crates.io-index"
274 dependencies = [
257 dependencies = [
275 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
258 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
276 ]
259 ]
277
260
278 [[package]]
261 [[package]]
279 name = "maybe-uninit"
262 name = "maybe-uninit"
280 version = "2.0.0"
263 version = "2.0.0"
281 source = "registry+https://github.com/rust-lang/crates.io-index"
264 source = "registry+https://github.com/rust-lang/crates.io-index"
282
265
283 [[package]]
266 [[package]]
284 name = "memchr"
267 name = "memchr"
285 version = "2.3.3"
268 version = "2.3.3"
286 source = "registry+https://github.com/rust-lang/crates.io-index"
269 source = "registry+https://github.com/rust-lang/crates.io-index"
287
270
288 [[package]]
271 [[package]]
289 name = "memmap"
272 name = "memmap"
290 version = "0.7.0"
273 version = "0.7.0"
291 source = "registry+https://github.com/rust-lang/crates.io-index"
274 source = "registry+https://github.com/rust-lang/crates.io-index"
292 dependencies = [
275 dependencies = [
293 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
276 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
294 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
277 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
295 ]
278 ]
296
279
297 [[package]]
280 [[package]]
298 name = "memoffset"
281 name = "memoffset"
299 version = "0.5.3"
282 version = "0.5.3"
300 source = "registry+https://github.com/rust-lang/crates.io-index"
283 source = "registry+https://github.com/rust-lang/crates.io-index"
301 dependencies = [
284 dependencies = [
302 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
285 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
303 ]
286 ]
304
287
305 [[package]]
288 [[package]]
306 name = "micro-timer"
289 name = "micro-timer"
307 version = "0.2.1"
290 version = "0.2.1"
308 source = "registry+https://github.com/rust-lang/crates.io-index"
291 source = "registry+https://github.com/rust-lang/crates.io-index"
309 dependencies = [
292 dependencies = [
310 "micro-timer-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
293 "micro-timer-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
311 "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
294 "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
312 ]
295 ]
313
296
314 [[package]]
297 [[package]]
315 name = "micro-timer-macros"
298 name = "micro-timer-macros"
316 version = "0.2.0"
299 version = "0.2.0"
317 source = "registry+https://github.com/rust-lang/crates.io-index"
300 source = "registry+https://github.com/rust-lang/crates.io-index"
318 dependencies = [
301 dependencies = [
319 "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
302 "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
320 "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
303 "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
321 "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
304 "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
322 "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
305 "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
323 ]
306 ]
324
307
325 [[package]]
308 [[package]]
326 name = "num-integer"
309 name = "num-integer"
327 version = "0.1.42"
310 version = "0.1.42"
328 source = "registry+https://github.com/rust-lang/crates.io-index"
311 source = "registry+https://github.com/rust-lang/crates.io-index"
329 dependencies = [
312 dependencies = [
330 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
313 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
331 "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
314 "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
332 ]
315 ]
333
316
334 [[package]]
317 [[package]]
335 name = "num-traits"
318 name = "num-traits"
336 version = "0.2.11"
319 version = "0.2.11"
337 source = "registry+https://github.com/rust-lang/crates.io-index"
320 source = "registry+https://github.com/rust-lang/crates.io-index"
338 dependencies = [
321 dependencies = [
339 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
322 "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
340 ]
323 ]
341
324
342 [[package]]
325 [[package]]
343 name = "num_cpus"
326 name = "num_cpus"
344 version = "1.12.0"
327 version = "1.12.0"
345 source = "registry+https://github.com/rust-lang/crates.io-index"
328 source = "registry+https://github.com/rust-lang/crates.io-index"
346 dependencies = [
329 dependencies = [
347 "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
330 "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
348 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
331 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
349 ]
332 ]
350
333
351 [[package]]
334 [[package]]
352 name = "output_vt100"
335 name = "output_vt100"
353 version = "0.1.2"
336 version = "0.1.2"
354 source = "registry+https://github.com/rust-lang/crates.io-index"
337 source = "registry+https://github.com/rust-lang/crates.io-index"
355 dependencies = [
338 dependencies = [
356 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
339 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
357 ]
340 ]
358
341
359 [[package]]
342 [[package]]
360 name = "ppv-lite86"
343 name = "ppv-lite86"
361 version = "0.2.6"
344 version = "0.2.6"
362 source = "registry+https://github.com/rust-lang/crates.io-index"
345 source = "registry+https://github.com/rust-lang/crates.io-index"
363
346
364 [[package]]
347 [[package]]
365 name = "pretty_assertions"
348 name = "pretty_assertions"
366 version = "0.6.1"
349 version = "0.6.1"
367 source = "registry+https://github.com/rust-lang/crates.io-index"
350 source = "registry+https://github.com/rust-lang/crates.io-index"
368 dependencies = [
351 dependencies = [
369 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
352 "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
370 "ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
353 "ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
371 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
354 "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
372 "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
355 "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
373 ]
356 ]
374
357
375 [[package]]
358 [[package]]
376 name = "proc-macro2"
359 name = "proc-macro2"
377 version = "1.0.9"
360 version = "1.0.9"
378 source = "registry+https://github.com/rust-lang/crates.io-index"
361 source = "registry+https://github.com/rust-lang/crates.io-index"
379 dependencies = [
362 dependencies = [
380 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
363 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
381 ]
364 ]
382
365
383 [[package]]
366 [[package]]
384 name = "python27-sys"
367 name = "python27-sys"
385 version = "0.4.1"
368 version = "0.4.1"
386 source = "registry+https://github.com/rust-lang/crates.io-index"
369 source = "registry+https://github.com/rust-lang/crates.io-index"
387 dependencies = [
370 dependencies = [
388 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
371 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
389 "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
372 "regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
390 ]
373 ]
391
374
392 [[package]]
375 [[package]]
393 name = "python3-sys"
376 name = "python3-sys"
394 version = "0.4.1"
377 version = "0.4.1"
395 source = "registry+https://github.com/rust-lang/crates.io-index"
378 source = "registry+https://github.com/rust-lang/crates.io-index"
396 dependencies = [
379 dependencies = [
397 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
380 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
398 "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
381 "regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
399 ]
382 ]
400
383
401 [[package]]
384 [[package]]
402 name = "quote"
385 name = "quote"
403 version = "1.0.3"
386 version = "1.0.3"
404 source = "registry+https://github.com/rust-lang/crates.io-index"
387 source = "registry+https://github.com/rust-lang/crates.io-index"
405 dependencies = [
388 dependencies = [
406 "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
389 "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
407 ]
390 ]
408
391
409 [[package]]
392 [[package]]
410 name = "rand"
393 name = "rand"
411 version = "0.6.5"
412 source = "registry+https://github.com/rust-lang/crates.io-index"
413 dependencies = [
414 "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
415 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
416 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
417 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
418 "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
419 "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
420 "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
421 "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
422 "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
423 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
424 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
425 ]
426
427 [[package]]
428 name = "rand"
429 version = "0.7.3"
394 version = "0.7.3"
430 source = "registry+https://github.com/rust-lang/crates.io-index"
395 source = "registry+https://github.com/rust-lang/crates.io-index"
431 dependencies = [
396 dependencies = [
432 "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
397 "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
433 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
398 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
434 "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
399 "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
435 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
400 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
436 "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
401 "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
437 ]
402 ]
438
403
439 [[package]]
404 [[package]]
440 name = "rand_chacha"
405 name = "rand_chacha"
441 version = "0.1.1"
442 source = "registry+https://github.com/rust-lang/crates.io-index"
443 dependencies = [
444 "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
445 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
446 ]
447
448 [[package]]
449 name = "rand_chacha"
450 version = "0.2.2"
406 version = "0.2.2"
451 source = "registry+https://github.com/rust-lang/crates.io-index"
407 source = "registry+https://github.com/rust-lang/crates.io-index"
452 dependencies = [
408 dependencies = [
453 "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
409 "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
454 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
410 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
455 ]
411 ]
456
412
457 [[package]]
413 [[package]]
458 name = "rand_core"
414 name = "rand_core"
459 version = "0.3.1"
460 source = "registry+https://github.com/rust-lang/crates.io-index"
461 dependencies = [
462 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
463 ]
464
465 [[package]]
466 name = "rand_core"
467 version = "0.4.2"
468 source = "registry+https://github.com/rust-lang/crates.io-index"
469
470 [[package]]
471 name = "rand_core"
472 version = "0.5.1"
415 version = "0.5.1"
473 source = "registry+https://github.com/rust-lang/crates.io-index"
416 source = "registry+https://github.com/rust-lang/crates.io-index"
474 dependencies = [
417 dependencies = [
475 "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
418 "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
476 ]
419 ]
477
420
478 [[package]]
421 [[package]]
479 name = "rand_hc"
422 name = "rand_distr"
480 version = "0.1.0"
423 version = "0.2.2"
481 source = "registry+https://github.com/rust-lang/crates.io-index"
424 source = "registry+https://github.com/rust-lang/crates.io-index"
482 dependencies = [
425 dependencies = [
483 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
426 "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
484 ]
427 ]
485
428
486 [[package]]
429 [[package]]
487 name = "rand_hc"
430 name = "rand_hc"
488 version = "0.2.0"
431 version = "0.2.0"
489 source = "registry+https://github.com/rust-lang/crates.io-index"
432 source = "registry+https://github.com/rust-lang/crates.io-index"
490 dependencies = [
433 dependencies = [
491 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
434 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
492 ]
435 ]
493
436
494 [[package]]
437 [[package]]
495 name = "rand_isaac"
438 name = "rand_pcg"
496 version = "0.1.1"
439 version = "0.2.1"
497 source = "registry+https://github.com/rust-lang/crates.io-index"
498 dependencies = [
499 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
500 ]
501
502 [[package]]
503 name = "rand_jitter"
504 version = "0.1.4"
505 source = "registry+https://github.com/rust-lang/crates.io-index"
506 dependencies = [
507 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
508 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
509 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
510 ]
511
512 [[package]]
513 name = "rand_os"
514 version = "0.1.3"
515 source = "registry+https://github.com/rust-lang/crates.io-index"
440 source = "registry+https://github.com/rust-lang/crates.io-index"
516 dependencies = [
441 dependencies = [
517 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
442 "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
518 "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
519 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
520 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
521 "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
522 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
523 ]
524
525 [[package]]
526 name = "rand_pcg"
527 version = "0.1.2"
528 source = "registry+https://github.com/rust-lang/crates.io-index"
529 dependencies = [
530 "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
531 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
532 ]
533
534 [[package]]
535 name = "rand_xorshift"
536 version = "0.1.1"
537 source = "registry+https://github.com/rust-lang/crates.io-index"
538 dependencies = [
539 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
540 ]
443 ]
541
444
542 [[package]]
445 [[package]]
543 name = "rayon"
446 name = "rayon"
544 version = "1.3.0"
447 version = "1.3.0"
545 source = "registry+https://github.com/rust-lang/crates.io-index"
448 source = "registry+https://github.com/rust-lang/crates.io-index"
546 dependencies = [
449 dependencies = [
547 "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
450 "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
548 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
451 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
549 "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
452 "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
550 ]
453 ]
551
454
552 [[package]]
455 [[package]]
553 name = "rayon-core"
456 name = "rayon-core"
554 version = "1.7.0"
457 version = "1.7.0"
555 source = "registry+https://github.com/rust-lang/crates.io-index"
458 source = "registry+https://github.com/rust-lang/crates.io-index"
556 dependencies = [
459 dependencies = [
557 "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
460 "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
558 "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
461 "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
559 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
462 "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
560 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
463 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
561 "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
464 "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
562 ]
465 ]
563
466
564 [[package]]
467 [[package]]
565 name = "rdrand"
566 version = "0.4.0"
567 source = "registry+https://github.com/rust-lang/crates.io-index"
568 dependencies = [
569 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
570 ]
571
572 [[package]]
573 name = "redox_syscall"
468 name = "redox_syscall"
574 version = "0.1.56"
469 version = "0.1.56"
575 source = "registry+https://github.com/rust-lang/crates.io-index"
470 source = "registry+https://github.com/rust-lang/crates.io-index"
576
471
577 [[package]]
472 [[package]]
578 name = "regex"
473 name = "regex"
579 version = "1.3.4"
474 version = "1.3.6"
580 source = "registry+https://github.com/rust-lang/crates.io-index"
475 source = "registry+https://github.com/rust-lang/crates.io-index"
581 dependencies = [
476 dependencies = [
582 "aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
477 "aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)",
583 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
478 "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
584 "regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
479 "regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
585 "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
480 "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
586 ]
481 ]
587
482
588 [[package]]
483 [[package]]
589 name = "regex-syntax"
484 name = "regex-syntax"
590 version = "0.6.16"
485 version = "0.6.17"
591 source = "registry+https://github.com/rust-lang/crates.io-index"
486 source = "registry+https://github.com/rust-lang/crates.io-index"
592
487
593 [[package]]
488 [[package]]
594 name = "remove_dir_all"
489 name = "remove_dir_all"
595 version = "0.5.2"
490 version = "0.5.2"
596 source = "registry+https://github.com/rust-lang/crates.io-index"
491 source = "registry+https://github.com/rust-lang/crates.io-index"
597 dependencies = [
492 dependencies = [
598 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
493 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
599 ]
494 ]
600
495
601 [[package]]
496 [[package]]
602 name = "rustc_version"
497 name = "rustc_version"
603 version = "0.2.3"
498 version = "0.2.3"
604 source = "registry+https://github.com/rust-lang/crates.io-index"
499 source = "registry+https://github.com/rust-lang/crates.io-index"
605 dependencies = [
500 dependencies = [
606 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
501 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
607 ]
502 ]
608
503
609 [[package]]
504 [[package]]
610 name = "same-file"
505 name = "same-file"
611 version = "1.0.6"
506 version = "1.0.6"
612 source = "registry+https://github.com/rust-lang/crates.io-index"
507 source = "registry+https://github.com/rust-lang/crates.io-index"
613 dependencies = [
508 dependencies = [
614 "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
509 "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
615 ]
510 ]
616
511
617 [[package]]
512 [[package]]
618 name = "scopeguard"
513 name = "scopeguard"
619 version = "1.1.0"
514 version = "1.1.0"
620 source = "registry+https://github.com/rust-lang/crates.io-index"
515 source = "registry+https://github.com/rust-lang/crates.io-index"
621
516
622 [[package]]
517 [[package]]
623 name = "semver"
518 name = "semver"
624 version = "0.9.0"
519 version = "0.9.0"
625 source = "registry+https://github.com/rust-lang/crates.io-index"
520 source = "registry+https://github.com/rust-lang/crates.io-index"
626 dependencies = [
521 dependencies = [
627 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
522 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
628 ]
523 ]
629
524
630 [[package]]
525 [[package]]
631 name = "semver-parser"
526 name = "semver-parser"
632 version = "0.7.0"
527 version = "0.7.0"
633 source = "registry+https://github.com/rust-lang/crates.io-index"
528 source = "registry+https://github.com/rust-lang/crates.io-index"
634
529
635 [[package]]
530 [[package]]
636 name = "simple_logger"
531 name = "simple_logger"
637 version = "1.6.0"
532 version = "1.6.0"
638 source = "registry+https://github.com/rust-lang/crates.io-index"
533 source = "registry+https://github.com/rust-lang/crates.io-index"
639 dependencies = [
534 dependencies = [
640 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
535 "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
641 "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
536 "chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
642 "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
537 "colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
643 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
538 "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
644 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
539 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
645 ]
540 ]
646
541
647 [[package]]
542 [[package]]
648 name = "strsim"
543 name = "strsim"
649 version = "0.8.0"
544 version = "0.8.0"
650 source = "registry+https://github.com/rust-lang/crates.io-index"
545 source = "registry+https://github.com/rust-lang/crates.io-index"
651
546
652 [[package]]
547 [[package]]
653 name = "syn"
548 name = "syn"
654 version = "1.0.16"
549 version = "1.0.16"
655 source = "registry+https://github.com/rust-lang/crates.io-index"
550 source = "registry+https://github.com/rust-lang/crates.io-index"
656 dependencies = [
551 dependencies = [
657 "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
552 "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
658 "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
553 "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
659 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
554 "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
660 ]
555 ]
661
556
662 [[package]]
557 [[package]]
663 name = "tempfile"
558 name = "tempfile"
664 version = "3.1.0"
559 version = "3.1.0"
665 source = "registry+https://github.com/rust-lang/crates.io-index"
560 source = "registry+https://github.com/rust-lang/crates.io-index"
666 dependencies = [
561 dependencies = [
667 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
562 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
668 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
563 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
669 "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
564 "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
670 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
565 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
671 "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
566 "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
672 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
567 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
673 ]
568 ]
674
569
675 [[package]]
570 [[package]]
676 name = "textwrap"
571 name = "textwrap"
677 version = "0.11.0"
572 version = "0.11.0"
678 source = "registry+https://github.com/rust-lang/crates.io-index"
573 source = "registry+https://github.com/rust-lang/crates.io-index"
679 dependencies = [
574 dependencies = [
680 "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
575 "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
681 ]
576 ]
682
577
683 [[package]]
578 [[package]]
684 name = "thread_local"
579 name = "thread_local"
685 version = "1.0.1"
580 version = "1.0.1"
686 source = "registry+https://github.com/rust-lang/crates.io-index"
581 source = "registry+https://github.com/rust-lang/crates.io-index"
687 dependencies = [
582 dependencies = [
688 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
583 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
689 ]
584 ]
690
585
691 [[package]]
586 [[package]]
692 name = "time"
587 name = "time"
693 version = "0.1.42"
588 version = "0.1.42"
694 source = "registry+https://github.com/rust-lang/crates.io-index"
589 source = "registry+https://github.com/rust-lang/crates.io-index"
695 dependencies = [
590 dependencies = [
696 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
591 "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
697 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
592 "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
698 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
593 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
699 ]
594 ]
700
595
701 [[package]]
596 [[package]]
702 name = "twox-hash"
597 name = "twox-hash"
703 version = "1.5.0"
598 version = "1.5.0"
704 source = "registry+https://github.com/rust-lang/crates.io-index"
599 source = "registry+https://github.com/rust-lang/crates.io-index"
705 dependencies = [
600 dependencies = [
706 "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
601 "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
707 ]
602 ]
708
603
709 [[package]]
604 [[package]]
710 name = "unicode-width"
605 name = "unicode-width"
711 version = "0.1.7"
606 version = "0.1.7"
712 source = "registry+https://github.com/rust-lang/crates.io-index"
607 source = "registry+https://github.com/rust-lang/crates.io-index"
713
608
714 [[package]]
609 [[package]]
715 name = "unicode-xid"
610 name = "unicode-xid"
716 version = "0.2.0"
611 version = "0.2.0"
717 source = "registry+https://github.com/rust-lang/crates.io-index"
612 source = "registry+https://github.com/rust-lang/crates.io-index"
718
613
719 [[package]]
614 [[package]]
720 name = "vec_map"
615 name = "vec_map"
721 version = "0.8.1"
616 version = "0.8.1"
722 source = "registry+https://github.com/rust-lang/crates.io-index"
617 source = "registry+https://github.com/rust-lang/crates.io-index"
723
618
724 [[package]]
619 [[package]]
725 name = "wasi"
620 name = "wasi"
726 version = "0.9.0+wasi-snapshot-preview1"
621 version = "0.9.0+wasi-snapshot-preview1"
727 source = "registry+https://github.com/rust-lang/crates.io-index"
622 source = "registry+https://github.com/rust-lang/crates.io-index"
728
623
729 [[package]]
624 [[package]]
730 name = "winapi"
625 name = "winapi"
731 version = "0.3.8"
626 version = "0.3.8"
732 source = "registry+https://github.com/rust-lang/crates.io-index"
627 source = "registry+https://github.com/rust-lang/crates.io-index"
733 dependencies = [
628 dependencies = [
734 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
629 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
735 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
630 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
736 ]
631 ]
737
632
738 [[package]]
633 [[package]]
739 name = "winapi-i686-pc-windows-gnu"
634 name = "winapi-i686-pc-windows-gnu"
740 version = "0.4.0"
635 version = "0.4.0"
741 source = "registry+https://github.com/rust-lang/crates.io-index"
636 source = "registry+https://github.com/rust-lang/crates.io-index"
742
637
743 [[package]]
638 [[package]]
744 name = "winapi-util"
639 name = "winapi-util"
745 version = "0.1.3"
640 version = "0.1.3"
746 source = "registry+https://github.com/rust-lang/crates.io-index"
641 source = "registry+https://github.com/rust-lang/crates.io-index"
747 dependencies = [
642 dependencies = [
748 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
643 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
749 ]
644 ]
750
645
751 [[package]]
646 [[package]]
752 name = "winapi-x86_64-pc-windows-gnu"
647 name = "winapi-x86_64-pc-windows-gnu"
753 version = "0.4.0"
648 version = "0.4.0"
754 source = "registry+https://github.com/rust-lang/crates.io-index"
649 source = "registry+https://github.com/rust-lang/crates.io-index"
755
650
756 [metadata]
651 [metadata]
757 "checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
652 "checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
758 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
653 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
759 "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
654 "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
760 "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
761 "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
655 "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
762 "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
656 "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
763 "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
657 "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
764 "checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
658 "checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
765 "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
659 "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
766 "checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
660 "checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
767 "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
661 "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
768 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
769 "checksum colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
662 "checksum colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
770 "checksum cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaf3847ab963e40c4f6dd8d6be279bdf74007ae2413786a0dcbb28c52139a95"
663 "checksum cpython 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaf3847ab963e40c4f6dd8d6be279bdf74007ae2413786a0dcbb28c52139a95"
771 "checksum crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e"
664 "checksum crossbeam 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "69323bff1fb41c635347b8ead484a5ca6c3f11914d784170b158d8449ab07f8e"
772 "checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061"
665 "checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061"
773 "checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
666 "checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
774 "checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
667 "checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
775 "checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
668 "checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
776 "checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
669 "checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
777 "checksum ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1"
670 "checksum ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1"
778 "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
671 "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
779 "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
672 "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
780 "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
781 "checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
673 "checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
782 "checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
674 "checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8"
783 "checksum hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
675 "checksum hex 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35"
784 "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
676 "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
785 "checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
677 "checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
786 "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
678 "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
787 "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
679 "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
788 "checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
680 "checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
789 "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
681 "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
790 "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
682 "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
791 "checksum micro-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "987429cd6162a80ed5ff44fc790f5090b1c6d617ac73a2e272965ed91201d79b"
683 "checksum micro-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "987429cd6162a80ed5ff44fc790f5090b1c6d617ac73a2e272965ed91201d79b"
792 "checksum micro-timer-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43cec5c0b38783eb33ef7bccf4b250b7a085703e11f5f2238fa31969e629388a"
684 "checksum micro-timer-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43cec5c0b38783eb33ef7bccf4b250b7a085703e11f5f2238fa31969e629388a"
793 "checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
685 "checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
794 "checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
686 "checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
795 "checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
687 "checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
796 "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
688 "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
797 "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
689 "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
798 "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
690 "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
799 "checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
691 "checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435"
800 "checksum python27-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67cb041de8615111bf224dd75667af5f25c6e032118251426fed7f1b70ce4c8c"
692 "checksum python27-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67cb041de8615111bf224dd75667af5f25c6e032118251426fed7f1b70ce4c8c"
801 "checksum python3-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90af11779515a1e530af60782d273b59ac79d33b0e253c071a728563957c76d4"
693 "checksum python3-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90af11779515a1e530af60782d273b59ac79d33b0e253c071a728563957c76d4"
802 "checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
694 "checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
803 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
804 "checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
695 "checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
805 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
806 "checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
696 "checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
807 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
808 "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
809 "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
697 "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
810 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
698 "checksum rand_distr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
811 "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
699 "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
812 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
700 "checksum rand_pcg 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
813 "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
814 "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
815 "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
816 "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
817 "checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
701 "checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
818 "checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
702 "checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
819 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
820 "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
703 "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
821 "checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8"
704 "checksum regex 1.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3"
822 "checksum regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1"
705 "checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
823 "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
706 "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
824 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
707 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
825 "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
708 "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
826 "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
709 "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
827 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
710 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
828 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
711 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
829 "checksum simple_logger 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fea0c4611f32f4c2bac73754f22dca1f57e6c1945e0590dae4e5f2a077b92367"
712 "checksum simple_logger 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fea0c4611f32f4c2bac73754f22dca1f57e6c1945e0590dae4e5f2a077b92367"
830 "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
713 "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
831 "checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
714 "checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859"
832 "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
715 "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
833 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
716 "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
834 "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
717 "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
835 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
718 "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
836 "checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56"
719 "checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56"
837 "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
720 "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
838 "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
721 "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
839 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
722 "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
840 "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
723 "checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
841 "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
724 "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
842 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
725 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
843 "checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
726 "checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80"
844 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
727 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
@@ -1,39 +1,40 b''
1 [package]
1 [package]
2 name = "hg-core"
2 name = "hg-core"
3 version = "0.1.0"
3 version = "0.1.0"
4 authors = ["Georges Racinet <gracinet@anybox.fr>"]
4 authors = ["Georges Racinet <gracinet@anybox.fr>"]
5 description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)"
5 description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)"
6 edition = "2018"
6 edition = "2018"
7 build = "build.rs"
7 build = "build.rs"
8
8
9 [lib]
9 [lib]
10 name = "hg"
10 name = "hg"
11
11
12 [dependencies]
12 [dependencies]
13 byteorder = "1.3.1"
13 byteorder = "1.3.4"
14 hex = "0.4.0"
14 hex = "0.4.2"
15 lazy_static = "1.3.0"
15 lazy_static = "1.4.0"
16 libc = { version = "0.2.66", optional = true }
16 libc = { version = "0.2.66", optional = true }
17 memchr = "2.2.0"
17 memchr = "2.3.3"
18 rand = "0.6.5"
18 rand = "0.7.3"
19 rand_pcg = "0.1.1"
19 rand_pcg = "0.2.1"
20 rand_distr = "0.2.2"
20 rayon = "1.3.0"
21 rayon = "1.3.0"
21 regex = "1.1.0"
22 regex = "1.3.6"
22 twox-hash = "1.5.0"
23 twox-hash = "1.5.0"
23 same-file = "1.0.6"
24 same-file = "1.0.6"
24 crossbeam = "0.7.3"
25 crossbeam = "0.7.3"
25 micro-timer = "0.2.1"
26 micro-timer = "0.2.1"
26 log = "0.4.8"
27 log = "0.4.8"
27
28
28 [dev-dependencies]
29 [dev-dependencies]
29 clap = "*"
30 clap = "*"
30 memmap = "0.7.0"
31 memmap = "0.7.0"
31 pretty_assertions = "0.6.1"
32 pretty_assertions = "0.6.1"
32 tempfile = "3.1.0"
33 tempfile = "3.1.0"
33
34
34 [build-dependencies]
35 [build-dependencies]
35 cc = { version = "1.0.48", optional = true }
36 cc = { version = "1.0.48", optional = true }
36
37
37 [features]
38 [features]
38 default = []
39 default = []
39 with-re2 = ["cc", "libc"]
40 with-re2 = ["cc", "libc"]
@@ -1,695 +1,695 b''
1 // discovery.rs
1 // discovery.rs
2 //
2 //
3 // Copyright 2019 Georges Racinet <georges.racinet@octobus.net>
3 // Copyright 2019 Georges Racinet <georges.racinet@octobus.net>
4 //
4 //
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 //! Discovery operations
8 //! Discovery operations
9 //!
9 //!
10 //! This is a Rust counterpart to the `partialdiscovery` class of
10 //! This is a Rust counterpart to the `partialdiscovery` class of
11 //! `mercurial.setdiscovery`
11 //! `mercurial.setdiscovery`
12
12
13 use super::{Graph, GraphError, Revision, NULL_REVISION};
13 use super::{Graph, GraphError, Revision, NULL_REVISION};
14 use crate::{ancestors::MissingAncestors, dagops, FastHashMap};
14 use crate::{ancestors::MissingAncestors, dagops, FastHashMap};
15 use rand::seq::SliceRandom;
15 use rand::seq::SliceRandom;
16 use rand::{thread_rng, RngCore, SeedableRng};
16 use rand::{thread_rng, RngCore, SeedableRng};
17 use std::cmp::{max, min};
17 use std::cmp::{max, min};
18 use std::collections::{HashSet, VecDeque};
18 use std::collections::{HashSet, VecDeque};
19
19
20 type Rng = rand_pcg::Pcg32;
20 type Rng = rand_pcg::Pcg32;
21 type Seed = [u8; 16];
21 type Seed = [u8; 16];
22
22
23 pub struct PartialDiscovery<G: Graph + Clone> {
23 pub struct PartialDiscovery<G: Graph + Clone> {
24 target_heads: Option<Vec<Revision>>,
24 target_heads: Option<Vec<Revision>>,
25 graph: G, // plays the role of self._repo
25 graph: G, // plays the role of self._repo
26 common: MissingAncestors<G>,
26 common: MissingAncestors<G>,
27 undecided: Option<HashSet<Revision>>,
27 undecided: Option<HashSet<Revision>>,
28 children_cache: Option<FastHashMap<Revision, Vec<Revision>>>,
28 children_cache: Option<FastHashMap<Revision, Vec<Revision>>>,
29 missing: HashSet<Revision>,
29 missing: HashSet<Revision>,
30 rng: Rng,
30 rng: Rng,
31 respect_size: bool,
31 respect_size: bool,
32 randomize: bool,
32 randomize: bool,
33 }
33 }
34
34
35 pub struct DiscoveryStats {
35 pub struct DiscoveryStats {
36 pub undecided: Option<usize>,
36 pub undecided: Option<usize>,
37 }
37 }
38
38
39 /// Update an existing sample to match the expected size
39 /// Update an existing sample to match the expected size
40 ///
40 ///
41 /// The sample is updated with revisions exponentially distant from each
41 /// The sample is updated with revisions exponentially distant from each
42 /// element of `heads`.
42 /// element of `heads`.
43 ///
43 ///
44 /// If a target size is specified, the sampling will stop once this size is
44 /// If a target size is specified, the sampling will stop once this size is
45 /// reached. Otherwise sampling will happen until roots of the <revs> set are
45 /// reached. Otherwise sampling will happen until roots of the <revs> set are
46 /// reached.
46 /// reached.
47 ///
47 ///
48 /// - `revs`: set of revs we want to discover (if None, `assume` the whole dag
48 /// - `revs`: set of revs we want to discover (if None, `assume` the whole dag
49 /// represented by `parentfn`
49 /// represented by `parentfn`
50 /// - `heads`: set of DAG head revs
50 /// - `heads`: set of DAG head revs
51 /// - `sample`: a sample to update
51 /// - `sample`: a sample to update
52 /// - `parentfn`: a callable to resolve parents for a revision
52 /// - `parentfn`: a callable to resolve parents for a revision
53 /// - `quicksamplesize`: optional target size of the sample
53 /// - `quicksamplesize`: optional target size of the sample
54 fn update_sample<I>(
54 fn update_sample<I>(
55 revs: Option<&HashSet<Revision>>,
55 revs: Option<&HashSet<Revision>>,
56 heads: impl IntoIterator<Item = Revision>,
56 heads: impl IntoIterator<Item = Revision>,
57 sample: &mut HashSet<Revision>,
57 sample: &mut HashSet<Revision>,
58 parentsfn: impl Fn(Revision) -> Result<I, GraphError>,
58 parentsfn: impl Fn(Revision) -> Result<I, GraphError>,
59 quicksamplesize: Option<usize>,
59 quicksamplesize: Option<usize>,
60 ) -> Result<(), GraphError>
60 ) -> Result<(), GraphError>
61 where
61 where
62 I: Iterator<Item = Revision>,
62 I: Iterator<Item = Revision>,
63 {
63 {
64 let mut distances: FastHashMap<Revision, u32> = FastHashMap::default();
64 let mut distances: FastHashMap<Revision, u32> = FastHashMap::default();
65 let mut visit: VecDeque<Revision> = heads.into_iter().collect();
65 let mut visit: VecDeque<Revision> = heads.into_iter().collect();
66 let mut factor: u32 = 1;
66 let mut factor: u32 = 1;
67 let mut seen: HashSet<Revision> = HashSet::new();
67 let mut seen: HashSet<Revision> = HashSet::new();
68 while let Some(current) = visit.pop_front() {
68 while let Some(current) = visit.pop_front() {
69 if !seen.insert(current) {
69 if !seen.insert(current) {
70 continue;
70 continue;
71 }
71 }
72
72
73 let d = *distances.entry(current).or_insert(1);
73 let d = *distances.entry(current).or_insert(1);
74 if d > factor {
74 if d > factor {
75 factor *= 2;
75 factor *= 2;
76 }
76 }
77 if d == factor {
77 if d == factor {
78 sample.insert(current);
78 sample.insert(current);
79 if let Some(sz) = quicksamplesize {
79 if let Some(sz) = quicksamplesize {
80 if sample.len() >= sz {
80 if sample.len() >= sz {
81 return Ok(());
81 return Ok(());
82 }
82 }
83 }
83 }
84 }
84 }
85 for p in parentsfn(current)? {
85 for p in parentsfn(current)? {
86 if let Some(revs) = revs {
86 if let Some(revs) = revs {
87 if !revs.contains(&p) {
87 if !revs.contains(&p) {
88 continue;
88 continue;
89 }
89 }
90 }
90 }
91 distances.entry(p).or_insert(d + 1);
91 distances.entry(p).or_insert(d + 1);
92 visit.push_back(p);
92 visit.push_back(p);
93 }
93 }
94 }
94 }
95 Ok(())
95 Ok(())
96 }
96 }
97
97
98 struct ParentsIterator {
98 struct ParentsIterator {
99 parents: [Revision; 2],
99 parents: [Revision; 2],
100 cur: usize,
100 cur: usize,
101 }
101 }
102
102
103 impl ParentsIterator {
103 impl ParentsIterator {
104 fn graph_parents(
104 fn graph_parents(
105 graph: &impl Graph,
105 graph: &impl Graph,
106 r: Revision,
106 r: Revision,
107 ) -> Result<ParentsIterator, GraphError> {
107 ) -> Result<ParentsIterator, GraphError> {
108 Ok(ParentsIterator {
108 Ok(ParentsIterator {
109 parents: graph.parents(r)?,
109 parents: graph.parents(r)?,
110 cur: 0,
110 cur: 0,
111 })
111 })
112 }
112 }
113 }
113 }
114
114
115 impl Iterator for ParentsIterator {
115 impl Iterator for ParentsIterator {
116 type Item = Revision;
116 type Item = Revision;
117
117
118 fn next(&mut self) -> Option<Revision> {
118 fn next(&mut self) -> Option<Revision> {
119 if self.cur > 1 {
119 if self.cur > 1 {
120 return None;
120 return None;
121 }
121 }
122 let rev = self.parents[self.cur];
122 let rev = self.parents[self.cur];
123 self.cur += 1;
123 self.cur += 1;
124 if rev == NULL_REVISION {
124 if rev == NULL_REVISION {
125 return self.next();
125 return self.next();
126 }
126 }
127 Some(rev)
127 Some(rev)
128 }
128 }
129 }
129 }
130
130
131 impl<G: Graph + Clone> PartialDiscovery<G> {
131 impl<G: Graph + Clone> PartialDiscovery<G> {
132 /// Create a PartialDiscovery object, with the intent
132 /// Create a PartialDiscovery object, with the intent
133 /// of comparing our `::<target_heads>` revset to the contents of another
133 /// of comparing our `::<target_heads>` revset to the contents of another
134 /// repo.
134 /// repo.
135 ///
135 ///
136 /// For now `target_heads` is passed as a vector, and will be used
136 /// For now `target_heads` is passed as a vector, and will be used
137 /// at the first call to `ensure_undecided()`.
137 /// at the first call to `ensure_undecided()`.
138 ///
138 ///
139 /// If we want to make the signature more flexible,
139 /// If we want to make the signature more flexible,
140 /// we'll have to make it a type argument of `PartialDiscovery` or a trait
140 /// we'll have to make it a type argument of `PartialDiscovery` or a trait
141 /// object since we'll keep it in the meanwhile
141 /// object since we'll keep it in the meanwhile
142 ///
142 ///
143 /// The `respect_size` boolean controls how the sampling methods
143 /// The `respect_size` boolean controls how the sampling methods
144 /// will interpret the size argument requested by the caller. If it's
144 /// will interpret the size argument requested by the caller. If it's
145 /// `false`, they are allowed to produce a sample whose size is more
145 /// `false`, they are allowed to produce a sample whose size is more
146 /// appropriate to the situation (typically bigger).
146 /// appropriate to the situation (typically bigger).
147 ///
147 ///
148 /// The `randomize` boolean affects sampling, and specifically how
148 /// The `randomize` boolean affects sampling, and specifically how
149 /// limiting or last-minute expanding is been done:
149 /// limiting or last-minute expanding is been done:
150 ///
150 ///
151 /// If `true`, both will perform random picking from `self.undecided`.
151 /// If `true`, both will perform random picking from `self.undecided`.
152 /// This is currently the best for actual discoveries.
152 /// This is currently the best for actual discoveries.
153 ///
153 ///
154 /// If `false`, a reproductible picking strategy is performed. This is
154 /// If `false`, a reproductible picking strategy is performed. This is
155 /// useful for integration tests.
155 /// useful for integration tests.
156 pub fn new(
156 pub fn new(
157 graph: G,
157 graph: G,
158 target_heads: Vec<Revision>,
158 target_heads: Vec<Revision>,
159 respect_size: bool,
159 respect_size: bool,
160 randomize: bool,
160 randomize: bool,
161 ) -> Self {
161 ) -> Self {
162 let mut seed = [0; 16];
162 let mut seed = [0; 16];
163 if randomize {
163 if randomize {
164 thread_rng().fill_bytes(&mut seed);
164 thread_rng().fill_bytes(&mut seed);
165 }
165 }
166 Self::new_with_seed(graph, target_heads, seed, respect_size, randomize)
166 Self::new_with_seed(graph, target_heads, seed, respect_size, randomize)
167 }
167 }
168
168
169 pub fn new_with_seed(
169 pub fn new_with_seed(
170 graph: G,
170 graph: G,
171 target_heads: Vec<Revision>,
171 target_heads: Vec<Revision>,
172 seed: Seed,
172 seed: Seed,
173 respect_size: bool,
173 respect_size: bool,
174 randomize: bool,
174 randomize: bool,
175 ) -> Self {
175 ) -> Self {
176 PartialDiscovery {
176 PartialDiscovery {
177 undecided: None,
177 undecided: None,
178 children_cache: None,
178 children_cache: None,
179 target_heads: Some(target_heads),
179 target_heads: Some(target_heads),
180 graph: graph.clone(),
180 graph: graph.clone(),
181 common: MissingAncestors::new(graph, vec![]),
181 common: MissingAncestors::new(graph, vec![]),
182 missing: HashSet::new(),
182 missing: HashSet::new(),
183 rng: Rng::from_seed(seed),
183 rng: Rng::from_seed(seed),
184 respect_size: respect_size,
184 respect_size: respect_size,
185 randomize: randomize,
185 randomize: randomize,
186 }
186 }
187 }
187 }
188
188
189 /// Extract at most `size` random elements from sample and return them
189 /// Extract at most `size` random elements from sample and return them
190 /// as a vector
190 /// as a vector
191 fn limit_sample(
191 fn limit_sample(
192 &mut self,
192 &mut self,
193 mut sample: Vec<Revision>,
193 mut sample: Vec<Revision>,
194 size: usize,
194 size: usize,
195 ) -> Vec<Revision> {
195 ) -> Vec<Revision> {
196 if !self.randomize {
196 if !self.randomize {
197 sample.sort();
197 sample.sort();
198 sample.truncate(size);
198 sample.truncate(size);
199 return sample;
199 return sample;
200 }
200 }
201 let sample_len = sample.len();
201 let sample_len = sample.len();
202 if sample_len <= size {
202 if sample_len <= size {
203 return sample;
203 return sample;
204 }
204 }
205 let rng = &mut self.rng;
205 let rng = &mut self.rng;
206 let dropped_size = sample_len - size;
206 let dropped_size = sample_len - size;
207 let limited_slice = if size < dropped_size {
207 let limited_slice = if size < dropped_size {
208 sample.partial_shuffle(rng, size).0
208 sample.partial_shuffle(rng, size).0
209 } else {
209 } else {
210 sample.partial_shuffle(rng, dropped_size).1
210 sample.partial_shuffle(rng, dropped_size).1
211 };
211 };
212 limited_slice.to_owned()
212 limited_slice.to_owned()
213 }
213 }
214
214
215 /// Register revisions known as being common
215 /// Register revisions known as being common
216 pub fn add_common_revisions(
216 pub fn add_common_revisions(
217 &mut self,
217 &mut self,
218 common: impl IntoIterator<Item = Revision>,
218 common: impl IntoIterator<Item = Revision>,
219 ) -> Result<(), GraphError> {
219 ) -> Result<(), GraphError> {
220 let before_len = self.common.get_bases().len();
220 let before_len = self.common.get_bases().len();
221 self.common.add_bases(common);
221 self.common.add_bases(common);
222 if self.common.get_bases().len() == before_len {
222 if self.common.get_bases().len() == before_len {
223 return Ok(());
223 return Ok(());
224 }
224 }
225 if let Some(ref mut undecided) = self.undecided {
225 if let Some(ref mut undecided) = self.undecided {
226 self.common.remove_ancestors_from(undecided)?;
226 self.common.remove_ancestors_from(undecided)?;
227 }
227 }
228 Ok(())
228 Ok(())
229 }
229 }
230
230
231 /// Register revisions known as being missing
231 /// Register revisions known as being missing
232 ///
232 ///
233 /// # Performance note
233 /// # Performance note
234 ///
234 ///
235 /// Except in the most trivial case, the first call of this method has
235 /// Except in the most trivial case, the first call of this method has
236 /// the side effect of computing `self.undecided` set for the first time,
236 /// the side effect of computing `self.undecided` set for the first time,
237 /// and the related caches it might need for efficiency of its internal
237 /// and the related caches it might need for efficiency of its internal
238 /// computation. This is typically faster if more information is
238 /// computation. This is typically faster if more information is
239 /// available in `self.common`. Therefore, for good performance, the
239 /// available in `self.common`. Therefore, for good performance, the
240 /// caller should avoid calling this too early.
240 /// caller should avoid calling this too early.
241 pub fn add_missing_revisions(
241 pub fn add_missing_revisions(
242 &mut self,
242 &mut self,
243 missing: impl IntoIterator<Item = Revision>,
243 missing: impl IntoIterator<Item = Revision>,
244 ) -> Result<(), GraphError> {
244 ) -> Result<(), GraphError> {
245 let mut tovisit: VecDeque<Revision> = missing.into_iter().collect();
245 let mut tovisit: VecDeque<Revision> = missing.into_iter().collect();
246 if tovisit.is_empty() {
246 if tovisit.is_empty() {
247 return Ok(());
247 return Ok(());
248 }
248 }
249 self.ensure_children_cache()?;
249 self.ensure_children_cache()?;
250 self.ensure_undecided()?; // for safety of possible future refactors
250 self.ensure_undecided()?; // for safety of possible future refactors
251 let children = self.children_cache.as_ref().unwrap();
251 let children = self.children_cache.as_ref().unwrap();
252 let mut seen: HashSet<Revision> = HashSet::new();
252 let mut seen: HashSet<Revision> = HashSet::new();
253 let undecided_mut = self.undecided.as_mut().unwrap();
253 let undecided_mut = self.undecided.as_mut().unwrap();
254 while let Some(rev) = tovisit.pop_front() {
254 while let Some(rev) = tovisit.pop_front() {
255 if !self.missing.insert(rev) {
255 if !self.missing.insert(rev) {
256 // either it's known to be missing from a previous
256 // either it's known to be missing from a previous
257 // invocation, and there's no need to iterate on its
257 // invocation, and there's no need to iterate on its
258 // children (we now they are all missing)
258 // children (we now they are all missing)
259 // or it's from a previous iteration of this loop
259 // or it's from a previous iteration of this loop
260 // and its children have already been queued
260 // and its children have already been queued
261 continue;
261 continue;
262 }
262 }
263 undecided_mut.remove(&rev);
263 undecided_mut.remove(&rev);
264 match children.get(&rev) {
264 match children.get(&rev) {
265 None => {
265 None => {
266 continue;
266 continue;
267 }
267 }
268 Some(this_children) => {
268 Some(this_children) => {
269 for child in this_children.iter().cloned() {
269 for child in this_children.iter().cloned() {
270 if seen.insert(child) {
270 if seen.insert(child) {
271 tovisit.push_back(child);
271 tovisit.push_back(child);
272 }
272 }
273 }
273 }
274 }
274 }
275 }
275 }
276 }
276 }
277 Ok(())
277 Ok(())
278 }
278 }
279
279
280 /// Do we have any information about the peer?
280 /// Do we have any information about the peer?
281 pub fn has_info(&self) -> bool {
281 pub fn has_info(&self) -> bool {
282 self.common.has_bases()
282 self.common.has_bases()
283 }
283 }
284
284
285 /// Did we acquire full knowledge of our Revisions that the peer has?
285 /// Did we acquire full knowledge of our Revisions that the peer has?
286 pub fn is_complete(&self) -> bool {
286 pub fn is_complete(&self) -> bool {
287 self.undecided.as_ref().map_or(false, |s| s.is_empty())
287 self.undecided.as_ref().map_or(false, |s| s.is_empty())
288 }
288 }
289
289
290 /// Return the heads of the currently known common set of revisions.
290 /// Return the heads of the currently known common set of revisions.
291 ///
291 ///
292 /// If the discovery process is not complete (see `is_complete()`), the
292 /// If the discovery process is not complete (see `is_complete()`), the
293 /// caller must be aware that this is an intermediate state.
293 /// caller must be aware that this is an intermediate state.
294 ///
294 ///
295 /// On the other hand, if it is complete, then this is currently
295 /// On the other hand, if it is complete, then this is currently
296 /// the only way to retrieve the end results of the discovery process.
296 /// the only way to retrieve the end results of the discovery process.
297 ///
297 ///
298 /// We may introduce in the future an `into_common_heads` call that
298 /// We may introduce in the future an `into_common_heads` call that
299 /// would be more appropriate for normal Rust callers, dropping `self`
299 /// would be more appropriate for normal Rust callers, dropping `self`
300 /// if it is complete.
300 /// if it is complete.
301 pub fn common_heads(&self) -> Result<HashSet<Revision>, GraphError> {
301 pub fn common_heads(&self) -> Result<HashSet<Revision>, GraphError> {
302 self.common.bases_heads()
302 self.common.bases_heads()
303 }
303 }
304
304
305 /// Force first computation of `self.undecided`
305 /// Force first computation of `self.undecided`
306 ///
306 ///
307 /// After this, `self.undecided.as_ref()` and `.as_mut()` can be
307 /// After this, `self.undecided.as_ref()` and `.as_mut()` can be
308 /// unwrapped to get workable immutable or mutable references without
308 /// unwrapped to get workable immutable or mutable references without
309 /// any panic.
309 /// any panic.
310 ///
310 ///
311 /// This is an imperative call instead of an access with added lazyness
311 /// This is an imperative call instead of an access with added lazyness
312 /// to reduce easily the scope of mutable borrow for the caller,
312 /// to reduce easily the scope of mutable borrow for the caller,
313 /// compared to undecided(&'a mut self) -> &'a… that would keep it
313 /// compared to undecided(&'a mut self) -> &'a… that would keep it
314 /// as long as the resulting immutable one.
314 /// as long as the resulting immutable one.
315 fn ensure_undecided(&mut self) -> Result<(), GraphError> {
315 fn ensure_undecided(&mut self) -> Result<(), GraphError> {
316 if self.undecided.is_some() {
316 if self.undecided.is_some() {
317 return Ok(());
317 return Ok(());
318 }
318 }
319 let tgt = self.target_heads.take().unwrap();
319 let tgt = self.target_heads.take().unwrap();
320 self.undecided =
320 self.undecided =
321 Some(self.common.missing_ancestors(tgt)?.into_iter().collect());
321 Some(self.common.missing_ancestors(tgt)?.into_iter().collect());
322 Ok(())
322 Ok(())
323 }
323 }
324
324
325 fn ensure_children_cache(&mut self) -> Result<(), GraphError> {
325 fn ensure_children_cache(&mut self) -> Result<(), GraphError> {
326 if self.children_cache.is_some() {
326 if self.children_cache.is_some() {
327 return Ok(());
327 return Ok(());
328 }
328 }
329 self.ensure_undecided()?;
329 self.ensure_undecided()?;
330
330
331 let mut children: FastHashMap<Revision, Vec<Revision>> =
331 let mut children: FastHashMap<Revision, Vec<Revision>> =
332 FastHashMap::default();
332 FastHashMap::default();
333 for &rev in self.undecided.as_ref().unwrap() {
333 for &rev in self.undecided.as_ref().unwrap() {
334 for p in ParentsIterator::graph_parents(&self.graph, rev)? {
334 for p in ParentsIterator::graph_parents(&self.graph, rev)? {
335 children.entry(p).or_insert_with(|| Vec::new()).push(rev);
335 children.entry(p).or_insert_with(|| Vec::new()).push(rev);
336 }
336 }
337 }
337 }
338 self.children_cache = Some(children);
338 self.children_cache = Some(children);
339 Ok(())
339 Ok(())
340 }
340 }
341
341
342 /// Provide statistics about the current state of the discovery process
342 /// Provide statistics about the current state of the discovery process
343 pub fn stats(&self) -> DiscoveryStats {
343 pub fn stats(&self) -> DiscoveryStats {
344 DiscoveryStats {
344 DiscoveryStats {
345 undecided: self.undecided.as_ref().map(|s| s.len()),
345 undecided: self.undecided.as_ref().map(|s| s.len()),
346 }
346 }
347 }
347 }
348
348
349 pub fn take_quick_sample(
349 pub fn take_quick_sample(
350 &mut self,
350 &mut self,
351 headrevs: impl IntoIterator<Item = Revision>,
351 headrevs: impl IntoIterator<Item = Revision>,
352 size: usize,
352 size: usize,
353 ) -> Result<Vec<Revision>, GraphError> {
353 ) -> Result<Vec<Revision>, GraphError> {
354 self.ensure_undecided()?;
354 self.ensure_undecided()?;
355 let mut sample = {
355 let mut sample = {
356 let undecided = self.undecided.as_ref().unwrap();
356 let undecided = self.undecided.as_ref().unwrap();
357 if undecided.len() <= size {
357 if undecided.len() <= size {
358 return Ok(undecided.iter().cloned().collect());
358 return Ok(undecided.iter().cloned().collect());
359 }
359 }
360 dagops::heads(&self.graph, undecided.iter())?
360 dagops::heads(&self.graph, undecided.iter())?
361 };
361 };
362 if sample.len() >= size {
362 if sample.len() >= size {
363 return Ok(self.limit_sample(sample.into_iter().collect(), size));
363 return Ok(self.limit_sample(sample.into_iter().collect(), size));
364 }
364 }
365 update_sample(
365 update_sample(
366 None,
366 None,
367 headrevs,
367 headrevs,
368 &mut sample,
368 &mut sample,
369 |r| ParentsIterator::graph_parents(&self.graph, r),
369 |r| ParentsIterator::graph_parents(&self.graph, r),
370 Some(size),
370 Some(size),
371 )?;
371 )?;
372 Ok(sample.into_iter().collect())
372 Ok(sample.into_iter().collect())
373 }
373 }
374
374
375 /// Extract a sample from `self.undecided`, going from its heads and roots.
375 /// Extract a sample from `self.undecided`, going from its heads and roots.
376 ///
376 ///
377 /// The `size` parameter is used to avoid useless computations if
377 /// The `size` parameter is used to avoid useless computations if
378 /// it turns out to be bigger than the whole set of undecided Revisions.
378 /// it turns out to be bigger than the whole set of undecided Revisions.
379 ///
379 ///
380 /// The sample is taken by using `update_sample` from the heads, then
380 /// The sample is taken by using `update_sample` from the heads, then
381 /// from the roots, working on the reverse DAG,
381 /// from the roots, working on the reverse DAG,
382 /// expressed by `self.children_cache`.
382 /// expressed by `self.children_cache`.
383 ///
383 ///
384 /// No effort is being made to complete or limit the sample to `size`
384 /// No effort is being made to complete or limit the sample to `size`
385 /// but this method returns another interesting size that it derives
385 /// but this method returns another interesting size that it derives
386 /// from its knowledge of the structure of the various sets, leaving
386 /// from its knowledge of the structure of the various sets, leaving
387 /// to the caller the decision to use it or not.
387 /// to the caller the decision to use it or not.
388 fn bidirectional_sample(
388 fn bidirectional_sample(
389 &mut self,
389 &mut self,
390 size: usize,
390 size: usize,
391 ) -> Result<(HashSet<Revision>, usize), GraphError> {
391 ) -> Result<(HashSet<Revision>, usize), GraphError> {
392 self.ensure_undecided()?;
392 self.ensure_undecided()?;
393 {
393 {
394 // we don't want to compute children_cache before this
394 // we don't want to compute children_cache before this
395 // but doing it after extracting self.undecided takes a mutable
395 // but doing it after extracting self.undecided takes a mutable
396 // ref to self while a shareable one is still active.
396 // ref to self while a shareable one is still active.
397 let undecided = self.undecided.as_ref().unwrap();
397 let undecided = self.undecided.as_ref().unwrap();
398 if undecided.len() <= size {
398 if undecided.len() <= size {
399 return Ok((undecided.clone(), size));
399 return Ok((undecided.clone(), size));
400 }
400 }
401 }
401 }
402
402
403 self.ensure_children_cache()?;
403 self.ensure_children_cache()?;
404 let revs = self.undecided.as_ref().unwrap();
404 let revs = self.undecided.as_ref().unwrap();
405 let mut sample: HashSet<Revision> = revs.clone();
405 let mut sample: HashSet<Revision> = revs.clone();
406
406
407 // it's possible that leveraging the children cache would be more
407 // it's possible that leveraging the children cache would be more
408 // efficient here
408 // efficient here
409 dagops::retain_heads(&self.graph, &mut sample)?;
409 dagops::retain_heads(&self.graph, &mut sample)?;
410 let revsheads = sample.clone(); // was again heads(revs) in python
410 let revsheads = sample.clone(); // was again heads(revs) in python
411
411
412 // update from heads
412 // update from heads
413 update_sample(
413 update_sample(
414 Some(revs),
414 Some(revs),
415 revsheads.iter().cloned(),
415 revsheads.iter().cloned(),
416 &mut sample,
416 &mut sample,
417 |r| ParentsIterator::graph_parents(&self.graph, r),
417 |r| ParentsIterator::graph_parents(&self.graph, r),
418 None,
418 None,
419 )?;
419 )?;
420
420
421 // update from roots
421 // update from roots
422 let revroots: HashSet<Revision> =
422 let revroots: HashSet<Revision> =
423 dagops::roots(&self.graph, revs)?.into_iter().collect();
423 dagops::roots(&self.graph, revs)?.into_iter().collect();
424 let prescribed_size = max(size, min(revroots.len(), revsheads.len()));
424 let prescribed_size = max(size, min(revroots.len(), revsheads.len()));
425
425
426 let children = self.children_cache.as_ref().unwrap();
426 let children = self.children_cache.as_ref().unwrap();
427 let empty_vec: Vec<Revision> = Vec::new();
427 let empty_vec: Vec<Revision> = Vec::new();
428 update_sample(
428 update_sample(
429 Some(revs),
429 Some(revs),
430 revroots,
430 revroots,
431 &mut sample,
431 &mut sample,
432 |r| Ok(children.get(&r).unwrap_or(&empty_vec).iter().cloned()),
432 |r| Ok(children.get(&r).unwrap_or(&empty_vec).iter().cloned()),
433 None,
433 None,
434 )?;
434 )?;
435 Ok((sample, prescribed_size))
435 Ok((sample, prescribed_size))
436 }
436 }
437
437
438 /// Fill up sample up to the wished size with random undecided Revisions.
438 /// Fill up sample up to the wished size with random undecided Revisions.
439 ///
439 ///
440 /// This is intended to be used as a last resort completion if the
440 /// This is intended to be used as a last resort completion if the
441 /// regular sampling algorithm returns too few elements.
441 /// regular sampling algorithm returns too few elements.
442 fn random_complete_sample(
442 fn random_complete_sample(
443 &mut self,
443 &mut self,
444 sample: &mut Vec<Revision>,
444 sample: &mut Vec<Revision>,
445 size: usize,
445 size: usize,
446 ) {
446 ) {
447 let sample_len = sample.len();
447 let sample_len = sample.len();
448 if size <= sample_len {
448 if size <= sample_len {
449 return;
449 return;
450 }
450 }
451 let take_from: Vec<Revision> = self
451 let take_from: Vec<Revision> = self
452 .undecided
452 .undecided
453 .as_ref()
453 .as_ref()
454 .unwrap()
454 .unwrap()
455 .iter()
455 .iter()
456 .filter(|&r| !sample.contains(r))
456 .filter(|&r| !sample.contains(r))
457 .cloned()
457 .cloned()
458 .collect();
458 .collect();
459 sample.extend(self.limit_sample(take_from, size - sample_len));
459 sample.extend(self.limit_sample(take_from, size - sample_len));
460 }
460 }
461
461
462 pub fn take_full_sample(
462 pub fn take_full_sample(
463 &mut self,
463 &mut self,
464 size: usize,
464 size: usize,
465 ) -> Result<Vec<Revision>, GraphError> {
465 ) -> Result<Vec<Revision>, GraphError> {
466 let (sample_set, prescribed_size) = self.bidirectional_sample(size)?;
466 let (sample_set, prescribed_size) = self.bidirectional_sample(size)?;
467 let size = if self.respect_size {
467 let size = if self.respect_size {
468 size
468 size
469 } else {
469 } else {
470 prescribed_size
470 prescribed_size
471 };
471 };
472 let mut sample =
472 let mut sample =
473 self.limit_sample(sample_set.into_iter().collect(), size);
473 self.limit_sample(sample_set.into_iter().collect(), size);
474 self.random_complete_sample(&mut sample, size);
474 self.random_complete_sample(&mut sample, size);
475 Ok(sample)
475 Ok(sample)
476 }
476 }
477 }
477 }
478
478
479 #[cfg(test)]
479 #[cfg(test)]
480 mod tests {
480 mod tests {
481 use super::*;
481 use super::*;
482 use crate::testing::SampleGraph;
482 use crate::testing::SampleGraph;
483
483
484 /// A PartialDiscovery as for pushing all the heads of `SampleGraph`
484 /// A PartialDiscovery as for pushing all the heads of `SampleGraph`
485 ///
485 ///
486 /// To avoid actual randomness in these tests, we give it a fixed
486 /// To avoid actual randomness in these tests, we give it a fixed
487 /// random seed, but by default we'll test the random version.
487 /// random seed, but by default we'll test the random version.
488 fn full_disco() -> PartialDiscovery<SampleGraph> {
488 fn full_disco() -> PartialDiscovery<SampleGraph> {
489 PartialDiscovery::new_with_seed(
489 PartialDiscovery::new_with_seed(
490 SampleGraph,
490 SampleGraph,
491 vec![10, 11, 12, 13],
491 vec![10, 11, 12, 13],
492 [0; 16],
492 [0; 16],
493 true,
493 true,
494 true,
494 true,
495 )
495 )
496 }
496 }
497
497
498 /// A PartialDiscovery as for pushing the 12 head of `SampleGraph`
498 /// A PartialDiscovery as for pushing the 12 head of `SampleGraph`
499 ///
499 ///
500 /// To avoid actual randomness in tests, we give it a fixed random seed.
500 /// To avoid actual randomness in tests, we give it a fixed random seed.
501 fn disco12() -> PartialDiscovery<SampleGraph> {
501 fn disco12() -> PartialDiscovery<SampleGraph> {
502 PartialDiscovery::new_with_seed(
502 PartialDiscovery::new_with_seed(
503 SampleGraph,
503 SampleGraph,
504 vec![12],
504 vec![12],
505 [0; 16],
505 [0; 16],
506 true,
506 true,
507 true,
507 true,
508 )
508 )
509 }
509 }
510
510
511 fn sorted_undecided(
511 fn sorted_undecided(
512 disco: &PartialDiscovery<SampleGraph>,
512 disco: &PartialDiscovery<SampleGraph>,
513 ) -> Vec<Revision> {
513 ) -> Vec<Revision> {
514 let mut as_vec: Vec<Revision> =
514 let mut as_vec: Vec<Revision> =
515 disco.undecided.as_ref().unwrap().iter().cloned().collect();
515 disco.undecided.as_ref().unwrap().iter().cloned().collect();
516 as_vec.sort();
516 as_vec.sort();
517 as_vec
517 as_vec
518 }
518 }
519
519
520 fn sorted_missing(disco: &PartialDiscovery<SampleGraph>) -> Vec<Revision> {
520 fn sorted_missing(disco: &PartialDiscovery<SampleGraph>) -> Vec<Revision> {
521 let mut as_vec: Vec<Revision> =
521 let mut as_vec: Vec<Revision> =
522 disco.missing.iter().cloned().collect();
522 disco.missing.iter().cloned().collect();
523 as_vec.sort();
523 as_vec.sort();
524 as_vec
524 as_vec
525 }
525 }
526
526
527 fn sorted_common_heads(
527 fn sorted_common_heads(
528 disco: &PartialDiscovery<SampleGraph>,
528 disco: &PartialDiscovery<SampleGraph>,
529 ) -> Result<Vec<Revision>, GraphError> {
529 ) -> Result<Vec<Revision>, GraphError> {
530 let mut as_vec: Vec<Revision> =
530 let mut as_vec: Vec<Revision> =
531 disco.common_heads()?.iter().cloned().collect();
531 disco.common_heads()?.iter().cloned().collect();
532 as_vec.sort();
532 as_vec.sort();
533 Ok(as_vec)
533 Ok(as_vec)
534 }
534 }
535
535
536 #[test]
536 #[test]
537 fn test_add_common_get_undecided() -> Result<(), GraphError> {
537 fn test_add_common_get_undecided() -> Result<(), GraphError> {
538 let mut disco = full_disco();
538 let mut disco = full_disco();
539 assert_eq!(disco.undecided, None);
539 assert_eq!(disco.undecided, None);
540 assert!(!disco.has_info());
540 assert!(!disco.has_info());
541 assert_eq!(disco.stats().undecided, None);
541 assert_eq!(disco.stats().undecided, None);
542
542
543 disco.add_common_revisions(vec![11, 12])?;
543 disco.add_common_revisions(vec![11, 12])?;
544 assert!(disco.has_info());
544 assert!(disco.has_info());
545 assert!(!disco.is_complete());
545 assert!(!disco.is_complete());
546 assert!(disco.missing.is_empty());
546 assert!(disco.missing.is_empty());
547
547
548 // add_common_revisions did not trigger a premature computation
548 // add_common_revisions did not trigger a premature computation
549 // of `undecided`, let's check that and ask for them
549 // of `undecided`, let's check that and ask for them
550 assert_eq!(disco.undecided, None);
550 assert_eq!(disco.undecided, None);
551 disco.ensure_undecided()?;
551 disco.ensure_undecided()?;
552 assert_eq!(sorted_undecided(&disco), vec![5, 8, 10, 13]);
552 assert_eq!(sorted_undecided(&disco), vec![5, 8, 10, 13]);
553 assert_eq!(disco.stats().undecided, Some(4));
553 assert_eq!(disco.stats().undecided, Some(4));
554 Ok(())
554 Ok(())
555 }
555 }
556
556
557 /// in this test, we pretend that our peer misses exactly (8+10)::
557 /// in this test, we pretend that our peer misses exactly (8+10)::
558 /// and we're comparing all our repo to it (as in a bare push)
558 /// and we're comparing all our repo to it (as in a bare push)
559 #[test]
559 #[test]
560 fn test_discovery() -> Result<(), GraphError> {
560 fn test_discovery() -> Result<(), GraphError> {
561 let mut disco = full_disco();
561 let mut disco = full_disco();
562 disco.add_common_revisions(vec![11, 12])?;
562 disco.add_common_revisions(vec![11, 12])?;
563 disco.add_missing_revisions(vec![8, 10])?;
563 disco.add_missing_revisions(vec![8, 10])?;
564 assert_eq!(sorted_undecided(&disco), vec![5]);
564 assert_eq!(sorted_undecided(&disco), vec![5]);
565 assert_eq!(sorted_missing(&disco), vec![8, 10, 13]);
565 assert_eq!(sorted_missing(&disco), vec![8, 10, 13]);
566 assert!(!disco.is_complete());
566 assert!(!disco.is_complete());
567
567
568 disco.add_common_revisions(vec![5])?;
568 disco.add_common_revisions(vec![5])?;
569 assert_eq!(sorted_undecided(&disco), vec![]);
569 assert_eq!(sorted_undecided(&disco), vec![]);
570 assert_eq!(sorted_missing(&disco), vec![8, 10, 13]);
570 assert_eq!(sorted_missing(&disco), vec![8, 10, 13]);
571 assert!(disco.is_complete());
571 assert!(disco.is_complete());
572 assert_eq!(sorted_common_heads(&disco)?, vec![5, 11, 12]);
572 assert_eq!(sorted_common_heads(&disco)?, vec![5, 11, 12]);
573 Ok(())
573 Ok(())
574 }
574 }
575
575
576 #[test]
576 #[test]
577 fn test_add_missing_early_continue() -> Result<(), GraphError> {
577 fn test_add_missing_early_continue() -> Result<(), GraphError> {
578 eprintln!("test_add_missing_early_stop");
578 eprintln!("test_add_missing_early_stop");
579 let mut disco = full_disco();
579 let mut disco = full_disco();
580 disco.add_common_revisions(vec![13, 3, 4])?;
580 disco.add_common_revisions(vec![13, 3, 4])?;
581 disco.ensure_children_cache()?;
581 disco.ensure_children_cache()?;
582 // 12 is grand-child of 6 through 9
582 // 12 is grand-child of 6 through 9
583 // passing them in this order maximizes the chances of the
583 // passing them in this order maximizes the chances of the
584 // early continue to do the wrong thing
584 // early continue to do the wrong thing
585 disco.add_missing_revisions(vec![6, 9, 12])?;
585 disco.add_missing_revisions(vec![6, 9, 12])?;
586 assert_eq!(sorted_undecided(&disco), vec![5, 7, 10, 11]);
586 assert_eq!(sorted_undecided(&disco), vec![5, 7, 10, 11]);
587 assert_eq!(sorted_missing(&disco), vec![6, 9, 12]);
587 assert_eq!(sorted_missing(&disco), vec![6, 9, 12]);
588 assert!(!disco.is_complete());
588 assert!(!disco.is_complete());
589 Ok(())
589 Ok(())
590 }
590 }
591
591
592 #[test]
592 #[test]
593 fn test_limit_sample_no_need_to() {
593 fn test_limit_sample_no_need_to() {
594 let sample = vec![1, 2, 3, 4];
594 let sample = vec![1, 2, 3, 4];
595 assert_eq!(full_disco().limit_sample(sample, 10), vec![1, 2, 3, 4]);
595 assert_eq!(full_disco().limit_sample(sample, 10), vec![1, 2, 3, 4]);
596 }
596 }
597
597
598 #[test]
598 #[test]
599 fn test_limit_sample_less_than_half() {
599 fn test_limit_sample_less_than_half() {
600 assert_eq!(full_disco().limit_sample((1..6).collect(), 2), vec![4, 2]);
600 assert_eq!(full_disco().limit_sample((1..6).collect(), 2), vec![2, 5]);
601 }
601 }
602
602
603 #[test]
603 #[test]
604 fn test_limit_sample_more_than_half() {
604 fn test_limit_sample_more_than_half() {
605 assert_eq!(full_disco().limit_sample((1..4).collect(), 2), vec![3, 2]);
605 assert_eq!(full_disco().limit_sample((1..4).collect(), 2), vec![1, 2]);
606 }
606 }
607
607
608 #[test]
608 #[test]
609 fn test_limit_sample_no_random() {
609 fn test_limit_sample_no_random() {
610 let mut disco = full_disco();
610 let mut disco = full_disco();
611 disco.randomize = false;
611 disco.randomize = false;
612 assert_eq!(
612 assert_eq!(
613 disco.limit_sample(vec![1, 8, 13, 5, 7, 3], 4),
613 disco.limit_sample(vec![1, 8, 13, 5, 7, 3], 4),
614 vec![1, 3, 5, 7]
614 vec![1, 3, 5, 7]
615 );
615 );
616 }
616 }
617
617
618 #[test]
618 #[test]
619 fn test_quick_sample_enough_undecided_heads() -> Result<(), GraphError> {
619 fn test_quick_sample_enough_undecided_heads() -> Result<(), GraphError> {
620 let mut disco = full_disco();
620 let mut disco = full_disco();
621 disco.undecided = Some((1..=13).collect());
621 disco.undecided = Some((1..=13).collect());
622
622
623 let mut sample_vec = disco.take_quick_sample(vec![], 4)?;
623 let mut sample_vec = disco.take_quick_sample(vec![], 4)?;
624 sample_vec.sort();
624 sample_vec.sort();
625 assert_eq!(sample_vec, vec![10, 11, 12, 13]);
625 assert_eq!(sample_vec, vec![10, 11, 12, 13]);
626 Ok(())
626 Ok(())
627 }
627 }
628
628
629 #[test]
629 #[test]
630 fn test_quick_sample_climbing_from_12() -> Result<(), GraphError> {
630 fn test_quick_sample_climbing_from_12() -> Result<(), GraphError> {
631 let mut disco = disco12();
631 let mut disco = disco12();
632 disco.ensure_undecided()?;
632 disco.ensure_undecided()?;
633
633
634 let mut sample_vec = disco.take_quick_sample(vec![12], 4)?;
634 let mut sample_vec = disco.take_quick_sample(vec![12], 4)?;
635 sample_vec.sort();
635 sample_vec.sort();
636 // r12's only parent is r9, whose unique grand-parent through the
636 // r12's only parent is r9, whose unique grand-parent through the
637 // diamond shape is r4. This ends there because the distance from r4
637 // diamond shape is r4. This ends there because the distance from r4
638 // to the root is only 3.
638 // to the root is only 3.
639 assert_eq!(sample_vec, vec![4, 9, 12]);
639 assert_eq!(sample_vec, vec![4, 9, 12]);
640 Ok(())
640 Ok(())
641 }
641 }
642
642
643 #[test]
643 #[test]
644 fn test_children_cache() -> Result<(), GraphError> {
644 fn test_children_cache() -> Result<(), GraphError> {
645 let mut disco = full_disco();
645 let mut disco = full_disco();
646 disco.ensure_children_cache()?;
646 disco.ensure_children_cache()?;
647
647
648 let cache = disco.children_cache.unwrap();
648 let cache = disco.children_cache.unwrap();
649 assert_eq!(cache.get(&2).cloned(), Some(vec![4]));
649 assert_eq!(cache.get(&2).cloned(), Some(vec![4]));
650 assert_eq!(cache.get(&10).cloned(), None);
650 assert_eq!(cache.get(&10).cloned(), None);
651
651
652 let mut children_4 = cache.get(&4).cloned().unwrap();
652 let mut children_4 = cache.get(&4).cloned().unwrap();
653 children_4.sort();
653 children_4.sort();
654 assert_eq!(children_4, vec![5, 6, 7]);
654 assert_eq!(children_4, vec![5, 6, 7]);
655
655
656 let mut children_7 = cache.get(&7).cloned().unwrap();
656 let mut children_7 = cache.get(&7).cloned().unwrap();
657 children_7.sort();
657 children_7.sort();
658 assert_eq!(children_7, vec![9, 11]);
658 assert_eq!(children_7, vec![9, 11]);
659
659
660 Ok(())
660 Ok(())
661 }
661 }
662
662
663 #[test]
663 #[test]
664 fn test_complete_sample() {
664 fn test_complete_sample() {
665 let mut disco = full_disco();
665 let mut disco = full_disco();
666 let undecided: HashSet<Revision> =
666 let undecided: HashSet<Revision> =
667 [4, 7, 9, 2, 3].iter().cloned().collect();
667 [4, 7, 9, 2, 3].iter().cloned().collect();
668 disco.undecided = Some(undecided);
668 disco.undecided = Some(undecided);
669
669
670 let mut sample = vec![0];
670 let mut sample = vec![0];
671 disco.random_complete_sample(&mut sample, 3);
671 disco.random_complete_sample(&mut sample, 3);
672 assert_eq!(sample.len(), 3);
672 assert_eq!(sample.len(), 3);
673
673
674 let mut sample = vec![2, 4, 7];
674 let mut sample = vec![2, 4, 7];
675 disco.random_complete_sample(&mut sample, 1);
675 disco.random_complete_sample(&mut sample, 1);
676 assert_eq!(sample.len(), 3);
676 assert_eq!(sample.len(), 3);
677 }
677 }
678
678
679 #[test]
679 #[test]
680 fn test_bidirectional_sample() -> Result<(), GraphError> {
680 fn test_bidirectional_sample() -> Result<(), GraphError> {
681 let mut disco = full_disco();
681 let mut disco = full_disco();
682 disco.undecided = Some((0..=13).into_iter().collect());
682 disco.undecided = Some((0..=13).into_iter().collect());
683
683
684 let (sample_set, size) = disco.bidirectional_sample(7)?;
684 let (sample_set, size) = disco.bidirectional_sample(7)?;
685 assert_eq!(size, 7);
685 assert_eq!(size, 7);
686 let mut sample: Vec<Revision> = sample_set.into_iter().collect();
686 let mut sample: Vec<Revision> = sample_set.into_iter().collect();
687 sample.sort();
687 sample.sort();
688 // our DAG is a bit too small for the results to be really interesting
688 // our DAG is a bit too small for the results to be really interesting
689 // at least it shows that
689 // at least it shows that
690 // - we went both ways
690 // - we went both ways
691 // - we didn't take all Revisions (6 is not in the sample)
691 // - we didn't take all Revisions (6 is not in the sample)
692 assert_eq!(sample, vec![0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13]);
692 assert_eq!(sample, vec![0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13]);
693 Ok(())
693 Ok(())
694 }
694 }
695 }
695 }
@@ -1,336 +1,337 b''
1 use hg::testing::VecGraph;
1 use hg::testing::VecGraph;
2 use hg::Revision;
2 use hg::Revision;
3 use hg::*;
3 use hg::*;
4 use rand::distributions::{Distribution, LogNormal, Uniform};
4 use rand::distributions::{Distribution, Uniform};
5 use rand::{thread_rng, Rng, RngCore, SeedableRng};
5 use rand::{thread_rng, Rng, RngCore, SeedableRng};
6 use rand_distr::LogNormal;
6 use std::cmp::min;
7 use std::cmp::min;
7 use std::collections::HashSet;
8 use std::collections::HashSet;
8 use std::env;
9 use std::env;
9 use std::fmt::Debug;
10 use std::fmt::Debug;
10
11
11 fn build_random_graph(
12 fn build_random_graph(
12 nodes_opt: Option<usize>,
13 nodes_opt: Option<usize>,
13 rootprob_opt: Option<f64>,
14 rootprob_opt: Option<f64>,
14 mergeprob_opt: Option<f64>,
15 mergeprob_opt: Option<f64>,
15 prevprob_opt: Option<f64>,
16 prevprob_opt: Option<f64>,
16 ) -> VecGraph {
17 ) -> VecGraph {
17 let nodes = nodes_opt.unwrap_or(100);
18 let nodes = nodes_opt.unwrap_or(100);
18 let rootprob = rootprob_opt.unwrap_or(0.05);
19 let rootprob = rootprob_opt.unwrap_or(0.05);
19 let mergeprob = mergeprob_opt.unwrap_or(0.2);
20 let mergeprob = mergeprob_opt.unwrap_or(0.2);
20 let prevprob = prevprob_opt.unwrap_or(0.7);
21 let prevprob = prevprob_opt.unwrap_or(0.7);
21
22
22 let mut rng = thread_rng();
23 let mut rng = thread_rng();
23 let mut vg: VecGraph = Vec::with_capacity(nodes);
24 let mut vg: VecGraph = Vec::with_capacity(nodes);
24 for i in 0..nodes {
25 for i in 0..nodes {
25 if i == 0 || rng.gen_bool(rootprob) {
26 if i == 0 || rng.gen_bool(rootprob) {
26 vg.push([NULL_REVISION, NULL_REVISION])
27 vg.push([NULL_REVISION, NULL_REVISION])
27 } else if i == 1 {
28 } else if i == 1 {
28 vg.push([0, NULL_REVISION])
29 vg.push([0, NULL_REVISION])
29 } else if rng.gen_bool(mergeprob) {
30 } else if rng.gen_bool(mergeprob) {
30 let p1 = {
31 let p1 = {
31 if i == 2 || rng.gen_bool(prevprob) {
32 if i == 2 || rng.gen_bool(prevprob) {
32 (i - 1) as Revision
33 (i - 1) as Revision
33 } else {
34 } else {
34 rng.gen_range(0, i - 1) as Revision
35 rng.gen_range(0, i - 1) as Revision
35 }
36 }
36 };
37 };
37 // p2 is a random revision lower than i and different from p1
38 // p2 is a random revision lower than i and different from p1
38 let mut p2 = rng.gen_range(0, i - 1) as Revision;
39 let mut p2 = rng.gen_range(0, i - 1) as Revision;
39 if p2 >= p1 {
40 if p2 >= p1 {
40 p2 = p2 + 1;
41 p2 = p2 + 1;
41 }
42 }
42 vg.push([p1, p2]);
43 vg.push([p1, p2]);
43 } else if rng.gen_bool(prevprob) {
44 } else if rng.gen_bool(prevprob) {
44 vg.push([(i - 1) as Revision, NULL_REVISION])
45 vg.push([(i - 1) as Revision, NULL_REVISION])
45 } else {
46 } else {
46 vg.push([rng.gen_range(0, i - 1) as Revision, NULL_REVISION])
47 vg.push([rng.gen_range(0, i - 1) as Revision, NULL_REVISION])
47 }
48 }
48 }
49 }
49 vg
50 vg
50 }
51 }
51
52
52 /// Compute the ancestors set of all revisions of a VecGraph
53 /// Compute the ancestors set of all revisions of a VecGraph
53 fn ancestors_sets(vg: &VecGraph) -> Vec<HashSet<Revision>> {
54 fn ancestors_sets(vg: &VecGraph) -> Vec<HashSet<Revision>> {
54 let mut ancs: Vec<HashSet<Revision>> = Vec::new();
55 let mut ancs: Vec<HashSet<Revision>> = Vec::new();
55 for i in 0..vg.len() {
56 for i in 0..vg.len() {
56 let mut ancs_i = HashSet::new();
57 let mut ancs_i = HashSet::new();
57 ancs_i.insert(i as Revision);
58 ancs_i.insert(i as Revision);
58 for p in vg[i].iter().cloned() {
59 for p in vg[i].iter().cloned() {
59 if p != NULL_REVISION {
60 if p != NULL_REVISION {
60 ancs_i.extend(&ancs[p as usize]);
61 ancs_i.extend(&ancs[p as usize]);
61 }
62 }
62 }
63 }
63 ancs.push(ancs_i);
64 ancs.push(ancs_i);
64 }
65 }
65 ancs
66 ancs
66 }
67 }
67
68
68 #[derive(Clone, Debug)]
69 #[derive(Clone, Debug)]
69 enum MissingAncestorsAction {
70 enum MissingAncestorsAction {
70 InitialBases(HashSet<Revision>),
71 InitialBases(HashSet<Revision>),
71 AddBases(HashSet<Revision>),
72 AddBases(HashSet<Revision>),
72 RemoveAncestorsFrom(HashSet<Revision>),
73 RemoveAncestorsFrom(HashSet<Revision>),
73 MissingAncestors(HashSet<Revision>),
74 MissingAncestors(HashSet<Revision>),
74 }
75 }
75
76
76 /// An instrumented naive yet obviously correct implementation
77 /// An instrumented naive yet obviously correct implementation
77 ///
78 ///
78 /// It also records all its actions for easy reproduction for replay
79 /// It also records all its actions for easy reproduction for replay
79 /// of problematic cases
80 /// of problematic cases
80 struct NaiveMissingAncestors<'a> {
81 struct NaiveMissingAncestors<'a> {
81 ancestors_sets: &'a Vec<HashSet<Revision>>,
82 ancestors_sets: &'a Vec<HashSet<Revision>>,
82 graph: &'a VecGraph, // used for error reporting only
83 graph: &'a VecGraph, // used for error reporting only
83 bases: HashSet<Revision>,
84 bases: HashSet<Revision>,
84 history: Vec<MissingAncestorsAction>,
85 history: Vec<MissingAncestorsAction>,
85 // for error reporting, assuming we are in a random test
86 // for error reporting, assuming we are in a random test
86 random_seed: String,
87 random_seed: String,
87 }
88 }
88
89
89 impl<'a> NaiveMissingAncestors<'a> {
90 impl<'a> NaiveMissingAncestors<'a> {
90 fn new(
91 fn new(
91 graph: &'a VecGraph,
92 graph: &'a VecGraph,
92 ancestors_sets: &'a Vec<HashSet<Revision>>,
93 ancestors_sets: &'a Vec<HashSet<Revision>>,
93 bases: &HashSet<Revision>,
94 bases: &HashSet<Revision>,
94 random_seed: &str,
95 random_seed: &str,
95 ) -> Self {
96 ) -> Self {
96 Self {
97 Self {
97 ancestors_sets: ancestors_sets,
98 ancestors_sets: ancestors_sets,
98 bases: bases.clone(),
99 bases: bases.clone(),
99 graph: graph,
100 graph: graph,
100 history: vec![MissingAncestorsAction::InitialBases(bases.clone())],
101 history: vec![MissingAncestorsAction::InitialBases(bases.clone())],
101 random_seed: random_seed.into(),
102 random_seed: random_seed.into(),
102 }
103 }
103 }
104 }
104
105
105 fn add_bases(&mut self, new_bases: HashSet<Revision>) {
106 fn add_bases(&mut self, new_bases: HashSet<Revision>) {
106 self.bases.extend(&new_bases);
107 self.bases.extend(&new_bases);
107 self.history
108 self.history
108 .push(MissingAncestorsAction::AddBases(new_bases))
109 .push(MissingAncestorsAction::AddBases(new_bases))
109 }
110 }
110
111
111 fn remove_ancestors_from(&mut self, revs: &mut HashSet<Revision>) {
112 fn remove_ancestors_from(&mut self, revs: &mut HashSet<Revision>) {
112 revs.remove(&NULL_REVISION);
113 revs.remove(&NULL_REVISION);
113 self.history
114 self.history
114 .push(MissingAncestorsAction::RemoveAncestorsFrom(revs.clone()));
115 .push(MissingAncestorsAction::RemoveAncestorsFrom(revs.clone()));
115 for base in self.bases.iter().cloned() {
116 for base in self.bases.iter().cloned() {
116 if base != NULL_REVISION {
117 if base != NULL_REVISION {
117 for rev in &self.ancestors_sets[base as usize] {
118 for rev in &self.ancestors_sets[base as usize] {
118 revs.remove(&rev);
119 revs.remove(&rev);
119 }
120 }
120 }
121 }
121 }
122 }
122 }
123 }
123
124
124 fn missing_ancestors(
125 fn missing_ancestors(
125 &mut self,
126 &mut self,
126 revs: impl IntoIterator<Item = Revision>,
127 revs: impl IntoIterator<Item = Revision>,
127 ) -> Vec<Revision> {
128 ) -> Vec<Revision> {
128 let revs_as_set: HashSet<Revision> = revs.into_iter().collect();
129 let revs_as_set: HashSet<Revision> = revs.into_iter().collect();
129
130
130 let mut missing: HashSet<Revision> = HashSet::new();
131 let mut missing: HashSet<Revision> = HashSet::new();
131 for rev in revs_as_set.iter().cloned() {
132 for rev in revs_as_set.iter().cloned() {
132 if rev != NULL_REVISION {
133 if rev != NULL_REVISION {
133 missing.extend(&self.ancestors_sets[rev as usize])
134 missing.extend(&self.ancestors_sets[rev as usize])
134 }
135 }
135 }
136 }
136 self.history
137 self.history
137 .push(MissingAncestorsAction::MissingAncestors(revs_as_set));
138 .push(MissingAncestorsAction::MissingAncestors(revs_as_set));
138
139
139 for base in self.bases.iter().cloned() {
140 for base in self.bases.iter().cloned() {
140 if base != NULL_REVISION {
141 if base != NULL_REVISION {
141 for rev in &self.ancestors_sets[base as usize] {
142 for rev in &self.ancestors_sets[base as usize] {
142 missing.remove(&rev);
143 missing.remove(&rev);
143 }
144 }
144 }
145 }
145 }
146 }
146 let mut res: Vec<Revision> = missing.iter().cloned().collect();
147 let mut res: Vec<Revision> = missing.iter().cloned().collect();
147 res.sort();
148 res.sort();
148 res
149 res
149 }
150 }
150
151
151 fn assert_eq<T>(&self, left: T, right: T)
152 fn assert_eq<T>(&self, left: T, right: T)
152 where
153 where
153 T: PartialEq + Debug,
154 T: PartialEq + Debug,
154 {
155 {
155 if left == right {
156 if left == right {
156 return;
157 return;
157 }
158 }
158 panic!(format!(
159 panic!(format!(
159 "Equality assertion failed (left != right)
160 "Equality assertion failed (left != right)
160 left={:?}
161 left={:?}
161 right={:?}
162 right={:?}
162 graph={:?}
163 graph={:?}
163 current bases={:?}
164 current bases={:?}
164 history={:?}
165 history={:?}
165 random seed={}
166 random seed={}
166 ",
167 ",
167 left,
168 left,
168 right,
169 right,
169 self.graph,
170 self.graph,
170 self.bases,
171 self.bases,
171 self.history,
172 self.history,
172 self.random_seed,
173 self.random_seed,
173 ));
174 ));
174 }
175 }
175 }
176 }
176
177
177 /// Choose a set of random revisions
178 /// Choose a set of random revisions
178 ///
179 ///
179 /// The size of the set is taken from a LogNormal distribution
180 /// The size of the set is taken from a LogNormal distribution
180 /// with default mu=1.1 and default sigma=0.8. Quoting the Python
181 /// with default mu=1.1 and default sigma=0.8. Quoting the Python
181 /// test this is taken from:
182 /// test this is taken from:
182 /// the default mu and sigma give us a nice distribution of mostly
183 /// the default mu and sigma give us a nice distribution of mostly
183 /// single-digit counts (including 0) with some higher ones
184 /// single-digit counts (including 0) with some higher ones
184 /// The sample may include NULL_REVISION
185 /// The sample may include NULL_REVISION
185 fn sample_revs<R: RngCore>(
186 fn sample_revs<R: RngCore>(
186 rng: &mut R,
187 rng: &mut R,
187 maxrev: Revision,
188 maxrev: Revision,
188 mu_opt: Option<f64>,
189 mu_opt: Option<f64>,
189 sigma_opt: Option<f64>,
190 sigma_opt: Option<f64>,
190 ) -> HashSet<Revision> {
191 ) -> HashSet<Revision> {
191 let mu = mu_opt.unwrap_or(1.1);
192 let mu = mu_opt.unwrap_or(1.1);
192 let sigma = sigma_opt.unwrap_or(0.8);
193 let sigma = sigma_opt.unwrap_or(0.8);
193
194
194 let log_normal = LogNormal::new(mu, sigma);
195 let log_normal = LogNormal::new(mu, sigma).unwrap();
195 let nb = min(maxrev as usize, log_normal.sample(rng).floor() as usize);
196 let nb = min(maxrev as usize, log_normal.sample(rng).floor() as usize);
196
197
197 let dist = Uniform::from(NULL_REVISION..maxrev);
198 let dist = Uniform::from(NULL_REVISION..maxrev);
198 return rng.sample_iter(&dist).take(nb).collect();
199 return rng.sample_iter(&dist).take(nb).collect();
199 }
200 }
200
201
201 /// Produces the hexadecimal representation of a slice of bytes
202 /// Produces the hexadecimal representation of a slice of bytes
202 fn hex_bytes(bytes: &[u8]) -> String {
203 fn hex_bytes(bytes: &[u8]) -> String {
203 let mut s = String::with_capacity(bytes.len() * 2);
204 let mut s = String::with_capacity(bytes.len() * 2);
204 for b in bytes {
205 for b in bytes {
205 s.push_str(&format!("{:x}", b));
206 s.push_str(&format!("{:x}", b));
206 }
207 }
207 s
208 s
208 }
209 }
209
210
210 /// Fill a random seed from its hexadecimal representation.
211 /// Fill a random seed from its hexadecimal representation.
211 ///
212 ///
212 /// This signature is meant to be consistent with `RngCore::fill_bytes`
213 /// This signature is meant to be consistent with `RngCore::fill_bytes`
213 fn seed_parse_in(hex: &str, seed: &mut [u8]) {
214 fn seed_parse_in(hex: &str, seed: &mut [u8]) {
214 if hex.len() != 32 {
215 if hex.len() != 32 {
215 panic!("Seed {} is too short for 128 bits hex", hex);
216 panic!("Seed {} is too short for 128 bits hex", hex);
216 }
217 }
217 for i in 0..8 {
218 for i in 0..8 {
218 seed[i] = u8::from_str_radix(&hex[2 * i..2 * (i + 1)], 16)
219 seed[i] = u8::from_str_radix(&hex[2 * i..2 * (i + 1)], 16)
219 .unwrap_or_else(|_e| panic!("Seed {} is not 128 bits hex", hex));
220 .unwrap_or_else(|_e| panic!("Seed {} is not 128 bits hex", hex));
220 }
221 }
221 }
222 }
222
223
223 /// Parse the parameters for `test_missing_ancestors()`
224 /// Parse the parameters for `test_missing_ancestors()`
224 ///
225 ///
225 /// Returns (graphs, instances, calls per instance)
226 /// Returns (graphs, instances, calls per instance)
226 fn parse_test_missing_ancestors_params(var: &str) -> (usize, usize, usize) {
227 fn parse_test_missing_ancestors_params(var: &str) -> (usize, usize, usize) {
227 let err_msg = "TEST_MISSING_ANCESTORS format: GRAPHS,INSTANCES,CALLS";
228 let err_msg = "TEST_MISSING_ANCESTORS format: GRAPHS,INSTANCES,CALLS";
228 let params: Vec<usize> = var
229 let params: Vec<usize> = var
229 .split(',')
230 .split(',')
230 .map(|n| n.trim().parse().expect(err_msg))
231 .map(|n| n.trim().parse().expect(err_msg))
231 .collect();
232 .collect();
232 if params.len() != 3 {
233 if params.len() != 3 {
233 panic!(err_msg);
234 panic!(err_msg);
234 }
235 }
235 (params[0], params[1], params[2])
236 (params[0], params[1], params[2])
236 }
237 }
237
238
238 #[test]
239 #[test]
239 /// This test creates lots of random VecGraphs,
240 /// This test creates lots of random VecGraphs,
240 /// and compare a bunch of MissingAncestors for them with
241 /// and compare a bunch of MissingAncestors for them with
241 /// NaiveMissingAncestors that rely on precomputed transitive closures of
242 /// NaiveMissingAncestors that rely on precomputed transitive closures of
242 /// these VecGraphs (ancestors_sets).
243 /// these VecGraphs (ancestors_sets).
243 ///
244 ///
244 /// For each generater graph, several instances of `MissingAncestors` are
245 /// For each generater graph, several instances of `MissingAncestors` are
245 /// created, whose methods are called and checked a given number of times.
246 /// created, whose methods are called and checked a given number of times.
246 ///
247 ///
247 /// This test can be parametrized by two environment variables:
248 /// This test can be parametrized by two environment variables:
248 ///
249 ///
249 /// - TEST_RANDOM_SEED: must be 128 bits in hexadecimal
250 /// - TEST_RANDOM_SEED: must be 128 bits in hexadecimal
250 /// - TEST_MISSING_ANCESTORS: "GRAPHS,INSTANCES,CALLS". The default is
251 /// - TEST_MISSING_ANCESTORS: "GRAPHS,INSTANCES,CALLS". The default is
251 /// "100,10,10"
252 /// "100,10,10"
252 ///
253 ///
253 /// This is slow: it runs on my workstation in about 5 seconds with the
254 /// This is slow: it runs on my workstation in about 5 seconds with the
254 /// default parameters with a plain `cargo --test`.
255 /// default parameters with a plain `cargo --test`.
255 ///
256 ///
256 /// If you want to run it faster, especially if you're changing the
257 /// If you want to run it faster, especially if you're changing the
257 /// parameters, use `cargo test --release`.
258 /// parameters, use `cargo test --release`.
258 /// For me, that gets it down to 0.15 seconds with the default parameters
259 /// For me, that gets it down to 0.15 seconds with the default parameters
259 fn test_missing_ancestors_compare_naive() {
260 fn test_missing_ancestors_compare_naive() {
260 let (graphcount, testcount, inccount) =
261 let (graphcount, testcount, inccount) =
261 match env::var("TEST_MISSING_ANCESTORS") {
262 match env::var("TEST_MISSING_ANCESTORS") {
262 Err(env::VarError::NotPresent) => (100, 10, 10),
263 Err(env::VarError::NotPresent) => (100, 10, 10),
263 Ok(val) => parse_test_missing_ancestors_params(&val),
264 Ok(val) => parse_test_missing_ancestors_params(&val),
264 Err(env::VarError::NotUnicode(_)) => {
265 Err(env::VarError::NotUnicode(_)) => {
265 panic!("TEST_MISSING_ANCESTORS is invalid");
266 panic!("TEST_MISSING_ANCESTORS is invalid");
266 }
267 }
267 };
268 };
268 let mut seed: [u8; 16] = [0; 16];
269 let mut seed: [u8; 16] = [0; 16];
269 match env::var("TEST_RANDOM_SEED") {
270 match env::var("TEST_RANDOM_SEED") {
270 Ok(val) => {
271 Ok(val) => {
271 seed_parse_in(&val, &mut seed);
272 seed_parse_in(&val, &mut seed);
272 }
273 }
273 Err(env::VarError::NotPresent) => {
274 Err(env::VarError::NotPresent) => {
274 thread_rng().fill_bytes(&mut seed);
275 thread_rng().fill_bytes(&mut seed);
275 }
276 }
276 Err(env::VarError::NotUnicode(_)) => {
277 Err(env::VarError::NotUnicode(_)) => {
277 panic!("TEST_RANDOM_SEED must be 128 bits in hex");
278 panic!("TEST_RANDOM_SEED must be 128 bits in hex");
278 }
279 }
279 }
280 }
280 let hex_seed = hex_bytes(&seed);
281 let hex_seed = hex_bytes(&seed);
281 eprintln!("Random seed: {}", hex_seed);
282 eprintln!("Random seed: {}", hex_seed);
282
283
283 let mut rng = rand_pcg::Pcg32::from_seed(seed);
284 let mut rng = rand_pcg::Pcg32::from_seed(seed);
284
285
285 eprint!("Checking MissingAncestors against brute force implementation ");
286 eprint!("Checking MissingAncestors against brute force implementation ");
286 eprint!("for {} random graphs, ", graphcount);
287 eprint!("for {} random graphs, ", graphcount);
287 eprintln!(
288 eprintln!(
288 "with {} instances for each and {} calls per instance",
289 "with {} instances for each and {} calls per instance",
289 testcount, inccount,
290 testcount, inccount,
290 );
291 );
291 for g in 0..graphcount {
292 for g in 0..graphcount {
292 if g != 0 && g % 100 == 0 {
293 if g != 0 && g % 100 == 0 {
293 eprintln!("Tested with {} graphs", g);
294 eprintln!("Tested with {} graphs", g);
294 }
295 }
295 let graph = build_random_graph(None, None, None, None);
296 let graph = build_random_graph(None, None, None, None);
296 let graph_len = graph.len() as Revision;
297 let graph_len = graph.len() as Revision;
297 let ancestors_sets = ancestors_sets(&graph);
298 let ancestors_sets = ancestors_sets(&graph);
298 for _testno in 0..testcount {
299 for _testno in 0..testcount {
299 let bases: HashSet<Revision> =
300 let bases: HashSet<Revision> =
300 sample_revs(&mut rng, graph_len, None, None);
301 sample_revs(&mut rng, graph_len, None, None);
301 let mut inc = MissingAncestors::<VecGraph>::new(
302 let mut inc = MissingAncestors::<VecGraph>::new(
302 graph.clone(),
303 graph.clone(),
303 bases.clone(),
304 bases.clone(),
304 );
305 );
305 let mut naive = NaiveMissingAncestors::new(
306 let mut naive = NaiveMissingAncestors::new(
306 &graph,
307 &graph,
307 &ancestors_sets,
308 &ancestors_sets,
308 &bases,
309 &bases,
309 &hex_seed,
310 &hex_seed,
310 );
311 );
311 for _m in 0..inccount {
312 for _m in 0..inccount {
312 if rng.gen_bool(0.2) {
313 if rng.gen_bool(0.2) {
313 let new_bases =
314 let new_bases =
314 sample_revs(&mut rng, graph_len, None, None);
315 sample_revs(&mut rng, graph_len, None, None);
315 inc.add_bases(new_bases.iter().cloned());
316 inc.add_bases(new_bases.iter().cloned());
316 naive.add_bases(new_bases);
317 naive.add_bases(new_bases);
317 }
318 }
318 if rng.gen_bool(0.4) {
319 if rng.gen_bool(0.4) {
319 // larger set so that there are more revs to remove from
320 // larger set so that there are more revs to remove from
320 let mut hrevs =
321 let mut hrevs =
321 sample_revs(&mut rng, graph_len, Some(1.5), None);
322 sample_revs(&mut rng, graph_len, Some(1.5), None);
322 let mut rrevs = hrevs.clone();
323 let mut rrevs = hrevs.clone();
323 inc.remove_ancestors_from(&mut hrevs).unwrap();
324 inc.remove_ancestors_from(&mut hrevs).unwrap();
324 naive.remove_ancestors_from(&mut rrevs);
325 naive.remove_ancestors_from(&mut rrevs);
325 naive.assert_eq(hrevs, rrevs);
326 naive.assert_eq(hrevs, rrevs);
326 } else {
327 } else {
327 let revs = sample_revs(&mut rng, graph_len, None, None);
328 let revs = sample_revs(&mut rng, graph_len, None, None);
328 let hm =
329 let hm =
329 inc.missing_ancestors(revs.iter().cloned()).unwrap();
330 inc.missing_ancestors(revs.iter().cloned()).unwrap();
330 let rm = naive.missing_ancestors(revs.iter().cloned());
331 let rm = naive.missing_ancestors(revs.iter().cloned());
331 naive.assert_eq(hm, rm);
332 naive.assert_eq(hm, rm);
332 }
333 }
333 }
334 }
334 }
335 }
335 }
336 }
336 }
337 }
@@ -1,32 +1,32 b''
1 [package]
1 [package]
2 name = "hg-cpython"
2 name = "hg-cpython"
3 version = "0.1.0"
3 version = "0.1.0"
4 authors = ["Georges Racinet <gracinet@anybox.fr>"]
4 authors = ["Georges Racinet <gracinet@anybox.fr>"]
5 edition = "2018"
5 edition = "2018"
6
6
7 [lib]
7 [lib]
8 name='rusthg'
8 name='rusthg'
9 crate-type = ["cdylib"]
9 crate-type = ["cdylib"]
10
10
11 [features]
11 [features]
12 default = ["python27"]
12 default = ["python27"]
13 with-re2 = ["hg-core/with-re2"]
13 with-re2 = ["hg-core/with-re2"]
14
14
15 # Features to build an extension module:
15 # Features to build an extension module:
16 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
16 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
17 python3 = ["cpython/python3-sys", "cpython/extension-module"]
17 python3 = ["cpython/python3-sys", "cpython/extension-module"]
18
18
19 # Enable one of these features to build a test executable linked to libpython:
19 # Enable one of these features to build a test executable linked to libpython:
20 # e.g. cargo test --no-default-features --features python27-bin
20 # e.g. cargo test --no-default-features --features python27-bin
21 python27-bin = ["cpython/python27-sys"]
21 python27-bin = ["cpython/python27-sys"]
22 python3-bin = ["cpython/python3-sys"]
22 python3-bin = ["cpython/python3-sys"]
23
23
24 [dependencies]
24 [dependencies]
25 hg-core = { path = "../hg-core"}
25 hg-core = { path = "../hg-core"}
26 libc = '*'
26 libc = '*'
27 log = "0.4.8"
27 log = "0.4.8"
28 simple_logger = "1.6.0"
28 simple_logger = "1.6.0"
29
29
30 [dependencies.cpython]
30 [dependencies.cpython]
31 version = "0.4"
31 version = "0.4.1"
32 default-features = false
32 default-features = false
General Comments 0
You need to be logged in to leave comments. Login now