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