##// END OF EJS Templates
rust: create wrapper struct to reduce `regex` contention issues...
Raphaël Gomès -
r50476:04f1dba5 6.3 stable
parent child Browse files
Show More
@@ -1,1284 +1,1294 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 version = 3
3 version = 3
4
4
5 [[package]]
5 [[package]]
6 name = "Inflector"
6 name = "Inflector"
7 version = "0.11.4"
7 version = "0.11.4"
8 source = "registry+https://github.com/rust-lang/crates.io-index"
8 source = "registry+https://github.com/rust-lang/crates.io-index"
9 checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
9 checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
10
10
11 [[package]]
11 [[package]]
12 name = "adler"
12 name = "adler"
13 version = "0.2.3"
13 version = "0.2.3"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
15 checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
15 checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
16
16
17 [[package]]
17 [[package]]
18 name = "ahash"
18 name = "ahash"
19 version = "0.4.7"
19 version = "0.4.7"
20 source = "registry+https://github.com/rust-lang/crates.io-index"
20 source = "registry+https://github.com/rust-lang/crates.io-index"
21 checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
21 checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
22
22
23 [[package]]
23 [[package]]
24 name = "aho-corasick"
24 name = "aho-corasick"
25 version = "0.7.18"
25 version = "0.7.18"
26 source = "registry+https://github.com/rust-lang/crates.io-index"
26 source = "registry+https://github.com/rust-lang/crates.io-index"
27 checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
27 checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
28 dependencies = [
28 dependencies = [
29 "memchr",
29 "memchr",
30 ]
30 ]
31
31
32 [[package]]
32 [[package]]
33 name = "aliasable"
33 name = "aliasable"
34 version = "0.1.3"
34 version = "0.1.3"
35 source = "registry+https://github.com/rust-lang/crates.io-index"
35 source = "registry+https://github.com/rust-lang/crates.io-index"
36 checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
36 checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
37
37
38 [[package]]
38 [[package]]
39 name = "ansi_term"
39 name = "ansi_term"
40 version = "0.12.1"
40 version = "0.12.1"
41 source = "registry+https://github.com/rust-lang/crates.io-index"
41 source = "registry+https://github.com/rust-lang/crates.io-index"
42 checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
42 checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
43 dependencies = [
43 dependencies = [
44 "winapi",
44 "winapi",
45 ]
45 ]
46
46
47 [[package]]
47 [[package]]
48 name = "atty"
48 name = "atty"
49 version = "0.2.14"
49 version = "0.2.14"
50 source = "registry+https://github.com/rust-lang/crates.io-index"
50 source = "registry+https://github.com/rust-lang/crates.io-index"
51 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
51 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
52 dependencies = [
52 dependencies = [
53 "hermit-abi",
53 "hermit-abi",
54 "libc",
54 "libc",
55 "winapi",
55 "winapi",
56 ]
56 ]
57
57
58 [[package]]
58 [[package]]
59 name = "autocfg"
59 name = "autocfg"
60 version = "1.0.1"
60 version = "1.0.1"
61 source = "registry+https://github.com/rust-lang/crates.io-index"
61 source = "registry+https://github.com/rust-lang/crates.io-index"
62 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
62 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
63
63
64 [[package]]
64 [[package]]
65 name = "bitflags"
65 name = "bitflags"
66 version = "1.3.2"
66 version = "1.3.2"
67 source = "registry+https://github.com/rust-lang/crates.io-index"
67 source = "registry+https://github.com/rust-lang/crates.io-index"
68 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
68 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
69
69
70 [[package]]
70 [[package]]
71 name = "bitmaps"
71 name = "bitmaps"
72 version = "2.1.0"
72 version = "2.1.0"
73 source = "registry+https://github.com/rust-lang/crates.io-index"
73 source = "registry+https://github.com/rust-lang/crates.io-index"
74 checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
74 checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
75 dependencies = [
75 dependencies = [
76 "typenum",
76 "typenum",
77 ]
77 ]
78
78
79 [[package]]
79 [[package]]
80 name = "block-buffer"
80 name = "block-buffer"
81 version = "0.9.0"
81 version = "0.9.0"
82 source = "registry+https://github.com/rust-lang/crates.io-index"
82 source = "registry+https://github.com/rust-lang/crates.io-index"
83 checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
83 checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
84 dependencies = [
84 dependencies = [
85 "generic-array",
85 "generic-array",
86 ]
86 ]
87
87
88 [[package]]
88 [[package]]
89 name = "block-buffer"
89 name = "block-buffer"
90 version = "0.10.2"
90 version = "0.10.2"
91 source = "registry+https://github.com/rust-lang/crates.io-index"
91 source = "registry+https://github.com/rust-lang/crates.io-index"
92 checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
92 checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
93 dependencies = [
93 dependencies = [
94 "generic-array",
94 "generic-array",
95 ]
95 ]
96
96
97 [[package]]
97 [[package]]
98 name = "byteorder"
98 name = "byteorder"
99 version = "1.4.3"
99 version = "1.4.3"
100 source = "registry+https://github.com/rust-lang/crates.io-index"
100 source = "registry+https://github.com/rust-lang/crates.io-index"
101 checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
101 checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
102
102
103 [[package]]
103 [[package]]
104 name = "bytes-cast"
104 name = "bytes-cast"
105 version = "0.2.0"
105 version = "0.2.0"
106 source = "registry+https://github.com/rust-lang/crates.io-index"
106 source = "registry+https://github.com/rust-lang/crates.io-index"
107 checksum = "0d434f9a4ecbe987e7ccfda7274b6f82ea52c9b63742565a65cb5e8ba0f2c452"
107 checksum = "0d434f9a4ecbe987e7ccfda7274b6f82ea52c9b63742565a65cb5e8ba0f2c452"
108 dependencies = [
108 dependencies = [
109 "bytes-cast-derive",
109 "bytes-cast-derive",
110 ]
110 ]
111
111
112 [[package]]
112 [[package]]
113 name = "bytes-cast-derive"
113 name = "bytes-cast-derive"
114 version = "0.1.0"
114 version = "0.1.0"
115 source = "registry+https://github.com/rust-lang/crates.io-index"
115 source = "registry+https://github.com/rust-lang/crates.io-index"
116 checksum = "cb936af9de38476664d6b58e529aff30d482e4ce1c5e150293d00730b0d81fdb"
116 checksum = "cb936af9de38476664d6b58e529aff30d482e4ce1c5e150293d00730b0d81fdb"
117 dependencies = [
117 dependencies = [
118 "proc-macro2",
118 "proc-macro2",
119 "quote",
119 "quote",
120 "syn",
120 "syn",
121 ]
121 ]
122
122
123 [[package]]
123 [[package]]
124 name = "cc"
124 name = "cc"
125 version = "1.0.66"
125 version = "1.0.66"
126 source = "registry+https://github.com/rust-lang/crates.io-index"
126 source = "registry+https://github.com/rust-lang/crates.io-index"
127 checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
127 checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
128 dependencies = [
128 dependencies = [
129 "jobserver",
129 "jobserver",
130 ]
130 ]
131
131
132 [[package]]
132 [[package]]
133 name = "cfg-if"
133 name = "cfg-if"
134 version = "0.1.10"
134 version = "0.1.10"
135 source = "registry+https://github.com/rust-lang/crates.io-index"
135 source = "registry+https://github.com/rust-lang/crates.io-index"
136 checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
136 checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
137
137
138 [[package]]
138 [[package]]
139 name = "cfg-if"
139 name = "cfg-if"
140 version = "1.0.0"
140 version = "1.0.0"
141 source = "registry+https://github.com/rust-lang/crates.io-index"
141 source = "registry+https://github.com/rust-lang/crates.io-index"
142 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
142 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
143
143
144 [[package]]
144 [[package]]
145 name = "chrono"
145 name = "chrono"
146 version = "0.4.19"
146 version = "0.4.19"
147 source = "registry+https://github.com/rust-lang/crates.io-index"
147 source = "registry+https://github.com/rust-lang/crates.io-index"
148 checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
148 checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
149 dependencies = [
149 dependencies = [
150 "libc",
150 "libc",
151 "num-integer",
151 "num-integer",
152 "num-traits",
152 "num-traits",
153 "time",
153 "time",
154 "winapi",
154 "winapi",
155 ]
155 ]
156
156
157 [[package]]
157 [[package]]
158 name = "clap"
158 name = "clap"
159 version = "2.34.0"
159 version = "2.34.0"
160 source = "registry+https://github.com/rust-lang/crates.io-index"
160 source = "registry+https://github.com/rust-lang/crates.io-index"
161 checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
161 checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
162 dependencies = [
162 dependencies = [
163 "ansi_term",
163 "ansi_term",
164 "atty",
164 "atty",
165 "bitflags",
165 "bitflags",
166 "strsim",
166 "strsim",
167 "textwrap",
167 "textwrap",
168 "unicode-width",
168 "unicode-width",
169 "vec_map",
169 "vec_map",
170 ]
170 ]
171
171
172 [[package]]
172 [[package]]
173 name = "const_fn"
173 name = "const_fn"
174 version = "0.4.4"
174 version = "0.4.4"
175 source = "registry+https://github.com/rust-lang/crates.io-index"
175 source = "registry+https://github.com/rust-lang/crates.io-index"
176 checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
176 checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
177
177
178 [[package]]
178 [[package]]
179 name = "convert_case"
179 name = "convert_case"
180 version = "0.4.0"
180 version = "0.4.0"
181 source = "registry+https://github.com/rust-lang/crates.io-index"
181 source = "registry+https://github.com/rust-lang/crates.io-index"
182 checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
182 checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
183
183
184 [[package]]
184 [[package]]
185 name = "cpufeatures"
185 name = "cpufeatures"
186 version = "0.1.4"
186 version = "0.1.4"
187 source = "registry+https://github.com/rust-lang/crates.io-index"
187 source = "registry+https://github.com/rust-lang/crates.io-index"
188 checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
188 checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
189 dependencies = [
189 dependencies = [
190 "libc",
190 "libc",
191 ]
191 ]
192
192
193 [[package]]
193 [[package]]
194 name = "cpufeatures"
194 name = "cpufeatures"
195 version = "0.2.1"
195 version = "0.2.1"
196 source = "registry+https://github.com/rust-lang/crates.io-index"
196 source = "registry+https://github.com/rust-lang/crates.io-index"
197 checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
197 checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
198 dependencies = [
198 dependencies = [
199 "libc",
199 "libc",
200 ]
200 ]
201
201
202 [[package]]
202 [[package]]
203 name = "cpython"
203 name = "cpython"
204 version = "0.7.0"
204 version = "0.7.0"
205 source = "registry+https://github.com/rust-lang/crates.io-index"
205 source = "registry+https://github.com/rust-lang/crates.io-index"
206 checksum = "b7d46ba8ace7f3a1d204ac5060a706d0a68de6b42eafb6a586cc08bebcffe664"
206 checksum = "b7d46ba8ace7f3a1d204ac5060a706d0a68de6b42eafb6a586cc08bebcffe664"
207 dependencies = [
207 dependencies = [
208 "libc",
208 "libc",
209 "num-traits",
209 "num-traits",
210 "paste",
210 "paste",
211 "python3-sys",
211 "python3-sys",
212 ]
212 ]
213
213
214 [[package]]
214 [[package]]
215 name = "crc32fast"
215 name = "crc32fast"
216 version = "1.2.1"
216 version = "1.2.1"
217 source = "registry+https://github.com/rust-lang/crates.io-index"
217 source = "registry+https://github.com/rust-lang/crates.io-index"
218 checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
218 checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
219 dependencies = [
219 dependencies = [
220 "cfg-if 1.0.0",
220 "cfg-if 1.0.0",
221 ]
221 ]
222
222
223 [[package]]
223 [[package]]
224 name = "crossbeam-channel"
224 name = "crossbeam-channel"
225 version = "0.5.2"
225 version = "0.5.2"
226 source = "registry+https://github.com/rust-lang/crates.io-index"
226 source = "registry+https://github.com/rust-lang/crates.io-index"
227 checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
227 checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
228 dependencies = [
228 dependencies = [
229 "cfg-if 1.0.0",
229 "cfg-if 1.0.0",
230 "crossbeam-utils",
230 "crossbeam-utils",
231 ]
231 ]
232
232
233 [[package]]
233 [[package]]
234 name = "crossbeam-deque"
234 name = "crossbeam-deque"
235 version = "0.8.0"
235 version = "0.8.0"
236 source = "registry+https://github.com/rust-lang/crates.io-index"
236 source = "registry+https://github.com/rust-lang/crates.io-index"
237 checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
237 checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
238 dependencies = [
238 dependencies = [
239 "cfg-if 1.0.0",
239 "cfg-if 1.0.0",
240 "crossbeam-epoch",
240 "crossbeam-epoch",
241 "crossbeam-utils",
241 "crossbeam-utils",
242 ]
242 ]
243
243
244 [[package]]
244 [[package]]
245 name = "crossbeam-epoch"
245 name = "crossbeam-epoch"
246 version = "0.9.1"
246 version = "0.9.1"
247 source = "registry+https://github.com/rust-lang/crates.io-index"
247 source = "registry+https://github.com/rust-lang/crates.io-index"
248 checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
248 checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
249 dependencies = [
249 dependencies = [
250 "cfg-if 1.0.0",
250 "cfg-if 1.0.0",
251 "const_fn",
251 "const_fn",
252 "crossbeam-utils",
252 "crossbeam-utils",
253 "lazy_static",
253 "lazy_static",
254 "memoffset",
254 "memoffset",
255 "scopeguard",
255 "scopeguard",
256 ]
256 ]
257
257
258 [[package]]
258 [[package]]
259 name = "crossbeam-utils"
259 name = "crossbeam-utils"
260 version = "0.8.1"
260 version = "0.8.1"
261 source = "registry+https://github.com/rust-lang/crates.io-index"
261 source = "registry+https://github.com/rust-lang/crates.io-index"
262 checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
262 checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
263 dependencies = [
263 dependencies = [
264 "autocfg",
264 "autocfg",
265 "cfg-if 1.0.0",
265 "cfg-if 1.0.0",
266 "lazy_static",
266 "lazy_static",
267 ]
267 ]
268
268
269 [[package]]
269 [[package]]
270 name = "crypto-common"
270 name = "crypto-common"
271 version = "0.1.2"
271 version = "0.1.2"
272 source = "registry+https://github.com/rust-lang/crates.io-index"
272 source = "registry+https://github.com/rust-lang/crates.io-index"
273 checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
273 checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06"
274 dependencies = [
274 dependencies = [
275 "generic-array",
275 "generic-array",
276 ]
276 ]
277
277
278 [[package]]
278 [[package]]
279 name = "ctor"
279 name = "ctor"
280 version = "0.1.16"
280 version = "0.1.16"
281 source = "registry+https://github.com/rust-lang/crates.io-index"
281 source = "registry+https://github.com/rust-lang/crates.io-index"
282 checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484"
282 checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484"
283 dependencies = [
283 dependencies = [
284 "quote",
284 "quote",
285 "syn",
285 "syn",
286 ]
286 ]
287
287
288 [[package]]
288 [[package]]
289 name = "derive_more"
289 name = "derive_more"
290 version = "0.99.17"
290 version = "0.99.17"
291 source = "registry+https://github.com/rust-lang/crates.io-index"
291 source = "registry+https://github.com/rust-lang/crates.io-index"
292 checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
292 checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
293 dependencies = [
293 dependencies = [
294 "convert_case",
294 "convert_case",
295 "proc-macro2",
295 "proc-macro2",
296 "quote",
296 "quote",
297 "rustc_version",
297 "rustc_version",
298 "syn",
298 "syn",
299 ]
299 ]
300
300
301 [[package]]
301 [[package]]
302 name = "diff"
302 name = "diff"
303 version = "0.1.12"
303 version = "0.1.12"
304 source = "registry+https://github.com/rust-lang/crates.io-index"
304 source = "registry+https://github.com/rust-lang/crates.io-index"
305 checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
305 checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
306
306
307 [[package]]
307 [[package]]
308 name = "digest"
308 name = "digest"
309 version = "0.9.0"
309 version = "0.9.0"
310 source = "registry+https://github.com/rust-lang/crates.io-index"
310 source = "registry+https://github.com/rust-lang/crates.io-index"
311 checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
311 checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
312 dependencies = [
312 dependencies = [
313 "generic-array",
313 "generic-array",
314 ]
314 ]
315
315
316 [[package]]
316 [[package]]
317 name = "digest"
317 name = "digest"
318 version = "0.10.2"
318 version = "0.10.2"
319 source = "registry+https://github.com/rust-lang/crates.io-index"
319 source = "registry+https://github.com/rust-lang/crates.io-index"
320 checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
320 checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837"
321 dependencies = [
321 dependencies = [
322 "block-buffer 0.10.2",
322 "block-buffer 0.10.2",
323 "crypto-common",
323 "crypto-common",
324 ]
324 ]
325
325
326 [[package]]
326 [[package]]
327 name = "either"
327 name = "either"
328 version = "1.6.1"
328 version = "1.6.1"
329 source = "registry+https://github.com/rust-lang/crates.io-index"
329 source = "registry+https://github.com/rust-lang/crates.io-index"
330 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
330 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
331
331
332 [[package]]
332 [[package]]
333 name = "env_logger"
333 name = "env_logger"
334 version = "0.9.0"
334 version = "0.9.0"
335 source = "registry+https://github.com/rust-lang/crates.io-index"
335 source = "registry+https://github.com/rust-lang/crates.io-index"
336 checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
336 checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
337 dependencies = [
337 dependencies = [
338 "atty",
338 "atty",
339 "humantime",
339 "humantime",
340 "log",
340 "log",
341 "regex",
341 "regex",
342 "termcolor",
342 "termcolor",
343 ]
343 ]
344
344
345 [[package]]
345 [[package]]
346 name = "fastrand"
346 name = "fastrand"
347 version = "1.7.0"
347 version = "1.7.0"
348 source = "registry+https://github.com/rust-lang/crates.io-index"
348 source = "registry+https://github.com/rust-lang/crates.io-index"
349 checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
349 checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
350 dependencies = [
350 dependencies = [
351 "instant",
351 "instant",
352 ]
352 ]
353
353
354 [[package]]
354 [[package]]
355 name = "flate2"
355 name = "flate2"
356 version = "1.0.22"
356 version = "1.0.22"
357 source = "registry+https://github.com/rust-lang/crates.io-index"
357 source = "registry+https://github.com/rust-lang/crates.io-index"
358 checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
358 checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
359 dependencies = [
359 dependencies = [
360 "cfg-if 1.0.0",
360 "cfg-if 1.0.0",
361 "crc32fast",
361 "crc32fast",
362 "libc",
362 "libc",
363 "libz-sys",
363 "libz-sys",
364 "miniz_oxide",
364 "miniz_oxide",
365 ]
365 ]
366
366
367 [[package]]
367 [[package]]
368 name = "format-bytes"
368 name = "format-bytes"
369 version = "0.3.0"
369 version = "0.3.0"
370 source = "registry+https://github.com/rust-lang/crates.io-index"
370 source = "registry+https://github.com/rust-lang/crates.io-index"
371 checksum = "48942366ef93975da38e175ac9e10068c6fc08ca9e85930d4f098f4d5b14c2fd"
371 checksum = "48942366ef93975da38e175ac9e10068c6fc08ca9e85930d4f098f4d5b14c2fd"
372 dependencies = [
372 dependencies = [
373 "format-bytes-macros",
373 "format-bytes-macros",
374 ]
374 ]
375
375
376 [[package]]
376 [[package]]
377 name = "format-bytes-macros"
377 name = "format-bytes-macros"
378 version = "0.4.0"
378 version = "0.4.0"
379 source = "registry+https://github.com/rust-lang/crates.io-index"
379 source = "registry+https://github.com/rust-lang/crates.io-index"
380 checksum = "203aadebefcc73d12038296c228eabf830f99cba991b0032adf20e9fa6ce7e4f"
380 checksum = "203aadebefcc73d12038296c228eabf830f99cba991b0032adf20e9fa6ce7e4f"
381 dependencies = [
381 dependencies = [
382 "proc-macro2",
382 "proc-macro2",
383 "quote",
383 "quote",
384 "syn",
384 "syn",
385 ]
385 ]
386
386
387 [[package]]
387 [[package]]
388 name = "generic-array"
388 name = "generic-array"
389 version = "0.14.4"
389 version = "0.14.4"
390 source = "registry+https://github.com/rust-lang/crates.io-index"
390 source = "registry+https://github.com/rust-lang/crates.io-index"
391 checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
391 checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
392 dependencies = [
392 dependencies = [
393 "typenum",
393 "typenum",
394 "version_check",
394 "version_check",
395 ]
395 ]
396
396
397 [[package]]
397 [[package]]
398 name = "getrandom"
398 name = "getrandom"
399 version = "0.1.15"
399 version = "0.1.15"
400 source = "registry+https://github.com/rust-lang/crates.io-index"
400 source = "registry+https://github.com/rust-lang/crates.io-index"
401 checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
401 checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
402 dependencies = [
402 dependencies = [
403 "cfg-if 0.1.10",
403 "cfg-if 0.1.10",
404 "libc",
404 "libc",
405 "wasi 0.9.0+wasi-snapshot-preview1",
405 "wasi 0.9.0+wasi-snapshot-preview1",
406 ]
406 ]
407
407
408 [[package]]
408 [[package]]
409 name = "getrandom"
409 name = "getrandom"
410 version = "0.2.4"
410 version = "0.2.4"
411 source = "registry+https://github.com/rust-lang/crates.io-index"
411 source = "registry+https://github.com/rust-lang/crates.io-index"
412 checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
412 checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
413 dependencies = [
413 dependencies = [
414 "cfg-if 1.0.0",
414 "cfg-if 1.0.0",
415 "libc",
415 "libc",
416 "wasi 0.10.0+wasi-snapshot-preview1",
416 "wasi 0.10.0+wasi-snapshot-preview1",
417 ]
417 ]
418
418
419 [[package]]
419 [[package]]
420 name = "glob"
420 name = "glob"
421 version = "0.3.0"
421 version = "0.3.0"
422 source = "registry+https://github.com/rust-lang/crates.io-index"
422 source = "registry+https://github.com/rust-lang/crates.io-index"
423 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
423 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
424
424
425 [[package]]
425 [[package]]
426 name = "hashbrown"
426 name = "hashbrown"
427 version = "0.9.1"
427 version = "0.9.1"
428 source = "registry+https://github.com/rust-lang/crates.io-index"
428 source = "registry+https://github.com/rust-lang/crates.io-index"
429 checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
429 checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
430 dependencies = [
430 dependencies = [
431 "ahash",
431 "ahash",
432 "rayon",
432 "rayon",
433 ]
433 ]
434
434
435 [[package]]
435 [[package]]
436 name = "hermit-abi"
436 name = "hermit-abi"
437 version = "0.1.17"
437 version = "0.1.17"
438 source = "registry+https://github.com/rust-lang/crates.io-index"
438 source = "registry+https://github.com/rust-lang/crates.io-index"
439 checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
439 checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
440 dependencies = [
440 dependencies = [
441 "libc",
441 "libc",
442 ]
442 ]
443
443
444 [[package]]
444 [[package]]
445 name = "hex"
445 name = "hex"
446 version = "0.4.3"
446 version = "0.4.3"
447 source = "registry+https://github.com/rust-lang/crates.io-index"
447 source = "registry+https://github.com/rust-lang/crates.io-index"
448 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
448 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
449
449
450 [[package]]
450 [[package]]
451 name = "hg-core"
451 name = "hg-core"
452 version = "0.1.0"
452 version = "0.1.0"
453 dependencies = [
453 dependencies = [
454 "bitflags",
454 "bitflags",
455 "byteorder",
455 "byteorder",
456 "bytes-cast",
456 "bytes-cast",
457 "clap",
457 "clap",
458 "crossbeam-channel",
458 "crossbeam-channel",
459 "derive_more",
459 "derive_more",
460 "flate2",
460 "flate2",
461 "format-bytes",
461 "format-bytes",
462 "hashbrown",
462 "hashbrown",
463 "home",
463 "home",
464 "im-rc",
464 "im-rc",
465 "itertools 0.10.3",
465 "itertools 0.10.3",
466 "lazy_static",
466 "lazy_static",
467 "libc",
467 "libc",
468 "log",
468 "log",
469 "memmap2",
469 "memmap2",
470 "micro-timer",
470 "micro-timer",
471 "once_cell",
471 "once_cell",
472 "ouroboros",
472 "ouroboros",
473 "pretty_assertions",
473 "pretty_assertions",
474 "rand 0.8.5",
474 "rand 0.8.5",
475 "rand_distr",
475 "rand_distr",
476 "rand_pcg",
476 "rand_pcg",
477 "rayon",
477 "rayon",
478 "regex",
478 "regex",
479 "same-file",
479 "same-file",
480 "sha-1 0.10.0",
480 "sha-1 0.10.0",
481 "tempfile",
481 "tempfile",
482 "thread_local",
482 "twox-hash",
483 "twox-hash",
483 "zstd",
484 "zstd",
484 ]
485 ]
485
486
486 [[package]]
487 [[package]]
487 name = "hg-cpython"
488 name = "hg-cpython"
488 version = "0.1.0"
489 version = "0.1.0"
489 dependencies = [
490 dependencies = [
490 "cpython",
491 "cpython",
491 "crossbeam-channel",
492 "crossbeam-channel",
492 "env_logger",
493 "env_logger",
493 "hg-core",
494 "hg-core",
494 "libc",
495 "libc",
495 "log",
496 "log",
496 "stable_deref_trait",
497 "stable_deref_trait",
497 "vcsgraph",
498 "vcsgraph",
498 ]
499 ]
499
500
500 [[package]]
501 [[package]]
501 name = "home"
502 name = "home"
502 version = "0.5.3"
503 version = "0.5.3"
503 source = "registry+https://github.com/rust-lang/crates.io-index"
504 source = "registry+https://github.com/rust-lang/crates.io-index"
504 checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
505 checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
505 dependencies = [
506 dependencies = [
506 "winapi",
507 "winapi",
507 ]
508 ]
508
509
509 [[package]]
510 [[package]]
510 name = "humantime"
511 name = "humantime"
511 version = "2.1.0"
512 version = "2.1.0"
512 source = "registry+https://github.com/rust-lang/crates.io-index"
513 source = "registry+https://github.com/rust-lang/crates.io-index"
513 checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
514 checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
514
515
515 [[package]]
516 [[package]]
516 name = "im-rc"
517 name = "im-rc"
517 version = "15.0.0"
518 version = "15.0.0"
518 source = "registry+https://github.com/rust-lang/crates.io-index"
519 source = "registry+https://github.com/rust-lang/crates.io-index"
519 checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
520 checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
520 dependencies = [
521 dependencies = [
521 "bitmaps",
522 "bitmaps",
522 "rand_core 0.5.1",
523 "rand_core 0.5.1",
523 "rand_xoshiro",
524 "rand_xoshiro",
524 "sized-chunks",
525 "sized-chunks",
525 "typenum",
526 "typenum",
526 "version_check",
527 "version_check",
527 ]
528 ]
528
529
529 [[package]]
530 [[package]]
530 name = "instant"
531 name = "instant"
531 version = "0.1.12"
532 version = "0.1.12"
532 source = "registry+https://github.com/rust-lang/crates.io-index"
533 source = "registry+https://github.com/rust-lang/crates.io-index"
533 checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
534 checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
534 dependencies = [
535 dependencies = [
535 "cfg-if 1.0.0",
536 "cfg-if 1.0.0",
536 ]
537 ]
537
538
538 [[package]]
539 [[package]]
539 name = "itertools"
540 name = "itertools"
540 version = "0.9.0"
541 version = "0.9.0"
541 source = "registry+https://github.com/rust-lang/crates.io-index"
542 source = "registry+https://github.com/rust-lang/crates.io-index"
542 checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
543 checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
543 dependencies = [
544 dependencies = [
544 "either",
545 "either",
545 ]
546 ]
546
547
547 [[package]]
548 [[package]]
548 name = "itertools"
549 name = "itertools"
549 version = "0.10.3"
550 version = "0.10.3"
550 source = "registry+https://github.com/rust-lang/crates.io-index"
551 source = "registry+https://github.com/rust-lang/crates.io-index"
551 checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
552 checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
552 dependencies = [
553 dependencies = [
553 "either",
554 "either",
554 ]
555 ]
555
556
556 [[package]]
557 [[package]]
557 name = "jobserver"
558 name = "jobserver"
558 version = "0.1.21"
559 version = "0.1.21"
559 source = "registry+https://github.com/rust-lang/crates.io-index"
560 source = "registry+https://github.com/rust-lang/crates.io-index"
560 checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
561 checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
561 dependencies = [
562 dependencies = [
562 "libc",
563 "libc",
563 ]
564 ]
564
565
565 [[package]]
566 [[package]]
566 name = "lazy_static"
567 name = "lazy_static"
567 version = "1.4.0"
568 version = "1.4.0"
568 source = "registry+https://github.com/rust-lang/crates.io-index"
569 source = "registry+https://github.com/rust-lang/crates.io-index"
569 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
570 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
570
571
571 [[package]]
572 [[package]]
572 name = "libc"
573 name = "libc"
573 version = "0.2.124"
574 version = "0.2.124"
574 source = "registry+https://github.com/rust-lang/crates.io-index"
575 source = "registry+https://github.com/rust-lang/crates.io-index"
575 checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
576 checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
576
577
577 [[package]]
578 [[package]]
578 name = "libm"
579 name = "libm"
579 version = "0.2.1"
580 version = "0.2.1"
580 source = "registry+https://github.com/rust-lang/crates.io-index"
581 source = "registry+https://github.com/rust-lang/crates.io-index"
581 checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
582 checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
582
583
583 [[package]]
584 [[package]]
584 name = "libz-sys"
585 name = "libz-sys"
585 version = "1.1.2"
586 version = "1.1.2"
586 source = "registry+https://github.com/rust-lang/crates.io-index"
587 source = "registry+https://github.com/rust-lang/crates.io-index"
587 checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
588 checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
588 dependencies = [
589 dependencies = [
589 "cc",
590 "cc",
590 "pkg-config",
591 "pkg-config",
591 "vcpkg",
592 "vcpkg",
592 ]
593 ]
593
594
594 [[package]]
595 [[package]]
595 name = "log"
596 name = "log"
596 version = "0.4.14"
597 version = "0.4.14"
597 source = "registry+https://github.com/rust-lang/crates.io-index"
598 source = "registry+https://github.com/rust-lang/crates.io-index"
598 checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
599 checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
599 dependencies = [
600 dependencies = [
600 "cfg-if 1.0.0",
601 "cfg-if 1.0.0",
601 ]
602 ]
602
603
603 [[package]]
604 [[package]]
604 name = "memchr"
605 name = "memchr"
605 version = "2.4.1"
606 version = "2.4.1"
606 source = "registry+https://github.com/rust-lang/crates.io-index"
607 source = "registry+https://github.com/rust-lang/crates.io-index"
607 checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
608 checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
608
609
609 [[package]]
610 [[package]]
610 name = "memmap2"
611 name = "memmap2"
611 version = "0.5.7"
612 version = "0.5.7"
612 source = "registry+https://github.com/rust-lang/crates.io-index"
613 source = "registry+https://github.com/rust-lang/crates.io-index"
613 checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
614 checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
614 dependencies = [
615 dependencies = [
615 "libc",
616 "libc",
616 "stable_deref_trait",
617 "stable_deref_trait",
617 ]
618 ]
618
619
619 [[package]]
620 [[package]]
620 name = "memoffset"
621 name = "memoffset"
621 version = "0.6.1"
622 version = "0.6.1"
622 source = "registry+https://github.com/rust-lang/crates.io-index"
623 source = "registry+https://github.com/rust-lang/crates.io-index"
623 checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
624 checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
624 dependencies = [
625 dependencies = [
625 "autocfg",
626 "autocfg",
626 ]
627 ]
627
628
628 [[package]]
629 [[package]]
629 name = "micro-timer"
630 name = "micro-timer"
630 version = "0.4.0"
631 version = "0.4.0"
631 source = "registry+https://github.com/rust-lang/crates.io-index"
632 source = "registry+https://github.com/rust-lang/crates.io-index"
632 checksum = "5de32cb59a062672560d6f0842c4aa7714727457b9fe2daf8987d995a176a405"
633 checksum = "5de32cb59a062672560d6f0842c4aa7714727457b9fe2daf8987d995a176a405"
633 dependencies = [
634 dependencies = [
634 "micro-timer-macros",
635 "micro-timer-macros",
635 "scopeguard",
636 "scopeguard",
636 ]
637 ]
637
638
638 [[package]]
639 [[package]]
639 name = "micro-timer-macros"
640 name = "micro-timer-macros"
640 version = "0.4.0"
641 version = "0.4.0"
641 source = "registry+https://github.com/rust-lang/crates.io-index"
642 source = "registry+https://github.com/rust-lang/crates.io-index"
642 checksum = "cee948b94700125b52dfb68dd17c19f6326696c1df57f92c05ee857463c93ba1"
643 checksum = "cee948b94700125b52dfb68dd17c19f6326696c1df57f92c05ee857463c93ba1"
643 dependencies = [
644 dependencies = [
644 "proc-macro2",
645 "proc-macro2",
645 "quote",
646 "quote",
646 "scopeguard",
647 "scopeguard",
647 "syn",
648 "syn",
648 ]
649 ]
649
650
650 [[package]]
651 [[package]]
651 name = "miniz_oxide"
652 name = "miniz_oxide"
652 version = "0.4.3"
653 version = "0.4.3"
653 source = "registry+https://github.com/rust-lang/crates.io-index"
654 source = "registry+https://github.com/rust-lang/crates.io-index"
654 checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
655 checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
655 dependencies = [
656 dependencies = [
656 "adler",
657 "adler",
657 "autocfg",
658 "autocfg",
658 ]
659 ]
659
660
660 [[package]]
661 [[package]]
661 name = "num-integer"
662 name = "num-integer"
662 version = "0.1.44"
663 version = "0.1.44"
663 source = "registry+https://github.com/rust-lang/crates.io-index"
664 source = "registry+https://github.com/rust-lang/crates.io-index"
664 checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
665 checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
665 dependencies = [
666 dependencies = [
666 "autocfg",
667 "autocfg",
667 "num-traits",
668 "num-traits",
668 ]
669 ]
669
670
670 [[package]]
671 [[package]]
671 name = "num-traits"
672 name = "num-traits"
672 version = "0.2.14"
673 version = "0.2.14"
673 source = "registry+https://github.com/rust-lang/crates.io-index"
674 source = "registry+https://github.com/rust-lang/crates.io-index"
674 checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
675 checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
675 dependencies = [
676 dependencies = [
676 "autocfg",
677 "autocfg",
677 "libm",
678 "libm",
678 ]
679 ]
679
680
680 [[package]]
681 [[package]]
681 name = "num_cpus"
682 name = "num_cpus"
682 version = "1.13.0"
683 version = "1.13.0"
683 source = "registry+https://github.com/rust-lang/crates.io-index"
684 source = "registry+https://github.com/rust-lang/crates.io-index"
684 checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
685 checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
685 dependencies = [
686 dependencies = [
686 "hermit-abi",
687 "hermit-abi",
687 "libc",
688 "libc",
688 ]
689 ]
689
690
690 [[package]]
691 [[package]]
691 name = "once_cell"
692 name = "once_cell"
692 version = "1.14.0"
693 version = "1.14.0"
693 source = "registry+https://github.com/rust-lang/crates.io-index"
694 source = "registry+https://github.com/rust-lang/crates.io-index"
694 checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
695 checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
695
696
696 [[package]]
697 [[package]]
697 name = "opaque-debug"
698 name = "opaque-debug"
698 version = "0.3.0"
699 version = "0.3.0"
699 source = "registry+https://github.com/rust-lang/crates.io-index"
700 source = "registry+https://github.com/rust-lang/crates.io-index"
700 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
701 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
701
702
702 [[package]]
703 [[package]]
703 name = "ouroboros"
704 name = "ouroboros"
704 version = "0.15.0"
705 version = "0.15.0"
705 source = "registry+https://github.com/rust-lang/crates.io-index"
706 source = "registry+https://github.com/rust-lang/crates.io-index"
706 checksum = "9f31a3b678685b150cba82b702dcdc5e155893f63610cf388d30cd988d4ca2bf"
707 checksum = "9f31a3b678685b150cba82b702dcdc5e155893f63610cf388d30cd988d4ca2bf"
707 dependencies = [
708 dependencies = [
708 "aliasable",
709 "aliasable",
709 "ouroboros_macro",
710 "ouroboros_macro",
710 "stable_deref_trait",
711 "stable_deref_trait",
711 ]
712 ]
712
713
713 [[package]]
714 [[package]]
714 name = "ouroboros_macro"
715 name = "ouroboros_macro"
715 version = "0.15.0"
716 version = "0.15.0"
716 source = "registry+https://github.com/rust-lang/crates.io-index"
717 source = "registry+https://github.com/rust-lang/crates.io-index"
717 checksum = "084fd65d5dd8b3772edccb5ffd1e4b7eba43897ecd0f9401e330e8c542959408"
718 checksum = "084fd65d5dd8b3772edccb5ffd1e4b7eba43897ecd0f9401e330e8c542959408"
718 dependencies = [
719 dependencies = [
719 "Inflector",
720 "Inflector",
720 "proc-macro-error",
721 "proc-macro-error",
721 "proc-macro2",
722 "proc-macro2",
722 "quote",
723 "quote",
723 "syn",
724 "syn",
724 ]
725 ]
725
726
726 [[package]]
727 [[package]]
727 name = "output_vt100"
728 name = "output_vt100"
728 version = "0.1.2"
729 version = "0.1.2"
729 source = "registry+https://github.com/rust-lang/crates.io-index"
730 source = "registry+https://github.com/rust-lang/crates.io-index"
730 checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
731 checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
731 dependencies = [
732 dependencies = [
732 "winapi",
733 "winapi",
733 ]
734 ]
734
735
735 [[package]]
736 [[package]]
736 name = "paste"
737 name = "paste"
737 version = "1.0.5"
738 version = "1.0.5"
738 source = "registry+https://github.com/rust-lang/crates.io-index"
739 source = "registry+https://github.com/rust-lang/crates.io-index"
739 checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
740 checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
740
741
741 [[package]]
742 [[package]]
742 name = "pkg-config"
743 name = "pkg-config"
743 version = "0.3.19"
744 version = "0.3.19"
744 source = "registry+https://github.com/rust-lang/crates.io-index"
745 source = "registry+https://github.com/rust-lang/crates.io-index"
745 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
746 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
746
747
747 [[package]]
748 [[package]]
748 name = "ppv-lite86"
749 name = "ppv-lite86"
749 version = "0.2.10"
750 version = "0.2.10"
750 source = "registry+https://github.com/rust-lang/crates.io-index"
751 source = "registry+https://github.com/rust-lang/crates.io-index"
751 checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
752 checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
752
753
753 [[package]]
754 [[package]]
754 name = "pretty_assertions"
755 name = "pretty_assertions"
755 version = "1.1.0"
756 version = "1.1.0"
756 source = "registry+https://github.com/rust-lang/crates.io-index"
757 source = "registry+https://github.com/rust-lang/crates.io-index"
757 checksum = "76d5b548b725018ab5496482b45cb8bef21e9fed1858a6d674e3a8a0f0bb5d50"
758 checksum = "76d5b548b725018ab5496482b45cb8bef21e9fed1858a6d674e3a8a0f0bb5d50"
758 dependencies = [
759 dependencies = [
759 "ansi_term",
760 "ansi_term",
760 "ctor",
761 "ctor",
761 "diff",
762 "diff",
762 "output_vt100",
763 "output_vt100",
763 ]
764 ]
764
765
765 [[package]]
766 [[package]]
766 name = "proc-macro-error"
767 name = "proc-macro-error"
767 version = "1.0.4"
768 version = "1.0.4"
768 source = "registry+https://github.com/rust-lang/crates.io-index"
769 source = "registry+https://github.com/rust-lang/crates.io-index"
769 checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
770 checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
770 dependencies = [
771 dependencies = [
771 "proc-macro-error-attr",
772 "proc-macro-error-attr",
772 "proc-macro2",
773 "proc-macro2",
773 "quote",
774 "quote",
774 "syn",
775 "syn",
775 "version_check",
776 "version_check",
776 ]
777 ]
777
778
778 [[package]]
779 [[package]]
779 name = "proc-macro-error-attr"
780 name = "proc-macro-error-attr"
780 version = "1.0.4"
781 version = "1.0.4"
781 source = "registry+https://github.com/rust-lang/crates.io-index"
782 source = "registry+https://github.com/rust-lang/crates.io-index"
782 checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
783 checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
783 dependencies = [
784 dependencies = [
784 "proc-macro2",
785 "proc-macro2",
785 "quote",
786 "quote",
786 "version_check",
787 "version_check",
787 ]
788 ]
788
789
789 [[package]]
790 [[package]]
790 name = "proc-macro2"
791 name = "proc-macro2"
791 version = "1.0.24"
792 version = "1.0.24"
792 source = "registry+https://github.com/rust-lang/crates.io-index"
793 source = "registry+https://github.com/rust-lang/crates.io-index"
793 checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
794 checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
794 dependencies = [
795 dependencies = [
795 "unicode-xid",
796 "unicode-xid",
796 ]
797 ]
797
798
798 [[package]]
799 [[package]]
799 name = "python3-sys"
800 name = "python3-sys"
800 version = "0.7.0"
801 version = "0.7.0"
801 source = "registry+https://github.com/rust-lang/crates.io-index"
802 source = "registry+https://github.com/rust-lang/crates.io-index"
802 checksum = "b18b32e64c103d5045f44644d7ddddd65336f7a0521f6fde673240a9ecceb77e"
803 checksum = "b18b32e64c103d5045f44644d7ddddd65336f7a0521f6fde673240a9ecceb77e"
803 dependencies = [
804 dependencies = [
804 "libc",
805 "libc",
805 "regex",
806 "regex",
806 ]
807 ]
807
808
808 [[package]]
809 [[package]]
809 name = "quote"
810 name = "quote"
810 version = "1.0.7"
811 version = "1.0.7"
811 source = "registry+https://github.com/rust-lang/crates.io-index"
812 source = "registry+https://github.com/rust-lang/crates.io-index"
812 checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
813 checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
813 dependencies = [
814 dependencies = [
814 "proc-macro2",
815 "proc-macro2",
815 ]
816 ]
816
817
817 [[package]]
818 [[package]]
818 name = "rand"
819 name = "rand"
819 version = "0.7.3"
820 version = "0.7.3"
820 source = "registry+https://github.com/rust-lang/crates.io-index"
821 source = "registry+https://github.com/rust-lang/crates.io-index"
821 checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
822 checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
822 dependencies = [
823 dependencies = [
823 "getrandom 0.1.15",
824 "getrandom 0.1.15",
824 "libc",
825 "libc",
825 "rand_chacha 0.2.2",
826 "rand_chacha 0.2.2",
826 "rand_core 0.5.1",
827 "rand_core 0.5.1",
827 "rand_hc",
828 "rand_hc",
828 ]
829 ]
829
830
830 [[package]]
831 [[package]]
831 name = "rand"
832 name = "rand"
832 version = "0.8.5"
833 version = "0.8.5"
833 source = "registry+https://github.com/rust-lang/crates.io-index"
834 source = "registry+https://github.com/rust-lang/crates.io-index"
834 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
835 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
835 dependencies = [
836 dependencies = [
836 "libc",
837 "libc",
837 "rand_chacha 0.3.1",
838 "rand_chacha 0.3.1",
838 "rand_core 0.6.3",
839 "rand_core 0.6.3",
839 ]
840 ]
840
841
841 [[package]]
842 [[package]]
842 name = "rand_chacha"
843 name = "rand_chacha"
843 version = "0.2.2"
844 version = "0.2.2"
844 source = "registry+https://github.com/rust-lang/crates.io-index"
845 source = "registry+https://github.com/rust-lang/crates.io-index"
845 checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
846 checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
846 dependencies = [
847 dependencies = [
847 "ppv-lite86",
848 "ppv-lite86",
848 "rand_core 0.5.1",
849 "rand_core 0.5.1",
849 ]
850 ]
850
851
851 [[package]]
852 [[package]]
852 name = "rand_chacha"
853 name = "rand_chacha"
853 version = "0.3.1"
854 version = "0.3.1"
854 source = "registry+https://github.com/rust-lang/crates.io-index"
855 source = "registry+https://github.com/rust-lang/crates.io-index"
855 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
856 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
856 dependencies = [
857 dependencies = [
857 "ppv-lite86",
858 "ppv-lite86",
858 "rand_core 0.6.3",
859 "rand_core 0.6.3",
859 ]
860 ]
860
861
861 [[package]]
862 [[package]]
862 name = "rand_core"
863 name = "rand_core"
863 version = "0.5.1"
864 version = "0.5.1"
864 source = "registry+https://github.com/rust-lang/crates.io-index"
865 source = "registry+https://github.com/rust-lang/crates.io-index"
865 checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
866 checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
866 dependencies = [
867 dependencies = [
867 "getrandom 0.1.15",
868 "getrandom 0.1.15",
868 ]
869 ]
869
870
870 [[package]]
871 [[package]]
871 name = "rand_core"
872 name = "rand_core"
872 version = "0.6.3"
873 version = "0.6.3"
873 source = "registry+https://github.com/rust-lang/crates.io-index"
874 source = "registry+https://github.com/rust-lang/crates.io-index"
874 checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
875 checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
875 dependencies = [
876 dependencies = [
876 "getrandom 0.2.4",
877 "getrandom 0.2.4",
877 ]
878 ]
878
879
879 [[package]]
880 [[package]]
880 name = "rand_distr"
881 name = "rand_distr"
881 version = "0.4.3"
882 version = "0.4.3"
882 source = "registry+https://github.com/rust-lang/crates.io-index"
883 source = "registry+https://github.com/rust-lang/crates.io-index"
883 checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
884 checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
884 dependencies = [
885 dependencies = [
885 "num-traits",
886 "num-traits",
886 "rand 0.8.5",
887 "rand 0.8.5",
887 ]
888 ]
888
889
889 [[package]]
890 [[package]]
890 name = "rand_hc"
891 name = "rand_hc"
891 version = "0.2.0"
892 version = "0.2.0"
892 source = "registry+https://github.com/rust-lang/crates.io-index"
893 source = "registry+https://github.com/rust-lang/crates.io-index"
893 checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
894 checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
894 dependencies = [
895 dependencies = [
895 "rand_core 0.5.1",
896 "rand_core 0.5.1",
896 ]
897 ]
897
898
898 [[package]]
899 [[package]]
899 name = "rand_pcg"
900 name = "rand_pcg"
900 version = "0.3.1"
901 version = "0.3.1"
901 source = "registry+https://github.com/rust-lang/crates.io-index"
902 source = "registry+https://github.com/rust-lang/crates.io-index"
902 checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
903 checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
903 dependencies = [
904 dependencies = [
904 "rand_core 0.6.3",
905 "rand_core 0.6.3",
905 ]
906 ]
906
907
907 [[package]]
908 [[package]]
908 name = "rand_xoshiro"
909 name = "rand_xoshiro"
909 version = "0.4.0"
910 version = "0.4.0"
910 source = "registry+https://github.com/rust-lang/crates.io-index"
911 source = "registry+https://github.com/rust-lang/crates.io-index"
911 checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
912 checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
912 dependencies = [
913 dependencies = [
913 "rand_core 0.5.1",
914 "rand_core 0.5.1",
914 ]
915 ]
915
916
916 [[package]]
917 [[package]]
917 name = "rayon"
918 name = "rayon"
918 version = "1.5.1"
919 version = "1.5.1"
919 source = "registry+https://github.com/rust-lang/crates.io-index"
920 source = "registry+https://github.com/rust-lang/crates.io-index"
920 checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
921 checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
921 dependencies = [
922 dependencies = [
922 "autocfg",
923 "autocfg",
923 "crossbeam-deque",
924 "crossbeam-deque",
924 "either",
925 "either",
925 "rayon-core",
926 "rayon-core",
926 ]
927 ]
927
928
928 [[package]]
929 [[package]]
929 name = "rayon-core"
930 name = "rayon-core"
930 version = "1.9.1"
931 version = "1.9.1"
931 source = "registry+https://github.com/rust-lang/crates.io-index"
932 source = "registry+https://github.com/rust-lang/crates.io-index"
932 checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
933 checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
933 dependencies = [
934 dependencies = [
934 "crossbeam-channel",
935 "crossbeam-channel",
935 "crossbeam-deque",
936 "crossbeam-deque",
936 "crossbeam-utils",
937 "crossbeam-utils",
937 "lazy_static",
938 "lazy_static",
938 "num_cpus",
939 "num_cpus",
939 ]
940 ]
940
941
941 [[package]]
942 [[package]]
942 name = "redox_syscall"
943 name = "redox_syscall"
943 version = "0.2.11"
944 version = "0.2.11"
944 source = "registry+https://github.com/rust-lang/crates.io-index"
945 source = "registry+https://github.com/rust-lang/crates.io-index"
945 checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
946 checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
946 dependencies = [
947 dependencies = [
947 "bitflags",
948 "bitflags",
948 ]
949 ]
949
950
950 [[package]]
951 [[package]]
951 name = "regex"
952 name = "regex"
952 version = "1.5.5"
953 version = "1.5.5"
953 source = "registry+https://github.com/rust-lang/crates.io-index"
954 source = "registry+https://github.com/rust-lang/crates.io-index"
954 checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
955 checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286"
955 dependencies = [
956 dependencies = [
956 "aho-corasick",
957 "aho-corasick",
957 "memchr",
958 "memchr",
958 "regex-syntax",
959 "regex-syntax",
959 ]
960 ]
960
961
961 [[package]]
962 [[package]]
962 name = "regex-syntax"
963 name = "regex-syntax"
963 version = "0.6.25"
964 version = "0.6.25"
964 source = "registry+https://github.com/rust-lang/crates.io-index"
965 source = "registry+https://github.com/rust-lang/crates.io-index"
965 checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
966 checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
966
967
967 [[package]]
968 [[package]]
968 name = "remove_dir_all"
969 name = "remove_dir_all"
969 version = "0.5.3"
970 version = "0.5.3"
970 source = "registry+https://github.com/rust-lang/crates.io-index"
971 source = "registry+https://github.com/rust-lang/crates.io-index"
971 checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
972 checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
972 dependencies = [
973 dependencies = [
973 "winapi",
974 "winapi",
974 ]
975 ]
975
976
976 [[package]]
977 [[package]]
977 name = "rhg"
978 name = "rhg"
978 version = "0.1.0"
979 version = "0.1.0"
979 dependencies = [
980 dependencies = [
980 "atty",
981 "atty",
981 "chrono",
982 "chrono",
982 "clap",
983 "clap",
983 "derive_more",
984 "derive_more",
984 "env_logger",
985 "env_logger",
985 "format-bytes",
986 "format-bytes",
986 "hg-core",
987 "hg-core",
987 "home",
988 "home",
988 "lazy_static",
989 "lazy_static",
989 "log",
990 "log",
990 "micro-timer",
991 "micro-timer",
991 "rayon",
992 "rayon",
992 "regex",
993 "regex",
993 "users",
994 "users",
994 "which",
995 "which",
995 ]
996 ]
996
997
997 [[package]]
998 [[package]]
998 name = "rustc_version"
999 name = "rustc_version"
999 version = "0.4.0"
1000 version = "0.4.0"
1000 source = "registry+https://github.com/rust-lang/crates.io-index"
1001 source = "registry+https://github.com/rust-lang/crates.io-index"
1001 checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
1002 checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
1002 dependencies = [
1003 dependencies = [
1003 "semver",
1004 "semver",
1004 ]
1005 ]
1005
1006
1006 [[package]]
1007 [[package]]
1007 name = "same-file"
1008 name = "same-file"
1008 version = "1.0.6"
1009 version = "1.0.6"
1009 source = "registry+https://github.com/rust-lang/crates.io-index"
1010 source = "registry+https://github.com/rust-lang/crates.io-index"
1010 checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
1011 checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
1011 dependencies = [
1012 dependencies = [
1012 "winapi-util",
1013 "winapi-util",
1013 ]
1014 ]
1014
1015
1015 [[package]]
1016 [[package]]
1016 name = "scopeguard"
1017 name = "scopeguard"
1017 version = "1.1.0"
1018 version = "1.1.0"
1018 source = "registry+https://github.com/rust-lang/crates.io-index"
1019 source = "registry+https://github.com/rust-lang/crates.io-index"
1019 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1020 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
1020
1021
1021 [[package]]
1022 [[package]]
1022 name = "semver"
1023 name = "semver"
1023 version = "1.0.6"
1024 version = "1.0.6"
1024 source = "registry+https://github.com/rust-lang/crates.io-index"
1025 source = "registry+https://github.com/rust-lang/crates.io-index"
1025 checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
1026 checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
1026
1027
1027 [[package]]
1028 [[package]]
1028 name = "sha-1"
1029 name = "sha-1"
1029 version = "0.9.6"
1030 version = "0.9.6"
1030 source = "registry+https://github.com/rust-lang/crates.io-index"
1031 source = "registry+https://github.com/rust-lang/crates.io-index"
1031 checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16"
1032 checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16"
1032 dependencies = [
1033 dependencies = [
1033 "block-buffer 0.9.0",
1034 "block-buffer 0.9.0",
1034 "cfg-if 1.0.0",
1035 "cfg-if 1.0.0",
1035 "cpufeatures 0.1.4",
1036 "cpufeatures 0.1.4",
1036 "digest 0.9.0",
1037 "digest 0.9.0",
1037 "opaque-debug",
1038 "opaque-debug",
1038 ]
1039 ]
1039
1040
1040 [[package]]
1041 [[package]]
1041 name = "sha-1"
1042 name = "sha-1"
1042 version = "0.10.0"
1043 version = "0.10.0"
1043 source = "registry+https://github.com/rust-lang/crates.io-index"
1044 source = "registry+https://github.com/rust-lang/crates.io-index"
1044 checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
1045 checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
1045 dependencies = [
1046 dependencies = [
1046 "cfg-if 1.0.0",
1047 "cfg-if 1.0.0",
1047 "cpufeatures 0.2.1",
1048 "cpufeatures 0.2.1",
1048 "digest 0.10.2",
1049 "digest 0.10.2",
1049 ]
1050 ]
1050
1051
1051 [[package]]
1052 [[package]]
1052 name = "sized-chunks"
1053 name = "sized-chunks"
1053 version = "0.6.2"
1054 version = "0.6.2"
1054 source = "registry+https://github.com/rust-lang/crates.io-index"
1055 source = "registry+https://github.com/rust-lang/crates.io-index"
1055 checksum = "1ec31ceca5644fa6d444cc77548b88b67f46db6f7c71683b0f9336e671830d2f"
1056 checksum = "1ec31ceca5644fa6d444cc77548b88b67f46db6f7c71683b0f9336e671830d2f"
1056 dependencies = [
1057 dependencies = [
1057 "bitmaps",
1058 "bitmaps",
1058 "typenum",
1059 "typenum",
1059 ]
1060 ]
1060
1061
1061 [[package]]
1062 [[package]]
1062 name = "stable_deref_trait"
1063 name = "stable_deref_trait"
1063 version = "1.2.0"
1064 version = "1.2.0"
1064 source = "registry+https://github.com/rust-lang/crates.io-index"
1065 source = "registry+https://github.com/rust-lang/crates.io-index"
1065 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
1066 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
1066
1067
1067 [[package]]
1068 [[package]]
1068 name = "static_assertions"
1069 name = "static_assertions"
1069 version = "1.1.0"
1070 version = "1.1.0"
1070 source = "registry+https://github.com/rust-lang/crates.io-index"
1071 source = "registry+https://github.com/rust-lang/crates.io-index"
1071 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1072 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1072
1073
1073 [[package]]
1074 [[package]]
1074 name = "strsim"
1075 name = "strsim"
1075 version = "0.8.0"
1076 version = "0.8.0"
1076 source = "registry+https://github.com/rust-lang/crates.io-index"
1077 source = "registry+https://github.com/rust-lang/crates.io-index"
1077 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
1078 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
1078
1079
1079 [[package]]
1080 [[package]]
1080 name = "syn"
1081 name = "syn"
1081 version = "1.0.54"
1082 version = "1.0.54"
1082 source = "registry+https://github.com/rust-lang/crates.io-index"
1083 source = "registry+https://github.com/rust-lang/crates.io-index"
1083 checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
1084 checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
1084 dependencies = [
1085 dependencies = [
1085 "proc-macro2",
1086 "proc-macro2",
1086 "quote",
1087 "quote",
1087 "unicode-xid",
1088 "unicode-xid",
1088 ]
1089 ]
1089
1090
1090 [[package]]
1091 [[package]]
1091 name = "tempfile"
1092 name = "tempfile"
1092 version = "3.3.0"
1093 version = "3.3.0"
1093 source = "registry+https://github.com/rust-lang/crates.io-index"
1094 source = "registry+https://github.com/rust-lang/crates.io-index"
1094 checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
1095 checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
1095 dependencies = [
1096 dependencies = [
1096 "cfg-if 1.0.0",
1097 "cfg-if 1.0.0",
1097 "fastrand",
1098 "fastrand",
1098 "libc",
1099 "libc",
1099 "redox_syscall",
1100 "redox_syscall",
1100 "remove_dir_all",
1101 "remove_dir_all",
1101 "winapi",
1102 "winapi",
1102 ]
1103 ]
1103
1104
1104 [[package]]
1105 [[package]]
1105 name = "termcolor"
1106 name = "termcolor"
1106 version = "1.1.2"
1107 version = "1.1.2"
1107 source = "registry+https://github.com/rust-lang/crates.io-index"
1108 source = "registry+https://github.com/rust-lang/crates.io-index"
1108 checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
1109 checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
1109 dependencies = [
1110 dependencies = [
1110 "winapi-util",
1111 "winapi-util",
1111 ]
1112 ]
1112
1113
1113 [[package]]
1114 [[package]]
1114 name = "textwrap"
1115 name = "textwrap"
1115 version = "0.11.0"
1116 version = "0.11.0"
1116 source = "registry+https://github.com/rust-lang/crates.io-index"
1117 source = "registry+https://github.com/rust-lang/crates.io-index"
1117 checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
1118 checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
1118 dependencies = [
1119 dependencies = [
1119 "unicode-width",
1120 "unicode-width",
1120 ]
1121 ]
1121
1122
1122 [[package]]
1123 [[package]]
1124 name = "thread_local"
1125 version = "1.1.4"
1126 source = "registry+https://github.com/rust-lang/crates.io-index"
1127 checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
1128 dependencies = [
1129 "once_cell",
1130 ]
1131
1132 [[package]]
1123 name = "time"
1133 name = "time"
1124 version = "0.1.44"
1134 version = "0.1.44"
1125 source = "registry+https://github.com/rust-lang/crates.io-index"
1135 source = "registry+https://github.com/rust-lang/crates.io-index"
1126 checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
1136 checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
1127 dependencies = [
1137 dependencies = [
1128 "libc",
1138 "libc",
1129 "wasi 0.10.0+wasi-snapshot-preview1",
1139 "wasi 0.10.0+wasi-snapshot-preview1",
1130 "winapi",
1140 "winapi",
1131 ]
1141 ]
1132
1142
1133 [[package]]
1143 [[package]]
1134 name = "twox-hash"
1144 name = "twox-hash"
1135 version = "1.6.2"
1145 version = "1.6.2"
1136 source = "registry+https://github.com/rust-lang/crates.io-index"
1146 source = "registry+https://github.com/rust-lang/crates.io-index"
1137 checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0"
1147 checksum = "4ee73e6e4924fe940354b8d4d98cad5231175d615cd855b758adc658c0aac6a0"
1138 dependencies = [
1148 dependencies = [
1139 "cfg-if 1.0.0",
1149 "cfg-if 1.0.0",
1140 "rand 0.8.5",
1150 "rand 0.8.5",
1141 "static_assertions",
1151 "static_assertions",
1142 ]
1152 ]
1143
1153
1144 [[package]]
1154 [[package]]
1145 name = "typenum"
1155 name = "typenum"
1146 version = "1.12.0"
1156 version = "1.12.0"
1147 source = "registry+https://github.com/rust-lang/crates.io-index"
1157 source = "registry+https://github.com/rust-lang/crates.io-index"
1148 checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
1158 checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
1149
1159
1150 [[package]]
1160 [[package]]
1151 name = "unicode-width"
1161 name = "unicode-width"
1152 version = "0.1.9"
1162 version = "0.1.9"
1153 source = "registry+https://github.com/rust-lang/crates.io-index"
1163 source = "registry+https://github.com/rust-lang/crates.io-index"
1154 checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
1164 checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
1155
1165
1156 [[package]]
1166 [[package]]
1157 name = "unicode-xid"
1167 name = "unicode-xid"
1158 version = "0.2.1"
1168 version = "0.2.1"
1159 source = "registry+https://github.com/rust-lang/crates.io-index"
1169 source = "registry+https://github.com/rust-lang/crates.io-index"
1160 checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
1170 checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
1161
1171
1162 [[package]]
1172 [[package]]
1163 name = "users"
1173 name = "users"
1164 version = "0.11.0"
1174 version = "0.11.0"
1165 source = "registry+https://github.com/rust-lang/crates.io-index"
1175 source = "registry+https://github.com/rust-lang/crates.io-index"
1166 checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
1176 checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
1167 dependencies = [
1177 dependencies = [
1168 "libc",
1178 "libc",
1169 "log",
1179 "log",
1170 ]
1180 ]
1171
1181
1172 [[package]]
1182 [[package]]
1173 name = "vcpkg"
1183 name = "vcpkg"
1174 version = "0.2.11"
1184 version = "0.2.11"
1175 source = "registry+https://github.com/rust-lang/crates.io-index"
1185 source = "registry+https://github.com/rust-lang/crates.io-index"
1176 checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
1186 checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
1177
1187
1178 [[package]]
1188 [[package]]
1179 name = "vcsgraph"
1189 name = "vcsgraph"
1180 version = "0.2.0"
1190 version = "0.2.0"
1181 source = "registry+https://github.com/rust-lang/crates.io-index"
1191 source = "registry+https://github.com/rust-lang/crates.io-index"
1182 checksum = "4cb68c231e2575f7503a7c19213875f9d4ec2e84e963a56ce3de4b6bee351ef7"
1192 checksum = "4cb68c231e2575f7503a7c19213875f9d4ec2e84e963a56ce3de4b6bee351ef7"
1183 dependencies = [
1193 dependencies = [
1184 "hex",
1194 "hex",
1185 "rand 0.7.3",
1195 "rand 0.7.3",
1186 "sha-1 0.9.6",
1196 "sha-1 0.9.6",
1187 ]
1197 ]
1188
1198
1189 [[package]]
1199 [[package]]
1190 name = "vec_map"
1200 name = "vec_map"
1191 version = "0.8.2"
1201 version = "0.8.2"
1192 source = "registry+https://github.com/rust-lang/crates.io-index"
1202 source = "registry+https://github.com/rust-lang/crates.io-index"
1193 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1203 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1194
1204
1195 [[package]]
1205 [[package]]
1196 name = "version_check"
1206 name = "version_check"
1197 version = "0.9.2"
1207 version = "0.9.2"
1198 source = "registry+https://github.com/rust-lang/crates.io-index"
1208 source = "registry+https://github.com/rust-lang/crates.io-index"
1199 checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
1209 checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
1200
1210
1201 [[package]]
1211 [[package]]
1202 name = "wasi"
1212 name = "wasi"
1203 version = "0.9.0+wasi-snapshot-preview1"
1213 version = "0.9.0+wasi-snapshot-preview1"
1204 source = "registry+https://github.com/rust-lang/crates.io-index"
1214 source = "registry+https://github.com/rust-lang/crates.io-index"
1205 checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
1215 checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
1206
1216
1207 [[package]]
1217 [[package]]
1208 name = "wasi"
1218 name = "wasi"
1209 version = "0.10.0+wasi-snapshot-preview1"
1219 version = "0.10.0+wasi-snapshot-preview1"
1210 source = "registry+https://github.com/rust-lang/crates.io-index"
1220 source = "registry+https://github.com/rust-lang/crates.io-index"
1211 checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1221 checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1212
1222
1213 [[package]]
1223 [[package]]
1214 name = "which"
1224 name = "which"
1215 version = "4.2.5"
1225 version = "4.2.5"
1216 source = "registry+https://github.com/rust-lang/crates.io-index"
1226 source = "registry+https://github.com/rust-lang/crates.io-index"
1217 checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
1227 checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
1218 dependencies = [
1228 dependencies = [
1219 "either",
1229 "either",
1220 "lazy_static",
1230 "lazy_static",
1221 "libc",
1231 "libc",
1222 ]
1232 ]
1223
1233
1224 [[package]]
1234 [[package]]
1225 name = "winapi"
1235 name = "winapi"
1226 version = "0.3.9"
1236 version = "0.3.9"
1227 source = "registry+https://github.com/rust-lang/crates.io-index"
1237 source = "registry+https://github.com/rust-lang/crates.io-index"
1228 checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1238 checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1229 dependencies = [
1239 dependencies = [
1230 "winapi-i686-pc-windows-gnu",
1240 "winapi-i686-pc-windows-gnu",
1231 "winapi-x86_64-pc-windows-gnu",
1241 "winapi-x86_64-pc-windows-gnu",
1232 ]
1242 ]
1233
1243
1234 [[package]]
1244 [[package]]
1235 name = "winapi-i686-pc-windows-gnu"
1245 name = "winapi-i686-pc-windows-gnu"
1236 version = "0.4.0"
1246 version = "0.4.0"
1237 source = "registry+https://github.com/rust-lang/crates.io-index"
1247 source = "registry+https://github.com/rust-lang/crates.io-index"
1238 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1248 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1239
1249
1240 [[package]]
1250 [[package]]
1241 name = "winapi-util"
1251 name = "winapi-util"
1242 version = "0.1.5"
1252 version = "0.1.5"
1243 source = "registry+https://github.com/rust-lang/crates.io-index"
1253 source = "registry+https://github.com/rust-lang/crates.io-index"
1244 checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1254 checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1245 dependencies = [
1255 dependencies = [
1246 "winapi",
1256 "winapi",
1247 ]
1257 ]
1248
1258
1249 [[package]]
1259 [[package]]
1250 name = "winapi-x86_64-pc-windows-gnu"
1260 name = "winapi-x86_64-pc-windows-gnu"
1251 version = "0.4.0"
1261 version = "0.4.0"
1252 source = "registry+https://github.com/rust-lang/crates.io-index"
1262 source = "registry+https://github.com/rust-lang/crates.io-index"
1253 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1263 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1254
1264
1255 [[package]]
1265 [[package]]
1256 name = "zstd"
1266 name = "zstd"
1257 version = "0.5.4+zstd.1.4.7"
1267 version = "0.5.4+zstd.1.4.7"
1258 source = "registry+https://github.com/rust-lang/crates.io-index"
1268 source = "registry+https://github.com/rust-lang/crates.io-index"
1259 checksum = "69996ebdb1ba8b1517f61387a883857818a66c8a295f487b1ffd8fd9d2c82910"
1269 checksum = "69996ebdb1ba8b1517f61387a883857818a66c8a295f487b1ffd8fd9d2c82910"
1260 dependencies = [
1270 dependencies = [
1261 "zstd-safe",
1271 "zstd-safe",
1262 ]
1272 ]
1263
1273
1264 [[package]]
1274 [[package]]
1265 name = "zstd-safe"
1275 name = "zstd-safe"
1266 version = "2.0.6+zstd.1.4.7"
1276 version = "2.0.6+zstd.1.4.7"
1267 source = "registry+https://github.com/rust-lang/crates.io-index"
1277 source = "registry+https://github.com/rust-lang/crates.io-index"
1268 checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e"
1278 checksum = "98aa931fb69ecee256d44589d19754e61851ae4769bf963b385119b1cc37a49e"
1269 dependencies = [
1279 dependencies = [
1270 "libc",
1280 "libc",
1271 "zstd-sys",
1281 "zstd-sys",
1272 ]
1282 ]
1273
1283
1274 [[package]]
1284 [[package]]
1275 name = "zstd-sys"
1285 name = "zstd-sys"
1276 version = "1.4.18+zstd.1.4.7"
1286 version = "1.4.18+zstd.1.4.7"
1277 source = "registry+https://github.com/rust-lang/crates.io-index"
1287 source = "registry+https://github.com/rust-lang/crates.io-index"
1278 checksum = "a1e6e8778706838f43f771d80d37787cb2fe06dafe89dd3aebaf6721b9eaec81"
1288 checksum = "a1e6e8778706838f43f771d80d37787cb2fe06dafe89dd3aebaf6721b9eaec81"
1279 dependencies = [
1289 dependencies = [
1280 "cc",
1290 "cc",
1281 "glob",
1291 "glob",
1282 "itertools 0.9.0",
1292 "itertools 0.9.0",
1283 "libc",
1293 "libc",
1284 ]
1294 ]
@@ -1,51 +1,52 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
7
8 [lib]
8 [lib]
9 name = "hg"
9 name = "hg"
10
10
11 [dependencies]
11 [dependencies]
12 bitflags = "1.3.2"
12 bitflags = "1.3.2"
13 bytes-cast = "0.2.0"
13 bytes-cast = "0.2.0"
14 byteorder = "1.4.3"
14 byteorder = "1.4.3"
15 derive_more = "0.99.17"
15 derive_more = "0.99.17"
16 hashbrown = { version = "0.9.1", features = ["rayon"] }
16 hashbrown = { version = "0.9.1", features = ["rayon"] }
17 home = "0.5.3"
17 home = "0.5.3"
18 im-rc = "15.0"
18 im-rc = "15.0"
19 itertools = "0.10.3"
19 itertools = "0.10.3"
20 lazy_static = "1.4.0"
20 lazy_static = "1.4.0"
21 libc = "0.2"
21 libc = "0.2"
22 ouroboros = "0.15.0"
22 ouroboros = "0.15.0"
23 rand = "0.8.4"
23 rand = "0.8.4"
24 rand_pcg = "0.3.1"
24 rand_pcg = "0.3.1"
25 rand_distr = "0.4.3"
25 rand_distr = "0.4.3"
26 rayon = "1.5.1"
26 rayon = "1.5.1"
27 regex = "1.5.5"
27 regex = "1.5.5"
28 sha-1 = "0.10.0"
28 sha-1 = "0.10.0"
29 twox-hash = "1.6.2"
29 twox-hash = "1.6.2"
30 same-file = "1.0.6"
30 same-file = "1.0.6"
31 tempfile = "3.1.0"
31 tempfile = "3.1.0"
32 thread_local = "1.1.4"
32 crossbeam-channel = "0.5.0"
33 crossbeam-channel = "0.5.0"
33 micro-timer = "0.4.0"
34 micro-timer = "0.4.0"
34 log = "0.4.8"
35 log = "0.4.8"
35 memmap2 = { version = "0.5.3", features = ["stable_deref_trait"] }
36 memmap2 = { version = "0.5.3", features = ["stable_deref_trait"] }
36 zstd = "0.5.3"
37 zstd = "0.5.3"
37 format-bytes = "0.3.0"
38 format-bytes = "0.3.0"
38 # once_cell 1.15 uses edition 2021, while the heptapod CI
39 # once_cell 1.15 uses edition 2021, while the heptapod CI
39 # uses an old version of Cargo that doesn't support it.
40 # uses an old version of Cargo that doesn't support it.
40 once_cell = "=1.14.0"
41 once_cell = "=1.14.0"
41
42
42 # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until
43 # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until
43 # we have a clearer view of which backend is the fastest.
44 # we have a clearer view of which backend is the fastest.
44 [dependencies.flate2]
45 [dependencies.flate2]
45 version = "1.0.22"
46 version = "1.0.22"
46 features = ["zlib"]
47 features = ["zlib"]
47 default-features = false
48 default-features = false
48
49
49 [dev-dependencies]
50 [dev-dependencies]
50 clap = "2.34.0"
51 clap = "2.34.0"
51 pretty_assertions = "1.1.0"
52 pretty_assertions = "1.1.0"
@@ -1,1688 +1,1722 b''
1 // matchers.rs
1 // matchers.rs
2 //
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
3 // Copyright 2019 Raphaël Gomès <rgomes@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 //! Structs and types for matching files and directories.
8 //! Structs and types for matching files and directories.
9
9
10 use crate::{
10 use crate::{
11 dirstate::dirs_multiset::DirsChildrenMultiset,
11 dirstate::dirs_multiset::DirsChildrenMultiset,
12 filepatterns::{
12 filepatterns::{
13 build_single_regex, filter_subincludes, get_patterns_from_file,
13 build_single_regex, filter_subincludes, get_patterns_from_file,
14 PatternFileWarning, PatternResult,
14 PatternFileWarning, PatternResult,
15 },
15 },
16 utils::{
16 utils::{
17 files::find_dirs,
17 files::find_dirs,
18 hg_path::{HgPath, HgPathBuf},
18 hg_path::{HgPath, HgPathBuf},
19 Escaped,
19 Escaped,
20 },
20 },
21 DirsMultiset, DirstateMapError, FastHashMap, IgnorePattern, PatternError,
21 DirsMultiset, DirstateMapError, FastHashMap, IgnorePattern, PatternError,
22 PatternSyntax,
22 PatternSyntax,
23 };
23 };
24
24
25 use crate::dirstate::status::IgnoreFnType;
25 use crate::dirstate::status::IgnoreFnType;
26 use crate::filepatterns::normalize_path_bytes;
26 use crate::filepatterns::normalize_path_bytes;
27 use std::borrow::ToOwned;
27 use std::borrow::ToOwned;
28 use std::collections::HashSet;
28 use std::collections::HashSet;
29 use std::fmt::{Display, Error, Formatter};
29 use std::fmt::{Display, Error, Formatter};
30 use std::iter::FromIterator;
30 use std::iter::FromIterator;
31 use std::ops::Deref;
31 use std::ops::Deref;
32 use std::path::{Path, PathBuf};
32 use std::path::{Path, PathBuf};
33
33
34 use micro_timer::timed;
34 use micro_timer::timed;
35
35
36 #[derive(Debug, PartialEq)]
36 #[derive(Debug, PartialEq)]
37 pub enum VisitChildrenSet {
37 pub enum VisitChildrenSet {
38 /// Don't visit anything
38 /// Don't visit anything
39 Empty,
39 Empty,
40 /// Only visit this directory
40 /// Only visit this directory
41 This,
41 This,
42 /// Visit this directory and these subdirectories
42 /// Visit this directory and these subdirectories
43 /// TODO Should we implement a `NonEmptyHashSet`?
43 /// TODO Should we implement a `NonEmptyHashSet`?
44 Set(HashSet<HgPathBuf>),
44 Set(HashSet<HgPathBuf>),
45 /// Visit this directory and all subdirectories
45 /// Visit this directory and all subdirectories
46 Recursive,
46 Recursive,
47 }
47 }
48
48
49 pub trait Matcher: core::fmt::Debug {
49 pub trait Matcher: core::fmt::Debug {
50 /// Explicitly listed files
50 /// Explicitly listed files
51 fn file_set(&self) -> Option<&HashSet<HgPathBuf>>;
51 fn file_set(&self) -> Option<&HashSet<HgPathBuf>>;
52 /// Returns whether `filename` is in `file_set`
52 /// Returns whether `filename` is in `file_set`
53 fn exact_match(&self, filename: &HgPath) -> bool;
53 fn exact_match(&self, filename: &HgPath) -> bool;
54 /// Returns whether `filename` is matched by this matcher
54 /// Returns whether `filename` is matched by this matcher
55 fn matches(&self, filename: &HgPath) -> bool;
55 fn matches(&self, filename: &HgPath) -> bool;
56 /// Decides whether a directory should be visited based on whether it
56 /// Decides whether a directory should be visited based on whether it
57 /// has potential matches in it or one of its subdirectories, and
57 /// has potential matches in it or one of its subdirectories, and
58 /// potentially lists which subdirectories of that directory should be
58 /// potentially lists which subdirectories of that directory should be
59 /// visited. This is based on the match's primary, included, and excluded
59 /// visited. This is based on the match's primary, included, and excluded
60 /// patterns.
60 /// patterns.
61 ///
61 ///
62 /// # Example
62 /// # Example
63 ///
63 ///
64 /// Assume matchers `['path:foo/bar', 'rootfilesin:qux']`, we would
64 /// Assume matchers `['path:foo/bar', 'rootfilesin:qux']`, we would
65 /// return the following values (assuming the implementation of
65 /// return the following values (assuming the implementation of
66 /// visit_children_set is capable of recognizing this; some implementations
66 /// visit_children_set is capable of recognizing this; some implementations
67 /// are not).
67 /// are not).
68 ///
68 ///
69 /// ```text
69 /// ```text
70 /// ```ignore
70 /// ```ignore
71 /// '' -> {'foo', 'qux'}
71 /// '' -> {'foo', 'qux'}
72 /// 'baz' -> set()
72 /// 'baz' -> set()
73 /// 'foo' -> {'bar'}
73 /// 'foo' -> {'bar'}
74 /// // Ideally this would be `Recursive`, but since the prefix nature of
74 /// // Ideally this would be `Recursive`, but since the prefix nature of
75 /// // matchers is applied to the entire matcher, we have to downgrade this
75 /// // matchers is applied to the entire matcher, we have to downgrade this
76 /// // to `This` due to the (yet to be implemented in Rust) non-prefix
76 /// // to `This` due to the (yet to be implemented in Rust) non-prefix
77 /// // `RootFilesIn'-kind matcher being mixed in.
77 /// // `RootFilesIn'-kind matcher being mixed in.
78 /// 'foo/bar' -> 'this'
78 /// 'foo/bar' -> 'this'
79 /// 'qux' -> 'this'
79 /// 'qux' -> 'this'
80 /// ```
80 /// ```
81 /// # Important
81 /// # Important
82 ///
82 ///
83 /// Most matchers do not know if they're representing files or
83 /// Most matchers do not know if they're representing files or
84 /// directories. They see `['path:dir/f']` and don't know whether `f` is a
84 /// directories. They see `['path:dir/f']` and don't know whether `f` is a
85 /// file or a directory, so `visit_children_set('dir')` for most matchers
85 /// file or a directory, so `visit_children_set('dir')` for most matchers
86 /// will return `HashSet{ HgPath { "f" } }`, but if the matcher knows it's
86 /// will return `HashSet{ HgPath { "f" } }`, but if the matcher knows it's
87 /// a file (like the yet to be implemented in Rust `ExactMatcher` does),
87 /// a file (like the yet to be implemented in Rust `ExactMatcher` does),
88 /// it may return `VisitChildrenSet::This`.
88 /// it may return `VisitChildrenSet::This`.
89 /// Do not rely on the return being a `HashSet` indicating that there are
89 /// Do not rely on the return being a `HashSet` indicating that there are
90 /// no files in this dir to investigate (or equivalently that if there are
90 /// no files in this dir to investigate (or equivalently that if there are
91 /// files to investigate in 'dir' that it will always return
91 /// files to investigate in 'dir' that it will always return
92 /// `VisitChildrenSet::This`).
92 /// `VisitChildrenSet::This`).
93 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet;
93 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet;
94 /// Matcher will match everything and `files_set()` will be empty:
94 /// Matcher will match everything and `files_set()` will be empty:
95 /// optimization might be possible.
95 /// optimization might be possible.
96 fn matches_everything(&self) -> bool;
96 fn matches_everything(&self) -> bool;
97 /// Matcher will match exactly the files in `files_set()`: optimization
97 /// Matcher will match exactly the files in `files_set()`: optimization
98 /// might be possible.
98 /// might be possible.
99 fn is_exact(&self) -> bool;
99 fn is_exact(&self) -> bool;
100 }
100 }
101
101
102 /// Matches everything.
102 /// Matches everything.
103 ///```
103 ///```
104 /// use hg::{ matchers::{Matcher, AlwaysMatcher}, utils::hg_path::HgPath };
104 /// use hg::{ matchers::{Matcher, AlwaysMatcher}, utils::hg_path::HgPath };
105 ///
105 ///
106 /// let matcher = AlwaysMatcher;
106 /// let matcher = AlwaysMatcher;
107 ///
107 ///
108 /// assert_eq!(matcher.matches(HgPath::new(b"whatever")), true);
108 /// assert_eq!(matcher.matches(HgPath::new(b"whatever")), true);
109 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), true);
109 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), true);
110 /// assert_eq!(matcher.matches(HgPath::new(b"main.c")), true);
110 /// assert_eq!(matcher.matches(HgPath::new(b"main.c")), true);
111 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
111 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
112 /// ```
112 /// ```
113 #[derive(Debug)]
113 #[derive(Debug)]
114 pub struct AlwaysMatcher;
114 pub struct AlwaysMatcher;
115
115
116 impl Matcher for AlwaysMatcher {
116 impl Matcher for AlwaysMatcher {
117 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
117 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
118 None
118 None
119 }
119 }
120 fn exact_match(&self, _filename: &HgPath) -> bool {
120 fn exact_match(&self, _filename: &HgPath) -> bool {
121 false
121 false
122 }
122 }
123 fn matches(&self, _filename: &HgPath) -> bool {
123 fn matches(&self, _filename: &HgPath) -> bool {
124 true
124 true
125 }
125 }
126 fn visit_children_set(&self, _directory: &HgPath) -> VisitChildrenSet {
126 fn visit_children_set(&self, _directory: &HgPath) -> VisitChildrenSet {
127 VisitChildrenSet::Recursive
127 VisitChildrenSet::Recursive
128 }
128 }
129 fn matches_everything(&self) -> bool {
129 fn matches_everything(&self) -> bool {
130 true
130 true
131 }
131 }
132 fn is_exact(&self) -> bool {
132 fn is_exact(&self) -> bool {
133 false
133 false
134 }
134 }
135 }
135 }
136
136
137 /// Matches nothing.
137 /// Matches nothing.
138 #[derive(Debug)]
138 #[derive(Debug)]
139 pub struct NeverMatcher;
139 pub struct NeverMatcher;
140
140
141 impl Matcher for NeverMatcher {
141 impl Matcher for NeverMatcher {
142 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
142 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
143 None
143 None
144 }
144 }
145 fn exact_match(&self, _filename: &HgPath) -> bool {
145 fn exact_match(&self, _filename: &HgPath) -> bool {
146 false
146 false
147 }
147 }
148 fn matches(&self, _filename: &HgPath) -> bool {
148 fn matches(&self, _filename: &HgPath) -> bool {
149 false
149 false
150 }
150 }
151 fn visit_children_set(&self, _directory: &HgPath) -> VisitChildrenSet {
151 fn visit_children_set(&self, _directory: &HgPath) -> VisitChildrenSet {
152 VisitChildrenSet::Empty
152 VisitChildrenSet::Empty
153 }
153 }
154 fn matches_everything(&self) -> bool {
154 fn matches_everything(&self) -> bool {
155 false
155 false
156 }
156 }
157 fn is_exact(&self) -> bool {
157 fn is_exact(&self) -> bool {
158 true
158 true
159 }
159 }
160 }
160 }
161
161
162 /// Matches the input files exactly. They are interpreted as paths, not
162 /// Matches the input files exactly. They are interpreted as paths, not
163 /// patterns.
163 /// patterns.
164 ///
164 ///
165 ///```
165 ///```
166 /// use hg::{ matchers::{Matcher, FileMatcher}, utils::hg_path::{HgPath, HgPathBuf} };
166 /// use hg::{ matchers::{Matcher, FileMatcher}, utils::hg_path::{HgPath, HgPathBuf} };
167 ///
167 ///
168 /// let files = vec![HgPathBuf::from_bytes(b"a.txt"), HgPathBuf::from_bytes(br"re:.*\.c$")];
168 /// let files = vec![HgPathBuf::from_bytes(b"a.txt"), HgPathBuf::from_bytes(br"re:.*\.c$")];
169 /// let matcher = FileMatcher::new(files).unwrap();
169 /// let matcher = FileMatcher::new(files).unwrap();
170 ///
170 ///
171 /// assert_eq!(matcher.matches(HgPath::new(b"a.txt")), true);
171 /// assert_eq!(matcher.matches(HgPath::new(b"a.txt")), true);
172 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), false);
172 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), false);
173 /// assert_eq!(matcher.matches(HgPath::new(b"main.c")), false);
173 /// assert_eq!(matcher.matches(HgPath::new(b"main.c")), false);
174 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
174 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
175 /// ```
175 /// ```
176 #[derive(Debug)]
176 #[derive(Debug)]
177 pub struct FileMatcher {
177 pub struct FileMatcher {
178 files: HashSet<HgPathBuf>,
178 files: HashSet<HgPathBuf>,
179 dirs: DirsMultiset,
179 dirs: DirsMultiset,
180 }
180 }
181
181
182 impl FileMatcher {
182 impl FileMatcher {
183 pub fn new(files: Vec<HgPathBuf>) -> Result<Self, DirstateMapError> {
183 pub fn new(files: Vec<HgPathBuf>) -> Result<Self, DirstateMapError> {
184 let dirs = DirsMultiset::from_manifest(&files)?;
184 let dirs = DirsMultiset::from_manifest(&files)?;
185 Ok(Self {
185 Ok(Self {
186 files: HashSet::from_iter(files.into_iter()),
186 files: HashSet::from_iter(files.into_iter()),
187 dirs,
187 dirs,
188 })
188 })
189 }
189 }
190 fn inner_matches(&self, filename: &HgPath) -> bool {
190 fn inner_matches(&self, filename: &HgPath) -> bool {
191 self.files.contains(filename.as_ref())
191 self.files.contains(filename.as_ref())
192 }
192 }
193 }
193 }
194
194
195 impl Matcher for FileMatcher {
195 impl Matcher for FileMatcher {
196 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
196 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
197 Some(&self.files)
197 Some(&self.files)
198 }
198 }
199 fn exact_match(&self, filename: &HgPath) -> bool {
199 fn exact_match(&self, filename: &HgPath) -> bool {
200 self.inner_matches(filename)
200 self.inner_matches(filename)
201 }
201 }
202 fn matches(&self, filename: &HgPath) -> bool {
202 fn matches(&self, filename: &HgPath) -> bool {
203 self.inner_matches(filename)
203 self.inner_matches(filename)
204 }
204 }
205 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
205 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
206 if self.files.is_empty() || !self.dirs.contains(&directory) {
206 if self.files.is_empty() || !self.dirs.contains(&directory) {
207 return VisitChildrenSet::Empty;
207 return VisitChildrenSet::Empty;
208 }
208 }
209 let mut candidates: HashSet<HgPathBuf> =
209 let mut candidates: HashSet<HgPathBuf> =
210 self.dirs.iter().cloned().collect();
210 self.dirs.iter().cloned().collect();
211
211
212 candidates.extend(self.files.iter().cloned());
212 candidates.extend(self.files.iter().cloned());
213 candidates.remove(HgPath::new(b""));
213 candidates.remove(HgPath::new(b""));
214
214
215 if !directory.as_ref().is_empty() {
215 if !directory.as_ref().is_empty() {
216 let directory = [directory.as_ref().as_bytes(), b"/"].concat();
216 let directory = [directory.as_ref().as_bytes(), b"/"].concat();
217 candidates = candidates
217 candidates = candidates
218 .iter()
218 .iter()
219 .filter_map(|c| {
219 .filter_map(|c| {
220 if c.as_bytes().starts_with(&directory) {
220 if c.as_bytes().starts_with(&directory) {
221 Some(HgPathBuf::from_bytes(
221 Some(HgPathBuf::from_bytes(
222 &c.as_bytes()[directory.len()..],
222 &c.as_bytes()[directory.len()..],
223 ))
223 ))
224 } else {
224 } else {
225 None
225 None
226 }
226 }
227 })
227 })
228 .collect();
228 .collect();
229 }
229 }
230
230
231 // `self.dirs` includes all of the directories, recursively, so if
231 // `self.dirs` includes all of the directories, recursively, so if
232 // we're attempting to match 'foo/bar/baz.txt', it'll have '', 'foo',
232 // we're attempting to match 'foo/bar/baz.txt', it'll have '', 'foo',
233 // 'foo/bar' in it. Thus we can safely ignore a candidate that has a
233 // 'foo/bar' in it. Thus we can safely ignore a candidate that has a
234 // '/' in it, indicating it's for a subdir-of-a-subdir; the immediate
234 // '/' in it, indicating it's for a subdir-of-a-subdir; the immediate
235 // subdir will be in there without a slash.
235 // subdir will be in there without a slash.
236 VisitChildrenSet::Set(
236 VisitChildrenSet::Set(
237 candidates
237 candidates
238 .into_iter()
238 .into_iter()
239 .filter_map(|c| {
239 .filter_map(|c| {
240 if c.bytes().all(|b| *b != b'/') {
240 if c.bytes().all(|b| *b != b'/') {
241 Some(c)
241 Some(c)
242 } else {
242 } else {
243 None
243 None
244 }
244 }
245 })
245 })
246 .collect(),
246 .collect(),
247 )
247 )
248 }
248 }
249 fn matches_everything(&self) -> bool {
249 fn matches_everything(&self) -> bool {
250 false
250 false
251 }
251 }
252 fn is_exact(&self) -> bool {
252 fn is_exact(&self) -> bool {
253 true
253 true
254 }
254 }
255 }
255 }
256
256
257 /// Matches files that are included in the ignore rules.
257 /// Matches files that are included in the ignore rules.
258 /// ```
258 /// ```
259 /// use hg::{
259 /// use hg::{
260 /// matchers::{IncludeMatcher, Matcher},
260 /// matchers::{IncludeMatcher, Matcher},
261 /// IgnorePattern,
261 /// IgnorePattern,
262 /// PatternSyntax,
262 /// PatternSyntax,
263 /// utils::hg_path::HgPath
263 /// utils::hg_path::HgPath
264 /// };
264 /// };
265 /// use std::path::Path;
265 /// use std::path::Path;
266 /// ///
266 /// ///
267 /// let ignore_patterns =
267 /// let ignore_patterns =
268 /// vec![IgnorePattern::new(PatternSyntax::RootGlob, b"this*", Path::new(""))];
268 /// vec![IgnorePattern::new(PatternSyntax::RootGlob, b"this*", Path::new(""))];
269 /// let matcher = IncludeMatcher::new(ignore_patterns).unwrap();
269 /// let matcher = IncludeMatcher::new(ignore_patterns).unwrap();
270 /// ///
270 /// ///
271 /// assert_eq!(matcher.matches(HgPath::new(b"testing")), false);
271 /// assert_eq!(matcher.matches(HgPath::new(b"testing")), false);
272 /// assert_eq!(matcher.matches(HgPath::new(b"this should work")), true);
272 /// assert_eq!(matcher.matches(HgPath::new(b"this should work")), true);
273 /// assert_eq!(matcher.matches(HgPath::new(b"this also")), true);
273 /// assert_eq!(matcher.matches(HgPath::new(b"this also")), true);
274 /// assert_eq!(matcher.matches(HgPath::new(b"but not this")), false);
274 /// assert_eq!(matcher.matches(HgPath::new(b"but not this")), false);
275 /// ```
275 /// ```
276 pub struct IncludeMatcher<'a> {
276 pub struct IncludeMatcher<'a> {
277 patterns: Vec<u8>,
277 patterns: Vec<u8>,
278 match_fn: IgnoreFnType<'a>,
278 match_fn: IgnoreFnType<'a>,
279 /// Whether all the patterns match a prefix (i.e. recursively)
279 /// Whether all the patterns match a prefix (i.e. recursively)
280 prefix: bool,
280 prefix: bool,
281 roots: HashSet<HgPathBuf>,
281 roots: HashSet<HgPathBuf>,
282 dirs: HashSet<HgPathBuf>,
282 dirs: HashSet<HgPathBuf>,
283 parents: HashSet<HgPathBuf>,
283 parents: HashSet<HgPathBuf>,
284 }
284 }
285
285
286 impl core::fmt::Debug for IncludeMatcher<'_> {
286 impl core::fmt::Debug for IncludeMatcher<'_> {
287 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
287 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
288 f.debug_struct("IncludeMatcher")
288 f.debug_struct("IncludeMatcher")
289 .field("patterns", &String::from_utf8_lossy(&self.patterns))
289 .field("patterns", &String::from_utf8_lossy(&self.patterns))
290 .field("prefix", &self.prefix)
290 .field("prefix", &self.prefix)
291 .field("roots", &self.roots)
291 .field("roots", &self.roots)
292 .field("dirs", &self.dirs)
292 .field("dirs", &self.dirs)
293 .field("parents", &self.parents)
293 .field("parents", &self.parents)
294 .finish()
294 .finish()
295 }
295 }
296 }
296 }
297
297
298 impl<'a> Matcher for IncludeMatcher<'a> {
298 impl<'a> Matcher for IncludeMatcher<'a> {
299 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
299 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
300 None
300 None
301 }
301 }
302
302
303 fn exact_match(&self, _filename: &HgPath) -> bool {
303 fn exact_match(&self, _filename: &HgPath) -> bool {
304 false
304 false
305 }
305 }
306
306
307 fn matches(&self, filename: &HgPath) -> bool {
307 fn matches(&self, filename: &HgPath) -> bool {
308 (self.match_fn)(filename.as_ref())
308 (self.match_fn)(filename.as_ref())
309 }
309 }
310
310
311 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
311 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
312 let dir = directory.as_ref();
312 let dir = directory.as_ref();
313 if self.prefix && self.roots.contains(dir) {
313 if self.prefix && self.roots.contains(dir) {
314 return VisitChildrenSet::Recursive;
314 return VisitChildrenSet::Recursive;
315 }
315 }
316 if self.roots.contains(HgPath::new(b""))
316 if self.roots.contains(HgPath::new(b""))
317 || self.roots.contains(dir)
317 || self.roots.contains(dir)
318 || self.dirs.contains(dir)
318 || self.dirs.contains(dir)
319 || find_dirs(dir).any(|parent_dir| self.roots.contains(parent_dir))
319 || find_dirs(dir).any(|parent_dir| self.roots.contains(parent_dir))
320 {
320 {
321 return VisitChildrenSet::This;
321 return VisitChildrenSet::This;
322 }
322 }
323
323
324 if self.parents.contains(directory.as_ref()) {
324 if self.parents.contains(directory.as_ref()) {
325 let multiset = self.get_all_parents_children();
325 let multiset = self.get_all_parents_children();
326 if let Some(children) = multiset.get(dir) {
326 if let Some(children) = multiset.get(dir) {
327 return VisitChildrenSet::Set(
327 return VisitChildrenSet::Set(
328 children.into_iter().map(HgPathBuf::from).collect(),
328 children.into_iter().map(HgPathBuf::from).collect(),
329 );
329 );
330 }
330 }
331 }
331 }
332 VisitChildrenSet::Empty
332 VisitChildrenSet::Empty
333 }
333 }
334
334
335 fn matches_everything(&self) -> bool {
335 fn matches_everything(&self) -> bool {
336 false
336 false
337 }
337 }
338
338
339 fn is_exact(&self) -> bool {
339 fn is_exact(&self) -> bool {
340 false
340 false
341 }
341 }
342 }
342 }
343
343
344 /// The union of multiple matchers. Will match if any of the matchers match.
344 /// The union of multiple matchers. Will match if any of the matchers match.
345 #[derive(Debug)]
345 #[derive(Debug)]
346 pub struct UnionMatcher {
346 pub struct UnionMatcher {
347 matchers: Vec<Box<dyn Matcher + Sync>>,
347 matchers: Vec<Box<dyn Matcher + Sync>>,
348 }
348 }
349
349
350 impl Matcher for UnionMatcher {
350 impl Matcher for UnionMatcher {
351 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
351 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
352 None
352 None
353 }
353 }
354
354
355 fn exact_match(&self, _filename: &HgPath) -> bool {
355 fn exact_match(&self, _filename: &HgPath) -> bool {
356 false
356 false
357 }
357 }
358
358
359 fn matches(&self, filename: &HgPath) -> bool {
359 fn matches(&self, filename: &HgPath) -> bool {
360 self.matchers.iter().any(|m| m.matches(filename))
360 self.matchers.iter().any(|m| m.matches(filename))
361 }
361 }
362
362
363 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
363 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
364 let mut result = HashSet::new();
364 let mut result = HashSet::new();
365 let mut this = false;
365 let mut this = false;
366 for matcher in self.matchers.iter() {
366 for matcher in self.matchers.iter() {
367 let visit = matcher.visit_children_set(directory);
367 let visit = matcher.visit_children_set(directory);
368 match visit {
368 match visit {
369 VisitChildrenSet::Empty => continue,
369 VisitChildrenSet::Empty => continue,
370 VisitChildrenSet::This => {
370 VisitChildrenSet::This => {
371 this = true;
371 this = true;
372 // Don't break, we might have an 'all' in here.
372 // Don't break, we might have an 'all' in here.
373 continue;
373 continue;
374 }
374 }
375 VisitChildrenSet::Set(set) => {
375 VisitChildrenSet::Set(set) => {
376 result.extend(set);
376 result.extend(set);
377 }
377 }
378 VisitChildrenSet::Recursive => {
378 VisitChildrenSet::Recursive => {
379 return visit;
379 return visit;
380 }
380 }
381 }
381 }
382 }
382 }
383 if this {
383 if this {
384 return VisitChildrenSet::This;
384 return VisitChildrenSet::This;
385 }
385 }
386 if result.is_empty() {
386 if result.is_empty() {
387 VisitChildrenSet::Empty
387 VisitChildrenSet::Empty
388 } else {
388 } else {
389 VisitChildrenSet::Set(result)
389 VisitChildrenSet::Set(result)
390 }
390 }
391 }
391 }
392
392
393 fn matches_everything(&self) -> bool {
393 fn matches_everything(&self) -> bool {
394 // TODO Maybe if all are AlwaysMatcher?
394 // TODO Maybe if all are AlwaysMatcher?
395 false
395 false
396 }
396 }
397
397
398 fn is_exact(&self) -> bool {
398 fn is_exact(&self) -> bool {
399 false
399 false
400 }
400 }
401 }
401 }
402
402
403 impl UnionMatcher {
403 impl UnionMatcher {
404 pub fn new(matchers: Vec<Box<dyn Matcher + Sync>>) -> Self {
404 pub fn new(matchers: Vec<Box<dyn Matcher + Sync>>) -> Self {
405 Self { matchers }
405 Self { matchers }
406 }
406 }
407 }
407 }
408
408
409 #[derive(Debug)]
409 #[derive(Debug)]
410 pub struct IntersectionMatcher {
410 pub struct IntersectionMatcher {
411 m1: Box<dyn Matcher + Sync>,
411 m1: Box<dyn Matcher + Sync>,
412 m2: Box<dyn Matcher + Sync>,
412 m2: Box<dyn Matcher + Sync>,
413 files: Option<HashSet<HgPathBuf>>,
413 files: Option<HashSet<HgPathBuf>>,
414 }
414 }
415
415
416 impl Matcher for IntersectionMatcher {
416 impl Matcher for IntersectionMatcher {
417 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
417 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
418 self.files.as_ref()
418 self.files.as_ref()
419 }
419 }
420
420
421 fn exact_match(&self, filename: &HgPath) -> bool {
421 fn exact_match(&self, filename: &HgPath) -> bool {
422 self.files.as_ref().map_or(false, |f| f.contains(filename))
422 self.files.as_ref().map_or(false, |f| f.contains(filename))
423 }
423 }
424
424
425 fn matches(&self, filename: &HgPath) -> bool {
425 fn matches(&self, filename: &HgPath) -> bool {
426 self.m1.matches(filename) && self.m2.matches(filename)
426 self.m1.matches(filename) && self.m2.matches(filename)
427 }
427 }
428
428
429 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
429 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
430 let m1_set = self.m1.visit_children_set(directory);
430 let m1_set = self.m1.visit_children_set(directory);
431 if m1_set == VisitChildrenSet::Empty {
431 if m1_set == VisitChildrenSet::Empty {
432 return VisitChildrenSet::Empty;
432 return VisitChildrenSet::Empty;
433 }
433 }
434 let m2_set = self.m2.visit_children_set(directory);
434 let m2_set = self.m2.visit_children_set(directory);
435 if m2_set == VisitChildrenSet::Empty {
435 if m2_set == VisitChildrenSet::Empty {
436 return VisitChildrenSet::Empty;
436 return VisitChildrenSet::Empty;
437 }
437 }
438
438
439 if m1_set == VisitChildrenSet::Recursive {
439 if m1_set == VisitChildrenSet::Recursive {
440 return m2_set;
440 return m2_set;
441 } else if m2_set == VisitChildrenSet::Recursive {
441 } else if m2_set == VisitChildrenSet::Recursive {
442 return m1_set;
442 return m1_set;
443 }
443 }
444
444
445 match (&m1_set, &m2_set) {
445 match (&m1_set, &m2_set) {
446 (VisitChildrenSet::Recursive, _) => m2_set,
446 (VisitChildrenSet::Recursive, _) => m2_set,
447 (_, VisitChildrenSet::Recursive) => m1_set,
447 (_, VisitChildrenSet::Recursive) => m1_set,
448 (VisitChildrenSet::This, _) | (_, VisitChildrenSet::This) => {
448 (VisitChildrenSet::This, _) | (_, VisitChildrenSet::This) => {
449 VisitChildrenSet::This
449 VisitChildrenSet::This
450 }
450 }
451 (VisitChildrenSet::Set(m1), VisitChildrenSet::Set(m2)) => {
451 (VisitChildrenSet::Set(m1), VisitChildrenSet::Set(m2)) => {
452 let set: HashSet<_> = m1.intersection(&m2).cloned().collect();
452 let set: HashSet<_> = m1.intersection(&m2).cloned().collect();
453 if set.is_empty() {
453 if set.is_empty() {
454 VisitChildrenSet::Empty
454 VisitChildrenSet::Empty
455 } else {
455 } else {
456 VisitChildrenSet::Set(set)
456 VisitChildrenSet::Set(set)
457 }
457 }
458 }
458 }
459 _ => unreachable!(),
459 _ => unreachable!(),
460 }
460 }
461 }
461 }
462
462
463 fn matches_everything(&self) -> bool {
463 fn matches_everything(&self) -> bool {
464 self.m1.matches_everything() && self.m2.matches_everything()
464 self.m1.matches_everything() && self.m2.matches_everything()
465 }
465 }
466
466
467 fn is_exact(&self) -> bool {
467 fn is_exact(&self) -> bool {
468 self.m1.is_exact() || self.m2.is_exact()
468 self.m1.is_exact() || self.m2.is_exact()
469 }
469 }
470 }
470 }
471
471
472 impl IntersectionMatcher {
472 impl IntersectionMatcher {
473 pub fn new(
473 pub fn new(
474 mut m1: Box<dyn Matcher + Sync>,
474 mut m1: Box<dyn Matcher + Sync>,
475 mut m2: Box<dyn Matcher + Sync>,
475 mut m2: Box<dyn Matcher + Sync>,
476 ) -> Self {
476 ) -> Self {
477 let files = if m1.is_exact() || m2.is_exact() {
477 let files = if m1.is_exact() || m2.is_exact() {
478 if !m1.is_exact() {
478 if !m1.is_exact() {
479 std::mem::swap(&mut m1, &mut m2);
479 std::mem::swap(&mut m1, &mut m2);
480 }
480 }
481 m1.file_set().map(|m1_files| {
481 m1.file_set().map(|m1_files| {
482 m1_files.iter().cloned().filter(|f| m2.matches(f)).collect()
482 m1_files.iter().cloned().filter(|f| m2.matches(f)).collect()
483 })
483 })
484 } else {
484 } else {
485 None
485 None
486 };
486 };
487 Self { m1, m2, files }
487 Self { m1, m2, files }
488 }
488 }
489 }
489 }
490
490
491 #[derive(Debug)]
491 #[derive(Debug)]
492 pub struct DifferenceMatcher {
492 pub struct DifferenceMatcher {
493 base: Box<dyn Matcher + Sync>,
493 base: Box<dyn Matcher + Sync>,
494 excluded: Box<dyn Matcher + Sync>,
494 excluded: Box<dyn Matcher + Sync>,
495 files: Option<HashSet<HgPathBuf>>,
495 files: Option<HashSet<HgPathBuf>>,
496 }
496 }
497
497
498 impl Matcher for DifferenceMatcher {
498 impl Matcher for DifferenceMatcher {
499 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
499 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
500 self.files.as_ref()
500 self.files.as_ref()
501 }
501 }
502
502
503 fn exact_match(&self, filename: &HgPath) -> bool {
503 fn exact_match(&self, filename: &HgPath) -> bool {
504 self.files.as_ref().map_or(false, |f| f.contains(filename))
504 self.files.as_ref().map_or(false, |f| f.contains(filename))
505 }
505 }
506
506
507 fn matches(&self, filename: &HgPath) -> bool {
507 fn matches(&self, filename: &HgPath) -> bool {
508 self.base.matches(filename) && !self.excluded.matches(filename)
508 self.base.matches(filename) && !self.excluded.matches(filename)
509 }
509 }
510
510
511 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
511 fn visit_children_set(&self, directory: &HgPath) -> VisitChildrenSet {
512 let excluded_set = self.excluded.visit_children_set(directory);
512 let excluded_set = self.excluded.visit_children_set(directory);
513 if excluded_set == VisitChildrenSet::Recursive {
513 if excluded_set == VisitChildrenSet::Recursive {
514 return VisitChildrenSet::Empty;
514 return VisitChildrenSet::Empty;
515 }
515 }
516 let base_set = self.base.visit_children_set(directory);
516 let base_set = self.base.visit_children_set(directory);
517 // Possible values for base: 'recursive', 'this', set(...), set()
517 // Possible values for base: 'recursive', 'this', set(...), set()
518 // Possible values for excluded: 'this', set(...), set()
518 // Possible values for excluded: 'this', set(...), set()
519 // If excluded has nothing under here that we care about, return base,
519 // If excluded has nothing under here that we care about, return base,
520 // even if it's 'recursive'.
520 // even if it's 'recursive'.
521 if excluded_set == VisitChildrenSet::Empty {
521 if excluded_set == VisitChildrenSet::Empty {
522 return base_set;
522 return base_set;
523 }
523 }
524 match base_set {
524 match base_set {
525 VisitChildrenSet::This | VisitChildrenSet::Recursive => {
525 VisitChildrenSet::This | VisitChildrenSet::Recursive => {
526 // Never return 'recursive' here if excluded_set is any kind of
526 // Never return 'recursive' here if excluded_set is any kind of
527 // non-empty (either 'this' or set(foo)), since excluded might
527 // non-empty (either 'this' or set(foo)), since excluded might
528 // return set() for a subdirectory.
528 // return set() for a subdirectory.
529 VisitChildrenSet::This
529 VisitChildrenSet::This
530 }
530 }
531 set => {
531 set => {
532 // Possible values for base: set(...), set()
532 // Possible values for base: set(...), set()
533 // Possible values for excluded: 'this', set(...)
533 // Possible values for excluded: 'this', set(...)
534 // We ignore excluded set results. They're possibly incorrect:
534 // We ignore excluded set results. They're possibly incorrect:
535 // base = path:dir/subdir
535 // base = path:dir/subdir
536 // excluded=rootfilesin:dir,
536 // excluded=rootfilesin:dir,
537 // visit_children_set(''):
537 // visit_children_set(''):
538 // base returns {'dir'}, excluded returns {'dir'}, if we
538 // base returns {'dir'}, excluded returns {'dir'}, if we
539 // subtracted we'd return set(), which is *not* correct, we
539 // subtracted we'd return set(), which is *not* correct, we
540 // still need to visit 'dir'!
540 // still need to visit 'dir'!
541 set
541 set
542 }
542 }
543 }
543 }
544 }
544 }
545
545
546 fn matches_everything(&self) -> bool {
546 fn matches_everything(&self) -> bool {
547 false
547 false
548 }
548 }
549
549
550 fn is_exact(&self) -> bool {
550 fn is_exact(&self) -> bool {
551 self.base.is_exact()
551 self.base.is_exact()
552 }
552 }
553 }
553 }
554
554
555 impl DifferenceMatcher {
555 impl DifferenceMatcher {
556 pub fn new(
556 pub fn new(
557 base: Box<dyn Matcher + Sync>,
557 base: Box<dyn Matcher + Sync>,
558 excluded: Box<dyn Matcher + Sync>,
558 excluded: Box<dyn Matcher + Sync>,
559 ) -> Self {
559 ) -> Self {
560 let base_is_exact = base.is_exact();
560 let base_is_exact = base.is_exact();
561 let base_files = base.file_set().map(ToOwned::to_owned);
561 let base_files = base.file_set().map(ToOwned::to_owned);
562 let mut new = Self {
562 let mut new = Self {
563 base,
563 base,
564 excluded,
564 excluded,
565 files: None,
565 files: None,
566 };
566 };
567 if base_is_exact {
567 if base_is_exact {
568 new.files = base_files.map(|files| {
568 new.files = base_files.map(|files| {
569 files.iter().cloned().filter(|f| new.matches(f)).collect()
569 files.iter().cloned().filter(|f| new.matches(f)).collect()
570 });
570 });
571 }
571 }
572 new
572 new
573 }
573 }
574 }
574 }
575
575
576 /// Wraps [`regex::bytes::Regex`] to improve performance in multithreaded
577 /// contexts.
578 ///
579 /// The `status` algorithm makes heavy use of threads, and calling `is_match`
580 /// from many threads at once is prone to contention, probably within the
581 /// scratch space needed as the regex DFA is built lazily.
582 ///
583 /// We are in the process of raising the issue upstream, but for now
584 /// the workaround used here is to store the `Regex` in a lazily populated
585 /// thread-local variable, sharing the initial read-only compilation, but
586 /// not the lazy dfa scratch space mentioned above.
587 ///
588 /// This reduces the contention observed with 16+ threads, but does not
589 /// completely remove it. Hopefully this can be addressed upstream.
590 struct RegexMatcher {
591 /// Compiled at the start of the status algorithm, used as a base for
592 /// cloning in each thread-local `self.local`, thus sharing the expensive
593 /// first compilation.
594 base: regex::bytes::Regex,
595 /// Thread-local variable that holds the `Regex` that is actually queried
596 /// from each thread.
597 local: thread_local::ThreadLocal<regex::bytes::Regex>,
598 }
599
600 impl RegexMatcher {
601 /// Returns whether the path matches the stored `Regex`.
602 pub fn is_match(&self, path: &HgPath) -> bool {
603 self.local
604 .get_or(|| self.base.clone())
605 .is_match(path.as_bytes())
606 }
607 }
608
576 /// Returns a function that matches an `HgPath` against the given regex
609 /// Returns a function that matches an `HgPath` against the given regex
577 /// pattern.
610 /// pattern.
578 ///
611 ///
579 /// This can fail when the pattern is invalid or not supported by the
612 /// This can fail when the pattern is invalid or not supported by the
580 /// underlying engine (the `regex` crate), for instance anything with
613 /// underlying engine (the `regex` crate), for instance anything with
581 /// back-references.
614 /// back-references.
582 #[timed]
615 #[timed]
583 fn re_matcher(
616 fn re_matcher(pattern: &[u8]) -> PatternResult<RegexMatcher> {
584 pattern: &[u8],
585 ) -> PatternResult<impl Fn(&HgPath) -> bool + Sync> {
586 use std::io::Write;
617 use std::io::Write;
587
618
588 // The `regex` crate adds `.*` to the start and end of expressions if there
619 // The `regex` crate adds `.*` to the start and end of expressions if there
589 // are no anchors, so add the start anchor.
620 // are no anchors, so add the start anchor.
590 let mut escaped_bytes = vec![b'^', b'(', b'?', b':'];
621 let mut escaped_bytes = vec![b'^', b'(', b'?', b':'];
591 for byte in pattern {
622 for byte in pattern {
592 if *byte > 127 {
623 if *byte > 127 {
593 write!(escaped_bytes, "\\x{:x}", *byte).unwrap();
624 write!(escaped_bytes, "\\x{:x}", *byte).unwrap();
594 } else {
625 } else {
595 escaped_bytes.push(*byte);
626 escaped_bytes.push(*byte);
596 }
627 }
597 }
628 }
598 escaped_bytes.push(b')');
629 escaped_bytes.push(b')');
599
630
600 // Avoid the cost of UTF8 checking
631 // Avoid the cost of UTF8 checking
601 //
632 //
602 // # Safety
633 // # Safety
603 // This is safe because we escaped all non-ASCII bytes.
634 // This is safe because we escaped all non-ASCII bytes.
604 let pattern_string = unsafe { String::from_utf8_unchecked(escaped_bytes) };
635 let pattern_string = unsafe { String::from_utf8_unchecked(escaped_bytes) };
605 let re = regex::bytes::RegexBuilder::new(&pattern_string)
636 let re = regex::bytes::RegexBuilder::new(&pattern_string)
606 .unicode(false)
637 .unicode(false)
607 // Big repos with big `.hgignore` will hit the default limit and
638 // Big repos with big `.hgignore` will hit the default limit and
608 // incur a significant performance hit. One repo's `hg status` hit
639 // incur a significant performance hit. One repo's `hg status` hit
609 // multiple *minutes*.
640 // multiple *minutes*.
610 .dfa_size_limit(50 * (1 << 20))
641 .dfa_size_limit(50 * (1 << 20))
611 .build()
642 .build()
612 .map_err(|e| PatternError::UnsupportedSyntax(e.to_string()))?;
643 .map_err(|e| PatternError::UnsupportedSyntax(e.to_string()))?;
613
644
614 Ok(move |path: &HgPath| re.is_match(path.as_bytes()))
645 Ok(RegexMatcher {
646 base: re,
647 local: Default::default(),
648 })
615 }
649 }
616
650
617 /// Returns the regex pattern and a function that matches an `HgPath` against
651 /// Returns the regex pattern and a function that matches an `HgPath` against
618 /// said regex formed by the given ignore patterns.
652 /// said regex formed by the given ignore patterns.
619 fn build_regex_match<'a, 'b>(
653 fn build_regex_match<'a, 'b>(
620 ignore_patterns: &'a [IgnorePattern],
654 ignore_patterns: &'a [IgnorePattern],
621 ) -> PatternResult<(Vec<u8>, IgnoreFnType<'b>)> {
655 ) -> PatternResult<(Vec<u8>, IgnoreFnType<'b>)> {
622 let mut regexps = vec![];
656 let mut regexps = vec![];
623 let mut exact_set = HashSet::new();
657 let mut exact_set = HashSet::new();
624
658
625 for pattern in ignore_patterns {
659 for pattern in ignore_patterns {
626 if let Some(re) = build_single_regex(pattern)? {
660 if let Some(re) = build_single_regex(pattern)? {
627 regexps.push(re);
661 regexps.push(re);
628 } else {
662 } else {
629 let exact = normalize_path_bytes(&pattern.pattern);
663 let exact = normalize_path_bytes(&pattern.pattern);
630 exact_set.insert(HgPathBuf::from_bytes(&exact));
664 exact_set.insert(HgPathBuf::from_bytes(&exact));
631 }
665 }
632 }
666 }
633
667
634 let full_regex = regexps.join(&b'|');
668 let full_regex = regexps.join(&b'|');
635
669
636 // An empty pattern would cause the regex engine to incorrectly match the
670 // An empty pattern would cause the regex engine to incorrectly match the
637 // (empty) root directory
671 // (empty) root directory
638 let func = if !(regexps.is_empty()) {
672 let func = if !(regexps.is_empty()) {
639 let matcher = re_matcher(&full_regex)?;
673 let matcher = re_matcher(&full_regex)?;
640 let func = move |filename: &HgPath| {
674 let func = move |filename: &HgPath| {
641 exact_set.contains(filename) || matcher(filename)
675 exact_set.contains(filename) || matcher.is_match(filename)
642 };
676 };
643 Box::new(func) as IgnoreFnType
677 Box::new(func) as IgnoreFnType
644 } else {
678 } else {
645 let func = move |filename: &HgPath| exact_set.contains(filename);
679 let func = move |filename: &HgPath| exact_set.contains(filename);
646 Box::new(func) as IgnoreFnType
680 Box::new(func) as IgnoreFnType
647 };
681 };
648
682
649 Ok((full_regex, func))
683 Ok((full_regex, func))
650 }
684 }
651
685
652 /// Returns roots and directories corresponding to each pattern.
686 /// Returns roots and directories corresponding to each pattern.
653 ///
687 ///
654 /// This calculates the roots and directories exactly matching the patterns and
688 /// This calculates the roots and directories exactly matching the patterns and
655 /// returns a tuple of (roots, dirs). It does not return other directories
689 /// returns a tuple of (roots, dirs). It does not return other directories
656 /// which may also need to be considered, like the parent directories.
690 /// which may also need to be considered, like the parent directories.
657 fn roots_and_dirs(
691 fn roots_and_dirs(
658 ignore_patterns: &[IgnorePattern],
692 ignore_patterns: &[IgnorePattern],
659 ) -> (Vec<HgPathBuf>, Vec<HgPathBuf>) {
693 ) -> (Vec<HgPathBuf>, Vec<HgPathBuf>) {
660 let mut roots = Vec::new();
694 let mut roots = Vec::new();
661 let mut dirs = Vec::new();
695 let mut dirs = Vec::new();
662
696
663 for ignore_pattern in ignore_patterns {
697 for ignore_pattern in ignore_patterns {
664 let IgnorePattern {
698 let IgnorePattern {
665 syntax, pattern, ..
699 syntax, pattern, ..
666 } = ignore_pattern;
700 } = ignore_pattern;
667 match syntax {
701 match syntax {
668 PatternSyntax::RootGlob | PatternSyntax::Glob => {
702 PatternSyntax::RootGlob | PatternSyntax::Glob => {
669 let mut root = HgPathBuf::new();
703 let mut root = HgPathBuf::new();
670 for p in pattern.split(|c| *c == b'/') {
704 for p in pattern.split(|c| *c == b'/') {
671 if p.iter().any(|c| match *c {
705 if p.iter().any(|c| match *c {
672 b'[' | b'{' | b'*' | b'?' => true,
706 b'[' | b'{' | b'*' | b'?' => true,
673 _ => false,
707 _ => false,
674 }) {
708 }) {
675 break;
709 break;
676 }
710 }
677 root.push(HgPathBuf::from_bytes(p).as_ref());
711 root.push(HgPathBuf::from_bytes(p).as_ref());
678 }
712 }
679 roots.push(root);
713 roots.push(root);
680 }
714 }
681 PatternSyntax::Path | PatternSyntax::RelPath => {
715 PatternSyntax::Path | PatternSyntax::RelPath => {
682 let pat = HgPath::new(if pattern == b"." {
716 let pat = HgPath::new(if pattern == b"." {
683 &[] as &[u8]
717 &[] as &[u8]
684 } else {
718 } else {
685 pattern
719 pattern
686 });
720 });
687 roots.push(pat.to_owned());
721 roots.push(pat.to_owned());
688 }
722 }
689 PatternSyntax::RootFiles => {
723 PatternSyntax::RootFiles => {
690 let pat = if pattern == b"." {
724 let pat = if pattern == b"." {
691 &[] as &[u8]
725 &[] as &[u8]
692 } else {
726 } else {
693 pattern
727 pattern
694 };
728 };
695 dirs.push(HgPathBuf::from_bytes(pat));
729 dirs.push(HgPathBuf::from_bytes(pat));
696 }
730 }
697 _ => {
731 _ => {
698 roots.push(HgPathBuf::new());
732 roots.push(HgPathBuf::new());
699 }
733 }
700 }
734 }
701 }
735 }
702 (roots, dirs)
736 (roots, dirs)
703 }
737 }
704
738
705 /// Paths extracted from patterns
739 /// Paths extracted from patterns
706 #[derive(Debug, PartialEq)]
740 #[derive(Debug, PartialEq)]
707 struct RootsDirsAndParents {
741 struct RootsDirsAndParents {
708 /// Directories to match recursively
742 /// Directories to match recursively
709 pub roots: HashSet<HgPathBuf>,
743 pub roots: HashSet<HgPathBuf>,
710 /// Directories to match non-recursively
744 /// Directories to match non-recursively
711 pub dirs: HashSet<HgPathBuf>,
745 pub dirs: HashSet<HgPathBuf>,
712 /// Implicitly required directories to go to items in either roots or dirs
746 /// Implicitly required directories to go to items in either roots or dirs
713 pub parents: HashSet<HgPathBuf>,
747 pub parents: HashSet<HgPathBuf>,
714 }
748 }
715
749
716 /// Extract roots, dirs and parents from patterns.
750 /// Extract roots, dirs and parents from patterns.
717 fn roots_dirs_and_parents(
751 fn roots_dirs_and_parents(
718 ignore_patterns: &[IgnorePattern],
752 ignore_patterns: &[IgnorePattern],
719 ) -> PatternResult<RootsDirsAndParents> {
753 ) -> PatternResult<RootsDirsAndParents> {
720 let (roots, dirs) = roots_and_dirs(ignore_patterns);
754 let (roots, dirs) = roots_and_dirs(ignore_patterns);
721
755
722 let mut parents = HashSet::new();
756 let mut parents = HashSet::new();
723
757
724 parents.extend(
758 parents.extend(
725 DirsMultiset::from_manifest(&dirs)
759 DirsMultiset::from_manifest(&dirs)
726 .map_err(|e| match e {
760 .map_err(|e| match e {
727 DirstateMapError::InvalidPath(e) => e,
761 DirstateMapError::InvalidPath(e) => e,
728 _ => unreachable!(),
762 _ => unreachable!(),
729 })?
763 })?
730 .iter()
764 .iter()
731 .map(ToOwned::to_owned),
765 .map(ToOwned::to_owned),
732 );
766 );
733 parents.extend(
767 parents.extend(
734 DirsMultiset::from_manifest(&roots)
768 DirsMultiset::from_manifest(&roots)
735 .map_err(|e| match e {
769 .map_err(|e| match e {
736 DirstateMapError::InvalidPath(e) => e,
770 DirstateMapError::InvalidPath(e) => e,
737 _ => unreachable!(),
771 _ => unreachable!(),
738 })?
772 })?
739 .iter()
773 .iter()
740 .map(ToOwned::to_owned),
774 .map(ToOwned::to_owned),
741 );
775 );
742
776
743 Ok(RootsDirsAndParents {
777 Ok(RootsDirsAndParents {
744 roots: HashSet::from_iter(roots),
778 roots: HashSet::from_iter(roots),
745 dirs: HashSet::from_iter(dirs),
779 dirs: HashSet::from_iter(dirs),
746 parents,
780 parents,
747 })
781 })
748 }
782 }
749
783
750 /// Returns a function that checks whether a given file (in the general sense)
784 /// Returns a function that checks whether a given file (in the general sense)
751 /// should be matched.
785 /// should be matched.
752 fn build_match<'a, 'b>(
786 fn build_match<'a, 'b>(
753 ignore_patterns: Vec<IgnorePattern>,
787 ignore_patterns: Vec<IgnorePattern>,
754 ) -> PatternResult<(Vec<u8>, IgnoreFnType<'b>)> {
788 ) -> PatternResult<(Vec<u8>, IgnoreFnType<'b>)> {
755 let mut match_funcs: Vec<IgnoreFnType<'b>> = vec![];
789 let mut match_funcs: Vec<IgnoreFnType<'b>> = vec![];
756 // For debugging and printing
790 // For debugging and printing
757 let mut patterns = vec![];
791 let mut patterns = vec![];
758
792
759 let (subincludes, ignore_patterns) = filter_subincludes(ignore_patterns)?;
793 let (subincludes, ignore_patterns) = filter_subincludes(ignore_patterns)?;
760
794
761 if !subincludes.is_empty() {
795 if !subincludes.is_empty() {
762 // Build prefix-based matcher functions for subincludes
796 // Build prefix-based matcher functions for subincludes
763 let mut submatchers = FastHashMap::default();
797 let mut submatchers = FastHashMap::default();
764 let mut prefixes = vec![];
798 let mut prefixes = vec![];
765
799
766 for sub_include in subincludes {
800 for sub_include in subincludes {
767 let matcher = IncludeMatcher::new(sub_include.included_patterns)?;
801 let matcher = IncludeMatcher::new(sub_include.included_patterns)?;
768 let match_fn =
802 let match_fn =
769 Box::new(move |path: &HgPath| matcher.matches(path));
803 Box::new(move |path: &HgPath| matcher.matches(path));
770 prefixes.push(sub_include.prefix.clone());
804 prefixes.push(sub_include.prefix.clone());
771 submatchers.insert(sub_include.prefix.clone(), match_fn);
805 submatchers.insert(sub_include.prefix.clone(), match_fn);
772 }
806 }
773
807
774 let match_subinclude = move |filename: &HgPath| {
808 let match_subinclude = move |filename: &HgPath| {
775 for prefix in prefixes.iter() {
809 for prefix in prefixes.iter() {
776 if let Some(rel) = filename.relative_to(prefix) {
810 if let Some(rel) = filename.relative_to(prefix) {
777 if (submatchers[prefix])(rel) {
811 if (submatchers[prefix])(rel) {
778 return true;
812 return true;
779 }
813 }
780 }
814 }
781 }
815 }
782 false
816 false
783 };
817 };
784
818
785 match_funcs.push(Box::new(match_subinclude));
819 match_funcs.push(Box::new(match_subinclude));
786 }
820 }
787
821
788 if !ignore_patterns.is_empty() {
822 if !ignore_patterns.is_empty() {
789 // Either do dumb matching if all patterns are rootfiles, or match
823 // Either do dumb matching if all patterns are rootfiles, or match
790 // with a regex.
824 // with a regex.
791 if ignore_patterns
825 if ignore_patterns
792 .iter()
826 .iter()
793 .all(|k| k.syntax == PatternSyntax::RootFiles)
827 .all(|k| k.syntax == PatternSyntax::RootFiles)
794 {
828 {
795 let dirs: HashSet<_> = ignore_patterns
829 let dirs: HashSet<_> = ignore_patterns
796 .iter()
830 .iter()
797 .map(|k| k.pattern.to_owned())
831 .map(|k| k.pattern.to_owned())
798 .collect();
832 .collect();
799 let mut dirs_vec: Vec<_> = dirs.iter().cloned().collect();
833 let mut dirs_vec: Vec<_> = dirs.iter().cloned().collect();
800
834
801 let match_func = move |path: &HgPath| -> bool {
835 let match_func = move |path: &HgPath| -> bool {
802 let path = path.as_bytes();
836 let path = path.as_bytes();
803 let i = path.iter().rfind(|a| **a == b'/');
837 let i = path.iter().rfind(|a| **a == b'/');
804 let dir = if let Some(i) = i {
838 let dir = if let Some(i) = i {
805 &path[..*i as usize]
839 &path[..*i as usize]
806 } else {
840 } else {
807 b"."
841 b"."
808 };
842 };
809 dirs.contains(dir.deref())
843 dirs.contains(dir.deref())
810 };
844 };
811 match_funcs.push(Box::new(match_func));
845 match_funcs.push(Box::new(match_func));
812
846
813 patterns.extend(b"rootfilesin: ");
847 patterns.extend(b"rootfilesin: ");
814 dirs_vec.sort();
848 dirs_vec.sort();
815 patterns.extend(dirs_vec.escaped_bytes());
849 patterns.extend(dirs_vec.escaped_bytes());
816 } else {
850 } else {
817 let (new_re, match_func) = build_regex_match(&ignore_patterns)?;
851 let (new_re, match_func) = build_regex_match(&ignore_patterns)?;
818 patterns = new_re;
852 patterns = new_re;
819 match_funcs.push(match_func)
853 match_funcs.push(match_func)
820 }
854 }
821 }
855 }
822
856
823 Ok(if match_funcs.len() == 1 {
857 Ok(if match_funcs.len() == 1 {
824 (patterns, match_funcs.remove(0))
858 (patterns, match_funcs.remove(0))
825 } else {
859 } else {
826 (
860 (
827 patterns,
861 patterns,
828 Box::new(move |f: &HgPath| -> bool {
862 Box::new(move |f: &HgPath| -> bool {
829 match_funcs.iter().any(|match_func| match_func(f))
863 match_funcs.iter().any(|match_func| match_func(f))
830 }),
864 }),
831 )
865 )
832 })
866 })
833 }
867 }
834
868
835 /// Parses all "ignore" files with their recursive includes and returns a
869 /// Parses all "ignore" files with their recursive includes and returns a
836 /// function that checks whether a given file (in the general sense) should be
870 /// function that checks whether a given file (in the general sense) should be
837 /// ignored.
871 /// ignored.
838 pub fn get_ignore_matcher<'a>(
872 pub fn get_ignore_matcher<'a>(
839 mut all_pattern_files: Vec<PathBuf>,
873 mut all_pattern_files: Vec<PathBuf>,
840 root_dir: &Path,
874 root_dir: &Path,
841 inspect_pattern_bytes: &mut impl FnMut(&Path, &[u8]),
875 inspect_pattern_bytes: &mut impl FnMut(&Path, &[u8]),
842 ) -> PatternResult<(IncludeMatcher<'a>, Vec<PatternFileWarning>)> {
876 ) -> PatternResult<(IncludeMatcher<'a>, Vec<PatternFileWarning>)> {
843 let mut all_patterns = vec![];
877 let mut all_patterns = vec![];
844 let mut all_warnings = vec![];
878 let mut all_warnings = vec![];
845
879
846 // Sort to make the ordering of calls to `inspect_pattern_bytes`
880 // Sort to make the ordering of calls to `inspect_pattern_bytes`
847 // deterministic even if the ordering of `all_pattern_files` is not (such
881 // deterministic even if the ordering of `all_pattern_files` is not (such
848 // as when a iteration order of a Python dict or Rust HashMap is involved).
882 // as when a iteration order of a Python dict or Rust HashMap is involved).
849 // Sort by "string" representation instead of the default by component
883 // Sort by "string" representation instead of the default by component
850 // (with a Rust-specific definition of a component)
884 // (with a Rust-specific definition of a component)
851 all_pattern_files
885 all_pattern_files
852 .sort_unstable_by(|a, b| a.as_os_str().cmp(b.as_os_str()));
886 .sort_unstable_by(|a, b| a.as_os_str().cmp(b.as_os_str()));
853
887
854 for pattern_file in &all_pattern_files {
888 for pattern_file in &all_pattern_files {
855 let (patterns, warnings) = get_patterns_from_file(
889 let (patterns, warnings) = get_patterns_from_file(
856 pattern_file,
890 pattern_file,
857 root_dir,
891 root_dir,
858 inspect_pattern_bytes,
892 inspect_pattern_bytes,
859 )?;
893 )?;
860
894
861 all_patterns.extend(patterns.to_owned());
895 all_patterns.extend(patterns.to_owned());
862 all_warnings.extend(warnings);
896 all_warnings.extend(warnings);
863 }
897 }
864 let matcher = IncludeMatcher::new(all_patterns)?;
898 let matcher = IncludeMatcher::new(all_patterns)?;
865 Ok((matcher, all_warnings))
899 Ok((matcher, all_warnings))
866 }
900 }
867
901
868 /// Parses all "ignore" files with their recursive includes and returns a
902 /// Parses all "ignore" files with their recursive includes and returns a
869 /// function that checks whether a given file (in the general sense) should be
903 /// function that checks whether a given file (in the general sense) should be
870 /// ignored.
904 /// ignored.
871 pub fn get_ignore_function<'a>(
905 pub fn get_ignore_function<'a>(
872 all_pattern_files: Vec<PathBuf>,
906 all_pattern_files: Vec<PathBuf>,
873 root_dir: &Path,
907 root_dir: &Path,
874 inspect_pattern_bytes: &mut impl FnMut(&Path, &[u8]),
908 inspect_pattern_bytes: &mut impl FnMut(&Path, &[u8]),
875 ) -> PatternResult<(IgnoreFnType<'a>, Vec<PatternFileWarning>)> {
909 ) -> PatternResult<(IgnoreFnType<'a>, Vec<PatternFileWarning>)> {
876 let res =
910 let res =
877 get_ignore_matcher(all_pattern_files, root_dir, inspect_pattern_bytes);
911 get_ignore_matcher(all_pattern_files, root_dir, inspect_pattern_bytes);
878 res.map(|(matcher, all_warnings)| {
912 res.map(|(matcher, all_warnings)| {
879 let res: IgnoreFnType<'a> =
913 let res: IgnoreFnType<'a> =
880 Box::new(move |path: &HgPath| matcher.matches(path));
914 Box::new(move |path: &HgPath| matcher.matches(path));
881
915
882 (res, all_warnings)
916 (res, all_warnings)
883 })
917 })
884 }
918 }
885
919
886 impl<'a> IncludeMatcher<'a> {
920 impl<'a> IncludeMatcher<'a> {
887 pub fn new(ignore_patterns: Vec<IgnorePattern>) -> PatternResult<Self> {
921 pub fn new(ignore_patterns: Vec<IgnorePattern>) -> PatternResult<Self> {
888 let RootsDirsAndParents {
922 let RootsDirsAndParents {
889 roots,
923 roots,
890 dirs,
924 dirs,
891 parents,
925 parents,
892 } = roots_dirs_and_parents(&ignore_patterns)?;
926 } = roots_dirs_and_parents(&ignore_patterns)?;
893 let prefix = ignore_patterns.iter().all(|k| match k.syntax {
927 let prefix = ignore_patterns.iter().all(|k| match k.syntax {
894 PatternSyntax::Path | PatternSyntax::RelPath => true,
928 PatternSyntax::Path | PatternSyntax::RelPath => true,
895 _ => false,
929 _ => false,
896 });
930 });
897 let (patterns, match_fn) = build_match(ignore_patterns)?;
931 let (patterns, match_fn) = build_match(ignore_patterns)?;
898
932
899 Ok(Self {
933 Ok(Self {
900 patterns,
934 patterns,
901 match_fn,
935 match_fn,
902 prefix,
936 prefix,
903 roots,
937 roots,
904 dirs,
938 dirs,
905 parents,
939 parents,
906 })
940 })
907 }
941 }
908
942
909 fn get_all_parents_children(&self) -> DirsChildrenMultiset {
943 fn get_all_parents_children(&self) -> DirsChildrenMultiset {
910 // TODO cache
944 // TODO cache
911 let thing = self
945 let thing = self
912 .dirs
946 .dirs
913 .iter()
947 .iter()
914 .chain(self.roots.iter())
948 .chain(self.roots.iter())
915 .chain(self.parents.iter());
949 .chain(self.parents.iter());
916 DirsChildrenMultiset::new(thing, Some(&self.parents))
950 DirsChildrenMultiset::new(thing, Some(&self.parents))
917 }
951 }
918
952
919 pub fn debug_get_patterns(&self) -> &[u8] {
953 pub fn debug_get_patterns(&self) -> &[u8] {
920 self.patterns.as_ref()
954 self.patterns.as_ref()
921 }
955 }
922 }
956 }
923
957
924 impl<'a> Display for IncludeMatcher<'a> {
958 impl<'a> Display for IncludeMatcher<'a> {
925 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
959 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
926 // XXX What about exact matches?
960 // XXX What about exact matches?
927 // I'm not sure it's worth it to clone the HashSet and keep it
961 // I'm not sure it's worth it to clone the HashSet and keep it
928 // around just in case someone wants to display the matcher, plus
962 // around just in case someone wants to display the matcher, plus
929 // it's going to be unreadable after a few entries, but we need to
963 // it's going to be unreadable after a few entries, but we need to
930 // inform in this display that exact matches are being used and are
964 // inform in this display that exact matches are being used and are
931 // (on purpose) missing from the `includes`.
965 // (on purpose) missing from the `includes`.
932 write!(
966 write!(
933 f,
967 f,
934 "IncludeMatcher(includes='{}')",
968 "IncludeMatcher(includes='{}')",
935 String::from_utf8_lossy(&self.patterns.escaped_bytes())
969 String::from_utf8_lossy(&self.patterns.escaped_bytes())
936 )
970 )
937 }
971 }
938 }
972 }
939
973
940 #[cfg(test)]
974 #[cfg(test)]
941 mod tests {
975 mod tests {
942 use super::*;
976 use super::*;
943 use pretty_assertions::assert_eq;
977 use pretty_assertions::assert_eq;
944 use std::path::Path;
978 use std::path::Path;
945
979
946 #[test]
980 #[test]
947 fn test_roots_and_dirs() {
981 fn test_roots_and_dirs() {
948 let pats = vec![
982 let pats = vec![
949 IgnorePattern::new(PatternSyntax::Glob, b"g/h/*", Path::new("")),
983 IgnorePattern::new(PatternSyntax::Glob, b"g/h/*", Path::new("")),
950 IgnorePattern::new(PatternSyntax::Glob, b"g/h", Path::new("")),
984 IgnorePattern::new(PatternSyntax::Glob, b"g/h", Path::new("")),
951 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
985 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
952 ];
986 ];
953 let (roots, dirs) = roots_and_dirs(&pats);
987 let (roots, dirs) = roots_and_dirs(&pats);
954
988
955 assert_eq!(
989 assert_eq!(
956 roots,
990 roots,
957 vec!(
991 vec!(
958 HgPathBuf::from_bytes(b"g/h"),
992 HgPathBuf::from_bytes(b"g/h"),
959 HgPathBuf::from_bytes(b"g/h"),
993 HgPathBuf::from_bytes(b"g/h"),
960 HgPathBuf::new()
994 HgPathBuf::new()
961 ),
995 ),
962 );
996 );
963 assert_eq!(dirs, vec!());
997 assert_eq!(dirs, vec!());
964 }
998 }
965
999
966 #[test]
1000 #[test]
967 fn test_roots_dirs_and_parents() {
1001 fn test_roots_dirs_and_parents() {
968 let pats = vec![
1002 let pats = vec![
969 IgnorePattern::new(PatternSyntax::Glob, b"g/h/*", Path::new("")),
1003 IgnorePattern::new(PatternSyntax::Glob, b"g/h/*", Path::new("")),
970 IgnorePattern::new(PatternSyntax::Glob, b"g/h", Path::new("")),
1004 IgnorePattern::new(PatternSyntax::Glob, b"g/h", Path::new("")),
971 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
1005 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
972 ];
1006 ];
973
1007
974 let mut roots = HashSet::new();
1008 let mut roots = HashSet::new();
975 roots.insert(HgPathBuf::from_bytes(b"g/h"));
1009 roots.insert(HgPathBuf::from_bytes(b"g/h"));
976 roots.insert(HgPathBuf::new());
1010 roots.insert(HgPathBuf::new());
977
1011
978 let dirs = HashSet::new();
1012 let dirs = HashSet::new();
979
1013
980 let mut parents = HashSet::new();
1014 let mut parents = HashSet::new();
981 parents.insert(HgPathBuf::new());
1015 parents.insert(HgPathBuf::new());
982 parents.insert(HgPathBuf::from_bytes(b"g"));
1016 parents.insert(HgPathBuf::from_bytes(b"g"));
983
1017
984 assert_eq!(
1018 assert_eq!(
985 roots_dirs_and_parents(&pats).unwrap(),
1019 roots_dirs_and_parents(&pats).unwrap(),
986 RootsDirsAndParents {
1020 RootsDirsAndParents {
987 roots,
1021 roots,
988 dirs,
1022 dirs,
989 parents
1023 parents
990 }
1024 }
991 );
1025 );
992 }
1026 }
993
1027
994 #[test]
1028 #[test]
995 fn test_filematcher_visit_children_set() {
1029 fn test_filematcher_visit_children_set() {
996 // Visitchildrenset
1030 // Visitchildrenset
997 let files = vec![HgPathBuf::from_bytes(b"dir/subdir/foo.txt")];
1031 let files = vec![HgPathBuf::from_bytes(b"dir/subdir/foo.txt")];
998 let matcher = FileMatcher::new(files).unwrap();
1032 let matcher = FileMatcher::new(files).unwrap();
999
1033
1000 let mut set = HashSet::new();
1034 let mut set = HashSet::new();
1001 set.insert(HgPathBuf::from_bytes(b"dir"));
1035 set.insert(HgPathBuf::from_bytes(b"dir"));
1002 assert_eq!(
1036 assert_eq!(
1003 matcher.visit_children_set(HgPath::new(b"")),
1037 matcher.visit_children_set(HgPath::new(b"")),
1004 VisitChildrenSet::Set(set)
1038 VisitChildrenSet::Set(set)
1005 );
1039 );
1006
1040
1007 let mut set = HashSet::new();
1041 let mut set = HashSet::new();
1008 set.insert(HgPathBuf::from_bytes(b"subdir"));
1042 set.insert(HgPathBuf::from_bytes(b"subdir"));
1009 assert_eq!(
1043 assert_eq!(
1010 matcher.visit_children_set(HgPath::new(b"dir")),
1044 matcher.visit_children_set(HgPath::new(b"dir")),
1011 VisitChildrenSet::Set(set)
1045 VisitChildrenSet::Set(set)
1012 );
1046 );
1013
1047
1014 let mut set = HashSet::new();
1048 let mut set = HashSet::new();
1015 set.insert(HgPathBuf::from_bytes(b"foo.txt"));
1049 set.insert(HgPathBuf::from_bytes(b"foo.txt"));
1016 assert_eq!(
1050 assert_eq!(
1017 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1051 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1018 VisitChildrenSet::Set(set)
1052 VisitChildrenSet::Set(set)
1019 );
1053 );
1020
1054
1021 assert_eq!(
1055 assert_eq!(
1022 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1056 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1023 VisitChildrenSet::Empty
1057 VisitChildrenSet::Empty
1024 );
1058 );
1025 assert_eq!(
1059 assert_eq!(
1026 matcher.visit_children_set(HgPath::new(b"dir/subdir/foo.txt")),
1060 matcher.visit_children_set(HgPath::new(b"dir/subdir/foo.txt")),
1027 VisitChildrenSet::Empty
1061 VisitChildrenSet::Empty
1028 );
1062 );
1029 assert_eq!(
1063 assert_eq!(
1030 matcher.visit_children_set(HgPath::new(b"folder")),
1064 matcher.visit_children_set(HgPath::new(b"folder")),
1031 VisitChildrenSet::Empty
1065 VisitChildrenSet::Empty
1032 );
1066 );
1033 }
1067 }
1034
1068
1035 #[test]
1069 #[test]
1036 fn test_filematcher_visit_children_set_files_and_dirs() {
1070 fn test_filematcher_visit_children_set_files_and_dirs() {
1037 let files = vec![
1071 let files = vec![
1038 HgPathBuf::from_bytes(b"rootfile.txt"),
1072 HgPathBuf::from_bytes(b"rootfile.txt"),
1039 HgPathBuf::from_bytes(b"a/file1.txt"),
1073 HgPathBuf::from_bytes(b"a/file1.txt"),
1040 HgPathBuf::from_bytes(b"a/b/file2.txt"),
1074 HgPathBuf::from_bytes(b"a/b/file2.txt"),
1041 // No file in a/b/c
1075 // No file in a/b/c
1042 HgPathBuf::from_bytes(b"a/b/c/d/file4.txt"),
1076 HgPathBuf::from_bytes(b"a/b/c/d/file4.txt"),
1043 ];
1077 ];
1044 let matcher = FileMatcher::new(files).unwrap();
1078 let matcher = FileMatcher::new(files).unwrap();
1045
1079
1046 let mut set = HashSet::new();
1080 let mut set = HashSet::new();
1047 set.insert(HgPathBuf::from_bytes(b"a"));
1081 set.insert(HgPathBuf::from_bytes(b"a"));
1048 set.insert(HgPathBuf::from_bytes(b"rootfile.txt"));
1082 set.insert(HgPathBuf::from_bytes(b"rootfile.txt"));
1049 assert_eq!(
1083 assert_eq!(
1050 matcher.visit_children_set(HgPath::new(b"")),
1084 matcher.visit_children_set(HgPath::new(b"")),
1051 VisitChildrenSet::Set(set)
1085 VisitChildrenSet::Set(set)
1052 );
1086 );
1053
1087
1054 let mut set = HashSet::new();
1088 let mut set = HashSet::new();
1055 set.insert(HgPathBuf::from_bytes(b"b"));
1089 set.insert(HgPathBuf::from_bytes(b"b"));
1056 set.insert(HgPathBuf::from_bytes(b"file1.txt"));
1090 set.insert(HgPathBuf::from_bytes(b"file1.txt"));
1057 assert_eq!(
1091 assert_eq!(
1058 matcher.visit_children_set(HgPath::new(b"a")),
1092 matcher.visit_children_set(HgPath::new(b"a")),
1059 VisitChildrenSet::Set(set)
1093 VisitChildrenSet::Set(set)
1060 );
1094 );
1061
1095
1062 let mut set = HashSet::new();
1096 let mut set = HashSet::new();
1063 set.insert(HgPathBuf::from_bytes(b"c"));
1097 set.insert(HgPathBuf::from_bytes(b"c"));
1064 set.insert(HgPathBuf::from_bytes(b"file2.txt"));
1098 set.insert(HgPathBuf::from_bytes(b"file2.txt"));
1065 assert_eq!(
1099 assert_eq!(
1066 matcher.visit_children_set(HgPath::new(b"a/b")),
1100 matcher.visit_children_set(HgPath::new(b"a/b")),
1067 VisitChildrenSet::Set(set)
1101 VisitChildrenSet::Set(set)
1068 );
1102 );
1069
1103
1070 let mut set = HashSet::new();
1104 let mut set = HashSet::new();
1071 set.insert(HgPathBuf::from_bytes(b"d"));
1105 set.insert(HgPathBuf::from_bytes(b"d"));
1072 assert_eq!(
1106 assert_eq!(
1073 matcher.visit_children_set(HgPath::new(b"a/b/c")),
1107 matcher.visit_children_set(HgPath::new(b"a/b/c")),
1074 VisitChildrenSet::Set(set)
1108 VisitChildrenSet::Set(set)
1075 );
1109 );
1076 let mut set = HashSet::new();
1110 let mut set = HashSet::new();
1077 set.insert(HgPathBuf::from_bytes(b"file4.txt"));
1111 set.insert(HgPathBuf::from_bytes(b"file4.txt"));
1078 assert_eq!(
1112 assert_eq!(
1079 matcher.visit_children_set(HgPath::new(b"a/b/c/d")),
1113 matcher.visit_children_set(HgPath::new(b"a/b/c/d")),
1080 VisitChildrenSet::Set(set)
1114 VisitChildrenSet::Set(set)
1081 );
1115 );
1082
1116
1083 assert_eq!(
1117 assert_eq!(
1084 matcher.visit_children_set(HgPath::new(b"a/b/c/d/e")),
1118 matcher.visit_children_set(HgPath::new(b"a/b/c/d/e")),
1085 VisitChildrenSet::Empty
1119 VisitChildrenSet::Empty
1086 );
1120 );
1087 assert_eq!(
1121 assert_eq!(
1088 matcher.visit_children_set(HgPath::new(b"folder")),
1122 matcher.visit_children_set(HgPath::new(b"folder")),
1089 VisitChildrenSet::Empty
1123 VisitChildrenSet::Empty
1090 );
1124 );
1091 }
1125 }
1092
1126
1093 #[test]
1127 #[test]
1094 fn test_includematcher() {
1128 fn test_includematcher() {
1095 // VisitchildrensetPrefix
1129 // VisitchildrensetPrefix
1096 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1130 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1097 PatternSyntax::RelPath,
1131 PatternSyntax::RelPath,
1098 b"dir/subdir",
1132 b"dir/subdir",
1099 Path::new(""),
1133 Path::new(""),
1100 )])
1134 )])
1101 .unwrap();
1135 .unwrap();
1102
1136
1103 let mut set = HashSet::new();
1137 let mut set = HashSet::new();
1104 set.insert(HgPathBuf::from_bytes(b"dir"));
1138 set.insert(HgPathBuf::from_bytes(b"dir"));
1105 assert_eq!(
1139 assert_eq!(
1106 matcher.visit_children_set(HgPath::new(b"")),
1140 matcher.visit_children_set(HgPath::new(b"")),
1107 VisitChildrenSet::Set(set)
1141 VisitChildrenSet::Set(set)
1108 );
1142 );
1109
1143
1110 let mut set = HashSet::new();
1144 let mut set = HashSet::new();
1111 set.insert(HgPathBuf::from_bytes(b"subdir"));
1145 set.insert(HgPathBuf::from_bytes(b"subdir"));
1112 assert_eq!(
1146 assert_eq!(
1113 matcher.visit_children_set(HgPath::new(b"dir")),
1147 matcher.visit_children_set(HgPath::new(b"dir")),
1114 VisitChildrenSet::Set(set)
1148 VisitChildrenSet::Set(set)
1115 );
1149 );
1116 assert_eq!(
1150 assert_eq!(
1117 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1151 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1118 VisitChildrenSet::Recursive
1152 VisitChildrenSet::Recursive
1119 );
1153 );
1120 // OPT: This should probably be 'all' if its parent is?
1154 // OPT: This should probably be 'all' if its parent is?
1121 assert_eq!(
1155 assert_eq!(
1122 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1156 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1123 VisitChildrenSet::This
1157 VisitChildrenSet::This
1124 );
1158 );
1125 assert_eq!(
1159 assert_eq!(
1126 matcher.visit_children_set(HgPath::new(b"folder")),
1160 matcher.visit_children_set(HgPath::new(b"folder")),
1127 VisitChildrenSet::Empty
1161 VisitChildrenSet::Empty
1128 );
1162 );
1129
1163
1130 // VisitchildrensetRootfilesin
1164 // VisitchildrensetRootfilesin
1131 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1165 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1132 PatternSyntax::RootFiles,
1166 PatternSyntax::RootFiles,
1133 b"dir/subdir",
1167 b"dir/subdir",
1134 Path::new(""),
1168 Path::new(""),
1135 )])
1169 )])
1136 .unwrap();
1170 .unwrap();
1137
1171
1138 let mut set = HashSet::new();
1172 let mut set = HashSet::new();
1139 set.insert(HgPathBuf::from_bytes(b"dir"));
1173 set.insert(HgPathBuf::from_bytes(b"dir"));
1140 assert_eq!(
1174 assert_eq!(
1141 matcher.visit_children_set(HgPath::new(b"")),
1175 matcher.visit_children_set(HgPath::new(b"")),
1142 VisitChildrenSet::Set(set)
1176 VisitChildrenSet::Set(set)
1143 );
1177 );
1144
1178
1145 let mut set = HashSet::new();
1179 let mut set = HashSet::new();
1146 set.insert(HgPathBuf::from_bytes(b"subdir"));
1180 set.insert(HgPathBuf::from_bytes(b"subdir"));
1147 assert_eq!(
1181 assert_eq!(
1148 matcher.visit_children_set(HgPath::new(b"dir")),
1182 matcher.visit_children_set(HgPath::new(b"dir")),
1149 VisitChildrenSet::Set(set)
1183 VisitChildrenSet::Set(set)
1150 );
1184 );
1151
1185
1152 assert_eq!(
1186 assert_eq!(
1153 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1187 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1154 VisitChildrenSet::This
1188 VisitChildrenSet::This
1155 );
1189 );
1156 assert_eq!(
1190 assert_eq!(
1157 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1191 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1158 VisitChildrenSet::Empty
1192 VisitChildrenSet::Empty
1159 );
1193 );
1160 assert_eq!(
1194 assert_eq!(
1161 matcher.visit_children_set(HgPath::new(b"folder")),
1195 matcher.visit_children_set(HgPath::new(b"folder")),
1162 VisitChildrenSet::Empty
1196 VisitChildrenSet::Empty
1163 );
1197 );
1164
1198
1165 // VisitchildrensetGlob
1199 // VisitchildrensetGlob
1166 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1200 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1167 PatternSyntax::Glob,
1201 PatternSyntax::Glob,
1168 b"dir/z*",
1202 b"dir/z*",
1169 Path::new(""),
1203 Path::new(""),
1170 )])
1204 )])
1171 .unwrap();
1205 .unwrap();
1172
1206
1173 let mut set = HashSet::new();
1207 let mut set = HashSet::new();
1174 set.insert(HgPathBuf::from_bytes(b"dir"));
1208 set.insert(HgPathBuf::from_bytes(b"dir"));
1175 assert_eq!(
1209 assert_eq!(
1176 matcher.visit_children_set(HgPath::new(b"")),
1210 matcher.visit_children_set(HgPath::new(b"")),
1177 VisitChildrenSet::Set(set)
1211 VisitChildrenSet::Set(set)
1178 );
1212 );
1179 assert_eq!(
1213 assert_eq!(
1180 matcher.visit_children_set(HgPath::new(b"folder")),
1214 matcher.visit_children_set(HgPath::new(b"folder")),
1181 VisitChildrenSet::Empty
1215 VisitChildrenSet::Empty
1182 );
1216 );
1183 assert_eq!(
1217 assert_eq!(
1184 matcher.visit_children_set(HgPath::new(b"dir")),
1218 matcher.visit_children_set(HgPath::new(b"dir")),
1185 VisitChildrenSet::This
1219 VisitChildrenSet::This
1186 );
1220 );
1187 // OPT: these should probably be set().
1221 // OPT: these should probably be set().
1188 assert_eq!(
1222 assert_eq!(
1189 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1223 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1190 VisitChildrenSet::This
1224 VisitChildrenSet::This
1191 );
1225 );
1192 assert_eq!(
1226 assert_eq!(
1193 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1227 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1194 VisitChildrenSet::This
1228 VisitChildrenSet::This
1195 );
1229 );
1196
1230
1197 // Test multiple patterns
1231 // Test multiple patterns
1198 let matcher = IncludeMatcher::new(vec![
1232 let matcher = IncludeMatcher::new(vec![
1199 IgnorePattern::new(PatternSyntax::RelPath, b"foo", Path::new("")),
1233 IgnorePattern::new(PatternSyntax::RelPath, b"foo", Path::new("")),
1200 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
1234 IgnorePattern::new(PatternSyntax::Glob, b"g*", Path::new("")),
1201 ])
1235 ])
1202 .unwrap();
1236 .unwrap();
1203
1237
1204 assert_eq!(
1238 assert_eq!(
1205 matcher.visit_children_set(HgPath::new(b"")),
1239 matcher.visit_children_set(HgPath::new(b"")),
1206 VisitChildrenSet::This
1240 VisitChildrenSet::This
1207 );
1241 );
1208
1242
1209 // Test multiple patterns
1243 // Test multiple patterns
1210 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1244 let matcher = IncludeMatcher::new(vec![IgnorePattern::new(
1211 PatternSyntax::Glob,
1245 PatternSyntax::Glob,
1212 b"**/*.exe",
1246 b"**/*.exe",
1213 Path::new(""),
1247 Path::new(""),
1214 )])
1248 )])
1215 .unwrap();
1249 .unwrap();
1216
1250
1217 assert_eq!(
1251 assert_eq!(
1218 matcher.visit_children_set(HgPath::new(b"")),
1252 matcher.visit_children_set(HgPath::new(b"")),
1219 VisitChildrenSet::This
1253 VisitChildrenSet::This
1220 );
1254 );
1221 }
1255 }
1222
1256
1223 #[test]
1257 #[test]
1224 fn test_unionmatcher() {
1258 fn test_unionmatcher() {
1225 // Path + Rootfiles
1259 // Path + Rootfiles
1226 let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
1260 let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
1227 PatternSyntax::RelPath,
1261 PatternSyntax::RelPath,
1228 b"dir/subdir",
1262 b"dir/subdir",
1229 Path::new(""),
1263 Path::new(""),
1230 )])
1264 )])
1231 .unwrap();
1265 .unwrap();
1232 let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
1266 let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
1233 PatternSyntax::RootFiles,
1267 PatternSyntax::RootFiles,
1234 b"dir",
1268 b"dir",
1235 Path::new(""),
1269 Path::new(""),
1236 )])
1270 )])
1237 .unwrap();
1271 .unwrap();
1238 let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
1272 let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
1239
1273
1240 let mut set = HashSet::new();
1274 let mut set = HashSet::new();
1241 set.insert(HgPathBuf::from_bytes(b"dir"));
1275 set.insert(HgPathBuf::from_bytes(b"dir"));
1242 assert_eq!(
1276 assert_eq!(
1243 matcher.visit_children_set(HgPath::new(b"")),
1277 matcher.visit_children_set(HgPath::new(b"")),
1244 VisitChildrenSet::Set(set)
1278 VisitChildrenSet::Set(set)
1245 );
1279 );
1246 assert_eq!(
1280 assert_eq!(
1247 matcher.visit_children_set(HgPath::new(b"dir")),
1281 matcher.visit_children_set(HgPath::new(b"dir")),
1248 VisitChildrenSet::This
1282 VisitChildrenSet::This
1249 );
1283 );
1250 assert_eq!(
1284 assert_eq!(
1251 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1285 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1252 VisitChildrenSet::Recursive
1286 VisitChildrenSet::Recursive
1253 );
1287 );
1254 assert_eq!(
1288 assert_eq!(
1255 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1289 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1256 VisitChildrenSet::Empty
1290 VisitChildrenSet::Empty
1257 );
1291 );
1258 assert_eq!(
1292 assert_eq!(
1259 matcher.visit_children_set(HgPath::new(b"folder")),
1293 matcher.visit_children_set(HgPath::new(b"folder")),
1260 VisitChildrenSet::Empty
1294 VisitChildrenSet::Empty
1261 );
1295 );
1262 assert_eq!(
1296 assert_eq!(
1263 matcher.visit_children_set(HgPath::new(b"folder")),
1297 matcher.visit_children_set(HgPath::new(b"folder")),
1264 VisitChildrenSet::Empty
1298 VisitChildrenSet::Empty
1265 );
1299 );
1266
1300
1267 // OPT: These next two could be 'all' instead of 'this'.
1301 // OPT: These next two could be 'all' instead of 'this'.
1268 assert_eq!(
1302 assert_eq!(
1269 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1303 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1270 VisitChildrenSet::This
1304 VisitChildrenSet::This
1271 );
1305 );
1272 assert_eq!(
1306 assert_eq!(
1273 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1307 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1274 VisitChildrenSet::This
1308 VisitChildrenSet::This
1275 );
1309 );
1276
1310
1277 // Path + unrelated Path
1311 // Path + unrelated Path
1278 let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
1312 let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
1279 PatternSyntax::RelPath,
1313 PatternSyntax::RelPath,
1280 b"dir/subdir",
1314 b"dir/subdir",
1281 Path::new(""),
1315 Path::new(""),
1282 )])
1316 )])
1283 .unwrap();
1317 .unwrap();
1284 let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
1318 let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
1285 PatternSyntax::RelPath,
1319 PatternSyntax::RelPath,
1286 b"folder",
1320 b"folder",
1287 Path::new(""),
1321 Path::new(""),
1288 )])
1322 )])
1289 .unwrap();
1323 .unwrap();
1290 let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
1324 let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
1291
1325
1292 let mut set = HashSet::new();
1326 let mut set = HashSet::new();
1293 set.insert(HgPathBuf::from_bytes(b"folder"));
1327 set.insert(HgPathBuf::from_bytes(b"folder"));
1294 set.insert(HgPathBuf::from_bytes(b"dir"));
1328 set.insert(HgPathBuf::from_bytes(b"dir"));
1295 assert_eq!(
1329 assert_eq!(
1296 matcher.visit_children_set(HgPath::new(b"")),
1330 matcher.visit_children_set(HgPath::new(b"")),
1297 VisitChildrenSet::Set(set)
1331 VisitChildrenSet::Set(set)
1298 );
1332 );
1299 let mut set = HashSet::new();
1333 let mut set = HashSet::new();
1300 set.insert(HgPathBuf::from_bytes(b"subdir"));
1334 set.insert(HgPathBuf::from_bytes(b"subdir"));
1301 assert_eq!(
1335 assert_eq!(
1302 matcher.visit_children_set(HgPath::new(b"dir")),
1336 matcher.visit_children_set(HgPath::new(b"dir")),
1303 VisitChildrenSet::Set(set)
1337 VisitChildrenSet::Set(set)
1304 );
1338 );
1305
1339
1306 assert_eq!(
1340 assert_eq!(
1307 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1341 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1308 VisitChildrenSet::Recursive
1342 VisitChildrenSet::Recursive
1309 );
1343 );
1310 assert_eq!(
1344 assert_eq!(
1311 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1345 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1312 VisitChildrenSet::Empty
1346 VisitChildrenSet::Empty
1313 );
1347 );
1314
1348
1315 assert_eq!(
1349 assert_eq!(
1316 matcher.visit_children_set(HgPath::new(b"folder")),
1350 matcher.visit_children_set(HgPath::new(b"folder")),
1317 VisitChildrenSet::Recursive
1351 VisitChildrenSet::Recursive
1318 );
1352 );
1319 // OPT: These next two could be 'all' instead of 'this'.
1353 // OPT: These next two could be 'all' instead of 'this'.
1320 assert_eq!(
1354 assert_eq!(
1321 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1355 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1322 VisitChildrenSet::This
1356 VisitChildrenSet::This
1323 );
1357 );
1324 assert_eq!(
1358 assert_eq!(
1325 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1359 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1326 VisitChildrenSet::This
1360 VisitChildrenSet::This
1327 );
1361 );
1328
1362
1329 // Path + subpath
1363 // Path + subpath
1330 let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
1364 let m1 = IncludeMatcher::new(vec![IgnorePattern::new(
1331 PatternSyntax::RelPath,
1365 PatternSyntax::RelPath,
1332 b"dir/subdir/x",
1366 b"dir/subdir/x",
1333 Path::new(""),
1367 Path::new(""),
1334 )])
1368 )])
1335 .unwrap();
1369 .unwrap();
1336 let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
1370 let m2 = IncludeMatcher::new(vec![IgnorePattern::new(
1337 PatternSyntax::RelPath,
1371 PatternSyntax::RelPath,
1338 b"dir/subdir",
1372 b"dir/subdir",
1339 Path::new(""),
1373 Path::new(""),
1340 )])
1374 )])
1341 .unwrap();
1375 .unwrap();
1342 let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
1376 let matcher = UnionMatcher::new(vec![Box::new(m1), Box::new(m2)]);
1343
1377
1344 let mut set = HashSet::new();
1378 let mut set = HashSet::new();
1345 set.insert(HgPathBuf::from_bytes(b"dir"));
1379 set.insert(HgPathBuf::from_bytes(b"dir"));
1346 assert_eq!(
1380 assert_eq!(
1347 matcher.visit_children_set(HgPath::new(b"")),
1381 matcher.visit_children_set(HgPath::new(b"")),
1348 VisitChildrenSet::Set(set)
1382 VisitChildrenSet::Set(set)
1349 );
1383 );
1350 let mut set = HashSet::new();
1384 let mut set = HashSet::new();
1351 set.insert(HgPathBuf::from_bytes(b"subdir"));
1385 set.insert(HgPathBuf::from_bytes(b"subdir"));
1352 assert_eq!(
1386 assert_eq!(
1353 matcher.visit_children_set(HgPath::new(b"dir")),
1387 matcher.visit_children_set(HgPath::new(b"dir")),
1354 VisitChildrenSet::Set(set)
1388 VisitChildrenSet::Set(set)
1355 );
1389 );
1356
1390
1357 assert_eq!(
1391 assert_eq!(
1358 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1392 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1359 VisitChildrenSet::Recursive
1393 VisitChildrenSet::Recursive
1360 );
1394 );
1361 assert_eq!(
1395 assert_eq!(
1362 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1396 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1363 VisitChildrenSet::Empty
1397 VisitChildrenSet::Empty
1364 );
1398 );
1365
1399
1366 assert_eq!(
1400 assert_eq!(
1367 matcher.visit_children_set(HgPath::new(b"folder")),
1401 matcher.visit_children_set(HgPath::new(b"folder")),
1368 VisitChildrenSet::Empty
1402 VisitChildrenSet::Empty
1369 );
1403 );
1370 assert_eq!(
1404 assert_eq!(
1371 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1405 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1372 VisitChildrenSet::Recursive
1406 VisitChildrenSet::Recursive
1373 );
1407 );
1374 // OPT: this should probably be 'all' not 'this'.
1408 // OPT: this should probably be 'all' not 'this'.
1375 assert_eq!(
1409 assert_eq!(
1376 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1410 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1377 VisitChildrenSet::This
1411 VisitChildrenSet::This
1378 );
1412 );
1379 }
1413 }
1380
1414
1381 #[test]
1415 #[test]
1382 fn test_intersectionmatcher() {
1416 fn test_intersectionmatcher() {
1383 // Include path + Include rootfiles
1417 // Include path + Include rootfiles
1384 let m1 = Box::new(
1418 let m1 = Box::new(
1385 IncludeMatcher::new(vec![IgnorePattern::new(
1419 IncludeMatcher::new(vec![IgnorePattern::new(
1386 PatternSyntax::RelPath,
1420 PatternSyntax::RelPath,
1387 b"dir/subdir",
1421 b"dir/subdir",
1388 Path::new(""),
1422 Path::new(""),
1389 )])
1423 )])
1390 .unwrap(),
1424 .unwrap(),
1391 );
1425 );
1392 let m2 = Box::new(
1426 let m2 = Box::new(
1393 IncludeMatcher::new(vec![IgnorePattern::new(
1427 IncludeMatcher::new(vec![IgnorePattern::new(
1394 PatternSyntax::RootFiles,
1428 PatternSyntax::RootFiles,
1395 b"dir",
1429 b"dir",
1396 Path::new(""),
1430 Path::new(""),
1397 )])
1431 )])
1398 .unwrap(),
1432 .unwrap(),
1399 );
1433 );
1400 let matcher = IntersectionMatcher::new(m1, m2);
1434 let matcher = IntersectionMatcher::new(m1, m2);
1401
1435
1402 let mut set = HashSet::new();
1436 let mut set = HashSet::new();
1403 set.insert(HgPathBuf::from_bytes(b"dir"));
1437 set.insert(HgPathBuf::from_bytes(b"dir"));
1404 assert_eq!(
1438 assert_eq!(
1405 matcher.visit_children_set(HgPath::new(b"")),
1439 matcher.visit_children_set(HgPath::new(b"")),
1406 VisitChildrenSet::Set(set)
1440 VisitChildrenSet::Set(set)
1407 );
1441 );
1408 assert_eq!(
1442 assert_eq!(
1409 matcher.visit_children_set(HgPath::new(b"dir")),
1443 matcher.visit_children_set(HgPath::new(b"dir")),
1410 VisitChildrenSet::This
1444 VisitChildrenSet::This
1411 );
1445 );
1412 assert_eq!(
1446 assert_eq!(
1413 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1447 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1414 VisitChildrenSet::Empty
1448 VisitChildrenSet::Empty
1415 );
1449 );
1416 assert_eq!(
1450 assert_eq!(
1417 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1451 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1418 VisitChildrenSet::Empty
1452 VisitChildrenSet::Empty
1419 );
1453 );
1420 assert_eq!(
1454 assert_eq!(
1421 matcher.visit_children_set(HgPath::new(b"folder")),
1455 matcher.visit_children_set(HgPath::new(b"folder")),
1422 VisitChildrenSet::Empty
1456 VisitChildrenSet::Empty
1423 );
1457 );
1424 assert_eq!(
1458 assert_eq!(
1425 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1459 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1426 VisitChildrenSet::Empty
1460 VisitChildrenSet::Empty
1427 );
1461 );
1428 assert_eq!(
1462 assert_eq!(
1429 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1463 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1430 VisitChildrenSet::Empty
1464 VisitChildrenSet::Empty
1431 );
1465 );
1432
1466
1433 // Non intersecting paths
1467 // Non intersecting paths
1434 let m1 = Box::new(
1468 let m1 = Box::new(
1435 IncludeMatcher::new(vec![IgnorePattern::new(
1469 IncludeMatcher::new(vec![IgnorePattern::new(
1436 PatternSyntax::RelPath,
1470 PatternSyntax::RelPath,
1437 b"dir/subdir",
1471 b"dir/subdir",
1438 Path::new(""),
1472 Path::new(""),
1439 )])
1473 )])
1440 .unwrap(),
1474 .unwrap(),
1441 );
1475 );
1442 let m2 = Box::new(
1476 let m2 = Box::new(
1443 IncludeMatcher::new(vec![IgnorePattern::new(
1477 IncludeMatcher::new(vec![IgnorePattern::new(
1444 PatternSyntax::RelPath,
1478 PatternSyntax::RelPath,
1445 b"folder",
1479 b"folder",
1446 Path::new(""),
1480 Path::new(""),
1447 )])
1481 )])
1448 .unwrap(),
1482 .unwrap(),
1449 );
1483 );
1450 let matcher = IntersectionMatcher::new(m1, m2);
1484 let matcher = IntersectionMatcher::new(m1, m2);
1451
1485
1452 assert_eq!(
1486 assert_eq!(
1453 matcher.visit_children_set(HgPath::new(b"")),
1487 matcher.visit_children_set(HgPath::new(b"")),
1454 VisitChildrenSet::Empty
1488 VisitChildrenSet::Empty
1455 );
1489 );
1456 assert_eq!(
1490 assert_eq!(
1457 matcher.visit_children_set(HgPath::new(b"dir")),
1491 matcher.visit_children_set(HgPath::new(b"dir")),
1458 VisitChildrenSet::Empty
1492 VisitChildrenSet::Empty
1459 );
1493 );
1460 assert_eq!(
1494 assert_eq!(
1461 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1495 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1462 VisitChildrenSet::Empty
1496 VisitChildrenSet::Empty
1463 );
1497 );
1464 assert_eq!(
1498 assert_eq!(
1465 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1499 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1466 VisitChildrenSet::Empty
1500 VisitChildrenSet::Empty
1467 );
1501 );
1468 assert_eq!(
1502 assert_eq!(
1469 matcher.visit_children_set(HgPath::new(b"folder")),
1503 matcher.visit_children_set(HgPath::new(b"folder")),
1470 VisitChildrenSet::Empty
1504 VisitChildrenSet::Empty
1471 );
1505 );
1472 assert_eq!(
1506 assert_eq!(
1473 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1507 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1474 VisitChildrenSet::Empty
1508 VisitChildrenSet::Empty
1475 );
1509 );
1476 assert_eq!(
1510 assert_eq!(
1477 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1511 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1478 VisitChildrenSet::Empty
1512 VisitChildrenSet::Empty
1479 );
1513 );
1480
1514
1481 // Nested paths
1515 // Nested paths
1482 let m1 = Box::new(
1516 let m1 = Box::new(
1483 IncludeMatcher::new(vec![IgnorePattern::new(
1517 IncludeMatcher::new(vec![IgnorePattern::new(
1484 PatternSyntax::RelPath,
1518 PatternSyntax::RelPath,
1485 b"dir/subdir/x",
1519 b"dir/subdir/x",
1486 Path::new(""),
1520 Path::new(""),
1487 )])
1521 )])
1488 .unwrap(),
1522 .unwrap(),
1489 );
1523 );
1490 let m2 = Box::new(
1524 let m2 = Box::new(
1491 IncludeMatcher::new(vec![IgnorePattern::new(
1525 IncludeMatcher::new(vec![IgnorePattern::new(
1492 PatternSyntax::RelPath,
1526 PatternSyntax::RelPath,
1493 b"dir/subdir",
1527 b"dir/subdir",
1494 Path::new(""),
1528 Path::new(""),
1495 )])
1529 )])
1496 .unwrap(),
1530 .unwrap(),
1497 );
1531 );
1498 let matcher = IntersectionMatcher::new(m1, m2);
1532 let matcher = IntersectionMatcher::new(m1, m2);
1499
1533
1500 let mut set = HashSet::new();
1534 let mut set = HashSet::new();
1501 set.insert(HgPathBuf::from_bytes(b"dir"));
1535 set.insert(HgPathBuf::from_bytes(b"dir"));
1502 assert_eq!(
1536 assert_eq!(
1503 matcher.visit_children_set(HgPath::new(b"")),
1537 matcher.visit_children_set(HgPath::new(b"")),
1504 VisitChildrenSet::Set(set)
1538 VisitChildrenSet::Set(set)
1505 );
1539 );
1506
1540
1507 let mut set = HashSet::new();
1541 let mut set = HashSet::new();
1508 set.insert(HgPathBuf::from_bytes(b"subdir"));
1542 set.insert(HgPathBuf::from_bytes(b"subdir"));
1509 assert_eq!(
1543 assert_eq!(
1510 matcher.visit_children_set(HgPath::new(b"dir")),
1544 matcher.visit_children_set(HgPath::new(b"dir")),
1511 VisitChildrenSet::Set(set)
1545 VisitChildrenSet::Set(set)
1512 );
1546 );
1513 let mut set = HashSet::new();
1547 let mut set = HashSet::new();
1514 set.insert(HgPathBuf::from_bytes(b"x"));
1548 set.insert(HgPathBuf::from_bytes(b"x"));
1515 assert_eq!(
1549 assert_eq!(
1516 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1550 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1517 VisitChildrenSet::Set(set)
1551 VisitChildrenSet::Set(set)
1518 );
1552 );
1519 assert_eq!(
1553 assert_eq!(
1520 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1554 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1521 VisitChildrenSet::Empty
1555 VisitChildrenSet::Empty
1522 );
1556 );
1523 assert_eq!(
1557 assert_eq!(
1524 matcher.visit_children_set(HgPath::new(b"folder")),
1558 matcher.visit_children_set(HgPath::new(b"folder")),
1525 VisitChildrenSet::Empty
1559 VisitChildrenSet::Empty
1526 );
1560 );
1527 assert_eq!(
1561 assert_eq!(
1528 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1562 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1529 VisitChildrenSet::Empty
1563 VisitChildrenSet::Empty
1530 );
1564 );
1531 // OPT: this should probably be 'all' not 'this'.
1565 // OPT: this should probably be 'all' not 'this'.
1532 assert_eq!(
1566 assert_eq!(
1533 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1567 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1534 VisitChildrenSet::This
1568 VisitChildrenSet::This
1535 );
1569 );
1536
1570
1537 // Diverging paths
1571 // Diverging paths
1538 let m1 = Box::new(
1572 let m1 = Box::new(
1539 IncludeMatcher::new(vec![IgnorePattern::new(
1573 IncludeMatcher::new(vec![IgnorePattern::new(
1540 PatternSyntax::RelPath,
1574 PatternSyntax::RelPath,
1541 b"dir/subdir/x",
1575 b"dir/subdir/x",
1542 Path::new(""),
1576 Path::new(""),
1543 )])
1577 )])
1544 .unwrap(),
1578 .unwrap(),
1545 );
1579 );
1546 let m2 = Box::new(
1580 let m2 = Box::new(
1547 IncludeMatcher::new(vec![IgnorePattern::new(
1581 IncludeMatcher::new(vec![IgnorePattern::new(
1548 PatternSyntax::RelPath,
1582 PatternSyntax::RelPath,
1549 b"dir/subdir/z",
1583 b"dir/subdir/z",
1550 Path::new(""),
1584 Path::new(""),
1551 )])
1585 )])
1552 .unwrap(),
1586 .unwrap(),
1553 );
1587 );
1554 let matcher = IntersectionMatcher::new(m1, m2);
1588 let matcher = IntersectionMatcher::new(m1, m2);
1555
1589
1556 // OPT: these next two could probably be Empty as well.
1590 // OPT: these next two could probably be Empty as well.
1557 let mut set = HashSet::new();
1591 let mut set = HashSet::new();
1558 set.insert(HgPathBuf::from_bytes(b"dir"));
1592 set.insert(HgPathBuf::from_bytes(b"dir"));
1559 assert_eq!(
1593 assert_eq!(
1560 matcher.visit_children_set(HgPath::new(b"")),
1594 matcher.visit_children_set(HgPath::new(b"")),
1561 VisitChildrenSet::Set(set)
1595 VisitChildrenSet::Set(set)
1562 );
1596 );
1563 // OPT: these next two could probably be Empty as well.
1597 // OPT: these next two could probably be Empty as well.
1564 let mut set = HashSet::new();
1598 let mut set = HashSet::new();
1565 set.insert(HgPathBuf::from_bytes(b"subdir"));
1599 set.insert(HgPathBuf::from_bytes(b"subdir"));
1566 assert_eq!(
1600 assert_eq!(
1567 matcher.visit_children_set(HgPath::new(b"dir")),
1601 matcher.visit_children_set(HgPath::new(b"dir")),
1568 VisitChildrenSet::Set(set)
1602 VisitChildrenSet::Set(set)
1569 );
1603 );
1570 assert_eq!(
1604 assert_eq!(
1571 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1605 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1572 VisitChildrenSet::Empty
1606 VisitChildrenSet::Empty
1573 );
1607 );
1574 assert_eq!(
1608 assert_eq!(
1575 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1609 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1576 VisitChildrenSet::Empty
1610 VisitChildrenSet::Empty
1577 );
1611 );
1578 assert_eq!(
1612 assert_eq!(
1579 matcher.visit_children_set(HgPath::new(b"folder")),
1613 matcher.visit_children_set(HgPath::new(b"folder")),
1580 VisitChildrenSet::Empty
1614 VisitChildrenSet::Empty
1581 );
1615 );
1582 assert_eq!(
1616 assert_eq!(
1583 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1617 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1584 VisitChildrenSet::Empty
1618 VisitChildrenSet::Empty
1585 );
1619 );
1586 assert_eq!(
1620 assert_eq!(
1587 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1621 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1588 VisitChildrenSet::Empty
1622 VisitChildrenSet::Empty
1589 );
1623 );
1590 }
1624 }
1591
1625
1592 #[test]
1626 #[test]
1593 fn test_differencematcher() {
1627 fn test_differencematcher() {
1594 // Two alwaysmatchers should function like a nevermatcher
1628 // Two alwaysmatchers should function like a nevermatcher
1595 let m1 = AlwaysMatcher;
1629 let m1 = AlwaysMatcher;
1596 let m2 = AlwaysMatcher;
1630 let m2 = AlwaysMatcher;
1597 let matcher = DifferenceMatcher::new(Box::new(m1), Box::new(m2));
1631 let matcher = DifferenceMatcher::new(Box::new(m1), Box::new(m2));
1598
1632
1599 for case in &[
1633 for case in &[
1600 &b""[..],
1634 &b""[..],
1601 b"dir",
1635 b"dir",
1602 b"dir/subdir",
1636 b"dir/subdir",
1603 b"dir/subdir/z",
1637 b"dir/subdir/z",
1604 b"dir/foo",
1638 b"dir/foo",
1605 b"dir/subdir/x",
1639 b"dir/subdir/x",
1606 b"folder",
1640 b"folder",
1607 ] {
1641 ] {
1608 assert_eq!(
1642 assert_eq!(
1609 matcher.visit_children_set(HgPath::new(case)),
1643 matcher.visit_children_set(HgPath::new(case)),
1610 VisitChildrenSet::Empty
1644 VisitChildrenSet::Empty
1611 );
1645 );
1612 }
1646 }
1613
1647
1614 // One always and one never should behave the same as an always
1648 // One always and one never should behave the same as an always
1615 let m1 = AlwaysMatcher;
1649 let m1 = AlwaysMatcher;
1616 let m2 = NeverMatcher;
1650 let m2 = NeverMatcher;
1617 let matcher = DifferenceMatcher::new(Box::new(m1), Box::new(m2));
1651 let matcher = DifferenceMatcher::new(Box::new(m1), Box::new(m2));
1618
1652
1619 for case in &[
1653 for case in &[
1620 &b""[..],
1654 &b""[..],
1621 b"dir",
1655 b"dir",
1622 b"dir/subdir",
1656 b"dir/subdir",
1623 b"dir/subdir/z",
1657 b"dir/subdir/z",
1624 b"dir/foo",
1658 b"dir/foo",
1625 b"dir/subdir/x",
1659 b"dir/subdir/x",
1626 b"folder",
1660 b"folder",
1627 ] {
1661 ] {
1628 assert_eq!(
1662 assert_eq!(
1629 matcher.visit_children_set(HgPath::new(case)),
1663 matcher.visit_children_set(HgPath::new(case)),
1630 VisitChildrenSet::Recursive
1664 VisitChildrenSet::Recursive
1631 );
1665 );
1632 }
1666 }
1633
1667
1634 // Two include matchers
1668 // Two include matchers
1635 let m1 = Box::new(
1669 let m1 = Box::new(
1636 IncludeMatcher::new(vec![IgnorePattern::new(
1670 IncludeMatcher::new(vec![IgnorePattern::new(
1637 PatternSyntax::RelPath,
1671 PatternSyntax::RelPath,
1638 b"dir/subdir",
1672 b"dir/subdir",
1639 Path::new("/repo"),
1673 Path::new("/repo"),
1640 )])
1674 )])
1641 .unwrap(),
1675 .unwrap(),
1642 );
1676 );
1643 let m2 = Box::new(
1677 let m2 = Box::new(
1644 IncludeMatcher::new(vec![IgnorePattern::new(
1678 IncludeMatcher::new(vec![IgnorePattern::new(
1645 PatternSyntax::RootFiles,
1679 PatternSyntax::RootFiles,
1646 b"dir",
1680 b"dir",
1647 Path::new("/repo"),
1681 Path::new("/repo"),
1648 )])
1682 )])
1649 .unwrap(),
1683 .unwrap(),
1650 );
1684 );
1651
1685
1652 let matcher = DifferenceMatcher::new(m1, m2);
1686 let matcher = DifferenceMatcher::new(m1, m2);
1653
1687
1654 let mut set = HashSet::new();
1688 let mut set = HashSet::new();
1655 set.insert(HgPathBuf::from_bytes(b"dir"));
1689 set.insert(HgPathBuf::from_bytes(b"dir"));
1656 assert_eq!(
1690 assert_eq!(
1657 matcher.visit_children_set(HgPath::new(b"")),
1691 matcher.visit_children_set(HgPath::new(b"")),
1658 VisitChildrenSet::Set(set)
1692 VisitChildrenSet::Set(set)
1659 );
1693 );
1660
1694
1661 let mut set = HashSet::new();
1695 let mut set = HashSet::new();
1662 set.insert(HgPathBuf::from_bytes(b"subdir"));
1696 set.insert(HgPathBuf::from_bytes(b"subdir"));
1663 assert_eq!(
1697 assert_eq!(
1664 matcher.visit_children_set(HgPath::new(b"dir")),
1698 matcher.visit_children_set(HgPath::new(b"dir")),
1665 VisitChildrenSet::Set(set)
1699 VisitChildrenSet::Set(set)
1666 );
1700 );
1667 assert_eq!(
1701 assert_eq!(
1668 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1702 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
1669 VisitChildrenSet::Recursive
1703 VisitChildrenSet::Recursive
1670 );
1704 );
1671 assert_eq!(
1705 assert_eq!(
1672 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1706 matcher.visit_children_set(HgPath::new(b"dir/foo")),
1673 VisitChildrenSet::Empty
1707 VisitChildrenSet::Empty
1674 );
1708 );
1675 assert_eq!(
1709 assert_eq!(
1676 matcher.visit_children_set(HgPath::new(b"folder")),
1710 matcher.visit_children_set(HgPath::new(b"folder")),
1677 VisitChildrenSet::Empty
1711 VisitChildrenSet::Empty
1678 );
1712 );
1679 assert_eq!(
1713 assert_eq!(
1680 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1714 matcher.visit_children_set(HgPath::new(b"dir/subdir/z")),
1681 VisitChildrenSet::This
1715 VisitChildrenSet::This
1682 );
1716 );
1683 assert_eq!(
1717 assert_eq!(
1684 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1718 matcher.visit_children_set(HgPath::new(b"dir/subdir/x")),
1685 VisitChildrenSet::This
1719 VisitChildrenSet::This
1686 );
1720 );
1687 }
1721 }
1688 }
1722 }
General Comments 0
You need to be logged in to leave comments. Login now