##// END OF EJS Templates
dirstate-tree: optimize HashMap lookups with raw_entry_mut...
Simon Sapin -
r49805:11c0411b default
parent child Browse files
Show More
@@ -1,1142 +1,1159 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 = "adler"
6 name = "adler"
7 version = "0.2.3"
7 version = "0.2.3"
8 source = "registry+https://github.com/rust-lang/crates.io-index"
8 source = "registry+https://github.com/rust-lang/crates.io-index"
9 checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
9 checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
10
10
11 [[package]]
11 [[package]]
12 name = "ahash"
13 version = "0.4.7"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
15 checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
16
17 [[package]]
12 name = "aho-corasick"
18 name = "aho-corasick"
13 version = "0.7.15"
19 version = "0.7.15"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
20 source = "registry+https://github.com/rust-lang/crates.io-index"
15 checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
21 checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
16 dependencies = [
22 dependencies = [
17 "memchr",
23 "memchr",
18 ]
24 ]
19
25
20 [[package]]
26 [[package]]
21 name = "ansi_term"
27 name = "ansi_term"
22 version = "0.11.0"
28 version = "0.11.0"
23 source = "registry+https://github.com/rust-lang/crates.io-index"
29 source = "registry+https://github.com/rust-lang/crates.io-index"
24 checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
30 checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
25 dependencies = [
31 dependencies = [
26 "winapi",
32 "winapi",
27 ]
33 ]
28
34
29 [[package]]
35 [[package]]
30 name = "atty"
36 name = "atty"
31 version = "0.2.14"
37 version = "0.2.14"
32 source = "registry+https://github.com/rust-lang/crates.io-index"
38 source = "registry+https://github.com/rust-lang/crates.io-index"
33 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
39 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
34 dependencies = [
40 dependencies = [
35 "hermit-abi",
41 "hermit-abi",
36 "libc",
42 "libc",
37 "winapi",
43 "winapi",
38 ]
44 ]
39
45
40 [[package]]
46 [[package]]
41 name = "autocfg"
47 name = "autocfg"
42 version = "1.0.1"
48 version = "1.0.1"
43 source = "registry+https://github.com/rust-lang/crates.io-index"
49 source = "registry+https://github.com/rust-lang/crates.io-index"
44 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
50 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
45
51
46 [[package]]
52 [[package]]
47 name = "bitflags"
53 name = "bitflags"
48 version = "1.2.1"
54 version = "1.2.1"
49 source = "registry+https://github.com/rust-lang/crates.io-index"
55 source = "registry+https://github.com/rust-lang/crates.io-index"
50 checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
56 checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
51
57
52 [[package]]
58 [[package]]
53 name = "bitmaps"
59 name = "bitmaps"
54 version = "2.1.0"
60 version = "2.1.0"
55 source = "registry+https://github.com/rust-lang/crates.io-index"
61 source = "registry+https://github.com/rust-lang/crates.io-index"
56 checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
62 checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
57 dependencies = [
63 dependencies = [
58 "typenum",
64 "typenum",
59 ]
65 ]
60
66
61 [[package]]
67 [[package]]
62 name = "block-buffer"
68 name = "block-buffer"
63 version = "0.9.0"
69 version = "0.9.0"
64 source = "registry+https://github.com/rust-lang/crates.io-index"
70 source = "registry+https://github.com/rust-lang/crates.io-index"
65 checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
71 checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
66 dependencies = [
72 dependencies = [
67 "generic-array",
73 "generic-array",
68 ]
74 ]
69
75
70 [[package]]
76 [[package]]
71 name = "byteorder"
77 name = "byteorder"
72 version = "1.3.4"
78 version = "1.3.4"
73 source = "registry+https://github.com/rust-lang/crates.io-index"
79 source = "registry+https://github.com/rust-lang/crates.io-index"
74 checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
80 checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
75
81
76 [[package]]
82 [[package]]
77 name = "bytes-cast"
83 name = "bytes-cast"
78 version = "0.2.0"
84 version = "0.2.0"
79 source = "registry+https://github.com/rust-lang/crates.io-index"
85 source = "registry+https://github.com/rust-lang/crates.io-index"
80 checksum = "0d434f9a4ecbe987e7ccfda7274b6f82ea52c9b63742565a65cb5e8ba0f2c452"
86 checksum = "0d434f9a4ecbe987e7ccfda7274b6f82ea52c9b63742565a65cb5e8ba0f2c452"
81 dependencies = [
87 dependencies = [
82 "bytes-cast-derive",
88 "bytes-cast-derive",
83 ]
89 ]
84
90
85 [[package]]
91 [[package]]
86 name = "bytes-cast-derive"
92 name = "bytes-cast-derive"
87 version = "0.1.0"
93 version = "0.1.0"
88 source = "registry+https://github.com/rust-lang/crates.io-index"
94 source = "registry+https://github.com/rust-lang/crates.io-index"
89 checksum = "cb936af9de38476664d6b58e529aff30d482e4ce1c5e150293d00730b0d81fdb"
95 checksum = "cb936af9de38476664d6b58e529aff30d482e4ce1c5e150293d00730b0d81fdb"
90 dependencies = [
96 dependencies = [
91 "proc-macro2",
97 "proc-macro2",
92 "quote",
98 "quote",
93 "syn",
99 "syn",
94 ]
100 ]
95
101
96 [[package]]
102 [[package]]
97 name = "cc"
103 name = "cc"
98 version = "1.0.66"
104 version = "1.0.66"
99 source = "registry+https://github.com/rust-lang/crates.io-index"
105 source = "registry+https://github.com/rust-lang/crates.io-index"
100 checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
106 checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
101 dependencies = [
107 dependencies = [
102 "jobserver",
108 "jobserver",
103 ]
109 ]
104
110
105 [[package]]
111 [[package]]
106 name = "cfg-if"
112 name = "cfg-if"
107 version = "0.1.10"
113 version = "0.1.10"
108 source = "registry+https://github.com/rust-lang/crates.io-index"
114 source = "registry+https://github.com/rust-lang/crates.io-index"
109 checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
115 checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
110
116
111 [[package]]
117 [[package]]
112 name = "cfg-if"
118 name = "cfg-if"
113 version = "1.0.0"
119 version = "1.0.0"
114 source = "registry+https://github.com/rust-lang/crates.io-index"
120 source = "registry+https://github.com/rust-lang/crates.io-index"
115 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
121 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
116
122
117 [[package]]
123 [[package]]
118 name = "chrono"
124 name = "chrono"
119 version = "0.4.19"
125 version = "0.4.19"
120 source = "registry+https://github.com/rust-lang/crates.io-index"
126 source = "registry+https://github.com/rust-lang/crates.io-index"
121 checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
127 checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
122 dependencies = [
128 dependencies = [
123 "libc",
129 "libc",
124 "num-integer",
130 "num-integer",
125 "num-traits",
131 "num-traits",
126 "time",
132 "time",
127 "winapi",
133 "winapi",
128 ]
134 ]
129
135
130 [[package]]
136 [[package]]
131 name = "clap"
137 name = "clap"
132 version = "2.33.3"
138 version = "2.33.3"
133 source = "registry+https://github.com/rust-lang/crates.io-index"
139 source = "registry+https://github.com/rust-lang/crates.io-index"
134 checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
140 checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
135 dependencies = [
141 dependencies = [
136 "ansi_term",
142 "ansi_term",
137 "atty",
143 "atty",
138 "bitflags",
144 "bitflags",
139 "strsim",
145 "strsim",
140 "textwrap",
146 "textwrap",
141 "unicode-width",
147 "unicode-width",
142 "vec_map",
148 "vec_map",
143 ]
149 ]
144
150
145 [[package]]
151 [[package]]
146 name = "const_fn"
152 name = "const_fn"
147 version = "0.4.4"
153 version = "0.4.4"
148 source = "registry+https://github.com/rust-lang/crates.io-index"
154 source = "registry+https://github.com/rust-lang/crates.io-index"
149 checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
155 checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
150
156
151 [[package]]
157 [[package]]
152 name = "cpufeatures"
158 name = "cpufeatures"
153 version = "0.1.4"
159 version = "0.1.4"
154 source = "registry+https://github.com/rust-lang/crates.io-index"
160 source = "registry+https://github.com/rust-lang/crates.io-index"
155 checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
161 checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
156 dependencies = [
162 dependencies = [
157 "libc",
163 "libc",
158 ]
164 ]
159
165
160 [[package]]
166 [[package]]
161 name = "cpython"
167 name = "cpython"
162 version = "0.7.0"
168 version = "0.7.0"
163 source = "registry+https://github.com/rust-lang/crates.io-index"
169 source = "registry+https://github.com/rust-lang/crates.io-index"
164 checksum = "b7d46ba8ace7f3a1d204ac5060a706d0a68de6b42eafb6a586cc08bebcffe664"
170 checksum = "b7d46ba8ace7f3a1d204ac5060a706d0a68de6b42eafb6a586cc08bebcffe664"
165 dependencies = [
171 dependencies = [
166 "libc",
172 "libc",
167 "num-traits",
173 "num-traits",
168 "paste",
174 "paste",
169 "python3-sys",
175 "python3-sys",
170 ]
176 ]
171
177
172 [[package]]
178 [[package]]
173 name = "crc32fast"
179 name = "crc32fast"
174 version = "1.2.1"
180 version = "1.2.1"
175 source = "registry+https://github.com/rust-lang/crates.io-index"
181 source = "registry+https://github.com/rust-lang/crates.io-index"
176 checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
182 checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
177 dependencies = [
183 dependencies = [
178 "cfg-if 1.0.0",
184 "cfg-if 1.0.0",
179 ]
185 ]
180
186
181 [[package]]
187 [[package]]
182 name = "crossbeam-channel"
188 name = "crossbeam-channel"
183 version = "0.4.4"
189 version = "0.4.4"
184 source = "registry+https://github.com/rust-lang/crates.io-index"
190 source = "registry+https://github.com/rust-lang/crates.io-index"
185 checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
191 checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
186 dependencies = [
192 dependencies = [
187 "crossbeam-utils 0.7.2",
193 "crossbeam-utils 0.7.2",
188 "maybe-uninit",
194 "maybe-uninit",
189 ]
195 ]
190
196
191 [[package]]
197 [[package]]
192 name = "crossbeam-channel"
198 name = "crossbeam-channel"
193 version = "0.5.0"
199 version = "0.5.0"
194 source = "registry+https://github.com/rust-lang/crates.io-index"
200 source = "registry+https://github.com/rust-lang/crates.io-index"
195 checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
201 checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
196 dependencies = [
202 dependencies = [
197 "cfg-if 1.0.0",
203 "cfg-if 1.0.0",
198 "crossbeam-utils 0.8.1",
204 "crossbeam-utils 0.8.1",
199 ]
205 ]
200
206
201 [[package]]
207 [[package]]
202 name = "crossbeam-deque"
208 name = "crossbeam-deque"
203 version = "0.8.0"
209 version = "0.8.0"
204 source = "registry+https://github.com/rust-lang/crates.io-index"
210 source = "registry+https://github.com/rust-lang/crates.io-index"
205 checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
211 checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
206 dependencies = [
212 dependencies = [
207 "cfg-if 1.0.0",
213 "cfg-if 1.0.0",
208 "crossbeam-epoch",
214 "crossbeam-epoch",
209 "crossbeam-utils 0.8.1",
215 "crossbeam-utils 0.8.1",
210 ]
216 ]
211
217
212 [[package]]
218 [[package]]
213 name = "crossbeam-epoch"
219 name = "crossbeam-epoch"
214 version = "0.9.1"
220 version = "0.9.1"
215 source = "registry+https://github.com/rust-lang/crates.io-index"
221 source = "registry+https://github.com/rust-lang/crates.io-index"
216 checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
222 checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
217 dependencies = [
223 dependencies = [
218 "cfg-if 1.0.0",
224 "cfg-if 1.0.0",
219 "const_fn",
225 "const_fn",
220 "crossbeam-utils 0.8.1",
226 "crossbeam-utils 0.8.1",
221 "lazy_static",
227 "lazy_static",
222 "memoffset",
228 "memoffset",
223 "scopeguard",
229 "scopeguard",
224 ]
230 ]
225
231
226 [[package]]
232 [[package]]
227 name = "crossbeam-utils"
233 name = "crossbeam-utils"
228 version = "0.7.2"
234 version = "0.7.2"
229 source = "registry+https://github.com/rust-lang/crates.io-index"
235 source = "registry+https://github.com/rust-lang/crates.io-index"
230 checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
236 checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
231 dependencies = [
237 dependencies = [
232 "autocfg",
238 "autocfg",
233 "cfg-if 0.1.10",
239 "cfg-if 0.1.10",
234 "lazy_static",
240 "lazy_static",
235 ]
241 ]
236
242
237 [[package]]
243 [[package]]
238 name = "crossbeam-utils"
244 name = "crossbeam-utils"
239 version = "0.8.1"
245 version = "0.8.1"
240 source = "registry+https://github.com/rust-lang/crates.io-index"
246 source = "registry+https://github.com/rust-lang/crates.io-index"
241 checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
247 checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
242 dependencies = [
248 dependencies = [
243 "autocfg",
249 "autocfg",
244 "cfg-if 1.0.0",
250 "cfg-if 1.0.0",
245 "lazy_static",
251 "lazy_static",
246 ]
252 ]
247
253
248 [[package]]
254 [[package]]
249 name = "ctor"
255 name = "ctor"
250 version = "0.1.16"
256 version = "0.1.16"
251 source = "registry+https://github.com/rust-lang/crates.io-index"
257 source = "registry+https://github.com/rust-lang/crates.io-index"
252 checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484"
258 checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484"
253 dependencies = [
259 dependencies = [
254 "quote",
260 "quote",
255 "syn",
261 "syn",
256 ]
262 ]
257
263
258 [[package]]
264 [[package]]
259 name = "derive_more"
265 name = "derive_more"
260 version = "0.99.11"
266 version = "0.99.11"
261 source = "registry+https://github.com/rust-lang/crates.io-index"
267 source = "registry+https://github.com/rust-lang/crates.io-index"
262 checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
268 checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
263 dependencies = [
269 dependencies = [
264 "proc-macro2",
270 "proc-macro2",
265 "quote",
271 "quote",
266 "syn",
272 "syn",
267 ]
273 ]
268
274
269 [[package]]
275 [[package]]
270 name = "difference"
276 name = "difference"
271 version = "2.0.0"
277 version = "2.0.0"
272 source = "registry+https://github.com/rust-lang/crates.io-index"
278 source = "registry+https://github.com/rust-lang/crates.io-index"
273 checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
279 checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
274
280
275 [[package]]
281 [[package]]
276 name = "digest"
282 name = "digest"
277 version = "0.9.0"
283 version = "0.9.0"
278 source = "registry+https://github.com/rust-lang/crates.io-index"
284 source = "registry+https://github.com/rust-lang/crates.io-index"
279 checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
285 checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
280 dependencies = [
286 dependencies = [
281 "generic-array",
287 "generic-array",
282 ]
288 ]
283
289
284 [[package]]
290 [[package]]
285 name = "either"
291 name = "either"
286 version = "1.6.1"
292 version = "1.6.1"
287 source = "registry+https://github.com/rust-lang/crates.io-index"
293 source = "registry+https://github.com/rust-lang/crates.io-index"
288 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
294 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
289
295
290 [[package]]
296 [[package]]
291 name = "env_logger"
297 name = "env_logger"
292 version = "0.7.1"
298 version = "0.7.1"
293 source = "registry+https://github.com/rust-lang/crates.io-index"
299 source = "registry+https://github.com/rust-lang/crates.io-index"
294 checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
300 checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
295 dependencies = [
301 dependencies = [
296 "atty",
302 "atty",
297 "humantime",
303 "humantime",
298 "log",
304 "log",
299 "regex",
305 "regex",
300 "termcolor",
306 "termcolor",
301 ]
307 ]
302
308
303 [[package]]
309 [[package]]
304 name = "flate2"
310 name = "flate2"
305 version = "1.0.19"
311 version = "1.0.19"
306 source = "registry+https://github.com/rust-lang/crates.io-index"
312 source = "registry+https://github.com/rust-lang/crates.io-index"
307 checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
313 checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
308 dependencies = [
314 dependencies = [
309 "cfg-if 1.0.0",
315 "cfg-if 1.0.0",
310 "crc32fast",
316 "crc32fast",
311 "libc",
317 "libc",
312 "libz-sys",
318 "libz-sys",
313 "miniz_oxide",
319 "miniz_oxide",
314 ]
320 ]
315
321
316 [[package]]
322 [[package]]
317 name = "format-bytes"
323 name = "format-bytes"
318 version = "0.3.0"
324 version = "0.3.0"
319 source = "registry+https://github.com/rust-lang/crates.io-index"
325 source = "registry+https://github.com/rust-lang/crates.io-index"
320 checksum = "48942366ef93975da38e175ac9e10068c6fc08ca9e85930d4f098f4d5b14c2fd"
326 checksum = "48942366ef93975da38e175ac9e10068c6fc08ca9e85930d4f098f4d5b14c2fd"
321 dependencies = [
327 dependencies = [
322 "format-bytes-macros",
328 "format-bytes-macros",
323 ]
329 ]
324
330
325 [[package]]
331 [[package]]
326 name = "format-bytes-macros"
332 name = "format-bytes-macros"
327 version = "0.4.0"
333 version = "0.4.0"
328 source = "registry+https://github.com/rust-lang/crates.io-index"
334 source = "registry+https://github.com/rust-lang/crates.io-index"
329 checksum = "203aadebefcc73d12038296c228eabf830f99cba991b0032adf20e9fa6ce7e4f"
335 checksum = "203aadebefcc73d12038296c228eabf830f99cba991b0032adf20e9fa6ce7e4f"
330 dependencies = [
336 dependencies = [
331 "proc-macro2",
337 "proc-macro2",
332 "quote",
338 "quote",
333 "syn",
339 "syn",
334 ]
340 ]
335
341
336 [[package]]
342 [[package]]
337 name = "generic-array"
343 name = "generic-array"
338 version = "0.14.4"
344 version = "0.14.4"
339 source = "registry+https://github.com/rust-lang/crates.io-index"
345 source = "registry+https://github.com/rust-lang/crates.io-index"
340 checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
346 checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
341 dependencies = [
347 dependencies = [
342 "typenum",
348 "typenum",
343 "version_check",
349 "version_check",
344 ]
350 ]
345
351
346 [[package]]
352 [[package]]
347 name = "getrandom"
353 name = "getrandom"
348 version = "0.1.15"
354 version = "0.1.15"
349 source = "registry+https://github.com/rust-lang/crates.io-index"
355 source = "registry+https://github.com/rust-lang/crates.io-index"
350 checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
356 checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
351 dependencies = [
357 dependencies = [
352 "cfg-if 0.1.10",
358 "cfg-if 0.1.10",
353 "libc",
359 "libc",
354 "wasi 0.9.0+wasi-snapshot-preview1",
360 "wasi 0.9.0+wasi-snapshot-preview1",
355 ]
361 ]
356
362
357 [[package]]
363 [[package]]
358 name = "getrandom"
364 name = "getrandom"
359 version = "0.2.4"
365 version = "0.2.4"
360 source = "registry+https://github.com/rust-lang/crates.io-index"
366 source = "registry+https://github.com/rust-lang/crates.io-index"
361 checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
367 checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
362 dependencies = [
368 dependencies = [
363 "cfg-if 1.0.0",
369 "cfg-if 1.0.0",
364 "libc",
370 "libc",
365 "wasi 0.10.0+wasi-snapshot-preview1",
371 "wasi 0.10.0+wasi-snapshot-preview1",
366 ]
372 ]
367
373
368 [[package]]
374 [[package]]
369 name = "glob"
375 name = "glob"
370 version = "0.3.0"
376 version = "0.3.0"
371 source = "registry+https://github.com/rust-lang/crates.io-index"
377 source = "registry+https://github.com/rust-lang/crates.io-index"
372 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
378 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
373
379
374 [[package]]
380 [[package]]
381 name = "hashbrown"
382 version = "0.9.1"
383 source = "registry+https://github.com/rust-lang/crates.io-index"
384 checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
385 dependencies = [
386 "ahash",
387 "rayon",
388 ]
389
390 [[package]]
375 name = "hermit-abi"
391 name = "hermit-abi"
376 version = "0.1.17"
392 version = "0.1.17"
377 source = "registry+https://github.com/rust-lang/crates.io-index"
393 source = "registry+https://github.com/rust-lang/crates.io-index"
378 checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
394 checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
379 dependencies = [
395 dependencies = [
380 "libc",
396 "libc",
381 ]
397 ]
382
398
383 [[package]]
399 [[package]]
384 name = "hex"
400 name = "hex"
385 version = "0.4.3"
401 version = "0.4.3"
386 source = "registry+https://github.com/rust-lang/crates.io-index"
402 source = "registry+https://github.com/rust-lang/crates.io-index"
387 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
403 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
388
404
389 [[package]]
405 [[package]]
390 name = "hg-core"
406 name = "hg-core"
391 version = "0.1.0"
407 version = "0.1.0"
392 dependencies = [
408 dependencies = [
393 "bitflags",
409 "bitflags",
394 "byteorder",
410 "byteorder",
395 "bytes-cast",
411 "bytes-cast",
396 "clap",
412 "clap",
397 "crossbeam-channel 0.4.4",
413 "crossbeam-channel 0.4.4",
398 "derive_more",
414 "derive_more",
399 "flate2",
415 "flate2",
400 "format-bytes",
416 "format-bytes",
417 "hashbrown",
401 "home",
418 "home",
402 "im-rc",
419 "im-rc",
403 "itertools",
420 "itertools",
404 "lazy_static",
421 "lazy_static",
405 "libc",
422 "libc",
406 "log",
423 "log",
407 "memmap2",
424 "memmap2",
408 "micro-timer",
425 "micro-timer",
409 "pretty_assertions",
426 "pretty_assertions",
410 "rand 0.8.4",
427 "rand 0.8.4",
411 "rand_distr",
428 "rand_distr",
412 "rand_pcg",
429 "rand_pcg",
413 "rayon",
430 "rayon",
414 "regex",
431 "regex",
415 "same-file",
432 "same-file",
416 "sha-1",
433 "sha-1",
417 "stable_deref_trait",
434 "stable_deref_trait",
418 "tempfile",
435 "tempfile",
419 "twox-hash",
436 "twox-hash",
420 "zstd",
437 "zstd",
421 ]
438 ]
422
439
423 [[package]]
440 [[package]]
424 name = "hg-cpython"
441 name = "hg-cpython"
425 version = "0.1.0"
442 version = "0.1.0"
426 dependencies = [
443 dependencies = [
427 "cpython",
444 "cpython",
428 "crossbeam-channel 0.4.4",
445 "crossbeam-channel 0.4.4",
429 "env_logger",
446 "env_logger",
430 "hg-core",
447 "hg-core",
431 "libc",
448 "libc",
432 "log",
449 "log",
433 "stable_deref_trait",
450 "stable_deref_trait",
434 "vcsgraph",
451 "vcsgraph",
435 ]
452 ]
436
453
437 [[package]]
454 [[package]]
438 name = "home"
455 name = "home"
439 version = "0.5.3"
456 version = "0.5.3"
440 source = "registry+https://github.com/rust-lang/crates.io-index"
457 source = "registry+https://github.com/rust-lang/crates.io-index"
441 checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
458 checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
442 dependencies = [
459 dependencies = [
443 "winapi",
460 "winapi",
444 ]
461 ]
445
462
446 [[package]]
463 [[package]]
447 name = "humantime"
464 name = "humantime"
448 version = "1.3.0"
465 version = "1.3.0"
449 source = "registry+https://github.com/rust-lang/crates.io-index"
466 source = "registry+https://github.com/rust-lang/crates.io-index"
450 checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
467 checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
451 dependencies = [
468 dependencies = [
452 "quick-error",
469 "quick-error",
453 ]
470 ]
454
471
455 [[package]]
472 [[package]]
456 name = "im-rc"
473 name = "im-rc"
457 version = "15.0.0"
474 version = "15.0.0"
458 source = "registry+https://github.com/rust-lang/crates.io-index"
475 source = "registry+https://github.com/rust-lang/crates.io-index"
459 checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
476 checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
460 dependencies = [
477 dependencies = [
461 "bitmaps",
478 "bitmaps",
462 "rand_core 0.5.1",
479 "rand_core 0.5.1",
463 "rand_xoshiro",
480 "rand_xoshiro",
464 "sized-chunks",
481 "sized-chunks",
465 "typenum",
482 "typenum",
466 "version_check",
483 "version_check",
467 ]
484 ]
468
485
469 [[package]]
486 [[package]]
470 name = "itertools"
487 name = "itertools"
471 version = "0.9.0"
488 version = "0.9.0"
472 source = "registry+https://github.com/rust-lang/crates.io-index"
489 source = "registry+https://github.com/rust-lang/crates.io-index"
473 checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
490 checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
474 dependencies = [
491 dependencies = [
475 "either",
492 "either",
476 ]
493 ]
477
494
478 [[package]]
495 [[package]]
479 name = "jobserver"
496 name = "jobserver"
480 version = "0.1.21"
497 version = "0.1.21"
481 source = "registry+https://github.com/rust-lang/crates.io-index"
498 source = "registry+https://github.com/rust-lang/crates.io-index"
482 checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
499 checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
483 dependencies = [
500 dependencies = [
484 "libc",
501 "libc",
485 ]
502 ]
486
503
487 [[package]]
504 [[package]]
488 name = "lazy_static"
505 name = "lazy_static"
489 version = "1.4.0"
506 version = "1.4.0"
490 source = "registry+https://github.com/rust-lang/crates.io-index"
507 source = "registry+https://github.com/rust-lang/crates.io-index"
491 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
508 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
492
509
493 [[package]]
510 [[package]]
494 name = "libc"
511 name = "libc"
495 version = "0.2.81"
512 version = "0.2.81"
496 source = "registry+https://github.com/rust-lang/crates.io-index"
513 source = "registry+https://github.com/rust-lang/crates.io-index"
497 checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
514 checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
498
515
499 [[package]]
516 [[package]]
500 name = "libm"
517 name = "libm"
501 version = "0.2.1"
518 version = "0.2.1"
502 source = "registry+https://github.com/rust-lang/crates.io-index"
519 source = "registry+https://github.com/rust-lang/crates.io-index"
503 checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
520 checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"
504
521
505 [[package]]
522 [[package]]
506 name = "libz-sys"
523 name = "libz-sys"
507 version = "1.1.2"
524 version = "1.1.2"
508 source = "registry+https://github.com/rust-lang/crates.io-index"
525 source = "registry+https://github.com/rust-lang/crates.io-index"
509 checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
526 checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
510 dependencies = [
527 dependencies = [
511 "cc",
528 "cc",
512 "pkg-config",
529 "pkg-config",
513 "vcpkg",
530 "vcpkg",
514 ]
531 ]
515
532
516 [[package]]
533 [[package]]
517 name = "log"
534 name = "log"
518 version = "0.4.11"
535 version = "0.4.11"
519 source = "registry+https://github.com/rust-lang/crates.io-index"
536 source = "registry+https://github.com/rust-lang/crates.io-index"
520 checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
537 checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
521 dependencies = [
538 dependencies = [
522 "cfg-if 0.1.10",
539 "cfg-if 0.1.10",
523 ]
540 ]
524
541
525 [[package]]
542 [[package]]
526 name = "maybe-uninit"
543 name = "maybe-uninit"
527 version = "2.0.0"
544 version = "2.0.0"
528 source = "registry+https://github.com/rust-lang/crates.io-index"
545 source = "registry+https://github.com/rust-lang/crates.io-index"
529 checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
546 checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
530
547
531 [[package]]
548 [[package]]
532 name = "memchr"
549 name = "memchr"
533 version = "2.3.4"
550 version = "2.3.4"
534 source = "registry+https://github.com/rust-lang/crates.io-index"
551 source = "registry+https://github.com/rust-lang/crates.io-index"
535 checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
552 checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
536
553
537 [[package]]
554 [[package]]
538 name = "memmap2"
555 name = "memmap2"
539 version = "0.4.0"
556 version = "0.4.0"
540 source = "registry+https://github.com/rust-lang/crates.io-index"
557 source = "registry+https://github.com/rust-lang/crates.io-index"
541 checksum = "de5d3112c080d58ce560081baeaab7e1e864ca21795ddbf533d5b1842bb1ecf8"
558 checksum = "de5d3112c080d58ce560081baeaab7e1e864ca21795ddbf533d5b1842bb1ecf8"
542 dependencies = [
559 dependencies = [
543 "libc",
560 "libc",
544 "stable_deref_trait",
561 "stable_deref_trait",
545 ]
562 ]
546
563
547 [[package]]
564 [[package]]
548 name = "memoffset"
565 name = "memoffset"
549 version = "0.6.1"
566 version = "0.6.1"
550 source = "registry+https://github.com/rust-lang/crates.io-index"
567 source = "registry+https://github.com/rust-lang/crates.io-index"
551 checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
568 checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
552 dependencies = [
569 dependencies = [
553 "autocfg",
570 "autocfg",
554 ]
571 ]
555
572
556 [[package]]
573 [[package]]
557 name = "micro-timer"
574 name = "micro-timer"
558 version = "0.3.1"
575 version = "0.3.1"
559 source = "registry+https://github.com/rust-lang/crates.io-index"
576 source = "registry+https://github.com/rust-lang/crates.io-index"
560 checksum = "2620153e1d903d26b72b89f0e9c48d8c4756cba941c185461dddc234980c298c"
577 checksum = "2620153e1d903d26b72b89f0e9c48d8c4756cba941c185461dddc234980c298c"
561 dependencies = [
578 dependencies = [
562 "micro-timer-macros",
579 "micro-timer-macros",
563 "scopeguard",
580 "scopeguard",
564 ]
581 ]
565
582
566 [[package]]
583 [[package]]
567 name = "micro-timer-macros"
584 name = "micro-timer-macros"
568 version = "0.3.1"
585 version = "0.3.1"
569 source = "registry+https://github.com/rust-lang/crates.io-index"
586 source = "registry+https://github.com/rust-lang/crates.io-index"
570 checksum = "e28a3473e6abd6e9aab36aaeef32ad22ae0bd34e79f376643594c2b152ec1c5d"
587 checksum = "e28a3473e6abd6e9aab36aaeef32ad22ae0bd34e79f376643594c2b152ec1c5d"
571 dependencies = [
588 dependencies = [
572 "proc-macro2",
589 "proc-macro2",
573 "quote",
590 "quote",
574 "scopeguard",
591 "scopeguard",
575 "syn",
592 "syn",
576 ]
593 ]
577
594
578 [[package]]
595 [[package]]
579 name = "miniz_oxide"
596 name = "miniz_oxide"
580 version = "0.4.3"
597 version = "0.4.3"
581 source = "registry+https://github.com/rust-lang/crates.io-index"
598 source = "registry+https://github.com/rust-lang/crates.io-index"
582 checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
599 checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
583 dependencies = [
600 dependencies = [
584 "adler",
601 "adler",
585 "autocfg",
602 "autocfg",
586 ]
603 ]
587
604
588 [[package]]
605 [[package]]
589 name = "num-integer"
606 name = "num-integer"
590 version = "0.1.44"
607 version = "0.1.44"
591 source = "registry+https://github.com/rust-lang/crates.io-index"
608 source = "registry+https://github.com/rust-lang/crates.io-index"
592 checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
609 checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
593 dependencies = [
610 dependencies = [
594 "autocfg",
611 "autocfg",
595 "num-traits",
612 "num-traits",
596 ]
613 ]
597
614
598 [[package]]
615 [[package]]
599 name = "num-traits"
616 name = "num-traits"
600 version = "0.2.14"
617 version = "0.2.14"
601 source = "registry+https://github.com/rust-lang/crates.io-index"
618 source = "registry+https://github.com/rust-lang/crates.io-index"
602 checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
619 checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
603 dependencies = [
620 dependencies = [
604 "autocfg",
621 "autocfg",
605 "libm",
622 "libm",
606 ]
623 ]
607
624
608 [[package]]
625 [[package]]
609 name = "num_cpus"
626 name = "num_cpus"
610 version = "1.13.0"
627 version = "1.13.0"
611 source = "registry+https://github.com/rust-lang/crates.io-index"
628 source = "registry+https://github.com/rust-lang/crates.io-index"
612 checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
629 checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
613 dependencies = [
630 dependencies = [
614 "hermit-abi",
631 "hermit-abi",
615 "libc",
632 "libc",
616 ]
633 ]
617
634
618 [[package]]
635 [[package]]
619 name = "opaque-debug"
636 name = "opaque-debug"
620 version = "0.3.0"
637 version = "0.3.0"
621 source = "registry+https://github.com/rust-lang/crates.io-index"
638 source = "registry+https://github.com/rust-lang/crates.io-index"
622 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
639 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
623
640
624 [[package]]
641 [[package]]
625 name = "output_vt100"
642 name = "output_vt100"
626 version = "0.1.2"
643 version = "0.1.2"
627 source = "registry+https://github.com/rust-lang/crates.io-index"
644 source = "registry+https://github.com/rust-lang/crates.io-index"
628 checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
645 checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
629 dependencies = [
646 dependencies = [
630 "winapi",
647 "winapi",
631 ]
648 ]
632
649
633 [[package]]
650 [[package]]
634 name = "paste"
651 name = "paste"
635 version = "1.0.5"
652 version = "1.0.5"
636 source = "registry+https://github.com/rust-lang/crates.io-index"
653 source = "registry+https://github.com/rust-lang/crates.io-index"
637 checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
654 checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
638
655
639 [[package]]
656 [[package]]
640 name = "pkg-config"
657 name = "pkg-config"
641 version = "0.3.19"
658 version = "0.3.19"
642 source = "registry+https://github.com/rust-lang/crates.io-index"
659 source = "registry+https://github.com/rust-lang/crates.io-index"
643 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
660 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
644
661
645 [[package]]
662 [[package]]
646 name = "ppv-lite86"
663 name = "ppv-lite86"
647 version = "0.2.10"
664 version = "0.2.10"
648 source = "registry+https://github.com/rust-lang/crates.io-index"
665 source = "registry+https://github.com/rust-lang/crates.io-index"
649 checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
666 checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
650
667
651 [[package]]
668 [[package]]
652 name = "pretty_assertions"
669 name = "pretty_assertions"
653 version = "0.6.1"
670 version = "0.6.1"
654 source = "registry+https://github.com/rust-lang/crates.io-index"
671 source = "registry+https://github.com/rust-lang/crates.io-index"
655 checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
672 checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
656 dependencies = [
673 dependencies = [
657 "ansi_term",
674 "ansi_term",
658 "ctor",
675 "ctor",
659 "difference",
676 "difference",
660 "output_vt100",
677 "output_vt100",
661 ]
678 ]
662
679
663 [[package]]
680 [[package]]
664 name = "proc-macro2"
681 name = "proc-macro2"
665 version = "1.0.24"
682 version = "1.0.24"
666 source = "registry+https://github.com/rust-lang/crates.io-index"
683 source = "registry+https://github.com/rust-lang/crates.io-index"
667 checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
684 checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
668 dependencies = [
685 dependencies = [
669 "unicode-xid",
686 "unicode-xid",
670 ]
687 ]
671
688
672 [[package]]
689 [[package]]
673 name = "python3-sys"
690 name = "python3-sys"
674 version = "0.7.0"
691 version = "0.7.0"
675 source = "registry+https://github.com/rust-lang/crates.io-index"
692 source = "registry+https://github.com/rust-lang/crates.io-index"
676 checksum = "b18b32e64c103d5045f44644d7ddddd65336f7a0521f6fde673240a9ecceb77e"
693 checksum = "b18b32e64c103d5045f44644d7ddddd65336f7a0521f6fde673240a9ecceb77e"
677 dependencies = [
694 dependencies = [
678 "libc",
695 "libc",
679 "regex",
696 "regex",
680 ]
697 ]
681
698
682 [[package]]
699 [[package]]
683 name = "quick-error"
700 name = "quick-error"
684 version = "1.2.3"
701 version = "1.2.3"
685 source = "registry+https://github.com/rust-lang/crates.io-index"
702 source = "registry+https://github.com/rust-lang/crates.io-index"
686 checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
703 checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
687
704
688 [[package]]
705 [[package]]
689 name = "quote"
706 name = "quote"
690 version = "1.0.7"
707 version = "1.0.7"
691 source = "registry+https://github.com/rust-lang/crates.io-index"
708 source = "registry+https://github.com/rust-lang/crates.io-index"
692 checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
709 checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
693 dependencies = [
710 dependencies = [
694 "proc-macro2",
711 "proc-macro2",
695 ]
712 ]
696
713
697 [[package]]
714 [[package]]
698 name = "rand"
715 name = "rand"
699 version = "0.7.3"
716 version = "0.7.3"
700 source = "registry+https://github.com/rust-lang/crates.io-index"
717 source = "registry+https://github.com/rust-lang/crates.io-index"
701 checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
718 checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
702 dependencies = [
719 dependencies = [
703 "getrandom 0.1.15",
720 "getrandom 0.1.15",
704 "libc",
721 "libc",
705 "rand_chacha 0.2.2",
722 "rand_chacha 0.2.2",
706 "rand_core 0.5.1",
723 "rand_core 0.5.1",
707 "rand_hc 0.2.0",
724 "rand_hc 0.2.0",
708 ]
725 ]
709
726
710 [[package]]
727 [[package]]
711 name = "rand"
728 name = "rand"
712 version = "0.8.4"
729 version = "0.8.4"
713 source = "registry+https://github.com/rust-lang/crates.io-index"
730 source = "registry+https://github.com/rust-lang/crates.io-index"
714 checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
731 checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
715 dependencies = [
732 dependencies = [
716 "libc",
733 "libc",
717 "rand_chacha 0.3.1",
734 "rand_chacha 0.3.1",
718 "rand_core 0.6.3",
735 "rand_core 0.6.3",
719 "rand_hc 0.3.1",
736 "rand_hc 0.3.1",
720 ]
737 ]
721
738
722 [[package]]
739 [[package]]
723 name = "rand_chacha"
740 name = "rand_chacha"
724 version = "0.2.2"
741 version = "0.2.2"
725 source = "registry+https://github.com/rust-lang/crates.io-index"
742 source = "registry+https://github.com/rust-lang/crates.io-index"
726 checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
743 checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
727 dependencies = [
744 dependencies = [
728 "ppv-lite86",
745 "ppv-lite86",
729 "rand_core 0.5.1",
746 "rand_core 0.5.1",
730 ]
747 ]
731
748
732 [[package]]
749 [[package]]
733 name = "rand_chacha"
750 name = "rand_chacha"
734 version = "0.3.1"
751 version = "0.3.1"
735 source = "registry+https://github.com/rust-lang/crates.io-index"
752 source = "registry+https://github.com/rust-lang/crates.io-index"
736 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
753 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
737 dependencies = [
754 dependencies = [
738 "ppv-lite86",
755 "ppv-lite86",
739 "rand_core 0.6.3",
756 "rand_core 0.6.3",
740 ]
757 ]
741
758
742 [[package]]
759 [[package]]
743 name = "rand_core"
760 name = "rand_core"
744 version = "0.5.1"
761 version = "0.5.1"
745 source = "registry+https://github.com/rust-lang/crates.io-index"
762 source = "registry+https://github.com/rust-lang/crates.io-index"
746 checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
763 checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
747 dependencies = [
764 dependencies = [
748 "getrandom 0.1.15",
765 "getrandom 0.1.15",
749 ]
766 ]
750
767
751 [[package]]
768 [[package]]
752 name = "rand_core"
769 name = "rand_core"
753 version = "0.6.3"
770 version = "0.6.3"
754 source = "registry+https://github.com/rust-lang/crates.io-index"
771 source = "registry+https://github.com/rust-lang/crates.io-index"
755 checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
772 checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
756 dependencies = [
773 dependencies = [
757 "getrandom 0.2.4",
774 "getrandom 0.2.4",
758 ]
775 ]
759
776
760 [[package]]
777 [[package]]
761 name = "rand_distr"
778 name = "rand_distr"
762 version = "0.4.2"
779 version = "0.4.2"
763 source = "registry+https://github.com/rust-lang/crates.io-index"
780 source = "registry+https://github.com/rust-lang/crates.io-index"
764 checksum = "964d548f8e7d12e102ef183a0de7e98180c9f8729f555897a857b96e48122d2f"
781 checksum = "964d548f8e7d12e102ef183a0de7e98180c9f8729f555897a857b96e48122d2f"
765 dependencies = [
782 dependencies = [
766 "num-traits",
783 "num-traits",
767 "rand 0.8.4",
784 "rand 0.8.4",
768 ]
785 ]
769
786
770 [[package]]
787 [[package]]
771 name = "rand_hc"
788 name = "rand_hc"
772 version = "0.2.0"
789 version = "0.2.0"
773 source = "registry+https://github.com/rust-lang/crates.io-index"
790 source = "registry+https://github.com/rust-lang/crates.io-index"
774 checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
791 checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
775 dependencies = [
792 dependencies = [
776 "rand_core 0.5.1",
793 "rand_core 0.5.1",
777 ]
794 ]
778
795
779 [[package]]
796 [[package]]
780 name = "rand_hc"
797 name = "rand_hc"
781 version = "0.3.1"
798 version = "0.3.1"
782 source = "registry+https://github.com/rust-lang/crates.io-index"
799 source = "registry+https://github.com/rust-lang/crates.io-index"
783 checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
800 checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
784 dependencies = [
801 dependencies = [
785 "rand_core 0.6.3",
802 "rand_core 0.6.3",
786 ]
803 ]
787
804
788 [[package]]
805 [[package]]
789 name = "rand_pcg"
806 name = "rand_pcg"
790 version = "0.3.1"
807 version = "0.3.1"
791 source = "registry+https://github.com/rust-lang/crates.io-index"
808 source = "registry+https://github.com/rust-lang/crates.io-index"
792 checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
809 checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
793 dependencies = [
810 dependencies = [
794 "rand_core 0.6.3",
811 "rand_core 0.6.3",
795 ]
812 ]
796
813
797 [[package]]
814 [[package]]
798 name = "rand_xoshiro"
815 name = "rand_xoshiro"
799 version = "0.4.0"
816 version = "0.4.0"
800 source = "registry+https://github.com/rust-lang/crates.io-index"
817 source = "registry+https://github.com/rust-lang/crates.io-index"
801 checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
818 checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
802 dependencies = [
819 dependencies = [
803 "rand_core 0.5.1",
820 "rand_core 0.5.1",
804 ]
821 ]
805
822
806 [[package]]
823 [[package]]
807 name = "rayon"
824 name = "rayon"
808 version = "1.5.0"
825 version = "1.5.0"
809 source = "registry+https://github.com/rust-lang/crates.io-index"
826 source = "registry+https://github.com/rust-lang/crates.io-index"
810 checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
827 checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
811 dependencies = [
828 dependencies = [
812 "autocfg",
829 "autocfg",
813 "crossbeam-deque",
830 "crossbeam-deque",
814 "either",
831 "either",
815 "rayon-core",
832 "rayon-core",
816 ]
833 ]
817
834
818 [[package]]
835 [[package]]
819 name = "rayon-core"
836 name = "rayon-core"
820 version = "1.9.0"
837 version = "1.9.0"
821 source = "registry+https://github.com/rust-lang/crates.io-index"
838 source = "registry+https://github.com/rust-lang/crates.io-index"
822 checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
839 checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
823 dependencies = [
840 dependencies = [
824 "crossbeam-channel 0.5.0",
841 "crossbeam-channel 0.5.0",
825 "crossbeam-deque",
842 "crossbeam-deque",
826 "crossbeam-utils 0.8.1",
843 "crossbeam-utils 0.8.1",
827 "lazy_static",
844 "lazy_static",
828 "num_cpus",
845 "num_cpus",
829 ]
846 ]
830
847
831 [[package]]
848 [[package]]
832 name = "redox_syscall"
849 name = "redox_syscall"
833 version = "0.1.57"
850 version = "0.1.57"
834 source = "registry+https://github.com/rust-lang/crates.io-index"
851 source = "registry+https://github.com/rust-lang/crates.io-index"
835 checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
852 checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
836
853
837 [[package]]
854 [[package]]
838 name = "regex"
855 name = "regex"
839 version = "1.4.2"
856 version = "1.4.2"
840 source = "registry+https://github.com/rust-lang/crates.io-index"
857 source = "registry+https://github.com/rust-lang/crates.io-index"
841 checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
858 checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
842 dependencies = [
859 dependencies = [
843 "aho-corasick",
860 "aho-corasick",
844 "memchr",
861 "memchr",
845 "regex-syntax",
862 "regex-syntax",
846 "thread_local",
863 "thread_local",
847 ]
864 ]
848
865
849 [[package]]
866 [[package]]
850 name = "regex-syntax"
867 name = "regex-syntax"
851 version = "0.6.21"
868 version = "0.6.21"
852 source = "registry+https://github.com/rust-lang/crates.io-index"
869 source = "registry+https://github.com/rust-lang/crates.io-index"
853 checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
870 checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
854
871
855 [[package]]
872 [[package]]
856 name = "remove_dir_all"
873 name = "remove_dir_all"
857 version = "0.5.3"
874 version = "0.5.3"
858 source = "registry+https://github.com/rust-lang/crates.io-index"
875 source = "registry+https://github.com/rust-lang/crates.io-index"
859 checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
876 checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
860 dependencies = [
877 dependencies = [
861 "winapi",
878 "winapi",
862 ]
879 ]
863
880
864 [[package]]
881 [[package]]
865 name = "rhg"
882 name = "rhg"
866 version = "0.1.0"
883 version = "0.1.0"
867 dependencies = [
884 dependencies = [
868 "atty",
885 "atty",
869 "chrono",
886 "chrono",
870 "clap",
887 "clap",
871 "derive_more",
888 "derive_more",
872 "env_logger",
889 "env_logger",
873 "format-bytes",
890 "format-bytes",
874 "hg-core",
891 "hg-core",
875 "home",
892 "home",
876 "lazy_static",
893 "lazy_static",
877 "log",
894 "log",
878 "micro-timer",
895 "micro-timer",
879 "regex",
896 "regex",
880 "users",
897 "users",
881 ]
898 ]
882
899
883 [[package]]
900 [[package]]
884 name = "same-file"
901 name = "same-file"
885 version = "1.0.6"
902 version = "1.0.6"
886 source = "registry+https://github.com/rust-lang/crates.io-index"
903 source = "registry+https://github.com/rust-lang/crates.io-index"
887 checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
904 checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
888 dependencies = [
905 dependencies = [
889 "winapi-util",
906 "winapi-util",
890 ]
907 ]
891
908
892 [[package]]
909 [[package]]
893 name = "scopeguard"
910 name = "scopeguard"
894 version = "1.1.0"
911 version = "1.1.0"
895 source = "registry+https://github.com/rust-lang/crates.io-index"
912 source = "registry+https://github.com/rust-lang/crates.io-index"
896 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
913 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
897
914
898 [[package]]
915 [[package]]
899 name = "sha-1"
916 name = "sha-1"
900 version = "0.9.6"
917 version = "0.9.6"
901 source = "registry+https://github.com/rust-lang/crates.io-index"
918 source = "registry+https://github.com/rust-lang/crates.io-index"
902 checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16"
919 checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16"
903 dependencies = [
920 dependencies = [
904 "block-buffer",
921 "block-buffer",
905 "cfg-if 1.0.0",
922 "cfg-if 1.0.0",
906 "cpufeatures",
923 "cpufeatures",
907 "digest",
924 "digest",
908 "opaque-debug",
925 "opaque-debug",
909 ]
926 ]
910
927
911 [[package]]
928 [[package]]
912 name = "sized-chunks"
929 name = "sized-chunks"
913 version = "0.6.2"
930 version = "0.6.2"
914 source = "registry+https://github.com/rust-lang/crates.io-index"
931 source = "registry+https://github.com/rust-lang/crates.io-index"
915 checksum = "1ec31ceca5644fa6d444cc77548b88b67f46db6f7c71683b0f9336e671830d2f"
932 checksum = "1ec31ceca5644fa6d444cc77548b88b67f46db6f7c71683b0f9336e671830d2f"
916 dependencies = [
933 dependencies = [
917 "bitmaps",
934 "bitmaps",
918 "typenum",
935 "typenum",
919 ]
936 ]
920
937
921 [[package]]
938 [[package]]
922 name = "stable_deref_trait"
939 name = "stable_deref_trait"
923 version = "1.2.0"
940 version = "1.2.0"
924 source = "registry+https://github.com/rust-lang/crates.io-index"
941 source = "registry+https://github.com/rust-lang/crates.io-index"
925 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
942 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
926
943
927 [[package]]
944 [[package]]
928 name = "static_assertions"
945 name = "static_assertions"
929 version = "1.1.0"
946 version = "1.1.0"
930 source = "registry+https://github.com/rust-lang/crates.io-index"
947 source = "registry+https://github.com/rust-lang/crates.io-index"
931 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
948 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
932
949
933 [[package]]
950 [[package]]
934 name = "strsim"
951 name = "strsim"
935 version = "0.8.0"
952 version = "0.8.0"
936 source = "registry+https://github.com/rust-lang/crates.io-index"
953 source = "registry+https://github.com/rust-lang/crates.io-index"
937 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
954 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
938
955
939 [[package]]
956 [[package]]
940 name = "syn"
957 name = "syn"
941 version = "1.0.54"
958 version = "1.0.54"
942 source = "registry+https://github.com/rust-lang/crates.io-index"
959 source = "registry+https://github.com/rust-lang/crates.io-index"
943 checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
960 checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
944 dependencies = [
961 dependencies = [
945 "proc-macro2",
962 "proc-macro2",
946 "quote",
963 "quote",
947 "unicode-xid",
964 "unicode-xid",
948 ]
965 ]
949
966
950 [[package]]
967 [[package]]
951 name = "tempfile"
968 name = "tempfile"
952 version = "3.1.0"
969 version = "3.1.0"
953 source = "registry+https://github.com/rust-lang/crates.io-index"
970 source = "registry+https://github.com/rust-lang/crates.io-index"
954 checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
971 checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
955 dependencies = [
972 dependencies = [
956 "cfg-if 0.1.10",
973 "cfg-if 0.1.10",
957 "libc",
974 "libc",
958 "rand 0.7.3",
975 "rand 0.7.3",
959 "redox_syscall",
976 "redox_syscall",
960 "remove_dir_all",
977 "remove_dir_all",
961 "winapi",
978 "winapi",
962 ]
979 ]
963
980
964 [[package]]
981 [[package]]
965 name = "termcolor"
982 name = "termcolor"
966 version = "1.1.2"
983 version = "1.1.2"
967 source = "registry+https://github.com/rust-lang/crates.io-index"
984 source = "registry+https://github.com/rust-lang/crates.io-index"
968 checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
985 checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
969 dependencies = [
986 dependencies = [
970 "winapi-util",
987 "winapi-util",
971 ]
988 ]
972
989
973 [[package]]
990 [[package]]
974 name = "textwrap"
991 name = "textwrap"
975 version = "0.11.0"
992 version = "0.11.0"
976 source = "registry+https://github.com/rust-lang/crates.io-index"
993 source = "registry+https://github.com/rust-lang/crates.io-index"
977 checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
994 checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
978 dependencies = [
995 dependencies = [
979 "unicode-width",
996 "unicode-width",
980 ]
997 ]
981
998
982 [[package]]
999 [[package]]
983 name = "thread_local"
1000 name = "thread_local"
984 version = "1.0.1"
1001 version = "1.0.1"
985 source = "registry+https://github.com/rust-lang/crates.io-index"
1002 source = "registry+https://github.com/rust-lang/crates.io-index"
986 checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
1003 checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
987 dependencies = [
1004 dependencies = [
988 "lazy_static",
1005 "lazy_static",
989 ]
1006 ]
990
1007
991 [[package]]
1008 [[package]]
992 name = "time"
1009 name = "time"
993 version = "0.1.44"
1010 version = "0.1.44"
994 source = "registry+https://github.com/rust-lang/crates.io-index"
1011 source = "registry+https://github.com/rust-lang/crates.io-index"
995 checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
1012 checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
996 dependencies = [
1013 dependencies = [
997 "libc",
1014 "libc",
998 "wasi 0.10.0+wasi-snapshot-preview1",
1015 "wasi 0.10.0+wasi-snapshot-preview1",
999 "winapi",
1016 "winapi",
1000 ]
1017 ]
1001
1018
1002 [[package]]
1019 [[package]]
1003 name = "twox-hash"
1020 name = "twox-hash"
1004 version = "1.6.0"
1021 version = "1.6.0"
1005 source = "registry+https://github.com/rust-lang/crates.io-index"
1022 source = "registry+https://github.com/rust-lang/crates.io-index"
1006 checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59"
1023 checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59"
1007 dependencies = [
1024 dependencies = [
1008 "cfg-if 0.1.10",
1025 "cfg-if 0.1.10",
1009 "rand 0.7.3",
1026 "rand 0.7.3",
1010 "static_assertions",
1027 "static_assertions",
1011 ]
1028 ]
1012
1029
1013 [[package]]
1030 [[package]]
1014 name = "typenum"
1031 name = "typenum"
1015 version = "1.12.0"
1032 version = "1.12.0"
1016 source = "registry+https://github.com/rust-lang/crates.io-index"
1033 source = "registry+https://github.com/rust-lang/crates.io-index"
1017 checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
1034 checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
1018
1035
1019 [[package]]
1036 [[package]]
1020 name = "unicode-width"
1037 name = "unicode-width"
1021 version = "0.1.8"
1038 version = "0.1.8"
1022 source = "registry+https://github.com/rust-lang/crates.io-index"
1039 source = "registry+https://github.com/rust-lang/crates.io-index"
1023 checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
1040 checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
1024
1041
1025 [[package]]
1042 [[package]]
1026 name = "unicode-xid"
1043 name = "unicode-xid"
1027 version = "0.2.1"
1044 version = "0.2.1"
1028 source = "registry+https://github.com/rust-lang/crates.io-index"
1045 source = "registry+https://github.com/rust-lang/crates.io-index"
1029 checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
1046 checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
1030
1047
1031 [[package]]
1048 [[package]]
1032 name = "users"
1049 name = "users"
1033 version = "0.11.0"
1050 version = "0.11.0"
1034 source = "registry+https://github.com/rust-lang/crates.io-index"
1051 source = "registry+https://github.com/rust-lang/crates.io-index"
1035 checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
1052 checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
1036 dependencies = [
1053 dependencies = [
1037 "libc",
1054 "libc",
1038 "log",
1055 "log",
1039 ]
1056 ]
1040
1057
1041 [[package]]
1058 [[package]]
1042 name = "vcpkg"
1059 name = "vcpkg"
1043 version = "0.2.11"
1060 version = "0.2.11"
1044 source = "registry+https://github.com/rust-lang/crates.io-index"
1061 source = "registry+https://github.com/rust-lang/crates.io-index"
1045 checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
1062 checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
1046
1063
1047 [[package]]
1064 [[package]]
1048 name = "vcsgraph"
1065 name = "vcsgraph"
1049 version = "0.2.0"
1066 version = "0.2.0"
1050 source = "registry+https://github.com/rust-lang/crates.io-index"
1067 source = "registry+https://github.com/rust-lang/crates.io-index"
1051 checksum = "4cb68c231e2575f7503a7c19213875f9d4ec2e84e963a56ce3de4b6bee351ef7"
1068 checksum = "4cb68c231e2575f7503a7c19213875f9d4ec2e84e963a56ce3de4b6bee351ef7"
1052 dependencies = [
1069 dependencies = [
1053 "hex",
1070 "hex",
1054 "rand 0.7.3",
1071 "rand 0.7.3",
1055 "sha-1",
1072 "sha-1",
1056 ]
1073 ]
1057
1074
1058 [[package]]
1075 [[package]]
1059 name = "vec_map"
1076 name = "vec_map"
1060 version = "0.8.2"
1077 version = "0.8.2"
1061 source = "registry+https://github.com/rust-lang/crates.io-index"
1078 source = "registry+https://github.com/rust-lang/crates.io-index"
1062 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1079 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
1063
1080
1064 [[package]]
1081 [[package]]
1065 name = "version_check"
1082 name = "version_check"
1066 version = "0.9.2"
1083 version = "0.9.2"
1067 source = "registry+https://github.com/rust-lang/crates.io-index"
1084 source = "registry+https://github.com/rust-lang/crates.io-index"
1068 checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
1085 checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
1069
1086
1070 [[package]]
1087 [[package]]
1071 name = "wasi"
1088 name = "wasi"
1072 version = "0.9.0+wasi-snapshot-preview1"
1089 version = "0.9.0+wasi-snapshot-preview1"
1073 source = "registry+https://github.com/rust-lang/crates.io-index"
1090 source = "registry+https://github.com/rust-lang/crates.io-index"
1074 checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
1091 checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
1075
1092
1076 [[package]]
1093 [[package]]
1077 name = "wasi"
1094 name = "wasi"
1078 version = "0.10.0+wasi-snapshot-preview1"
1095 version = "0.10.0+wasi-snapshot-preview1"
1079 source = "registry+https://github.com/rust-lang/crates.io-index"
1096 source = "registry+https://github.com/rust-lang/crates.io-index"
1080 checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1097 checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1081
1098
1082 [[package]]
1099 [[package]]
1083 name = "winapi"
1100 name = "winapi"
1084 version = "0.3.9"
1101 version = "0.3.9"
1085 source = "registry+https://github.com/rust-lang/crates.io-index"
1102 source = "registry+https://github.com/rust-lang/crates.io-index"
1086 checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1103 checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1087 dependencies = [
1104 dependencies = [
1088 "winapi-i686-pc-windows-gnu",
1105 "winapi-i686-pc-windows-gnu",
1089 "winapi-x86_64-pc-windows-gnu",
1106 "winapi-x86_64-pc-windows-gnu",
1090 ]
1107 ]
1091
1108
1092 [[package]]
1109 [[package]]
1093 name = "winapi-i686-pc-windows-gnu"
1110 name = "winapi-i686-pc-windows-gnu"
1094 version = "0.4.0"
1111 version = "0.4.0"
1095 source = "registry+https://github.com/rust-lang/crates.io-index"
1112 source = "registry+https://github.com/rust-lang/crates.io-index"
1096 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1113 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1097
1114
1098 [[package]]
1115 [[package]]
1099 name = "winapi-util"
1116 name = "winapi-util"
1100 version = "0.1.5"
1117 version = "0.1.5"
1101 source = "registry+https://github.com/rust-lang/crates.io-index"
1118 source = "registry+https://github.com/rust-lang/crates.io-index"
1102 checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1119 checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1103 dependencies = [
1120 dependencies = [
1104 "winapi",
1121 "winapi",
1105 ]
1122 ]
1106
1123
1107 [[package]]
1124 [[package]]
1108 name = "winapi-x86_64-pc-windows-gnu"
1125 name = "winapi-x86_64-pc-windows-gnu"
1109 version = "0.4.0"
1126 version = "0.4.0"
1110 source = "registry+https://github.com/rust-lang/crates.io-index"
1127 source = "registry+https://github.com/rust-lang/crates.io-index"
1111 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1128 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1112
1129
1113 [[package]]
1130 [[package]]
1114 name = "zstd"
1131 name = "zstd"
1115 version = "0.5.3+zstd.1.4.5"
1132 version = "0.5.3+zstd.1.4.5"
1116 source = "registry+https://github.com/rust-lang/crates.io-index"
1133 source = "registry+https://github.com/rust-lang/crates.io-index"
1117 checksum = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8"
1134 checksum = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8"
1118 dependencies = [
1135 dependencies = [
1119 "zstd-safe",
1136 "zstd-safe",
1120 ]
1137 ]
1121
1138
1122 [[package]]
1139 [[package]]
1123 name = "zstd-safe"
1140 name = "zstd-safe"
1124 version = "2.0.5+zstd.1.4.5"
1141 version = "2.0.5+zstd.1.4.5"
1125 source = "registry+https://github.com/rust-lang/crates.io-index"
1142 source = "registry+https://github.com/rust-lang/crates.io-index"
1126 checksum = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055"
1143 checksum = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055"
1127 dependencies = [
1144 dependencies = [
1128 "libc",
1145 "libc",
1129 "zstd-sys",
1146 "zstd-sys",
1130 ]
1147 ]
1131
1148
1132 [[package]]
1149 [[package]]
1133 name = "zstd-sys"
1150 name = "zstd-sys"
1134 version = "1.4.17+zstd.1.4.5"
1151 version = "1.4.17+zstd.1.4.5"
1135 source = "registry+https://github.com/rust-lang/crates.io-index"
1152 source = "registry+https://github.com/rust-lang/crates.io-index"
1136 checksum = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b"
1153 checksum = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b"
1137 dependencies = [
1154 dependencies = [
1138 "cc",
1155 "cc",
1139 "glob",
1156 "glob",
1140 "itertools",
1157 "itertools",
1141 "libc",
1158 "libc",
1142 ]
1159 ]
@@ -1,47 +1,48 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.2"
12 bitflags = "1.2"
13 bytes-cast = "0.2"
13 bytes-cast = "0.2"
14 byteorder = "1.3.4"
14 byteorder = "1.3.4"
15 derive_more = "0.99"
15 derive_more = "0.99"
16 hashbrown = {version = "0.9.1", features = ["rayon"]}
16 home = "0.5"
17 home = "0.5"
17 im-rc = "15.0.*"
18 im-rc = "15.0.*"
18 itertools = "0.9"
19 itertools = "0.9"
19 lazy_static = "1.4.0"
20 lazy_static = "1.4.0"
20 libc = "0.2"
21 libc = "0.2"
21 rand = "0.8.4"
22 rand = "0.8.4"
22 rand_pcg = "0.3.1"
23 rand_pcg = "0.3.1"
23 rand_distr = "0.4.2"
24 rand_distr = "0.4.2"
24 rayon = "1.3.0"
25 rayon = "1.3.0"
25 regex = "1.3.9"
26 regex = "1.3.9"
26 sha-1 = "0.9.6"
27 sha-1 = "0.9.6"
27 twox-hash = "1.5.0"
28 twox-hash = "1.5.0"
28 same-file = "1.0.6"
29 same-file = "1.0.6"
29 stable_deref_trait = "1.2.0"
30 stable_deref_trait = "1.2.0"
30 tempfile = "3.1.0"
31 tempfile = "3.1.0"
31 crossbeam-channel = "0.4"
32 crossbeam-channel = "0.4"
32 micro-timer = "0.3.0"
33 micro-timer = "0.3.0"
33 log = "0.4.8"
34 log = "0.4.8"
34 memmap2 = {version = "0.4", features = ["stable_deref_trait"]}
35 memmap2 = {version = "0.4", features = ["stable_deref_trait"]}
35 zstd = "0.5.3"
36 zstd = "0.5.3"
36 format-bytes = "0.3.0"
37 format-bytes = "0.3.0"
37
38
38 # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until
39 # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until
39 # we have a clearer view of which backend is the fastest.
40 # we have a clearer view of which backend is the fastest.
40 [dependencies.flate2]
41 [dependencies.flate2]
41 version = "1.0.16"
42 version = "1.0.16"
42 features = ["zlib"]
43 features = ["zlib"]
43 default-features = false
44 default-features = false
44
45
45 [dev-dependencies]
46 [dev-dependencies]
46 clap = "*"
47 clap = "*"
47 pretty_assertions = "0.6.1"
48 pretty_assertions = "0.6.1"
@@ -1,1158 +1,1156 b''
1 use bytes_cast::BytesCast;
1 use bytes_cast::BytesCast;
2 use micro_timer::timed;
2 use micro_timer::timed;
3 use std::borrow::Cow;
3 use std::borrow::Cow;
4 use std::path::PathBuf;
4 use std::path::PathBuf;
5
5
6 use super::on_disk;
6 use super::on_disk;
7 use super::on_disk::DirstateV2ParseError;
7 use super::on_disk::DirstateV2ParseError;
8 use super::owning::OwningDirstateMap;
8 use super::owning::OwningDirstateMap;
9 use super::path_with_basename::WithBasename;
9 use super::path_with_basename::WithBasename;
10 use crate::dirstate::parsers::pack_entry;
10 use crate::dirstate::parsers::pack_entry;
11 use crate::dirstate::parsers::packed_entry_size;
11 use crate::dirstate::parsers::packed_entry_size;
12 use crate::dirstate::parsers::parse_dirstate_entries;
12 use crate::dirstate::parsers::parse_dirstate_entries;
13 use crate::dirstate::CopyMapIter;
13 use crate::dirstate::CopyMapIter;
14 use crate::dirstate::StateMapIter;
14 use crate::dirstate::StateMapIter;
15 use crate::dirstate::TruncatedTimestamp;
15 use crate::dirstate::TruncatedTimestamp;
16 use crate::dirstate::SIZE_FROM_OTHER_PARENT;
16 use crate::dirstate::SIZE_FROM_OTHER_PARENT;
17 use crate::dirstate::SIZE_NON_NORMAL;
17 use crate::dirstate::SIZE_NON_NORMAL;
18 use crate::matchers::Matcher;
18 use crate::matchers::Matcher;
19 use crate::utils::hg_path::{HgPath, HgPathBuf};
19 use crate::utils::hg_path::{HgPath, HgPathBuf};
20 use crate::DirstateEntry;
20 use crate::DirstateEntry;
21 use crate::DirstateError;
21 use crate::DirstateError;
22 use crate::DirstateParents;
22 use crate::DirstateParents;
23 use crate::DirstateStatus;
23 use crate::DirstateStatus;
24 use crate::EntryState;
24 use crate::EntryState;
25 use crate::FastHashMap;
25 use crate::FastHashbrownMap as FastHashMap;
26 use crate::PatternFileWarning;
26 use crate::PatternFileWarning;
27 use crate::StatusError;
27 use crate::StatusError;
28 use crate::StatusOptions;
28 use crate::StatusOptions;
29
29
30 /// Append to an existing data file if the amount of unreachable data (not used
30 /// Append to an existing data file if the amount of unreachable data (not used
31 /// anymore) is less than this fraction of the total amount of existing data.
31 /// anymore) is less than this fraction of the total amount of existing data.
32 const ACCEPTABLE_UNREACHABLE_BYTES_RATIO: f32 = 0.5;
32 const ACCEPTABLE_UNREACHABLE_BYTES_RATIO: f32 = 0.5;
33
33
34 pub struct DirstateMap<'on_disk> {
34 pub struct DirstateMap<'on_disk> {
35 /// Contents of the `.hg/dirstate` file
35 /// Contents of the `.hg/dirstate` file
36 pub(super) on_disk: &'on_disk [u8],
36 pub(super) on_disk: &'on_disk [u8],
37
37
38 pub(super) root: ChildNodes<'on_disk>,
38 pub(super) root: ChildNodes<'on_disk>,
39
39
40 /// Number of nodes anywhere in the tree that have `.entry.is_some()`.
40 /// Number of nodes anywhere in the tree that have `.entry.is_some()`.
41 pub(super) nodes_with_entry_count: u32,
41 pub(super) nodes_with_entry_count: u32,
42
42
43 /// Number of nodes anywhere in the tree that have
43 /// Number of nodes anywhere in the tree that have
44 /// `.copy_source.is_some()`.
44 /// `.copy_source.is_some()`.
45 pub(super) nodes_with_copy_source_count: u32,
45 pub(super) nodes_with_copy_source_count: u32,
46
46
47 /// See on_disk::Header
47 /// See on_disk::Header
48 pub(super) ignore_patterns_hash: on_disk::IgnorePatternsHash,
48 pub(super) ignore_patterns_hash: on_disk::IgnorePatternsHash,
49
49
50 /// How many bytes of `on_disk` are not used anymore
50 /// How many bytes of `on_disk` are not used anymore
51 pub(super) unreachable_bytes: u32,
51 pub(super) unreachable_bytes: u32,
52 }
52 }
53
53
54 /// Using a plain `HgPathBuf` of the full path from the repository root as a
54 /// Using a plain `HgPathBuf` of the full path from the repository root as a
55 /// map key would also work: all paths in a given map have the same parent
55 /// map key would also work: all paths in a given map have the same parent
56 /// path, so comparing full paths gives the same result as comparing base
56 /// path, so comparing full paths gives the same result as comparing base
57 /// names. However `HashMap` would waste time always re-hashing the same
57 /// names. However `HashMap` would waste time always re-hashing the same
58 /// string prefix.
58 /// string prefix.
59 pub(super) type NodeKey<'on_disk> = WithBasename<Cow<'on_disk, HgPath>>;
59 pub(super) type NodeKey<'on_disk> = WithBasename<Cow<'on_disk, HgPath>>;
60
60
61 /// Similar to `&'tree Cow<'on_disk, HgPath>`, but can also be returned
61 /// Similar to `&'tree Cow<'on_disk, HgPath>`, but can also be returned
62 /// for on-disk nodes that don’t actually have a `Cow` to borrow.
62 /// for on-disk nodes that don’t actually have a `Cow` to borrow.
63 pub(super) enum BorrowedPath<'tree, 'on_disk> {
63 pub(super) enum BorrowedPath<'tree, 'on_disk> {
64 InMemory(&'tree HgPathBuf),
64 InMemory(&'tree HgPathBuf),
65 OnDisk(&'on_disk HgPath),
65 OnDisk(&'on_disk HgPath),
66 }
66 }
67
67
68 pub(super) enum ChildNodes<'on_disk> {
68 pub(super) enum ChildNodes<'on_disk> {
69 InMemory(FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>),
69 InMemory(FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>),
70 OnDisk(&'on_disk [on_disk::Node]),
70 OnDisk(&'on_disk [on_disk::Node]),
71 }
71 }
72
72
73 pub(super) enum ChildNodesRef<'tree, 'on_disk> {
73 pub(super) enum ChildNodesRef<'tree, 'on_disk> {
74 InMemory(&'tree FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>),
74 InMemory(&'tree FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>),
75 OnDisk(&'on_disk [on_disk::Node]),
75 OnDisk(&'on_disk [on_disk::Node]),
76 }
76 }
77
77
78 pub(super) enum NodeRef<'tree, 'on_disk> {
78 pub(super) enum NodeRef<'tree, 'on_disk> {
79 InMemory(&'tree NodeKey<'on_disk>, &'tree Node<'on_disk>),
79 InMemory(&'tree NodeKey<'on_disk>, &'tree Node<'on_disk>),
80 OnDisk(&'on_disk on_disk::Node),
80 OnDisk(&'on_disk on_disk::Node),
81 }
81 }
82
82
83 impl<'tree, 'on_disk> BorrowedPath<'tree, 'on_disk> {
83 impl<'tree, 'on_disk> BorrowedPath<'tree, 'on_disk> {
84 pub fn detach_from_tree(&self) -> Cow<'on_disk, HgPath> {
84 pub fn detach_from_tree(&self) -> Cow<'on_disk, HgPath> {
85 match *self {
85 match *self {
86 BorrowedPath::InMemory(in_memory) => Cow::Owned(in_memory.clone()),
86 BorrowedPath::InMemory(in_memory) => Cow::Owned(in_memory.clone()),
87 BorrowedPath::OnDisk(on_disk) => Cow::Borrowed(on_disk),
87 BorrowedPath::OnDisk(on_disk) => Cow::Borrowed(on_disk),
88 }
88 }
89 }
89 }
90 }
90 }
91
91
92 impl<'tree, 'on_disk> std::ops::Deref for BorrowedPath<'tree, 'on_disk> {
92 impl<'tree, 'on_disk> std::ops::Deref for BorrowedPath<'tree, 'on_disk> {
93 type Target = HgPath;
93 type Target = HgPath;
94
94
95 fn deref(&self) -> &HgPath {
95 fn deref(&self) -> &HgPath {
96 match *self {
96 match *self {
97 BorrowedPath::InMemory(in_memory) => in_memory,
97 BorrowedPath::InMemory(in_memory) => in_memory,
98 BorrowedPath::OnDisk(on_disk) => on_disk,
98 BorrowedPath::OnDisk(on_disk) => on_disk,
99 }
99 }
100 }
100 }
101 }
101 }
102
102
103 impl Default for ChildNodes<'_> {
103 impl Default for ChildNodes<'_> {
104 fn default() -> Self {
104 fn default() -> Self {
105 ChildNodes::InMemory(Default::default())
105 ChildNodes::InMemory(Default::default())
106 }
106 }
107 }
107 }
108
108
109 impl<'on_disk> ChildNodes<'on_disk> {
109 impl<'on_disk> ChildNodes<'on_disk> {
110 pub(super) fn as_ref<'tree>(
110 pub(super) fn as_ref<'tree>(
111 &'tree self,
111 &'tree self,
112 ) -> ChildNodesRef<'tree, 'on_disk> {
112 ) -> ChildNodesRef<'tree, 'on_disk> {
113 match self {
113 match self {
114 ChildNodes::InMemory(nodes) => ChildNodesRef::InMemory(nodes),
114 ChildNodes::InMemory(nodes) => ChildNodesRef::InMemory(nodes),
115 ChildNodes::OnDisk(nodes) => ChildNodesRef::OnDisk(nodes),
115 ChildNodes::OnDisk(nodes) => ChildNodesRef::OnDisk(nodes),
116 }
116 }
117 }
117 }
118
118
119 pub(super) fn is_empty(&self) -> bool {
119 pub(super) fn is_empty(&self) -> bool {
120 match self {
120 match self {
121 ChildNodes::InMemory(nodes) => nodes.is_empty(),
121 ChildNodes::InMemory(nodes) => nodes.is_empty(),
122 ChildNodes::OnDisk(nodes) => nodes.is_empty(),
122 ChildNodes::OnDisk(nodes) => nodes.is_empty(),
123 }
123 }
124 }
124 }
125
125
126 fn make_mut(
126 fn make_mut(
127 &mut self,
127 &mut self,
128 on_disk: &'on_disk [u8],
128 on_disk: &'on_disk [u8],
129 unreachable_bytes: &mut u32,
129 unreachable_bytes: &mut u32,
130 ) -> Result<
130 ) -> Result<
131 &mut FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>,
131 &mut FastHashMap<NodeKey<'on_disk>, Node<'on_disk>>,
132 DirstateV2ParseError,
132 DirstateV2ParseError,
133 > {
133 > {
134 match self {
134 match self {
135 ChildNodes::InMemory(nodes) => Ok(nodes),
135 ChildNodes::InMemory(nodes) => Ok(nodes),
136 ChildNodes::OnDisk(nodes) => {
136 ChildNodes::OnDisk(nodes) => {
137 *unreachable_bytes +=
137 *unreachable_bytes +=
138 std::mem::size_of_val::<[on_disk::Node]>(nodes) as u32;
138 std::mem::size_of_val::<[on_disk::Node]>(nodes) as u32;
139 let nodes = nodes
139 let nodes = nodes
140 .iter()
140 .iter()
141 .map(|node| {
141 .map(|node| {
142 Ok((
142 Ok((
143 node.path(on_disk)?,
143 node.path(on_disk)?,
144 node.to_in_memory_node(on_disk)?,
144 node.to_in_memory_node(on_disk)?,
145 ))
145 ))
146 })
146 })
147 .collect::<Result<_, _>>()?;
147 .collect::<Result<_, _>>()?;
148 *self = ChildNodes::InMemory(nodes);
148 *self = ChildNodes::InMemory(nodes);
149 match self {
149 match self {
150 ChildNodes::InMemory(nodes) => Ok(nodes),
150 ChildNodes::InMemory(nodes) => Ok(nodes),
151 ChildNodes::OnDisk(_) => unreachable!(),
151 ChildNodes::OnDisk(_) => unreachable!(),
152 }
152 }
153 }
153 }
154 }
154 }
155 }
155 }
156 }
156 }
157
157
158 impl<'tree, 'on_disk> ChildNodesRef<'tree, 'on_disk> {
158 impl<'tree, 'on_disk> ChildNodesRef<'tree, 'on_disk> {
159 pub(super) fn get(
159 pub(super) fn get(
160 &self,
160 &self,
161 base_name: &HgPath,
161 base_name: &HgPath,
162 on_disk: &'on_disk [u8],
162 on_disk: &'on_disk [u8],
163 ) -> Result<Option<NodeRef<'tree, 'on_disk>>, DirstateV2ParseError> {
163 ) -> Result<Option<NodeRef<'tree, 'on_disk>>, DirstateV2ParseError> {
164 match self {
164 match self {
165 ChildNodesRef::InMemory(nodes) => Ok(nodes
165 ChildNodesRef::InMemory(nodes) => Ok(nodes
166 .get_key_value(base_name)
166 .get_key_value(base_name)
167 .map(|(k, v)| NodeRef::InMemory(k, v))),
167 .map(|(k, v)| NodeRef::InMemory(k, v))),
168 ChildNodesRef::OnDisk(nodes) => {
168 ChildNodesRef::OnDisk(nodes) => {
169 let mut parse_result = Ok(());
169 let mut parse_result = Ok(());
170 let search_result = nodes.binary_search_by(|node| {
170 let search_result = nodes.binary_search_by(|node| {
171 match node.base_name(on_disk) {
171 match node.base_name(on_disk) {
172 Ok(node_base_name) => node_base_name.cmp(base_name),
172 Ok(node_base_name) => node_base_name.cmp(base_name),
173 Err(e) => {
173 Err(e) => {
174 parse_result = Err(e);
174 parse_result = Err(e);
175 // Dummy comparison result, `search_result` won’t
175 // Dummy comparison result, `search_result` won’t
176 // be used since `parse_result` is an error
176 // be used since `parse_result` is an error
177 std::cmp::Ordering::Equal
177 std::cmp::Ordering::Equal
178 }
178 }
179 }
179 }
180 });
180 });
181 parse_result.map(|()| {
181 parse_result.map(|()| {
182 search_result.ok().map(|i| NodeRef::OnDisk(&nodes[i]))
182 search_result.ok().map(|i| NodeRef::OnDisk(&nodes[i]))
183 })
183 })
184 }
184 }
185 }
185 }
186 }
186 }
187
187
188 /// Iterate in undefined order
188 /// Iterate in undefined order
189 pub(super) fn iter(
189 pub(super) fn iter(
190 &self,
190 &self,
191 ) -> impl Iterator<Item = NodeRef<'tree, 'on_disk>> {
191 ) -> impl Iterator<Item = NodeRef<'tree, 'on_disk>> {
192 match self {
192 match self {
193 ChildNodesRef::InMemory(nodes) => itertools::Either::Left(
193 ChildNodesRef::InMemory(nodes) => itertools::Either::Left(
194 nodes.iter().map(|(k, v)| NodeRef::InMemory(k, v)),
194 nodes.iter().map(|(k, v)| NodeRef::InMemory(k, v)),
195 ),
195 ),
196 ChildNodesRef::OnDisk(nodes) => {
196 ChildNodesRef::OnDisk(nodes) => {
197 itertools::Either::Right(nodes.iter().map(NodeRef::OnDisk))
197 itertools::Either::Right(nodes.iter().map(NodeRef::OnDisk))
198 }
198 }
199 }
199 }
200 }
200 }
201
201
202 /// Iterate in parallel in undefined order
202 /// Iterate in parallel in undefined order
203 pub(super) fn par_iter(
203 pub(super) fn par_iter(
204 &self,
204 &self,
205 ) -> impl rayon::iter::ParallelIterator<Item = NodeRef<'tree, 'on_disk>>
205 ) -> impl rayon::iter::ParallelIterator<Item = NodeRef<'tree, 'on_disk>>
206 {
206 {
207 use rayon::prelude::*;
207 use rayon::prelude::*;
208 match self {
208 match self {
209 ChildNodesRef::InMemory(nodes) => rayon::iter::Either::Left(
209 ChildNodesRef::InMemory(nodes) => rayon::iter::Either::Left(
210 nodes.par_iter().map(|(k, v)| NodeRef::InMemory(k, v)),
210 nodes.par_iter().map(|(k, v)| NodeRef::InMemory(k, v)),
211 ),
211 ),
212 ChildNodesRef::OnDisk(nodes) => rayon::iter::Either::Right(
212 ChildNodesRef::OnDisk(nodes) => rayon::iter::Either::Right(
213 nodes.par_iter().map(NodeRef::OnDisk),
213 nodes.par_iter().map(NodeRef::OnDisk),
214 ),
214 ),
215 }
215 }
216 }
216 }
217
217
218 pub(super) fn sorted(&self) -> Vec<NodeRef<'tree, 'on_disk>> {
218 pub(super) fn sorted(&self) -> Vec<NodeRef<'tree, 'on_disk>> {
219 match self {
219 match self {
220 ChildNodesRef::InMemory(nodes) => {
220 ChildNodesRef::InMemory(nodes) => {
221 let mut vec: Vec<_> = nodes
221 let mut vec: Vec<_> = nodes
222 .iter()
222 .iter()
223 .map(|(k, v)| NodeRef::InMemory(k, v))
223 .map(|(k, v)| NodeRef::InMemory(k, v))
224 .collect();
224 .collect();
225 fn sort_key<'a>(node: &'a NodeRef) -> &'a HgPath {
225 fn sort_key<'a>(node: &'a NodeRef) -> &'a HgPath {
226 match node {
226 match node {
227 NodeRef::InMemory(path, _node) => path.base_name(),
227 NodeRef::InMemory(path, _node) => path.base_name(),
228 NodeRef::OnDisk(_) => unreachable!(),
228 NodeRef::OnDisk(_) => unreachable!(),
229 }
229 }
230 }
230 }
231 // `sort_unstable_by_key` doesn’t allow keys borrowing from the
231 // `sort_unstable_by_key` doesn’t allow keys borrowing from the
232 // value: https://github.com/rust-lang/rust/issues/34162
232 // value: https://github.com/rust-lang/rust/issues/34162
233 vec.sort_unstable_by(|a, b| sort_key(a).cmp(sort_key(b)));
233 vec.sort_unstable_by(|a, b| sort_key(a).cmp(sort_key(b)));
234 vec
234 vec
235 }
235 }
236 ChildNodesRef::OnDisk(nodes) => {
236 ChildNodesRef::OnDisk(nodes) => {
237 // Nodes on disk are already sorted
237 // Nodes on disk are already sorted
238 nodes.iter().map(NodeRef::OnDisk).collect()
238 nodes.iter().map(NodeRef::OnDisk).collect()
239 }
239 }
240 }
240 }
241 }
241 }
242 }
242 }
243
243
244 impl<'tree, 'on_disk> NodeRef<'tree, 'on_disk> {
244 impl<'tree, 'on_disk> NodeRef<'tree, 'on_disk> {
245 pub(super) fn full_path(
245 pub(super) fn full_path(
246 &self,
246 &self,
247 on_disk: &'on_disk [u8],
247 on_disk: &'on_disk [u8],
248 ) -> Result<&'tree HgPath, DirstateV2ParseError> {
248 ) -> Result<&'tree HgPath, DirstateV2ParseError> {
249 match self {
249 match self {
250 NodeRef::InMemory(path, _node) => Ok(path.full_path()),
250 NodeRef::InMemory(path, _node) => Ok(path.full_path()),
251 NodeRef::OnDisk(node) => node.full_path(on_disk),
251 NodeRef::OnDisk(node) => node.full_path(on_disk),
252 }
252 }
253 }
253 }
254
254
255 /// Returns a `BorrowedPath`, which can be turned into a `Cow<'on_disk,
255 /// Returns a `BorrowedPath`, which can be turned into a `Cow<'on_disk,
256 /// HgPath>` detached from `'tree`
256 /// HgPath>` detached from `'tree`
257 pub(super) fn full_path_borrowed(
257 pub(super) fn full_path_borrowed(
258 &self,
258 &self,
259 on_disk: &'on_disk [u8],
259 on_disk: &'on_disk [u8],
260 ) -> Result<BorrowedPath<'tree, 'on_disk>, DirstateV2ParseError> {
260 ) -> Result<BorrowedPath<'tree, 'on_disk>, DirstateV2ParseError> {
261 match self {
261 match self {
262 NodeRef::InMemory(path, _node) => match path.full_path() {
262 NodeRef::InMemory(path, _node) => match path.full_path() {
263 Cow::Borrowed(on_disk) => Ok(BorrowedPath::OnDisk(on_disk)),
263 Cow::Borrowed(on_disk) => Ok(BorrowedPath::OnDisk(on_disk)),
264 Cow::Owned(in_memory) => Ok(BorrowedPath::InMemory(in_memory)),
264 Cow::Owned(in_memory) => Ok(BorrowedPath::InMemory(in_memory)),
265 },
265 },
266 NodeRef::OnDisk(node) => {
266 NodeRef::OnDisk(node) => {
267 Ok(BorrowedPath::OnDisk(node.full_path(on_disk)?))
267 Ok(BorrowedPath::OnDisk(node.full_path(on_disk)?))
268 }
268 }
269 }
269 }
270 }
270 }
271
271
272 pub(super) fn base_name(
272 pub(super) fn base_name(
273 &self,
273 &self,
274 on_disk: &'on_disk [u8],
274 on_disk: &'on_disk [u8],
275 ) -> Result<&'tree HgPath, DirstateV2ParseError> {
275 ) -> Result<&'tree HgPath, DirstateV2ParseError> {
276 match self {
276 match self {
277 NodeRef::InMemory(path, _node) => Ok(path.base_name()),
277 NodeRef::InMemory(path, _node) => Ok(path.base_name()),
278 NodeRef::OnDisk(node) => node.base_name(on_disk),
278 NodeRef::OnDisk(node) => node.base_name(on_disk),
279 }
279 }
280 }
280 }
281
281
282 pub(super) fn children(
282 pub(super) fn children(
283 &self,
283 &self,
284 on_disk: &'on_disk [u8],
284 on_disk: &'on_disk [u8],
285 ) -> Result<ChildNodesRef<'tree, 'on_disk>, DirstateV2ParseError> {
285 ) -> Result<ChildNodesRef<'tree, 'on_disk>, DirstateV2ParseError> {
286 match self {
286 match self {
287 NodeRef::InMemory(_path, node) => Ok(node.children.as_ref()),
287 NodeRef::InMemory(_path, node) => Ok(node.children.as_ref()),
288 NodeRef::OnDisk(node) => {
288 NodeRef::OnDisk(node) => {
289 Ok(ChildNodesRef::OnDisk(node.children(on_disk)?))
289 Ok(ChildNodesRef::OnDisk(node.children(on_disk)?))
290 }
290 }
291 }
291 }
292 }
292 }
293
293
294 pub(super) fn has_copy_source(&self) -> bool {
294 pub(super) fn has_copy_source(&self) -> bool {
295 match self {
295 match self {
296 NodeRef::InMemory(_path, node) => node.copy_source.is_some(),
296 NodeRef::InMemory(_path, node) => node.copy_source.is_some(),
297 NodeRef::OnDisk(node) => node.has_copy_source(),
297 NodeRef::OnDisk(node) => node.has_copy_source(),
298 }
298 }
299 }
299 }
300
300
301 pub(super) fn copy_source(
301 pub(super) fn copy_source(
302 &self,
302 &self,
303 on_disk: &'on_disk [u8],
303 on_disk: &'on_disk [u8],
304 ) -> Result<Option<&'tree HgPath>, DirstateV2ParseError> {
304 ) -> Result<Option<&'tree HgPath>, DirstateV2ParseError> {
305 match self {
305 match self {
306 NodeRef::InMemory(_path, node) => {
306 NodeRef::InMemory(_path, node) => {
307 Ok(node.copy_source.as_ref().map(|s| &**s))
307 Ok(node.copy_source.as_ref().map(|s| &**s))
308 }
308 }
309 NodeRef::OnDisk(node) => node.copy_source(on_disk),
309 NodeRef::OnDisk(node) => node.copy_source(on_disk),
310 }
310 }
311 }
311 }
312 /// Returns a `BorrowedPath`, which can be turned into a `Cow<'on_disk,
312 /// Returns a `BorrowedPath`, which can be turned into a `Cow<'on_disk,
313 /// HgPath>` detached from `'tree`
313 /// HgPath>` detached from `'tree`
314 pub(super) fn copy_source_borrowed(
314 pub(super) fn copy_source_borrowed(
315 &self,
315 &self,
316 on_disk: &'on_disk [u8],
316 on_disk: &'on_disk [u8],
317 ) -> Result<Option<BorrowedPath<'tree, 'on_disk>>, DirstateV2ParseError>
317 ) -> Result<Option<BorrowedPath<'tree, 'on_disk>>, DirstateV2ParseError>
318 {
318 {
319 Ok(match self {
319 Ok(match self {
320 NodeRef::InMemory(_path, node) => {
320 NodeRef::InMemory(_path, node) => {
321 node.copy_source.as_ref().map(|source| match source {
321 node.copy_source.as_ref().map(|source| match source {
322 Cow::Borrowed(on_disk) => BorrowedPath::OnDisk(on_disk),
322 Cow::Borrowed(on_disk) => BorrowedPath::OnDisk(on_disk),
323 Cow::Owned(in_memory) => BorrowedPath::InMemory(in_memory),
323 Cow::Owned(in_memory) => BorrowedPath::InMemory(in_memory),
324 })
324 })
325 }
325 }
326 NodeRef::OnDisk(node) => node
326 NodeRef::OnDisk(node) => node
327 .copy_source(on_disk)?
327 .copy_source(on_disk)?
328 .map(|source| BorrowedPath::OnDisk(source)),
328 .map(|source| BorrowedPath::OnDisk(source)),
329 })
329 })
330 }
330 }
331
331
332 pub(super) fn entry(
332 pub(super) fn entry(
333 &self,
333 &self,
334 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> {
334 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> {
335 match self {
335 match self {
336 NodeRef::InMemory(_path, node) => {
336 NodeRef::InMemory(_path, node) => {
337 Ok(node.data.as_entry().copied())
337 Ok(node.data.as_entry().copied())
338 }
338 }
339 NodeRef::OnDisk(node) => node.entry(),
339 NodeRef::OnDisk(node) => node.entry(),
340 }
340 }
341 }
341 }
342
342
343 pub(super) fn state(
343 pub(super) fn state(
344 &self,
344 &self,
345 ) -> Result<Option<EntryState>, DirstateV2ParseError> {
345 ) -> Result<Option<EntryState>, DirstateV2ParseError> {
346 Ok(self.entry()?.map(|e| e.state()))
346 Ok(self.entry()?.map(|e| e.state()))
347 }
347 }
348
348
349 pub(super) fn cached_directory_mtime(
349 pub(super) fn cached_directory_mtime(
350 &self,
350 &self,
351 ) -> Result<Option<TruncatedTimestamp>, DirstateV2ParseError> {
351 ) -> Result<Option<TruncatedTimestamp>, DirstateV2ParseError> {
352 match self {
352 match self {
353 NodeRef::InMemory(_path, node) => Ok(match node.data {
353 NodeRef::InMemory(_path, node) => Ok(match node.data {
354 NodeData::CachedDirectory { mtime } => Some(mtime),
354 NodeData::CachedDirectory { mtime } => Some(mtime),
355 _ => None,
355 _ => None,
356 }),
356 }),
357 NodeRef::OnDisk(node) => node.cached_directory_mtime(),
357 NodeRef::OnDisk(node) => node.cached_directory_mtime(),
358 }
358 }
359 }
359 }
360
360
361 pub(super) fn descendants_with_entry_count(&self) -> u32 {
361 pub(super) fn descendants_with_entry_count(&self) -> u32 {
362 match self {
362 match self {
363 NodeRef::InMemory(_path, node) => {
363 NodeRef::InMemory(_path, node) => {
364 node.descendants_with_entry_count
364 node.descendants_with_entry_count
365 }
365 }
366 NodeRef::OnDisk(node) => node.descendants_with_entry_count.get(),
366 NodeRef::OnDisk(node) => node.descendants_with_entry_count.get(),
367 }
367 }
368 }
368 }
369
369
370 pub(super) fn tracked_descendants_count(&self) -> u32 {
370 pub(super) fn tracked_descendants_count(&self) -> u32 {
371 match self {
371 match self {
372 NodeRef::InMemory(_path, node) => node.tracked_descendants_count,
372 NodeRef::InMemory(_path, node) => node.tracked_descendants_count,
373 NodeRef::OnDisk(node) => node.tracked_descendants_count.get(),
373 NodeRef::OnDisk(node) => node.tracked_descendants_count.get(),
374 }
374 }
375 }
375 }
376 }
376 }
377
377
378 /// Represents a file or a directory
378 /// Represents a file or a directory
379 #[derive(Default)]
379 #[derive(Default)]
380 pub(super) struct Node<'on_disk> {
380 pub(super) struct Node<'on_disk> {
381 pub(super) data: NodeData,
381 pub(super) data: NodeData,
382
382
383 pub(super) copy_source: Option<Cow<'on_disk, HgPath>>,
383 pub(super) copy_source: Option<Cow<'on_disk, HgPath>>,
384
384
385 pub(super) children: ChildNodes<'on_disk>,
385 pub(super) children: ChildNodes<'on_disk>,
386
386
387 /// How many (non-inclusive) descendants of this node have an entry.
387 /// How many (non-inclusive) descendants of this node have an entry.
388 pub(super) descendants_with_entry_count: u32,
388 pub(super) descendants_with_entry_count: u32,
389
389
390 /// How many (non-inclusive) descendants of this node have an entry whose
390 /// How many (non-inclusive) descendants of this node have an entry whose
391 /// state is "tracked".
391 /// state is "tracked".
392 pub(super) tracked_descendants_count: u32,
392 pub(super) tracked_descendants_count: u32,
393 }
393 }
394
394
395 pub(super) enum NodeData {
395 pub(super) enum NodeData {
396 Entry(DirstateEntry),
396 Entry(DirstateEntry),
397 CachedDirectory { mtime: TruncatedTimestamp },
397 CachedDirectory { mtime: TruncatedTimestamp },
398 None,
398 None,
399 }
399 }
400
400
401 impl Default for NodeData {
401 impl Default for NodeData {
402 fn default() -> Self {
402 fn default() -> Self {
403 NodeData::None
403 NodeData::None
404 }
404 }
405 }
405 }
406
406
407 impl NodeData {
407 impl NodeData {
408 fn has_entry(&self) -> bool {
408 fn has_entry(&self) -> bool {
409 match self {
409 match self {
410 NodeData::Entry(_) => true,
410 NodeData::Entry(_) => true,
411 _ => false,
411 _ => false,
412 }
412 }
413 }
413 }
414
414
415 fn as_entry(&self) -> Option<&DirstateEntry> {
415 fn as_entry(&self) -> Option<&DirstateEntry> {
416 match self {
416 match self {
417 NodeData::Entry(entry) => Some(entry),
417 NodeData::Entry(entry) => Some(entry),
418 _ => None,
418 _ => None,
419 }
419 }
420 }
420 }
421 }
421 }
422
422
423 impl<'on_disk> DirstateMap<'on_disk> {
423 impl<'on_disk> DirstateMap<'on_disk> {
424 pub(super) fn empty(on_disk: &'on_disk [u8]) -> Self {
424 pub(super) fn empty(on_disk: &'on_disk [u8]) -> Self {
425 Self {
425 Self {
426 on_disk,
426 on_disk,
427 root: ChildNodes::default(),
427 root: ChildNodes::default(),
428 nodes_with_entry_count: 0,
428 nodes_with_entry_count: 0,
429 nodes_with_copy_source_count: 0,
429 nodes_with_copy_source_count: 0,
430 ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN],
430 ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN],
431 unreachable_bytes: 0,
431 unreachable_bytes: 0,
432 }
432 }
433 }
433 }
434
434
435 #[timed]
435 #[timed]
436 pub fn new_v2(
436 pub fn new_v2(
437 on_disk: &'on_disk [u8],
437 on_disk: &'on_disk [u8],
438 data_size: usize,
438 data_size: usize,
439 metadata: &[u8],
439 metadata: &[u8],
440 ) -> Result<Self, DirstateError> {
440 ) -> Result<Self, DirstateError> {
441 if let Some(data) = on_disk.get(..data_size) {
441 if let Some(data) = on_disk.get(..data_size) {
442 Ok(on_disk::read(data, metadata)?)
442 Ok(on_disk::read(data, metadata)?)
443 } else {
443 } else {
444 Err(DirstateV2ParseError.into())
444 Err(DirstateV2ParseError.into())
445 }
445 }
446 }
446 }
447
447
448 #[timed]
448 #[timed]
449 pub fn new_v1(
449 pub fn new_v1(
450 on_disk: &'on_disk [u8],
450 on_disk: &'on_disk [u8],
451 ) -> Result<(Self, Option<DirstateParents>), DirstateError> {
451 ) -> Result<(Self, Option<DirstateParents>), DirstateError> {
452 let mut map = Self::empty(on_disk);
452 let mut map = Self::empty(on_disk);
453 if map.on_disk.is_empty() {
453 if map.on_disk.is_empty() {
454 return Ok((map, None));
454 return Ok((map, None));
455 }
455 }
456
456
457 let parents = parse_dirstate_entries(
457 let parents = parse_dirstate_entries(
458 map.on_disk,
458 map.on_disk,
459 |path, entry, copy_source| {
459 |path, entry, copy_source| {
460 let tracked = entry.state().is_tracked();
460 let tracked = entry.state().is_tracked();
461 let node = Self::get_or_insert_node(
461 let node = Self::get_or_insert_node(
462 map.on_disk,
462 map.on_disk,
463 &mut map.unreachable_bytes,
463 &mut map.unreachable_bytes,
464 &mut map.root,
464 &mut map.root,
465 path,
465 path,
466 WithBasename::to_cow_borrowed,
466 WithBasename::to_cow_borrowed,
467 |ancestor| {
467 |ancestor| {
468 if tracked {
468 if tracked {
469 ancestor.tracked_descendants_count += 1
469 ancestor.tracked_descendants_count += 1
470 }
470 }
471 ancestor.descendants_with_entry_count += 1
471 ancestor.descendants_with_entry_count += 1
472 },
472 },
473 )?;
473 )?;
474 assert!(
474 assert!(
475 !node.data.has_entry(),
475 !node.data.has_entry(),
476 "duplicate dirstate entry in read"
476 "duplicate dirstate entry in read"
477 );
477 );
478 assert!(
478 assert!(
479 node.copy_source.is_none(),
479 node.copy_source.is_none(),
480 "duplicate dirstate entry in read"
480 "duplicate dirstate entry in read"
481 );
481 );
482 node.data = NodeData::Entry(*entry);
482 node.data = NodeData::Entry(*entry);
483 node.copy_source = copy_source.map(Cow::Borrowed);
483 node.copy_source = copy_source.map(Cow::Borrowed);
484 map.nodes_with_entry_count += 1;
484 map.nodes_with_entry_count += 1;
485 if copy_source.is_some() {
485 if copy_source.is_some() {
486 map.nodes_with_copy_source_count += 1
486 map.nodes_with_copy_source_count += 1
487 }
487 }
488 Ok(())
488 Ok(())
489 },
489 },
490 )?;
490 )?;
491 let parents = Some(parents.clone());
491 let parents = Some(parents.clone());
492
492
493 Ok((map, parents))
493 Ok((map, parents))
494 }
494 }
495
495
496 /// Assuming dirstate-v2 format, returns whether the next write should
496 /// Assuming dirstate-v2 format, returns whether the next write should
497 /// append to the existing data file that contains `self.on_disk` (true),
497 /// append to the existing data file that contains `self.on_disk` (true),
498 /// or create a new data file from scratch (false).
498 /// or create a new data file from scratch (false).
499 pub(super) fn write_should_append(&self) -> bool {
499 pub(super) fn write_should_append(&self) -> bool {
500 let ratio = self.unreachable_bytes as f32 / self.on_disk.len() as f32;
500 let ratio = self.unreachable_bytes as f32 / self.on_disk.len() as f32;
501 ratio < ACCEPTABLE_UNREACHABLE_BYTES_RATIO
501 ratio < ACCEPTABLE_UNREACHABLE_BYTES_RATIO
502 }
502 }
503
503
504 fn get_node<'tree>(
504 fn get_node<'tree>(
505 &'tree self,
505 &'tree self,
506 path: &HgPath,
506 path: &HgPath,
507 ) -> Result<Option<NodeRef<'tree, 'on_disk>>, DirstateV2ParseError> {
507 ) -> Result<Option<NodeRef<'tree, 'on_disk>>, DirstateV2ParseError> {
508 let mut children = self.root.as_ref();
508 let mut children = self.root.as_ref();
509 let mut components = path.components();
509 let mut components = path.components();
510 let mut component =
510 let mut component =
511 components.next().expect("expected at least one components");
511 components.next().expect("expected at least one components");
512 loop {
512 loop {
513 if let Some(child) = children.get(component, self.on_disk)? {
513 if let Some(child) = children.get(component, self.on_disk)? {
514 if let Some(next_component) = components.next() {
514 if let Some(next_component) = components.next() {
515 component = next_component;
515 component = next_component;
516 children = child.children(self.on_disk)?;
516 children = child.children(self.on_disk)?;
517 } else {
517 } else {
518 return Ok(Some(child));
518 return Ok(Some(child));
519 }
519 }
520 } else {
520 } else {
521 return Ok(None);
521 return Ok(None);
522 }
522 }
523 }
523 }
524 }
524 }
525
525
526 /// Returns a mutable reference to the node at `path` if it exists
526 /// Returns a mutable reference to the node at `path` if it exists
527 ///
527 ///
528 /// This takes `root` instead of `&mut self` so that callers can mutate
528 /// This takes `root` instead of `&mut self` so that callers can mutate
529 /// other fields while the returned borrow is still valid
529 /// other fields while the returned borrow is still valid
530 fn get_node_mut<'tree>(
530 fn get_node_mut<'tree>(
531 on_disk: &'on_disk [u8],
531 on_disk: &'on_disk [u8],
532 unreachable_bytes: &mut u32,
532 unreachable_bytes: &mut u32,
533 root: &'tree mut ChildNodes<'on_disk>,
533 root: &'tree mut ChildNodes<'on_disk>,
534 path: &HgPath,
534 path: &HgPath,
535 ) -> Result<Option<&'tree mut Node<'on_disk>>, DirstateV2ParseError> {
535 ) -> Result<Option<&'tree mut Node<'on_disk>>, DirstateV2ParseError> {
536 let mut children = root;
536 let mut children = root;
537 let mut components = path.components();
537 let mut components = path.components();
538 let mut component =
538 let mut component =
539 components.next().expect("expected at least one components");
539 components.next().expect("expected at least one components");
540 loop {
540 loop {
541 if let Some(child) = children
541 if let Some(child) = children
542 .make_mut(on_disk, unreachable_bytes)?
542 .make_mut(on_disk, unreachable_bytes)?
543 .get_mut(component)
543 .get_mut(component)
544 {
544 {
545 if let Some(next_component) = components.next() {
545 if let Some(next_component) = components.next() {
546 component = next_component;
546 component = next_component;
547 children = &mut child.children;
547 children = &mut child.children;
548 } else {
548 } else {
549 return Ok(Some(child));
549 return Ok(Some(child));
550 }
550 }
551 } else {
551 } else {
552 return Ok(None);
552 return Ok(None);
553 }
553 }
554 }
554 }
555 }
555 }
556
556
557 pub(super) fn get_or_insert<'tree, 'path>(
557 pub(super) fn get_or_insert<'tree, 'path>(
558 &'tree mut self,
558 &'tree mut self,
559 path: &HgPath,
559 path: &HgPath,
560 ) -> Result<&'tree mut Node<'on_disk>, DirstateV2ParseError> {
560 ) -> Result<&'tree mut Node<'on_disk>, DirstateV2ParseError> {
561 Self::get_or_insert_node(
561 Self::get_or_insert_node(
562 self.on_disk,
562 self.on_disk,
563 &mut self.unreachable_bytes,
563 &mut self.unreachable_bytes,
564 &mut self.root,
564 &mut self.root,
565 path,
565 path,
566 WithBasename::to_cow_owned,
566 WithBasename::to_cow_owned,
567 |_| {},
567 |_| {},
568 )
568 )
569 }
569 }
570
570
571 fn get_or_insert_node<'tree, 'path>(
571 fn get_or_insert_node<'tree, 'path>(
572 on_disk: &'on_disk [u8],
572 on_disk: &'on_disk [u8],
573 unreachable_bytes: &mut u32,
573 unreachable_bytes: &mut u32,
574 root: &'tree mut ChildNodes<'on_disk>,
574 root: &'tree mut ChildNodes<'on_disk>,
575 path: &'path HgPath,
575 path: &'path HgPath,
576 to_cow: impl Fn(
576 to_cow: impl Fn(
577 WithBasename<&'path HgPath>,
577 WithBasename<&'path HgPath>,
578 ) -> WithBasename<Cow<'on_disk, HgPath>>,
578 ) -> WithBasename<Cow<'on_disk, HgPath>>,
579 mut each_ancestor: impl FnMut(&mut Node),
579 mut each_ancestor: impl FnMut(&mut Node),
580 ) -> Result<&'tree mut Node<'on_disk>, DirstateV2ParseError> {
580 ) -> Result<&'tree mut Node<'on_disk>, DirstateV2ParseError> {
581 let mut child_nodes = root;
581 let mut child_nodes = root;
582 let mut inclusive_ancestor_paths =
582 let mut inclusive_ancestor_paths =
583 WithBasename::inclusive_ancestors_of(path);
583 WithBasename::inclusive_ancestors_of(path);
584 let mut ancestor_path = inclusive_ancestor_paths
584 let mut ancestor_path = inclusive_ancestor_paths
585 .next()
585 .next()
586 .expect("expected at least one inclusive ancestor");
586 .expect("expected at least one inclusive ancestor");
587 loop {
587 loop {
588 // TODO: can we avoid allocating an owned key in cases where the
588 let (_, child_node) = child_nodes
589 // map already contains that key, without introducing double
590 // lookup?
591 let child_node = child_nodes
592 .make_mut(on_disk, unreachable_bytes)?
589 .make_mut(on_disk, unreachable_bytes)?
593 .entry(to_cow(ancestor_path))
590 .raw_entry_mut()
594 .or_default();
591 .from_key(ancestor_path.base_name())
592 .or_insert_with(|| (to_cow(ancestor_path), Node::default()));
595 if let Some(next) = inclusive_ancestor_paths.next() {
593 if let Some(next) = inclusive_ancestor_paths.next() {
596 each_ancestor(child_node);
594 each_ancestor(child_node);
597 ancestor_path = next;
595 ancestor_path = next;
598 child_nodes = &mut child_node.children;
596 child_nodes = &mut child_node.children;
599 } else {
597 } else {
600 return Ok(child_node);
598 return Ok(child_node);
601 }
599 }
602 }
600 }
603 }
601 }
604
602
605 fn add_or_remove_file(
603 fn add_or_remove_file(
606 &mut self,
604 &mut self,
607 path: &HgPath,
605 path: &HgPath,
608 old_state: Option<EntryState>,
606 old_state: Option<EntryState>,
609 new_entry: DirstateEntry,
607 new_entry: DirstateEntry,
610 ) -> Result<(), DirstateV2ParseError> {
608 ) -> Result<(), DirstateV2ParseError> {
611 let had_entry = old_state.is_some();
609 let had_entry = old_state.is_some();
612 let was_tracked = old_state.map_or(false, |s| s.is_tracked());
610 let was_tracked = old_state.map_or(false, |s| s.is_tracked());
613 let tracked_count_increment =
611 let tracked_count_increment =
614 match (was_tracked, new_entry.state().is_tracked()) {
612 match (was_tracked, new_entry.state().is_tracked()) {
615 (false, true) => 1,
613 (false, true) => 1,
616 (true, false) => -1,
614 (true, false) => -1,
617 _ => 0,
615 _ => 0,
618 };
616 };
619
617
620 let node = Self::get_or_insert_node(
618 let node = Self::get_or_insert_node(
621 self.on_disk,
619 self.on_disk,
622 &mut self.unreachable_bytes,
620 &mut self.unreachable_bytes,
623 &mut self.root,
621 &mut self.root,
624 path,
622 path,
625 WithBasename::to_cow_owned,
623 WithBasename::to_cow_owned,
626 |ancestor| {
624 |ancestor| {
627 if !had_entry {
625 if !had_entry {
628 ancestor.descendants_with_entry_count += 1;
626 ancestor.descendants_with_entry_count += 1;
629 }
627 }
630
628
631 // We can’t use `+= increment` because the counter is unsigned,
629 // We can’t use `+= increment` because the counter is unsigned,
632 // and we want debug builds to detect accidental underflow
630 // and we want debug builds to detect accidental underflow
633 // through zero
631 // through zero
634 match tracked_count_increment {
632 match tracked_count_increment {
635 1 => ancestor.tracked_descendants_count += 1,
633 1 => ancestor.tracked_descendants_count += 1,
636 -1 => ancestor.tracked_descendants_count -= 1,
634 -1 => ancestor.tracked_descendants_count -= 1,
637 _ => {}
635 _ => {}
638 }
636 }
639 },
637 },
640 )?;
638 )?;
641 if !had_entry {
639 if !had_entry {
642 self.nodes_with_entry_count += 1
640 self.nodes_with_entry_count += 1
643 }
641 }
644 node.data = NodeData::Entry(new_entry);
642 node.data = NodeData::Entry(new_entry);
645 Ok(())
643 Ok(())
646 }
644 }
647
645
648 fn iter_nodes<'tree>(
646 fn iter_nodes<'tree>(
649 &'tree self,
647 &'tree self,
650 ) -> impl Iterator<
648 ) -> impl Iterator<
651 Item = Result<NodeRef<'tree, 'on_disk>, DirstateV2ParseError>,
649 Item = Result<NodeRef<'tree, 'on_disk>, DirstateV2ParseError>,
652 > + 'tree {
650 > + 'tree {
653 // Depth first tree traversal.
651 // Depth first tree traversal.
654 //
652 //
655 // If we could afford internal iteration and recursion,
653 // If we could afford internal iteration and recursion,
656 // this would look like:
654 // this would look like:
657 //
655 //
658 // ```
656 // ```
659 // fn traverse_children(
657 // fn traverse_children(
660 // children: &ChildNodes,
658 // children: &ChildNodes,
661 // each: &mut impl FnMut(&Node),
659 // each: &mut impl FnMut(&Node),
662 // ) {
660 // ) {
663 // for child in children.values() {
661 // for child in children.values() {
664 // traverse_children(&child.children, each);
662 // traverse_children(&child.children, each);
665 // each(child);
663 // each(child);
666 // }
664 // }
667 // }
665 // }
668 // ```
666 // ```
669 //
667 //
670 // However we want an external iterator and therefore can’t use the
668 // However we want an external iterator and therefore can’t use the
671 // call stack. Use an explicit stack instead:
669 // call stack. Use an explicit stack instead:
672 let mut stack = Vec::new();
670 let mut stack = Vec::new();
673 let mut iter = self.root.as_ref().iter();
671 let mut iter = self.root.as_ref().iter();
674 std::iter::from_fn(move || {
672 std::iter::from_fn(move || {
675 while let Some(child_node) = iter.next() {
673 while let Some(child_node) = iter.next() {
676 let children = match child_node.children(self.on_disk) {
674 let children = match child_node.children(self.on_disk) {
677 Ok(children) => children,
675 Ok(children) => children,
678 Err(error) => return Some(Err(error)),
676 Err(error) => return Some(Err(error)),
679 };
677 };
680 // Pseudo-recursion
678 // Pseudo-recursion
681 let new_iter = children.iter();
679 let new_iter = children.iter();
682 let old_iter = std::mem::replace(&mut iter, new_iter);
680 let old_iter = std::mem::replace(&mut iter, new_iter);
683 stack.push((child_node, old_iter));
681 stack.push((child_node, old_iter));
684 }
682 }
685 // Found the end of a `children.iter()` iterator.
683 // Found the end of a `children.iter()` iterator.
686 if let Some((child_node, next_iter)) = stack.pop() {
684 if let Some((child_node, next_iter)) = stack.pop() {
687 // "Return" from pseudo-recursion by restoring state from the
685 // "Return" from pseudo-recursion by restoring state from the
688 // explicit stack
686 // explicit stack
689 iter = next_iter;
687 iter = next_iter;
690
688
691 Some(Ok(child_node))
689 Some(Ok(child_node))
692 } else {
690 } else {
693 // Reached the bottom of the stack, we’re done
691 // Reached the bottom of the stack, we’re done
694 None
692 None
695 }
693 }
696 })
694 })
697 }
695 }
698
696
699 fn count_dropped_path(unreachable_bytes: &mut u32, path: &Cow<HgPath>) {
697 fn count_dropped_path(unreachable_bytes: &mut u32, path: &Cow<HgPath>) {
700 if let Cow::Borrowed(path) = path {
698 if let Cow::Borrowed(path) = path {
701 *unreachable_bytes += path.len() as u32
699 *unreachable_bytes += path.len() as u32
702 }
700 }
703 }
701 }
704 }
702 }
705
703
706 /// Like `Iterator::filter_map`, but over a fallible iterator of `Result`s.
704 /// Like `Iterator::filter_map`, but over a fallible iterator of `Result`s.
707 ///
705 ///
708 /// The callback is only called for incoming `Ok` values. Errors are passed
706 /// The callback is only called for incoming `Ok` values. Errors are passed
709 /// through as-is. In order to let it use the `?` operator the callback is
707 /// through as-is. In order to let it use the `?` operator the callback is
710 /// expected to return a `Result` of `Option`, instead of an `Option` of
708 /// expected to return a `Result` of `Option`, instead of an `Option` of
711 /// `Result`.
709 /// `Result`.
712 fn filter_map_results<'a, I, F, A, B, E>(
710 fn filter_map_results<'a, I, F, A, B, E>(
713 iter: I,
711 iter: I,
714 f: F,
712 f: F,
715 ) -> impl Iterator<Item = Result<B, E>> + 'a
713 ) -> impl Iterator<Item = Result<B, E>> + 'a
716 where
714 where
717 I: Iterator<Item = Result<A, E>> + 'a,
715 I: Iterator<Item = Result<A, E>> + 'a,
718 F: Fn(A) -> Result<Option<B>, E> + 'a,
716 F: Fn(A) -> Result<Option<B>, E> + 'a,
719 {
717 {
720 iter.filter_map(move |result| match result {
718 iter.filter_map(move |result| match result {
721 Ok(node) => f(node).transpose(),
719 Ok(node) => f(node).transpose(),
722 Err(e) => Some(Err(e)),
720 Err(e) => Some(Err(e)),
723 })
721 })
724 }
722 }
725
723
726 impl OwningDirstateMap {
724 impl OwningDirstateMap {
727 pub fn clear(&mut self) {
725 pub fn clear(&mut self) {
728 let map = self.get_map_mut();
726 let map = self.get_map_mut();
729 map.root = Default::default();
727 map.root = Default::default();
730 map.nodes_with_entry_count = 0;
728 map.nodes_with_entry_count = 0;
731 map.nodes_with_copy_source_count = 0;
729 map.nodes_with_copy_source_count = 0;
732 }
730 }
733
731
734 pub fn set_entry(
732 pub fn set_entry(
735 &mut self,
733 &mut self,
736 filename: &HgPath,
734 filename: &HgPath,
737 entry: DirstateEntry,
735 entry: DirstateEntry,
738 ) -> Result<(), DirstateV2ParseError> {
736 ) -> Result<(), DirstateV2ParseError> {
739 let map = self.get_map_mut();
737 let map = self.get_map_mut();
740 map.get_or_insert(&filename)?.data = NodeData::Entry(entry);
738 map.get_or_insert(&filename)?.data = NodeData::Entry(entry);
741 Ok(())
739 Ok(())
742 }
740 }
743
741
744 pub fn add_file(
742 pub fn add_file(
745 &mut self,
743 &mut self,
746 filename: &HgPath,
744 filename: &HgPath,
747 entry: DirstateEntry,
745 entry: DirstateEntry,
748 ) -> Result<(), DirstateError> {
746 ) -> Result<(), DirstateError> {
749 let old_state = self.get(filename)?.map(|e| e.state());
747 let old_state = self.get(filename)?.map(|e| e.state());
750 let map = self.get_map_mut();
748 let map = self.get_map_mut();
751 Ok(map.add_or_remove_file(filename, old_state, entry)?)
749 Ok(map.add_or_remove_file(filename, old_state, entry)?)
752 }
750 }
753
751
754 pub fn remove_file(
752 pub fn remove_file(
755 &mut self,
753 &mut self,
756 filename: &HgPath,
754 filename: &HgPath,
757 in_merge: bool,
755 in_merge: bool,
758 ) -> Result<(), DirstateError> {
756 ) -> Result<(), DirstateError> {
759 let old_entry_opt = self.get(filename)?;
757 let old_entry_opt = self.get(filename)?;
760 let old_state = old_entry_opt.map(|e| e.state());
758 let old_state = old_entry_opt.map(|e| e.state());
761 let mut size = 0;
759 let mut size = 0;
762 if in_merge {
760 if in_merge {
763 // XXX we should not be able to have 'm' state and 'FROM_P2' if not
761 // XXX we should not be able to have 'm' state and 'FROM_P2' if not
764 // during a merge. So I (marmoute) am not sure we need the
762 // during a merge. So I (marmoute) am not sure we need the
765 // conditionnal at all. Adding double checking this with assert
763 // conditionnal at all. Adding double checking this with assert
766 // would be nice.
764 // would be nice.
767 if let Some(old_entry) = old_entry_opt {
765 if let Some(old_entry) = old_entry_opt {
768 // backup the previous state
766 // backup the previous state
769 if old_entry.state() == EntryState::Merged {
767 if old_entry.state() == EntryState::Merged {
770 size = SIZE_NON_NORMAL;
768 size = SIZE_NON_NORMAL;
771 } else if old_entry.state() == EntryState::Normal
769 } else if old_entry.state() == EntryState::Normal
772 && old_entry.size() == SIZE_FROM_OTHER_PARENT
770 && old_entry.size() == SIZE_FROM_OTHER_PARENT
773 {
771 {
774 // other parent
772 // other parent
775 size = SIZE_FROM_OTHER_PARENT;
773 size = SIZE_FROM_OTHER_PARENT;
776 }
774 }
777 }
775 }
778 }
776 }
779 if size == 0 {
777 if size == 0 {
780 self.copy_map_remove(filename)?;
778 self.copy_map_remove(filename)?;
781 }
779 }
782 let map = self.get_map_mut();
780 let map = self.get_map_mut();
783 let entry = DirstateEntry::new_removed(size);
781 let entry = DirstateEntry::new_removed(size);
784 Ok(map.add_or_remove_file(filename, old_state, entry)?)
782 Ok(map.add_or_remove_file(filename, old_state, entry)?)
785 }
783 }
786
784
787 pub fn drop_entry_and_copy_source(
785 pub fn drop_entry_and_copy_source(
788 &mut self,
786 &mut self,
789 filename: &HgPath,
787 filename: &HgPath,
790 ) -> Result<(), DirstateError> {
788 ) -> Result<(), DirstateError> {
791 let was_tracked = self
789 let was_tracked = self
792 .get(filename)?
790 .get(filename)?
793 .map_or(false, |e| e.state().is_tracked());
791 .map_or(false, |e| e.state().is_tracked());
794 let map = self.get_map_mut();
792 let map = self.get_map_mut();
795 struct Dropped {
793 struct Dropped {
796 was_tracked: bool,
794 was_tracked: bool,
797 had_entry: bool,
795 had_entry: bool,
798 had_copy_source: bool,
796 had_copy_source: bool,
799 }
797 }
800
798
801 /// If this returns `Ok(Some((dropped, removed)))`, then
799 /// If this returns `Ok(Some((dropped, removed)))`, then
802 ///
800 ///
803 /// * `dropped` is about the leaf node that was at `filename`
801 /// * `dropped` is about the leaf node that was at `filename`
804 /// * `removed` is whether this particular level of recursion just
802 /// * `removed` is whether this particular level of recursion just
805 /// removed a node in `nodes`.
803 /// removed a node in `nodes`.
806 fn recur<'on_disk>(
804 fn recur<'on_disk>(
807 on_disk: &'on_disk [u8],
805 on_disk: &'on_disk [u8],
808 unreachable_bytes: &mut u32,
806 unreachable_bytes: &mut u32,
809 nodes: &mut ChildNodes<'on_disk>,
807 nodes: &mut ChildNodes<'on_disk>,
810 path: &HgPath,
808 path: &HgPath,
811 ) -> Result<Option<(Dropped, bool)>, DirstateV2ParseError> {
809 ) -> Result<Option<(Dropped, bool)>, DirstateV2ParseError> {
812 let (first_path_component, rest_of_path) =
810 let (first_path_component, rest_of_path) =
813 path.split_first_component();
811 path.split_first_component();
814 let nodes = nodes.make_mut(on_disk, unreachable_bytes)?;
812 let nodes = nodes.make_mut(on_disk, unreachable_bytes)?;
815 let node = if let Some(node) = nodes.get_mut(first_path_component)
813 let node = if let Some(node) = nodes.get_mut(first_path_component)
816 {
814 {
817 node
815 node
818 } else {
816 } else {
819 return Ok(None);
817 return Ok(None);
820 };
818 };
821 let dropped;
819 let dropped;
822 if let Some(rest) = rest_of_path {
820 if let Some(rest) = rest_of_path {
823 if let Some((d, removed)) = recur(
821 if let Some((d, removed)) = recur(
824 on_disk,
822 on_disk,
825 unreachable_bytes,
823 unreachable_bytes,
826 &mut node.children,
824 &mut node.children,
827 rest,
825 rest,
828 )? {
826 )? {
829 dropped = d;
827 dropped = d;
830 if dropped.had_entry {
828 if dropped.had_entry {
831 node.descendants_with_entry_count -= 1;
829 node.descendants_with_entry_count -= 1;
832 }
830 }
833 if dropped.was_tracked {
831 if dropped.was_tracked {
834 node.tracked_descendants_count -= 1;
832 node.tracked_descendants_count -= 1;
835 }
833 }
836
834
837 // Directory caches must be invalidated when removing a
835 // Directory caches must be invalidated when removing a
838 // child node
836 // child node
839 if removed {
837 if removed {
840 if let NodeData::CachedDirectory { .. } = &node.data {
838 if let NodeData::CachedDirectory { .. } = &node.data {
841 node.data = NodeData::None
839 node.data = NodeData::None
842 }
840 }
843 }
841 }
844 } else {
842 } else {
845 return Ok(None);
843 return Ok(None);
846 }
844 }
847 } else {
845 } else {
848 let had_entry = node.data.has_entry();
846 let had_entry = node.data.has_entry();
849 if had_entry {
847 if had_entry {
850 node.data = NodeData::None
848 node.data = NodeData::None
851 }
849 }
852 if let Some(source) = &node.copy_source {
850 if let Some(source) = &node.copy_source {
853 DirstateMap::count_dropped_path(unreachable_bytes, source);
851 DirstateMap::count_dropped_path(unreachable_bytes, source);
854 node.copy_source = None
852 node.copy_source = None
855 }
853 }
856 dropped = Dropped {
854 dropped = Dropped {
857 was_tracked: node
855 was_tracked: node
858 .data
856 .data
859 .as_entry()
857 .as_entry()
860 .map_or(false, |entry| entry.state().is_tracked()),
858 .map_or(false, |entry| entry.state().is_tracked()),
861 had_entry,
859 had_entry,
862 had_copy_source: node.copy_source.take().is_some(),
860 had_copy_source: node.copy_source.take().is_some(),
863 };
861 };
864 }
862 }
865 // After recursion, for both leaf (rest_of_path is None) nodes and
863 // After recursion, for both leaf (rest_of_path is None) nodes and
866 // parent nodes, remove a node if it just became empty.
864 // parent nodes, remove a node if it just became empty.
867 let remove = !node.data.has_entry()
865 let remove = !node.data.has_entry()
868 && node.copy_source.is_none()
866 && node.copy_source.is_none()
869 && node.children.is_empty();
867 && node.children.is_empty();
870 if remove {
868 if remove {
871 let (key, _) =
869 let (key, _) =
872 nodes.remove_entry(first_path_component).unwrap();
870 nodes.remove_entry(first_path_component).unwrap();
873 DirstateMap::count_dropped_path(
871 DirstateMap::count_dropped_path(
874 unreachable_bytes,
872 unreachable_bytes,
875 key.full_path(),
873 key.full_path(),
876 )
874 )
877 }
875 }
878 Ok(Some((dropped, remove)))
876 Ok(Some((dropped, remove)))
879 }
877 }
880
878
881 if let Some((dropped, _removed)) = recur(
879 if let Some((dropped, _removed)) = recur(
882 map.on_disk,
880 map.on_disk,
883 &mut map.unreachable_bytes,
881 &mut map.unreachable_bytes,
884 &mut map.root,
882 &mut map.root,
885 filename,
883 filename,
886 )? {
884 )? {
887 if dropped.had_entry {
885 if dropped.had_entry {
888 map.nodes_with_entry_count -= 1
886 map.nodes_with_entry_count -= 1
889 }
887 }
890 if dropped.had_copy_source {
888 if dropped.had_copy_source {
891 map.nodes_with_copy_source_count -= 1
889 map.nodes_with_copy_source_count -= 1
892 }
890 }
893 } else {
891 } else {
894 debug_assert!(!was_tracked);
892 debug_assert!(!was_tracked);
895 }
893 }
896 Ok(())
894 Ok(())
897 }
895 }
898
896
899 pub fn has_tracked_dir(
897 pub fn has_tracked_dir(
900 &mut self,
898 &mut self,
901 directory: &HgPath,
899 directory: &HgPath,
902 ) -> Result<bool, DirstateError> {
900 ) -> Result<bool, DirstateError> {
903 let map = self.get_map_mut();
901 let map = self.get_map_mut();
904 if let Some(node) = map.get_node(directory)? {
902 if let Some(node) = map.get_node(directory)? {
905 // A node without a `DirstateEntry` was created to hold child
903 // A node without a `DirstateEntry` was created to hold child
906 // nodes, and is therefore a directory.
904 // nodes, and is therefore a directory.
907 let state = node.state()?;
905 let state = node.state()?;
908 Ok(state.is_none() && node.tracked_descendants_count() > 0)
906 Ok(state.is_none() && node.tracked_descendants_count() > 0)
909 } else {
907 } else {
910 Ok(false)
908 Ok(false)
911 }
909 }
912 }
910 }
913
911
914 pub fn has_dir(
912 pub fn has_dir(
915 &mut self,
913 &mut self,
916 directory: &HgPath,
914 directory: &HgPath,
917 ) -> Result<bool, DirstateError> {
915 ) -> Result<bool, DirstateError> {
918 let map = self.get_map_mut();
916 let map = self.get_map_mut();
919 if let Some(node) = map.get_node(directory)? {
917 if let Some(node) = map.get_node(directory)? {
920 // A node without a `DirstateEntry` was created to hold child
918 // A node without a `DirstateEntry` was created to hold child
921 // nodes, and is therefore a directory.
919 // nodes, and is therefore a directory.
922 let state = node.state()?;
920 let state = node.state()?;
923 Ok(state.is_none() && node.descendants_with_entry_count() > 0)
921 Ok(state.is_none() && node.descendants_with_entry_count() > 0)
924 } else {
922 } else {
925 Ok(false)
923 Ok(false)
926 }
924 }
927 }
925 }
928
926
929 #[timed]
927 #[timed]
930 pub fn pack_v1(
928 pub fn pack_v1(
931 &self,
929 &self,
932 parents: DirstateParents,
930 parents: DirstateParents,
933 ) -> Result<Vec<u8>, DirstateError> {
931 ) -> Result<Vec<u8>, DirstateError> {
934 let map = self.get_map();
932 let map = self.get_map();
935 // Optizimation (to be measured?): pre-compute size to avoid `Vec`
933 // Optizimation (to be measured?): pre-compute size to avoid `Vec`
936 // reallocations
934 // reallocations
937 let mut size = parents.as_bytes().len();
935 let mut size = parents.as_bytes().len();
938 for node in map.iter_nodes() {
936 for node in map.iter_nodes() {
939 let node = node?;
937 let node = node?;
940 if node.entry()?.is_some() {
938 if node.entry()?.is_some() {
941 size += packed_entry_size(
939 size += packed_entry_size(
942 node.full_path(map.on_disk)?,
940 node.full_path(map.on_disk)?,
943 node.copy_source(map.on_disk)?,
941 node.copy_source(map.on_disk)?,
944 );
942 );
945 }
943 }
946 }
944 }
947
945
948 let mut packed = Vec::with_capacity(size);
946 let mut packed = Vec::with_capacity(size);
949 packed.extend(parents.as_bytes());
947 packed.extend(parents.as_bytes());
950
948
951 for node in map.iter_nodes() {
949 for node in map.iter_nodes() {
952 let node = node?;
950 let node = node?;
953 if let Some(entry) = node.entry()? {
951 if let Some(entry) = node.entry()? {
954 pack_entry(
952 pack_entry(
955 node.full_path(map.on_disk)?,
953 node.full_path(map.on_disk)?,
956 &entry,
954 &entry,
957 node.copy_source(map.on_disk)?,
955 node.copy_source(map.on_disk)?,
958 &mut packed,
956 &mut packed,
959 );
957 );
960 }
958 }
961 }
959 }
962 Ok(packed)
960 Ok(packed)
963 }
961 }
964
962
965 /// Returns new data and metadata together with whether that data should be
963 /// Returns new data and metadata together with whether that data should be
966 /// appended to the existing data file whose content is at
964 /// appended to the existing data file whose content is at
967 /// `map.on_disk` (true), instead of written to a new data file
965 /// `map.on_disk` (true), instead of written to a new data file
968 /// (false).
966 /// (false).
969 #[timed]
967 #[timed]
970 pub fn pack_v2(
968 pub fn pack_v2(
971 &self,
969 &self,
972 can_append: bool,
970 can_append: bool,
973 ) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool), DirstateError> {
971 ) -> Result<(Vec<u8>, on_disk::TreeMetadata, bool), DirstateError> {
974 let map = self.get_map();
972 let map = self.get_map();
975 on_disk::write(map, can_append)
973 on_disk::write(map, can_append)
976 }
974 }
977
975
978 pub fn status<'a>(
976 pub fn status<'a>(
979 &'a mut self,
977 &'a mut self,
980 matcher: &'a (dyn Matcher + Sync),
978 matcher: &'a (dyn Matcher + Sync),
981 root_dir: PathBuf,
979 root_dir: PathBuf,
982 ignore_files: Vec<PathBuf>,
980 ignore_files: Vec<PathBuf>,
983 options: StatusOptions,
981 options: StatusOptions,
984 ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>
982 ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>
985 {
983 {
986 let map = self.get_map_mut();
984 let map = self.get_map_mut();
987 super::status::status(map, matcher, root_dir, ignore_files, options)
985 super::status::status(map, matcher, root_dir, ignore_files, options)
988 }
986 }
989
987
990 pub fn copy_map_len(&self) -> usize {
988 pub fn copy_map_len(&self) -> usize {
991 let map = self.get_map();
989 let map = self.get_map();
992 map.nodes_with_copy_source_count as usize
990 map.nodes_with_copy_source_count as usize
993 }
991 }
994
992
995 pub fn copy_map_iter(&self) -> CopyMapIter<'_> {
993 pub fn copy_map_iter(&self) -> CopyMapIter<'_> {
996 let map = self.get_map();
994 let map = self.get_map();
997 Box::new(filter_map_results(map.iter_nodes(), move |node| {
995 Box::new(filter_map_results(map.iter_nodes(), move |node| {
998 Ok(if let Some(source) = node.copy_source(map.on_disk)? {
996 Ok(if let Some(source) = node.copy_source(map.on_disk)? {
999 Some((node.full_path(map.on_disk)?, source))
997 Some((node.full_path(map.on_disk)?, source))
1000 } else {
998 } else {
1001 None
999 None
1002 })
1000 })
1003 }))
1001 }))
1004 }
1002 }
1005
1003
1006 pub fn copy_map_contains_key(
1004 pub fn copy_map_contains_key(
1007 &self,
1005 &self,
1008 key: &HgPath,
1006 key: &HgPath,
1009 ) -> Result<bool, DirstateV2ParseError> {
1007 ) -> Result<bool, DirstateV2ParseError> {
1010 let map = self.get_map();
1008 let map = self.get_map();
1011 Ok(if let Some(node) = map.get_node(key)? {
1009 Ok(if let Some(node) = map.get_node(key)? {
1012 node.has_copy_source()
1010 node.has_copy_source()
1013 } else {
1011 } else {
1014 false
1012 false
1015 })
1013 })
1016 }
1014 }
1017
1015
1018 pub fn copy_map_get(
1016 pub fn copy_map_get(
1019 &self,
1017 &self,
1020 key: &HgPath,
1018 key: &HgPath,
1021 ) -> Result<Option<&HgPath>, DirstateV2ParseError> {
1019 ) -> Result<Option<&HgPath>, DirstateV2ParseError> {
1022 let map = self.get_map();
1020 let map = self.get_map();
1023 if let Some(node) = map.get_node(key)? {
1021 if let Some(node) = map.get_node(key)? {
1024 if let Some(source) = node.copy_source(map.on_disk)? {
1022 if let Some(source) = node.copy_source(map.on_disk)? {
1025 return Ok(Some(source));
1023 return Ok(Some(source));
1026 }
1024 }
1027 }
1025 }
1028 Ok(None)
1026 Ok(None)
1029 }
1027 }
1030
1028
1031 pub fn copy_map_remove(
1029 pub fn copy_map_remove(
1032 &mut self,
1030 &mut self,
1033 key: &HgPath,
1031 key: &HgPath,
1034 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
1032 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
1035 let map = self.get_map_mut();
1033 let map = self.get_map_mut();
1036 let count = &mut map.nodes_with_copy_source_count;
1034 let count = &mut map.nodes_with_copy_source_count;
1037 let unreachable_bytes = &mut map.unreachable_bytes;
1035 let unreachable_bytes = &mut map.unreachable_bytes;
1038 Ok(DirstateMap::get_node_mut(
1036 Ok(DirstateMap::get_node_mut(
1039 map.on_disk,
1037 map.on_disk,
1040 unreachable_bytes,
1038 unreachable_bytes,
1041 &mut map.root,
1039 &mut map.root,
1042 key,
1040 key,
1043 )?
1041 )?
1044 .and_then(|node| {
1042 .and_then(|node| {
1045 if let Some(source) = &node.copy_source {
1043 if let Some(source) = &node.copy_source {
1046 *count -= 1;
1044 *count -= 1;
1047 DirstateMap::count_dropped_path(unreachable_bytes, source);
1045 DirstateMap::count_dropped_path(unreachable_bytes, source);
1048 }
1046 }
1049 node.copy_source.take().map(Cow::into_owned)
1047 node.copy_source.take().map(Cow::into_owned)
1050 }))
1048 }))
1051 }
1049 }
1052
1050
1053 pub fn copy_map_insert(
1051 pub fn copy_map_insert(
1054 &mut self,
1052 &mut self,
1055 key: HgPathBuf,
1053 key: HgPathBuf,
1056 value: HgPathBuf,
1054 value: HgPathBuf,
1057 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
1055 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
1058 let map = self.get_map_mut();
1056 let map = self.get_map_mut();
1059 let node = DirstateMap::get_or_insert_node(
1057 let node = DirstateMap::get_or_insert_node(
1060 map.on_disk,
1058 map.on_disk,
1061 &mut map.unreachable_bytes,
1059 &mut map.unreachable_bytes,
1062 &mut map.root,
1060 &mut map.root,
1063 &key,
1061 &key,
1064 WithBasename::to_cow_owned,
1062 WithBasename::to_cow_owned,
1065 |_ancestor| {},
1063 |_ancestor| {},
1066 )?;
1064 )?;
1067 if node.copy_source.is_none() {
1065 if node.copy_source.is_none() {
1068 map.nodes_with_copy_source_count += 1
1066 map.nodes_with_copy_source_count += 1
1069 }
1067 }
1070 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned))
1068 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned))
1071 }
1069 }
1072
1070
1073 pub fn len(&self) -> usize {
1071 pub fn len(&self) -> usize {
1074 let map = self.get_map();
1072 let map = self.get_map();
1075 map.nodes_with_entry_count as usize
1073 map.nodes_with_entry_count as usize
1076 }
1074 }
1077
1075
1078 pub fn contains_key(
1076 pub fn contains_key(
1079 &self,
1077 &self,
1080 key: &HgPath,
1078 key: &HgPath,
1081 ) -> Result<bool, DirstateV2ParseError> {
1079 ) -> Result<bool, DirstateV2ParseError> {
1082 Ok(self.get(key)?.is_some())
1080 Ok(self.get(key)?.is_some())
1083 }
1081 }
1084
1082
1085 pub fn get(
1083 pub fn get(
1086 &self,
1084 &self,
1087 key: &HgPath,
1085 key: &HgPath,
1088 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> {
1086 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> {
1089 let map = self.get_map();
1087 let map = self.get_map();
1090 Ok(if let Some(node) = map.get_node(key)? {
1088 Ok(if let Some(node) = map.get_node(key)? {
1091 node.entry()?
1089 node.entry()?
1092 } else {
1090 } else {
1093 None
1091 None
1094 })
1092 })
1095 }
1093 }
1096
1094
1097 pub fn iter(&self) -> StateMapIter<'_> {
1095 pub fn iter(&self) -> StateMapIter<'_> {
1098 let map = self.get_map();
1096 let map = self.get_map();
1099 Box::new(filter_map_results(map.iter_nodes(), move |node| {
1097 Box::new(filter_map_results(map.iter_nodes(), move |node| {
1100 Ok(if let Some(entry) = node.entry()? {
1098 Ok(if let Some(entry) = node.entry()? {
1101 Some((node.full_path(map.on_disk)?, entry))
1099 Some((node.full_path(map.on_disk)?, entry))
1102 } else {
1100 } else {
1103 None
1101 None
1104 })
1102 })
1105 }))
1103 }))
1106 }
1104 }
1107
1105
1108 pub fn iter_tracked_dirs(
1106 pub fn iter_tracked_dirs(
1109 &mut self,
1107 &mut self,
1110 ) -> Result<
1108 ) -> Result<
1111 Box<
1109 Box<
1112 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>>
1110 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>>
1113 + Send
1111 + Send
1114 + '_,
1112 + '_,
1115 >,
1113 >,
1116 DirstateError,
1114 DirstateError,
1117 > {
1115 > {
1118 let map = self.get_map_mut();
1116 let map = self.get_map_mut();
1119 let on_disk = map.on_disk;
1117 let on_disk = map.on_disk;
1120 Ok(Box::new(filter_map_results(
1118 Ok(Box::new(filter_map_results(
1121 map.iter_nodes(),
1119 map.iter_nodes(),
1122 move |node| {
1120 move |node| {
1123 Ok(if node.tracked_descendants_count() > 0 {
1121 Ok(if node.tracked_descendants_count() > 0 {
1124 Some(node.full_path(on_disk)?)
1122 Some(node.full_path(on_disk)?)
1125 } else {
1123 } else {
1126 None
1124 None
1127 })
1125 })
1128 },
1126 },
1129 )))
1127 )))
1130 }
1128 }
1131
1129
1132 pub fn debug_iter(
1130 pub fn debug_iter(
1133 &self,
1131 &self,
1134 all: bool,
1132 all: bool,
1135 ) -> Box<
1133 ) -> Box<
1136 dyn Iterator<
1134 dyn Iterator<
1137 Item = Result<
1135 Item = Result<
1138 (&HgPath, (u8, i32, i32, i32)),
1136 (&HgPath, (u8, i32, i32, i32)),
1139 DirstateV2ParseError,
1137 DirstateV2ParseError,
1140 >,
1138 >,
1141 > + Send
1139 > + Send
1142 + '_,
1140 + '_,
1143 > {
1141 > {
1144 let map = self.get_map();
1142 let map = self.get_map();
1145 Box::new(filter_map_results(map.iter_nodes(), move |node| {
1143 Box::new(filter_map_results(map.iter_nodes(), move |node| {
1146 let debug_tuple = if let Some(entry) = node.entry()? {
1144 let debug_tuple = if let Some(entry) = node.entry()? {
1147 entry.debug_tuple()
1145 entry.debug_tuple()
1148 } else if !all {
1146 } else if !all {
1149 return Ok(None);
1147 return Ok(None);
1150 } else if let Some(mtime) = node.cached_directory_mtime()? {
1148 } else if let Some(mtime) = node.cached_directory_mtime()? {
1151 (b' ', 0, -1, mtime.truncated_seconds() as i32)
1149 (b' ', 0, -1, mtime.truncated_seconds() as i32)
1152 } else {
1150 } else {
1153 (b' ', 0, -1, -1)
1151 (b' ', 0, -1, -1)
1154 };
1152 };
1155 Ok(Some((node.full_path(map.on_disk)?, debug_tuple)))
1153 Ok(Some((node.full_path(map.on_disk)?, debug_tuple)))
1156 }))
1154 }))
1157 }
1155 }
1158 }
1156 }
@@ -1,132 +1,137 b''
1 // Copyright 2018-2020 Georges Racinet <georges.racinet@octobus.net>
1 // Copyright 2018-2020 Georges Racinet <georges.racinet@octobus.net>
2 // and Mercurial contributors
2 // and Mercurial contributors
3 //
3 //
4 // This software may be used and distributed according to the terms of the
4 // This software may be used and distributed according to the terms of the
5 // GNU General Public License version 2 or any later version.
5 // GNU General Public License version 2 or any later version.
6
6
7 mod ancestors;
7 mod ancestors;
8 pub mod dagops;
8 pub mod dagops;
9 pub mod errors;
9 pub mod errors;
10 pub use ancestors::{AncestorsIterator, MissingAncestors};
10 pub use ancestors::{AncestorsIterator, MissingAncestors};
11 pub mod dirstate;
11 pub mod dirstate;
12 pub mod dirstate_tree;
12 pub mod dirstate_tree;
13 pub mod discovery;
13 pub mod discovery;
14 pub mod exit_codes;
14 pub mod exit_codes;
15 pub mod requirements;
15 pub mod requirements;
16 pub mod testing; // unconditionally built, for use from integration tests
16 pub mod testing; // unconditionally built, for use from integration tests
17 pub use dirstate::{
17 pub use dirstate::{
18 dirs_multiset::{DirsMultiset, DirsMultisetIter},
18 dirs_multiset::{DirsMultiset, DirsMultisetIter},
19 status::{
19 status::{
20 BadMatch, BadType, DirstateStatus, HgPathCow, StatusError,
20 BadMatch, BadType, DirstateStatus, HgPathCow, StatusError,
21 StatusOptions,
21 StatusOptions,
22 },
22 },
23 DirstateEntry, DirstateParents, EntryState,
23 DirstateEntry, DirstateParents, EntryState,
24 };
24 };
25 pub mod copy_tracing;
25 pub mod copy_tracing;
26 mod filepatterns;
26 mod filepatterns;
27 pub mod matchers;
27 pub mod matchers;
28 pub mod repo;
28 pub mod repo;
29 pub mod revlog;
29 pub mod revlog;
30 pub use revlog::*;
30 pub use revlog::*;
31 pub mod config;
31 pub mod config;
32 pub mod lock;
32 pub mod lock;
33 pub mod logging;
33 pub mod logging;
34 pub mod operations;
34 pub mod operations;
35 pub mod revset;
35 pub mod revset;
36 pub mod utils;
36 pub mod utils;
37 pub mod vfs;
37 pub mod vfs;
38
38
39 use crate::utils::hg_path::{HgPathBuf, HgPathError};
39 use crate::utils::hg_path::{HgPathBuf, HgPathError};
40 pub use filepatterns::{
40 pub use filepatterns::{
41 parse_pattern_syntax, read_pattern_file, IgnorePattern,
41 parse_pattern_syntax, read_pattern_file, IgnorePattern,
42 PatternFileWarning, PatternSyntax,
42 PatternFileWarning, PatternSyntax,
43 };
43 };
44 use std::collections::HashMap;
44 use std::collections::HashMap;
45 use std::fmt;
45 use std::fmt;
46 use twox_hash::RandomXxHashBuilder64;
46 use twox_hash::RandomXxHashBuilder64;
47
47
48 /// This is a contract between the `micro-timer` crate and us, to expose
48 /// This is a contract between the `micro-timer` crate and us, to expose
49 /// the `log` crate as `crate::log`.
49 /// the `log` crate as `crate::log`.
50 use log;
50 use log;
51
51
52 pub type LineNumber = usize;
52 pub type LineNumber = usize;
53
53
54 /// Rust's default hasher is too slow because it tries to prevent collision
54 /// Rust's default hasher is too slow because it tries to prevent collision
55 /// attacks. We are not concerned about those: if an ill-minded person has
55 /// attacks. We are not concerned about those: if an ill-minded person has
56 /// write access to your repository, you have other issues.
56 /// write access to your repository, you have other issues.
57 pub type FastHashMap<K, V> = HashMap<K, V, RandomXxHashBuilder64>;
57 pub type FastHashMap<K, V> = HashMap<K, V, RandomXxHashBuilder64>;
58
58
59 // TODO: should this be the default `FastHashMap` for all of hg-core, not just
60 // dirstate_tree? How does XxHash compare with AHash, hashbrown’s default?
61 pub type FastHashbrownMap<K, V> =
62 hashbrown::HashMap<K, V, RandomXxHashBuilder64>;
63
59 #[derive(Debug, PartialEq)]
64 #[derive(Debug, PartialEq)]
60 pub enum DirstateMapError {
65 pub enum DirstateMapError {
61 PathNotFound(HgPathBuf),
66 PathNotFound(HgPathBuf),
62 EmptyPath,
67 EmptyPath,
63 InvalidPath(HgPathError),
68 InvalidPath(HgPathError),
64 }
69 }
65
70
66 impl fmt::Display for DirstateMapError {
71 impl fmt::Display for DirstateMapError {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 match self {
73 match self {
69 DirstateMapError::PathNotFound(_) => {
74 DirstateMapError::PathNotFound(_) => {
70 f.write_str("expected a value, found none")
75 f.write_str("expected a value, found none")
71 }
76 }
72 DirstateMapError::EmptyPath => {
77 DirstateMapError::EmptyPath => {
73 f.write_str("Overflow in dirstate.")
78 f.write_str("Overflow in dirstate.")
74 }
79 }
75 DirstateMapError::InvalidPath(path_error) => path_error.fmt(f),
80 DirstateMapError::InvalidPath(path_error) => path_error.fmt(f),
76 }
81 }
77 }
82 }
78 }
83 }
79
84
80 #[derive(Debug, derive_more::From)]
85 #[derive(Debug, derive_more::From)]
81 pub enum DirstateError {
86 pub enum DirstateError {
82 Map(DirstateMapError),
87 Map(DirstateMapError),
83 Common(errors::HgError),
88 Common(errors::HgError),
84 }
89 }
85
90
86 impl fmt::Display for DirstateError {
91 impl fmt::Display for DirstateError {
87 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88 match self {
93 match self {
89 DirstateError::Map(error) => error.fmt(f),
94 DirstateError::Map(error) => error.fmt(f),
90 DirstateError::Common(error) => error.fmt(f),
95 DirstateError::Common(error) => error.fmt(f),
91 }
96 }
92 }
97 }
93 }
98 }
94
99
95 #[derive(Debug, derive_more::From)]
100 #[derive(Debug, derive_more::From)]
96 pub enum PatternError {
101 pub enum PatternError {
97 #[from]
102 #[from]
98 Path(HgPathError),
103 Path(HgPathError),
99 UnsupportedSyntax(String),
104 UnsupportedSyntax(String),
100 UnsupportedSyntaxInFile(String, String, usize),
105 UnsupportedSyntaxInFile(String, String, usize),
101 TooLong(usize),
106 TooLong(usize),
102 #[from]
107 #[from]
103 IO(std::io::Error),
108 IO(std::io::Error),
104 /// Needed a pattern that can be turned into a regex but got one that
109 /// Needed a pattern that can be turned into a regex but got one that
105 /// can't. This should only happen through programmer error.
110 /// can't. This should only happen through programmer error.
106 NonRegexPattern(IgnorePattern),
111 NonRegexPattern(IgnorePattern),
107 }
112 }
108
113
109 impl fmt::Display for PatternError {
114 impl fmt::Display for PatternError {
110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111 match self {
116 match self {
112 PatternError::UnsupportedSyntax(syntax) => {
117 PatternError::UnsupportedSyntax(syntax) => {
113 write!(f, "Unsupported syntax {}", syntax)
118 write!(f, "Unsupported syntax {}", syntax)
114 }
119 }
115 PatternError::UnsupportedSyntaxInFile(syntax, file_path, line) => {
120 PatternError::UnsupportedSyntaxInFile(syntax, file_path, line) => {
116 write!(
121 write!(
117 f,
122 f,
118 "{}:{}: unsupported syntax {}",
123 "{}:{}: unsupported syntax {}",
119 file_path, line, syntax
124 file_path, line, syntax
120 )
125 )
121 }
126 }
122 PatternError::TooLong(size) => {
127 PatternError::TooLong(size) => {
123 write!(f, "matcher pattern is too long ({} bytes)", size)
128 write!(f, "matcher pattern is too long ({} bytes)", size)
124 }
129 }
125 PatternError::IO(error) => error.fmt(f),
130 PatternError::IO(error) => error.fmt(f),
126 PatternError::Path(error) => error.fmt(f),
131 PatternError::Path(error) => error.fmt(f),
127 PatternError::NonRegexPattern(pattern) => {
132 PatternError::NonRegexPattern(pattern) => {
128 write!(f, "'{:?}' cannot be turned into a regex", pattern)
133 write!(f, "'{:?}' cannot be turned into a regex", pattern)
129 }
134 }
130 }
135 }
131 }
136 }
132 }
137 }
General Comments 0
You need to be logged in to leave comments. Login now