##// END OF EJS Templates
rust: Make OwningDirstateMap generic and move it into hg-core...
Simon Sapin -
r48766:4afd6cc4 default
parent child Browse files
Show More
@@ -1,1071 +1,1081 b''
1 1 # This file is automatically @generated by Cargo.
2 2 # It is not intended for manual editing.
3 version = 3
4
3 5 [[package]]
4 6 name = "adler"
5 7 version = "0.2.3"
6 8 source = "registry+https://github.com/rust-lang/crates.io-index"
7 9 checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
8 10
9 11 [[package]]
10 12 name = "aho-corasick"
11 13 version = "0.7.15"
12 14 source = "registry+https://github.com/rust-lang/crates.io-index"
13 15 checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
14 16 dependencies = [
15 17 "memchr",
16 18 ]
17 19
18 20 [[package]]
19 21 name = "ansi_term"
20 22 version = "0.11.0"
21 23 source = "registry+https://github.com/rust-lang/crates.io-index"
22 24 checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
23 25 dependencies = [
24 26 "winapi",
25 27 ]
26 28
27 29 [[package]]
28 30 name = "atty"
29 31 version = "0.2.14"
30 32 source = "registry+https://github.com/rust-lang/crates.io-index"
31 33 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
32 34 dependencies = [
33 35 "hermit-abi",
34 36 "libc",
35 37 "winapi",
36 38 ]
37 39
38 40 [[package]]
39 41 name = "autocfg"
40 42 version = "1.0.1"
41 43 source = "registry+https://github.com/rust-lang/crates.io-index"
42 44 checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
43 45
44 46 [[package]]
45 47 name = "bitflags"
46 48 version = "1.2.1"
47 49 source = "registry+https://github.com/rust-lang/crates.io-index"
48 50 checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
49 51
50 52 [[package]]
51 53 name = "bitmaps"
52 54 version = "2.1.0"
53 55 source = "registry+https://github.com/rust-lang/crates.io-index"
54 56 checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2"
55 57 dependencies = [
56 58 "typenum",
57 59 ]
58 60
59 61 [[package]]
60 62 name = "block-buffer"
61 63 version = "0.9.0"
62 64 source = "registry+https://github.com/rust-lang/crates.io-index"
63 65 checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
64 66 dependencies = [
65 67 "generic-array",
66 68 ]
67 69
68 70 [[package]]
69 71 name = "byteorder"
70 72 version = "1.3.4"
71 73 source = "registry+https://github.com/rust-lang/crates.io-index"
72 74 checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
73 75
74 76 [[package]]
75 77 name = "bytes-cast"
76 78 version = "0.2.0"
77 79 source = "registry+https://github.com/rust-lang/crates.io-index"
78 80 checksum = "0d434f9a4ecbe987e7ccfda7274b6f82ea52c9b63742565a65cb5e8ba0f2c452"
79 81 dependencies = [
80 82 "bytes-cast-derive",
81 83 ]
82 84
83 85 [[package]]
84 86 name = "bytes-cast-derive"
85 87 version = "0.1.0"
86 88 source = "registry+https://github.com/rust-lang/crates.io-index"
87 89 checksum = "cb936af9de38476664d6b58e529aff30d482e4ce1c5e150293d00730b0d81fdb"
88 90 dependencies = [
89 91 "proc-macro2",
90 92 "quote",
91 93 "syn",
92 94 ]
93 95
94 96 [[package]]
95 97 name = "cc"
96 98 version = "1.0.66"
97 99 source = "registry+https://github.com/rust-lang/crates.io-index"
98 100 checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
99 101 dependencies = [
100 102 "jobserver",
101 103 ]
102 104
103 105 [[package]]
104 106 name = "cfg-if"
105 107 version = "0.1.10"
106 108 source = "registry+https://github.com/rust-lang/crates.io-index"
107 109 checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
108 110
109 111 [[package]]
110 112 name = "cfg-if"
111 113 version = "1.0.0"
112 114 source = "registry+https://github.com/rust-lang/crates.io-index"
113 115 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
114 116
115 117 [[package]]
116 118 name = "chrono"
117 119 version = "0.4.19"
118 120 source = "registry+https://github.com/rust-lang/crates.io-index"
119 121 checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
120 122 dependencies = [
121 123 "libc",
122 124 "num-integer",
123 125 "num-traits",
124 126 "time",
125 127 "winapi",
126 128 ]
127 129
128 130 [[package]]
129 131 name = "clap"
130 132 version = "2.33.3"
131 133 source = "registry+https://github.com/rust-lang/crates.io-index"
132 134 checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
133 135 dependencies = [
134 136 "ansi_term",
135 137 "atty",
136 138 "bitflags",
137 139 "strsim",
138 140 "textwrap",
139 141 "unicode-width",
140 142 "vec_map",
141 143 ]
142 144
143 145 [[package]]
144 146 name = "const_fn"
145 147 version = "0.4.4"
146 148 source = "registry+https://github.com/rust-lang/crates.io-index"
147 149 checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826"
148 150
149 151 [[package]]
150 152 name = "cpufeatures"
151 153 version = "0.1.4"
152 154 source = "registry+https://github.com/rust-lang/crates.io-index"
153 155 checksum = "ed00c67cb5d0a7d64a44f6ad2668db7e7530311dd53ea79bcd4fb022c64911c8"
154 156 dependencies = [
155 157 "libc",
156 158 ]
157 159
158 160 [[package]]
159 161 name = "cpython"
160 162 version = "0.6.0"
161 163 source = "registry+https://github.com/rust-lang/crates.io-index"
162 164 checksum = "8094679a4e9bfc8035572162624bc800eda35b5f9eff2537b9cd9aacc3d9782e"
163 165 dependencies = [
164 166 "libc",
165 167 "num-traits",
166 168 "paste",
167 169 "python27-sys",
168 170 "python3-sys",
169 171 ]
170 172
171 173 [[package]]
172 174 name = "crc32fast"
173 175 version = "1.2.1"
174 176 source = "registry+https://github.com/rust-lang/crates.io-index"
175 177 checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
176 178 dependencies = [
177 179 "cfg-if 1.0.0",
178 180 ]
179 181
180 182 [[package]]
181 183 name = "crossbeam-channel"
182 184 version = "0.4.4"
183 185 source = "registry+https://github.com/rust-lang/crates.io-index"
184 186 checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
185 187 dependencies = [
186 188 "crossbeam-utils 0.7.2",
187 189 "maybe-uninit",
188 190 ]
189 191
190 192 [[package]]
191 193 name = "crossbeam-channel"
192 194 version = "0.5.0"
193 195 source = "registry+https://github.com/rust-lang/crates.io-index"
194 196 checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
195 197 dependencies = [
196 198 "cfg-if 1.0.0",
197 199 "crossbeam-utils 0.8.1",
198 200 ]
199 201
200 202 [[package]]
201 203 name = "crossbeam-deque"
202 204 version = "0.8.0"
203 205 source = "registry+https://github.com/rust-lang/crates.io-index"
204 206 checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
205 207 dependencies = [
206 208 "cfg-if 1.0.0",
207 209 "crossbeam-epoch",
208 210 "crossbeam-utils 0.8.1",
209 211 ]
210 212
211 213 [[package]]
212 214 name = "crossbeam-epoch"
213 215 version = "0.9.1"
214 216 source = "registry+https://github.com/rust-lang/crates.io-index"
215 217 checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
216 218 dependencies = [
217 219 "cfg-if 1.0.0",
218 220 "const_fn",
219 221 "crossbeam-utils 0.8.1",
220 222 "lazy_static",
221 223 "memoffset",
222 224 "scopeguard",
223 225 ]
224 226
225 227 [[package]]
226 228 name = "crossbeam-utils"
227 229 version = "0.7.2"
228 230 source = "registry+https://github.com/rust-lang/crates.io-index"
229 231 checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
230 232 dependencies = [
231 233 "autocfg",
232 234 "cfg-if 0.1.10",
233 235 "lazy_static",
234 236 ]
235 237
236 238 [[package]]
237 239 name = "crossbeam-utils"
238 240 version = "0.8.1"
239 241 source = "registry+https://github.com/rust-lang/crates.io-index"
240 242 checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
241 243 dependencies = [
242 244 "autocfg",
243 245 "cfg-if 1.0.0",
244 246 "lazy_static",
245 247 ]
246 248
247 249 [[package]]
248 250 name = "ctor"
249 251 version = "0.1.16"
250 252 source = "registry+https://github.com/rust-lang/crates.io-index"
251 253 checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484"
252 254 dependencies = [
253 255 "quote",
254 256 "syn",
255 257 ]
256 258
257 259 [[package]]
258 260 name = "derive_more"
259 261 version = "0.99.11"
260 262 source = "registry+https://github.com/rust-lang/crates.io-index"
261 263 checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
262 264 dependencies = [
263 265 "proc-macro2",
264 266 "quote",
265 267 "syn",
266 268 ]
267 269
268 270 [[package]]
269 271 name = "difference"
270 272 version = "2.0.0"
271 273 source = "registry+https://github.com/rust-lang/crates.io-index"
272 274 checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
273 275
274 276 [[package]]
275 277 name = "digest"
276 278 version = "0.9.0"
277 279 source = "registry+https://github.com/rust-lang/crates.io-index"
278 280 checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
279 281 dependencies = [
280 282 "generic-array",
281 283 ]
282 284
283 285 [[package]]
284 286 name = "either"
285 287 version = "1.6.1"
286 288 source = "registry+https://github.com/rust-lang/crates.io-index"
287 289 checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
288 290
289 291 [[package]]
290 292 name = "env_logger"
291 293 version = "0.7.1"
292 294 source = "registry+https://github.com/rust-lang/crates.io-index"
293 295 checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
294 296 dependencies = [
295 297 "atty",
296 298 "humantime",
297 299 "log",
298 300 "regex",
299 301 "termcolor",
300 302 ]
301 303
302 304 [[package]]
303 305 name = "flate2"
304 306 version = "1.0.19"
305 307 source = "registry+https://github.com/rust-lang/crates.io-index"
306 308 checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129"
307 309 dependencies = [
308 310 "cfg-if 1.0.0",
309 311 "crc32fast",
310 312 "libc",
311 313 "libz-sys",
312 314 "miniz_oxide",
313 315 ]
314 316
315 317 [[package]]
316 318 name = "format-bytes"
317 319 version = "0.2.2"
318 320 source = "registry+https://github.com/rust-lang/crates.io-index"
319 321 checksum = "1c4e89040c7fd7b4e6ba2820ac705a45def8a0c098ec78d170ae88f1ef1d5762"
320 322 dependencies = [
321 323 "format-bytes-macros",
322 324 "proc-macro-hack",
323 325 ]
324 326
325 327 [[package]]
326 328 name = "format-bytes-macros"
327 329 version = "0.3.0"
328 330 source = "registry+https://github.com/rust-lang/crates.io-index"
329 331 checksum = "b05089e341a0460449e2210c3bf7b61597860b07f0deae58da38dbed0a4c6b6d"
330 332 dependencies = [
331 333 "proc-macro-hack",
332 334 "proc-macro2",
333 335 "quote",
334 336 "syn",
335 337 ]
336 338
337 339 [[package]]
338 340 name = "generic-array"
339 341 version = "0.14.4"
340 342 source = "registry+https://github.com/rust-lang/crates.io-index"
341 343 checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
342 344 dependencies = [
343 345 "typenum",
344 346 "version_check",
345 347 ]
346 348
347 349 [[package]]
348 350 name = "getrandom"
349 351 version = "0.1.15"
350 352 source = "registry+https://github.com/rust-lang/crates.io-index"
351 353 checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
352 354 dependencies = [
353 355 "cfg-if 0.1.10",
354 356 "libc",
355 357 "wasi 0.9.0+wasi-snapshot-preview1",
356 358 ]
357 359
358 360 [[package]]
359 361 name = "glob"
360 362 version = "0.3.0"
361 363 source = "registry+https://github.com/rust-lang/crates.io-index"
362 364 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
363 365
364 366 [[package]]
365 367 name = "hermit-abi"
366 368 version = "0.1.17"
367 369 source = "registry+https://github.com/rust-lang/crates.io-index"
368 370 checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
369 371 dependencies = [
370 372 "libc",
371 373 ]
372 374
373 375 [[package]]
374 376 name = "hg-core"
375 377 version = "0.1.0"
376 378 dependencies = [
377 379 "byteorder",
378 380 "bytes-cast",
379 381 "clap",
380 382 "crossbeam-channel 0.4.4",
381 383 "derive_more",
382 384 "flate2",
383 385 "format-bytes",
384 386 "home",
385 387 "im-rc",
386 388 "itertools",
387 389 "lazy_static",
388 390 "log",
389 391 "memmap",
390 392 "micro-timer",
391 393 "pretty_assertions",
392 394 "rand",
393 395 "rand_distr",
394 396 "rand_pcg",
395 397 "rayon",
396 398 "regex",
397 399 "same-file",
398 400 "sha-1",
401 "stable_deref_trait",
399 402 "tempfile",
400 403 "twox-hash",
401 404 "zstd",
402 405 ]
403 406
404 407 [[package]]
405 408 name = "hg-cpython"
406 409 version = "0.1.0"
407 410 dependencies = [
408 411 "cpython",
409 412 "crossbeam-channel 0.4.4",
410 413 "env_logger",
411 414 "hg-core",
412 415 "libc",
413 416 "log",
417 "stable_deref_trait",
414 418 ]
415 419
416 420 [[package]]
417 421 name = "home"
418 422 version = "0.5.3"
419 423 source = "registry+https://github.com/rust-lang/crates.io-index"
420 424 checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
421 425 dependencies = [
422 426 "winapi",
423 427 ]
424 428
425 429 [[package]]
426 430 name = "humantime"
427 431 version = "1.3.0"
428 432 source = "registry+https://github.com/rust-lang/crates.io-index"
429 433 checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
430 434 dependencies = [
431 435 "quick-error",
432 436 ]
433 437
434 438 [[package]]
435 439 name = "im-rc"
436 440 version = "15.0.0"
437 441 source = "registry+https://github.com/rust-lang/crates.io-index"
438 442 checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
439 443 dependencies = [
440 444 "bitmaps",
441 445 "rand_core",
442 446 "rand_xoshiro",
443 447 "sized-chunks",
444 448 "typenum",
445 449 "version_check",
446 450 ]
447 451
448 452 [[package]]
449 453 name = "itertools"
450 454 version = "0.9.0"
451 455 source = "registry+https://github.com/rust-lang/crates.io-index"
452 456 checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
453 457 dependencies = [
454 458 "either",
455 459 ]
456 460
457 461 [[package]]
458 462 name = "jobserver"
459 463 version = "0.1.21"
460 464 source = "registry+https://github.com/rust-lang/crates.io-index"
461 465 checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
462 466 dependencies = [
463 467 "libc",
464 468 ]
465 469
466 470 [[package]]
467 471 name = "lazy_static"
468 472 version = "1.4.0"
469 473 source = "registry+https://github.com/rust-lang/crates.io-index"
470 474 checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
471 475
472 476 [[package]]
473 477 name = "libc"
474 478 version = "0.2.81"
475 479 source = "registry+https://github.com/rust-lang/crates.io-index"
476 480 checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
477 481
478 482 [[package]]
479 483 name = "libz-sys"
480 484 version = "1.1.2"
481 485 source = "registry+https://github.com/rust-lang/crates.io-index"
482 486 checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
483 487 dependencies = [
484 488 "cc",
485 489 "pkg-config",
486 490 "vcpkg",
487 491 ]
488 492
489 493 [[package]]
490 494 name = "log"
491 495 version = "0.4.11"
492 496 source = "registry+https://github.com/rust-lang/crates.io-index"
493 497 checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
494 498 dependencies = [
495 499 "cfg-if 0.1.10",
496 500 ]
497 501
498 502 [[package]]
499 503 name = "maybe-uninit"
500 504 version = "2.0.0"
501 505 source = "registry+https://github.com/rust-lang/crates.io-index"
502 506 checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
503 507
504 508 [[package]]
505 509 name = "memchr"
506 510 version = "2.3.4"
507 511 source = "registry+https://github.com/rust-lang/crates.io-index"
508 512 checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
509 513
510 514 [[package]]
511 515 name = "memmap"
512 516 version = "0.7.0"
513 517 source = "registry+https://github.com/rust-lang/crates.io-index"
514 518 checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
515 519 dependencies = [
516 520 "libc",
517 521 "winapi",
518 522 ]
519 523
520 524 [[package]]
521 525 name = "memoffset"
522 526 version = "0.6.1"
523 527 source = "registry+https://github.com/rust-lang/crates.io-index"
524 528 checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
525 529 dependencies = [
526 530 "autocfg",
527 531 ]
528 532
529 533 [[package]]
530 534 name = "micro-timer"
531 535 version = "0.3.1"
532 536 source = "registry+https://github.com/rust-lang/crates.io-index"
533 537 checksum = "2620153e1d903d26b72b89f0e9c48d8c4756cba941c185461dddc234980c298c"
534 538 dependencies = [
535 539 "micro-timer-macros",
536 540 "scopeguard",
537 541 ]
538 542
539 543 [[package]]
540 544 name = "micro-timer-macros"
541 545 version = "0.3.1"
542 546 source = "registry+https://github.com/rust-lang/crates.io-index"
543 547 checksum = "e28a3473e6abd6e9aab36aaeef32ad22ae0bd34e79f376643594c2b152ec1c5d"
544 548 dependencies = [
545 549 "proc-macro2",
546 550 "quote",
547 551 "scopeguard",
548 552 "syn",
549 553 ]
550 554
551 555 [[package]]
552 556 name = "miniz_oxide"
553 557 version = "0.4.3"
554 558 source = "registry+https://github.com/rust-lang/crates.io-index"
555 559 checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
556 560 dependencies = [
557 561 "adler",
558 562 "autocfg",
559 563 ]
560 564
561 565 [[package]]
562 566 name = "num-integer"
563 567 version = "0.1.44"
564 568 source = "registry+https://github.com/rust-lang/crates.io-index"
565 569 checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
566 570 dependencies = [
567 571 "autocfg",
568 572 "num-traits",
569 573 ]
570 574
571 575 [[package]]
572 576 name = "num-traits"
573 577 version = "0.2.14"
574 578 source = "registry+https://github.com/rust-lang/crates.io-index"
575 579 checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
576 580 dependencies = [
577 581 "autocfg",
578 582 ]
579 583
580 584 [[package]]
581 585 name = "num_cpus"
582 586 version = "1.13.0"
583 587 source = "registry+https://github.com/rust-lang/crates.io-index"
584 588 checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
585 589 dependencies = [
586 590 "hermit-abi",
587 591 "libc",
588 592 ]
589 593
590 594 [[package]]
591 595 name = "opaque-debug"
592 596 version = "0.3.0"
593 597 source = "registry+https://github.com/rust-lang/crates.io-index"
594 598 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
595 599
596 600 [[package]]
597 601 name = "output_vt100"
598 602 version = "0.1.2"
599 603 source = "registry+https://github.com/rust-lang/crates.io-index"
600 604 checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
601 605 dependencies = [
602 606 "winapi",
603 607 ]
604 608
605 609 [[package]]
606 610 name = "paste"
607 611 version = "1.0.5"
608 612 source = "registry+https://github.com/rust-lang/crates.io-index"
609 613 checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
610 614
611 615 [[package]]
612 616 name = "pkg-config"
613 617 version = "0.3.19"
614 618 source = "registry+https://github.com/rust-lang/crates.io-index"
615 619 checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
616 620
617 621 [[package]]
618 622 name = "ppv-lite86"
619 623 version = "0.2.10"
620 624 source = "registry+https://github.com/rust-lang/crates.io-index"
621 625 checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
622 626
623 627 [[package]]
624 628 name = "pretty_assertions"
625 629 version = "0.6.1"
626 630 source = "registry+https://github.com/rust-lang/crates.io-index"
627 631 checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"
628 632 dependencies = [
629 633 "ansi_term",
630 634 "ctor",
631 635 "difference",
632 636 "output_vt100",
633 637 ]
634 638
635 639 [[package]]
636 640 name = "proc-macro-hack"
637 641 version = "0.5.19"
638 642 source = "registry+https://github.com/rust-lang/crates.io-index"
639 643 checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
640 644
641 645 [[package]]
642 646 name = "proc-macro2"
643 647 version = "1.0.24"
644 648 source = "registry+https://github.com/rust-lang/crates.io-index"
645 649 checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
646 650 dependencies = [
647 651 "unicode-xid",
648 652 ]
649 653
650 654 [[package]]
651 655 name = "python27-sys"
652 656 version = "0.6.0"
653 657 source = "registry+https://github.com/rust-lang/crates.io-index"
654 658 checksum = "5826ddbc5366eb0b0492040fdc25bf50bb49092c192bd45e80fb7a24dc6832ab"
655 659 dependencies = [
656 660 "libc",
657 661 "regex",
658 662 ]
659 663
660 664 [[package]]
661 665 name = "python3-sys"
662 666 version = "0.6.0"
663 667 source = "registry+https://github.com/rust-lang/crates.io-index"
664 668 checksum = "b78af21b29594951a47fc3dac9b9eff0a3f077dec2f780ee943ae16a668f3b6a"
665 669 dependencies = [
666 670 "libc",
667 671 "regex",
668 672 ]
669 673
670 674 [[package]]
671 675 name = "quick-error"
672 676 version = "1.2.3"
673 677 source = "registry+https://github.com/rust-lang/crates.io-index"
674 678 checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
675 679
676 680 [[package]]
677 681 name = "quote"
678 682 version = "1.0.7"
679 683 source = "registry+https://github.com/rust-lang/crates.io-index"
680 684 checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
681 685 dependencies = [
682 686 "proc-macro2",
683 687 ]
684 688
685 689 [[package]]
686 690 name = "rand"
687 691 version = "0.7.3"
688 692 source = "registry+https://github.com/rust-lang/crates.io-index"
689 693 checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
690 694 dependencies = [
691 695 "getrandom",
692 696 "libc",
693 697 "rand_chacha",
694 698 "rand_core",
695 699 "rand_hc",
696 700 ]
697 701
698 702 [[package]]
699 703 name = "rand_chacha"
700 704 version = "0.2.2"
701 705 source = "registry+https://github.com/rust-lang/crates.io-index"
702 706 checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
703 707 dependencies = [
704 708 "ppv-lite86",
705 709 "rand_core",
706 710 ]
707 711
708 712 [[package]]
709 713 name = "rand_core"
710 714 version = "0.5.1"
711 715 source = "registry+https://github.com/rust-lang/crates.io-index"
712 716 checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
713 717 dependencies = [
714 718 "getrandom",
715 719 ]
716 720
717 721 [[package]]
718 722 name = "rand_distr"
719 723 version = "0.2.2"
720 724 source = "registry+https://github.com/rust-lang/crates.io-index"
721 725 checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
722 726 dependencies = [
723 727 "rand",
724 728 ]
725 729
726 730 [[package]]
727 731 name = "rand_hc"
728 732 version = "0.2.0"
729 733 source = "registry+https://github.com/rust-lang/crates.io-index"
730 734 checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
731 735 dependencies = [
732 736 "rand_core",
733 737 ]
734 738
735 739 [[package]]
736 740 name = "rand_pcg"
737 741 version = "0.2.1"
738 742 source = "registry+https://github.com/rust-lang/crates.io-index"
739 743 checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
740 744 dependencies = [
741 745 "rand_core",
742 746 ]
743 747
744 748 [[package]]
745 749 name = "rand_xoshiro"
746 750 version = "0.4.0"
747 751 source = "registry+https://github.com/rust-lang/crates.io-index"
748 752 checksum = "a9fcdd2e881d02f1d9390ae47ad8e5696a9e4be7b547a1da2afbc61973217004"
749 753 dependencies = [
750 754 "rand_core",
751 755 ]
752 756
753 757 [[package]]
754 758 name = "rayon"
755 759 version = "1.5.0"
756 760 source = "registry+https://github.com/rust-lang/crates.io-index"
757 761 checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674"
758 762 dependencies = [
759 763 "autocfg",
760 764 "crossbeam-deque",
761 765 "either",
762 766 "rayon-core",
763 767 ]
764 768
765 769 [[package]]
766 770 name = "rayon-core"
767 771 version = "1.9.0"
768 772 source = "registry+https://github.com/rust-lang/crates.io-index"
769 773 checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a"
770 774 dependencies = [
771 775 "crossbeam-channel 0.5.0",
772 776 "crossbeam-deque",
773 777 "crossbeam-utils 0.8.1",
774 778 "lazy_static",
775 779 "num_cpus",
776 780 ]
777 781
778 782 [[package]]
779 783 name = "redox_syscall"
780 784 version = "0.1.57"
781 785 source = "registry+https://github.com/rust-lang/crates.io-index"
782 786 checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
783 787
784 788 [[package]]
785 789 name = "regex"
786 790 version = "1.4.2"
787 791 source = "registry+https://github.com/rust-lang/crates.io-index"
788 792 checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c"
789 793 dependencies = [
790 794 "aho-corasick",
791 795 "memchr",
792 796 "regex-syntax",
793 797 "thread_local",
794 798 ]
795 799
796 800 [[package]]
797 801 name = "regex-syntax"
798 802 version = "0.6.21"
799 803 source = "registry+https://github.com/rust-lang/crates.io-index"
800 804 checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
801 805
802 806 [[package]]
803 807 name = "remove_dir_all"
804 808 version = "0.5.3"
805 809 source = "registry+https://github.com/rust-lang/crates.io-index"
806 810 checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
807 811 dependencies = [
808 812 "winapi",
809 813 ]
810 814
811 815 [[package]]
812 816 name = "rhg"
813 817 version = "0.1.0"
814 818 dependencies = [
815 819 "chrono",
816 820 "clap",
817 821 "derive_more",
818 822 "env_logger",
819 823 "format-bytes",
820 824 "hg-core",
821 825 "home",
822 826 "lazy_static",
823 827 "log",
824 828 "micro-timer",
825 829 "regex",
826 830 "users",
827 831 ]
828 832
829 833 [[package]]
830 834 name = "same-file"
831 835 version = "1.0.6"
832 836 source = "registry+https://github.com/rust-lang/crates.io-index"
833 837 checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
834 838 dependencies = [
835 839 "winapi-util",
836 840 ]
837 841
838 842 [[package]]
839 843 name = "scopeguard"
840 844 version = "1.1.0"
841 845 source = "registry+https://github.com/rust-lang/crates.io-index"
842 846 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
843 847
844 848 [[package]]
845 849 name = "sha-1"
846 850 version = "0.9.6"
847 851 source = "registry+https://github.com/rust-lang/crates.io-index"
848 852 checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16"
849 853 dependencies = [
850 854 "block-buffer",
851 855 "cfg-if 1.0.0",
852 856 "cpufeatures",
853 857 "digest",
854 858 "opaque-debug",
855 859 ]
856 860
857 861 [[package]]
858 862 name = "sized-chunks"
859 863 version = "0.6.2"
860 864 source = "registry+https://github.com/rust-lang/crates.io-index"
861 865 checksum = "1ec31ceca5644fa6d444cc77548b88b67f46db6f7c71683b0f9336e671830d2f"
862 866 dependencies = [
863 867 "bitmaps",
864 868 "typenum",
865 869 ]
866 870
867 871 [[package]]
872 name = "stable_deref_trait"
873 version = "1.2.0"
874 source = "registry+https://github.com/rust-lang/crates.io-index"
875 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
876
877 [[package]]
868 878 name = "static_assertions"
869 879 version = "1.1.0"
870 880 source = "registry+https://github.com/rust-lang/crates.io-index"
871 881 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
872 882
873 883 [[package]]
874 884 name = "strsim"
875 885 version = "0.8.0"
876 886 source = "registry+https://github.com/rust-lang/crates.io-index"
877 887 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
878 888
879 889 [[package]]
880 890 name = "syn"
881 891 version = "1.0.54"
882 892 source = "registry+https://github.com/rust-lang/crates.io-index"
883 893 checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44"
884 894 dependencies = [
885 895 "proc-macro2",
886 896 "quote",
887 897 "unicode-xid",
888 898 ]
889 899
890 900 [[package]]
891 901 name = "tempfile"
892 902 version = "3.1.0"
893 903 source = "registry+https://github.com/rust-lang/crates.io-index"
894 904 checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
895 905 dependencies = [
896 906 "cfg-if 0.1.10",
897 907 "libc",
898 908 "rand",
899 909 "redox_syscall",
900 910 "remove_dir_all",
901 911 "winapi",
902 912 ]
903 913
904 914 [[package]]
905 915 name = "termcolor"
906 916 version = "1.1.2"
907 917 source = "registry+https://github.com/rust-lang/crates.io-index"
908 918 checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
909 919 dependencies = [
910 920 "winapi-util",
911 921 ]
912 922
913 923 [[package]]
914 924 name = "textwrap"
915 925 version = "0.11.0"
916 926 source = "registry+https://github.com/rust-lang/crates.io-index"
917 927 checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
918 928 dependencies = [
919 929 "unicode-width",
920 930 ]
921 931
922 932 [[package]]
923 933 name = "thread_local"
924 934 version = "1.0.1"
925 935 source = "registry+https://github.com/rust-lang/crates.io-index"
926 936 checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
927 937 dependencies = [
928 938 "lazy_static",
929 939 ]
930 940
931 941 [[package]]
932 942 name = "time"
933 943 version = "0.1.44"
934 944 source = "registry+https://github.com/rust-lang/crates.io-index"
935 945 checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
936 946 dependencies = [
937 947 "libc",
938 948 "wasi 0.10.0+wasi-snapshot-preview1",
939 949 "winapi",
940 950 ]
941 951
942 952 [[package]]
943 953 name = "twox-hash"
944 954 version = "1.6.0"
945 955 source = "registry+https://github.com/rust-lang/crates.io-index"
946 956 checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59"
947 957 dependencies = [
948 958 "cfg-if 0.1.10",
949 959 "rand",
950 960 "static_assertions",
951 961 ]
952 962
953 963 [[package]]
954 964 name = "typenum"
955 965 version = "1.12.0"
956 966 source = "registry+https://github.com/rust-lang/crates.io-index"
957 967 checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
958 968
959 969 [[package]]
960 970 name = "unicode-width"
961 971 version = "0.1.8"
962 972 source = "registry+https://github.com/rust-lang/crates.io-index"
963 973 checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
964 974
965 975 [[package]]
966 976 name = "unicode-xid"
967 977 version = "0.2.1"
968 978 source = "registry+https://github.com/rust-lang/crates.io-index"
969 979 checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
970 980
971 981 [[package]]
972 982 name = "users"
973 983 version = "0.11.0"
974 984 source = "registry+https://github.com/rust-lang/crates.io-index"
975 985 checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
976 986 dependencies = [
977 987 "libc",
978 988 "log",
979 989 ]
980 990
981 991 [[package]]
982 992 name = "vcpkg"
983 993 version = "0.2.11"
984 994 source = "registry+https://github.com/rust-lang/crates.io-index"
985 995 checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb"
986 996
987 997 [[package]]
988 998 name = "vec_map"
989 999 version = "0.8.2"
990 1000 source = "registry+https://github.com/rust-lang/crates.io-index"
991 1001 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
992 1002
993 1003 [[package]]
994 1004 name = "version_check"
995 1005 version = "0.9.2"
996 1006 source = "registry+https://github.com/rust-lang/crates.io-index"
997 1007 checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
998 1008
999 1009 [[package]]
1000 1010 name = "wasi"
1001 1011 version = "0.9.0+wasi-snapshot-preview1"
1002 1012 source = "registry+https://github.com/rust-lang/crates.io-index"
1003 1013 checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
1004 1014
1005 1015 [[package]]
1006 1016 name = "wasi"
1007 1017 version = "0.10.0+wasi-snapshot-preview1"
1008 1018 source = "registry+https://github.com/rust-lang/crates.io-index"
1009 1019 checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
1010 1020
1011 1021 [[package]]
1012 1022 name = "winapi"
1013 1023 version = "0.3.9"
1014 1024 source = "registry+https://github.com/rust-lang/crates.io-index"
1015 1025 checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
1016 1026 dependencies = [
1017 1027 "winapi-i686-pc-windows-gnu",
1018 1028 "winapi-x86_64-pc-windows-gnu",
1019 1029 ]
1020 1030
1021 1031 [[package]]
1022 1032 name = "winapi-i686-pc-windows-gnu"
1023 1033 version = "0.4.0"
1024 1034 source = "registry+https://github.com/rust-lang/crates.io-index"
1025 1035 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
1026 1036
1027 1037 [[package]]
1028 1038 name = "winapi-util"
1029 1039 version = "0.1.5"
1030 1040 source = "registry+https://github.com/rust-lang/crates.io-index"
1031 1041 checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
1032 1042 dependencies = [
1033 1043 "winapi",
1034 1044 ]
1035 1045
1036 1046 [[package]]
1037 1047 name = "winapi-x86_64-pc-windows-gnu"
1038 1048 version = "0.4.0"
1039 1049 source = "registry+https://github.com/rust-lang/crates.io-index"
1040 1050 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
1041 1051
1042 1052 [[package]]
1043 1053 name = "zstd"
1044 1054 version = "0.5.3+zstd.1.4.5"
1045 1055 source = "registry+https://github.com/rust-lang/crates.io-index"
1046 1056 checksum = "01b32eaf771efa709e8308605bbf9319bf485dc1503179ec0469b611937c0cd8"
1047 1057 dependencies = [
1048 1058 "zstd-safe",
1049 1059 ]
1050 1060
1051 1061 [[package]]
1052 1062 name = "zstd-safe"
1053 1063 version = "2.0.5+zstd.1.4.5"
1054 1064 source = "registry+https://github.com/rust-lang/crates.io-index"
1055 1065 checksum = "1cfb642e0d27f64729a639c52db457e0ae906e7bc6f5fe8f5c453230400f1055"
1056 1066 dependencies = [
1057 1067 "libc",
1058 1068 "zstd-sys",
1059 1069 ]
1060 1070
1061 1071 [[package]]
1062 1072 name = "zstd-sys"
1063 1073 version = "1.4.17+zstd.1.4.5"
1064 1074 source = "registry+https://github.com/rust-lang/crates.io-index"
1065 1075 checksum = "b89249644df056b522696b1bb9e7c18c87e8ffa3e2f0dc3b0155875d6498f01b"
1066 1076 dependencies = [
1067 1077 "cc",
1068 1078 "glob",
1069 1079 "itertools",
1070 1080 "libc",
1071 1081 ]
@@ -1,44 +1,45 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 bytes-cast = "0.2"
13 13 byteorder = "1.3.4"
14 14 derive_more = "0.99"
15 15 home = "0.5"
16 16 im-rc = "15.0.*"
17 17 itertools = "0.9"
18 18 lazy_static = "1.4.0"
19 19 rand = "0.7.3"
20 20 rand_pcg = "0.2.1"
21 21 rand_distr = "0.2.2"
22 22 rayon = "1.3.0"
23 23 regex = "1.3.9"
24 24 sha-1 = "0.9.6"
25 25 twox-hash = "1.5.0"
26 26 same-file = "1.0.6"
27 stable_deref_trait = "1.2.0"
27 28 tempfile = "3.1.0"
28 29 crossbeam-channel = "0.4"
29 30 micro-timer = "0.3.0"
30 31 log = "0.4.8"
31 32 memmap = "0.7.0"
32 33 zstd = "0.5.3"
33 34 format-bytes = "0.2.2"
34 35
35 36 # We don't use the `miniz-oxide` backend to not change rhg benchmarks and until
36 37 # we have a clearer view of which backend is the fastest.
37 38 [dependencies.flate2]
38 39 version = "1.0.16"
39 40 features = ["zlib"]
40 41 default-features = false
41 42
42 43 [dev-dependencies]
43 44 clap = "*"
44 45 pretty_assertions = "0.6.1"
@@ -1,5 +1,7 b''
1 1 pub mod dirstate_map;
2 2 pub mod dispatch;
3 3 pub mod on_disk;
4 pub mod owning;
5 mod owning_dispatch;
4 6 pub mod path_with_basename;
5 7 pub mod status;
@@ -1,117 +1,105 b''
1 use cpython::PyBytes;
2 use cpython::Python;
3 use hg::dirstate_tree::dirstate_map::DirstateMap;
4 use hg::DirstateError;
5 use hg::DirstateParents;
1 use super::dirstate_map::DirstateMap;
2 use stable_deref_trait::StableDeref;
3 use std::ops::Deref;
6 4
7 5 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
8 /// borrows. This is similar to the owning-ref crate.
6 /// borrows.
9 7 ///
10 8 /// This is similar to [`OwningRef`] which is more limited because it
11 9 /// represents exactly one `&T` reference next to the value it borrows, as
12 10 /// opposed to a struct that may contain an arbitrary number of references in
13 11 /// arbitrarily-nested data structures.
14 12 ///
15 13 /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
16 pub(super) struct OwningDirstateMap {
14 pub struct OwningDirstateMap {
17 15 /// Owned handle to a bytes buffer with a stable address.
18 16 ///
19 17 /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
20 on_disk: PyBytes,
18 on_disk: Box<dyn Deref<Target = [u8]> + Send>,
21 19
22 20 /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
23 21 /// language cannot represent a lifetime referencing a sibling field.
24 22 /// This is not quite a self-referencial struct (moving this struct is not
25 23 /// a problem as it doesn’t change the address of the bytes buffer owned
26 24 /// by `PyBytes`) but touches similar borrow-checker limitations.
27 25 ptr: *mut (),
28 26 }
29 27
30 28 impl OwningDirstateMap {
31 pub fn new_v1(
32 py: Python,
33 on_disk: PyBytes,
34 ) -> Result<(Self, Option<DirstateParents>), DirstateError> {
35 let bytes: &'_ [u8] = on_disk.data(py);
36 let (map, parents) = DirstateMap::new_v1(bytes)?;
29 pub fn new_empty<OnDisk>(on_disk: OnDisk) -> Self
30 where
31 OnDisk: Deref<Target = [u8]> + StableDeref + Send + 'static,
32 {
33 let on_disk = Box::new(on_disk);
34 let bytes: &'_ [u8] = &on_disk;
35 let map = DirstateMap::empty(bytes);
37 36
38 37 // Like in `bytes` above, this `'_` lifetime parameter borrows from
39 38 // the bytes buffer owned by `on_disk`.
40 39 let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
41 40
42 41 // Erase the pointed type entirely in order to erase the lifetime.
43 42 let ptr: *mut () = ptr.cast();
44 43
45 Ok((Self { on_disk, ptr }, parents))
44 Self { on_disk, ptr }
46 45 }
47 46
48 pub fn new_v2(
49 py: Python,
50 on_disk: PyBytes,
51 data_size: usize,
52 tree_metadata: PyBytes,
53 ) -> Result<Self, DirstateError> {
54 let bytes: &'_ [u8] = on_disk.data(py);
55 let map =
56 DirstateMap::new_v2(bytes, data_size, tree_metadata.data(py))?;
57
58 // Like in `bytes` above, this `'_` lifetime parameter borrows from
59 // the bytes buffer owned by `on_disk`.
60 let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
61
62 // Erase the pointed type entirely in order to erase the lifetime.
63 let ptr: *mut () = ptr.cast();
64
65 Ok(Self { on_disk, ptr })
66 }
67
68 pub fn get_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
47 pub fn get_mut_pair<'a>(
48 &'a mut self,
49 ) -> (&'a [u8], &'a mut DirstateMap<'a>) {
69 50 // SAFETY: We cast the type-erased pointer back to the same type it had
70 51 // in `new`, except with a different lifetime parameter. This time we
71 52 // connect the lifetime to that of `self`. This cast is valid because
72 53 // `self` owns the same `PyBytes` whose buffer `DirstateMap`
73 54 // references. That buffer has a stable memory address because the byte
74 55 // string value of a `PyBytes` is immutable.
75 56 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
76 57 // SAFETY: we dereference that pointer, connecting the lifetime of the
77 58 // new `&mut` to that of `self`. This is valid because the
78 59 // raw pointer is to a boxed value, and `self` owns that box.
79 unsafe { &mut *ptr }
60 (&self.on_disk, unsafe { &mut *ptr })
61 }
62
63 pub fn get_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
64 self.get_mut_pair().1
80 65 }
81 66
82 67 pub fn get<'a>(&'a self) -> &'a DirstateMap<'a> {
83 68 // SAFETY: same reasoning as in `get_mut` above.
84 69 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
85 70 unsafe { &*ptr }
86 71 }
72
73 pub fn on_disk<'a>(&'a self) -> &'a [u8] {
74 &self.on_disk
75 }
87 76 }
88 77
89 78 impl Drop for OwningDirstateMap {
90 79 fn drop(&mut self) {
91 80 // Silence a "field is never read" warning, and demonstrate that this
92 81 // value is still alive.
93 82 let _ = &self.on_disk;
94 83 // SAFETY: this cast is the same as in `get_mut`, and is valid for the
95 84 // same reason. `self.on_disk` still exists at this point, drop glue
96 85 // will drop it implicitly after this `drop` method returns.
97 86 let ptr: *mut DirstateMap<'_> = self.ptr.cast();
98 87 // SAFETY: `Box::from_raw` takes ownership of the box away from `self`.
99 88 // This is fine because drop glue does nothig for `*mut ()` and we’re
100 89 // in `drop`, so `get` and `get_mut` cannot be called again.
101 90 unsafe { drop(Box::from_raw(ptr)) }
102 91 }
103 92 }
104 93
105 94 fn _static_assert_is_send<T: Send>() {}
106 95
107 96 fn _static_assert_fields_are_send() {
108 _static_assert_is_send::<PyBytes>();
109 97 _static_assert_is_send::<Box<DirstateMap<'_>>>();
110 98 }
111 99
112 100 // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
113 101 // thread-safety of raw pointers is unknown in the general case. However this
114 102 // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
115 // own. Since that `Box` and `PyBytes` are both `Send` as shown in above, it
116 // is sound to mark this struct as `Send` too.
103 // own. Since that `Box` is `Send` as shown in above, it is sound to mark
104 // this struct as `Send` too.
117 105 unsafe impl Send for OwningDirstateMap {}
@@ -1,240 +1,240 b''
1 use crate::dirstate::owning::OwningDirstateMap;
2 use hg::dirstate::parsers::Timestamp;
3 use hg::dirstate_tree::dispatch::DirstateMapMethods;
4 use hg::dirstate_tree::on_disk::DirstateV2ParseError;
5 use hg::matchers::Matcher;
6 use hg::utils::hg_path::{HgPath, HgPathBuf};
7 use hg::CopyMapIter;
8 use hg::DirstateEntry;
9 use hg::DirstateError;
10 use hg::DirstateParents;
11 use hg::DirstateStatus;
12 use hg::PatternFileWarning;
13 use hg::StateMapIter;
14 use hg::StatusError;
15 use hg::StatusOptions;
1 use crate::dirstate::parsers::Timestamp;
2 use crate::dirstate_tree::dispatch::DirstateMapMethods;
3 use crate::dirstate_tree::on_disk::DirstateV2ParseError;
4 use crate::dirstate_tree::owning::OwningDirstateMap;
5 use crate::matchers::Matcher;
6 use crate::utils::hg_path::{HgPath, HgPathBuf};
7 use crate::CopyMapIter;
8 use crate::DirstateEntry;
9 use crate::DirstateError;
10 use crate::DirstateParents;
11 use crate::DirstateStatus;
12 use crate::PatternFileWarning;
13 use crate::StateMapIter;
14 use crate::StatusError;
15 use crate::StatusOptions;
16 16 use std::path::PathBuf;
17 17
18 18 impl DirstateMapMethods for OwningDirstateMap {
19 19 fn clear(&mut self) {
20 20 self.get_mut().clear()
21 21 }
22 22
23 23 fn set_v1(&mut self, filename: &HgPath, entry: DirstateEntry) {
24 24 self.get_mut().set_v1(filename, entry)
25 25 }
26 26
27 27 fn add_file(
28 28 &mut self,
29 29 filename: &HgPath,
30 30 entry: DirstateEntry,
31 31 added: bool,
32 32 merged: bool,
33 33 from_p2: bool,
34 34 possibly_dirty: bool,
35 35 ) -> Result<(), DirstateError> {
36 36 self.get_mut().add_file(
37 37 filename,
38 38 entry,
39 39 added,
40 40 merged,
41 41 from_p2,
42 42 possibly_dirty,
43 43 )
44 44 }
45 45
46 46 fn remove_file(
47 47 &mut self,
48 48 filename: &HgPath,
49 49 in_merge: bool,
50 50 ) -> Result<(), DirstateError> {
51 51 self.get_mut().remove_file(filename, in_merge)
52 52 }
53 53
54 54 fn drop_file(&mut self, filename: &HgPath) -> Result<bool, DirstateError> {
55 55 self.get_mut().drop_file(filename)
56 56 }
57 57
58 58 fn clear_ambiguous_times(
59 59 &mut self,
60 60 filenames: Vec<HgPathBuf>,
61 61 now: i32,
62 62 ) -> Result<(), DirstateV2ParseError> {
63 63 self.get_mut().clear_ambiguous_times(filenames, now)
64 64 }
65 65
66 66 fn non_normal_entries_contains(
67 67 &mut self,
68 68 key: &HgPath,
69 69 ) -> Result<bool, DirstateV2ParseError> {
70 70 self.get_mut().non_normal_entries_contains(key)
71 71 }
72 72
73 73 fn non_normal_entries_remove(&mut self, key: &HgPath) -> bool {
74 74 self.get_mut().non_normal_entries_remove(key)
75 75 }
76 76
77 77 fn non_normal_entries_add(&mut self, key: &HgPath) {
78 78 self.get_mut().non_normal_entries_add(key)
79 79 }
80 80
81 81 fn non_normal_or_other_parent_paths(
82 82 &mut self,
83 83 ) -> Box<dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + '_>
84 84 {
85 85 self.get_mut().non_normal_or_other_parent_paths()
86 86 }
87 87
88 88 fn set_non_normal_other_parent_entries(&mut self, force: bool) {
89 89 self.get_mut().set_non_normal_other_parent_entries(force)
90 90 }
91 91
92 92 fn iter_non_normal_paths(
93 93 &mut self,
94 94 ) -> Box<
95 95 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
96 96 > {
97 97 self.get_mut().iter_non_normal_paths()
98 98 }
99 99
100 100 fn iter_non_normal_paths_panic(
101 101 &self,
102 102 ) -> Box<
103 103 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
104 104 > {
105 105 self.get().iter_non_normal_paths_panic()
106 106 }
107 107
108 108 fn iter_other_parent_paths(
109 109 &mut self,
110 110 ) -> Box<
111 111 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>> + Send + '_,
112 112 > {
113 113 self.get_mut().iter_other_parent_paths()
114 114 }
115 115
116 116 fn has_tracked_dir(
117 117 &mut self,
118 118 directory: &HgPath,
119 119 ) -> Result<bool, DirstateError> {
120 120 self.get_mut().has_tracked_dir(directory)
121 121 }
122 122
123 123 fn has_dir(&mut self, directory: &HgPath) -> Result<bool, DirstateError> {
124 124 self.get_mut().has_dir(directory)
125 125 }
126 126
127 127 fn pack_v1(
128 128 &mut self,
129 129 parents: DirstateParents,
130 130 now: Timestamp,
131 131 ) -> Result<Vec<u8>, DirstateError> {
132 132 self.get_mut().pack_v1(parents, now)
133 133 }
134 134
135 135 fn pack_v2(
136 136 &mut self,
137 137 now: Timestamp,
138 138 can_append: bool,
139 139 ) -> Result<(Vec<u8>, Vec<u8>, bool), DirstateError> {
140 140 self.get_mut().pack_v2(now, can_append)
141 141 }
142 142
143 143 fn status<'a>(
144 144 &'a mut self,
145 145 matcher: &'a (dyn Matcher + Sync),
146 146 root_dir: PathBuf,
147 147 ignore_files: Vec<PathBuf>,
148 148 options: StatusOptions,
149 149 ) -> Result<(DirstateStatus<'a>, Vec<PatternFileWarning>), StatusError>
150 150 {
151 151 self.get_mut()
152 152 .status(matcher, root_dir, ignore_files, options)
153 153 }
154 154
155 155 fn copy_map_len(&self) -> usize {
156 156 self.get().copy_map_len()
157 157 }
158 158
159 159 fn copy_map_iter(&self) -> CopyMapIter<'_> {
160 160 self.get().copy_map_iter()
161 161 }
162 162
163 163 fn copy_map_contains_key(
164 164 &self,
165 165 key: &HgPath,
166 166 ) -> Result<bool, DirstateV2ParseError> {
167 167 self.get().copy_map_contains_key(key)
168 168 }
169 169
170 170 fn copy_map_get(
171 171 &self,
172 172 key: &HgPath,
173 173 ) -> Result<Option<&HgPath>, DirstateV2ParseError> {
174 174 self.get().copy_map_get(key)
175 175 }
176 176
177 177 fn copy_map_remove(
178 178 &mut self,
179 179 key: &HgPath,
180 180 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
181 181 self.get_mut().copy_map_remove(key)
182 182 }
183 183
184 184 fn copy_map_insert(
185 185 &mut self,
186 186 key: HgPathBuf,
187 187 value: HgPathBuf,
188 188 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
189 189 self.get_mut().copy_map_insert(key, value)
190 190 }
191 191
192 192 fn len(&self) -> usize {
193 193 self.get().len()
194 194 }
195 195
196 196 fn contains_key(
197 197 &self,
198 198 key: &HgPath,
199 199 ) -> Result<bool, DirstateV2ParseError> {
200 200 self.get().contains_key(key)
201 201 }
202 202
203 203 fn get(
204 204 &self,
205 205 key: &HgPath,
206 206 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> {
207 207 self.get().get(key)
208 208 }
209 209
210 210 fn iter(&self) -> StateMapIter<'_> {
211 211 self.get().iter()
212 212 }
213 213
214 214 fn iter_tracked_dirs(
215 215 &mut self,
216 216 ) -> Result<
217 217 Box<
218 218 dyn Iterator<Item = Result<&HgPath, DirstateV2ParseError>>
219 219 + Send
220 220 + '_,
221 221 >,
222 222 DirstateError,
223 223 > {
224 224 self.get_mut().iter_tracked_dirs()
225 225 }
226 226
227 227 fn debug_iter(
228 228 &self,
229 229 ) -> Box<
230 230 dyn Iterator<
231 231 Item = Result<
232 232 (&HgPath, (u8, i32, i32, i32)),
233 233 DirstateV2ParseError,
234 234 >,
235 235 > + Send
236 236 + '_,
237 237 > {
238 238 self.get().debug_iter()
239 239 }
240 240 }
@@ -1,32 +1,33 b''
1 1 [package]
2 2 name = "hg-cpython"
3 3 version = "0.1.0"
4 4 authors = ["Georges Racinet <gracinet@anybox.fr>"]
5 5 edition = "2018"
6 6
7 7 [lib]
8 8 name='rusthg'
9 9 crate-type = ["cdylib"]
10 10
11 11 [features]
12 12 default = ["python27"]
13 13
14 14 # Features to build an extension module:
15 15 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
16 16 python3 = ["cpython/python3-sys", "cpython/extension-module"]
17 17
18 18 # Enable one of these features to build a test executable linked to libpython:
19 19 # e.g. cargo test --no-default-features --features python27-bin
20 20 python27-bin = ["cpython/python27-sys"]
21 21 python3-bin = ["cpython/python3-sys"]
22 22
23 23 [dependencies]
24 24 crossbeam-channel = "0.4"
25 25 hg-core = { path = "../hg-core"}
26 26 libc = '*'
27 27 log = "0.4.8"
28 28 env_logger = "0.7.1"
29 stable_deref_trait = "1.2.0"
29 30
30 31 [dependencies.cpython]
31 32 version = "0.6.0"
32 33 default-features = false
@@ -1,154 +1,152 b''
1 1 // dirstate.rs
2 2 //
3 3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings for the `hg::dirstate` module provided by the
9 9 //! `hg-core` package.
10 10 //!
11 11 //! From Python, this will be seen as `mercurial.rustext.dirstate`
12 12 mod copymap;
13 13 mod dirs_multiset;
14 14 mod dirstate_map;
15 mod dispatch;
16 15 mod non_normal_entries;
17 mod owning;
18 16 mod status;
19 17 use crate::{
20 18 dirstate::{
21 19 dirs_multiset::Dirs, dirstate_map::DirstateMap, status::status_wrapper,
22 20 },
23 21 exceptions,
24 22 };
25 23 use cpython::{
26 24 exc, PyBytes, PyDict, PyErr, PyList, PyModule, PyObject, PyResult,
27 25 PySequence, Python,
28 26 };
29 27 use hg::dirstate_tree::on_disk::V2_FORMAT_MARKER;
30 28 use hg::{utils::hg_path::HgPathBuf, DirstateEntry, EntryState, StateMap};
31 29 use libc::{c_char, c_int};
32 30 use std::convert::TryFrom;
33 31
34 32 // C code uses a custom `dirstate_tuple` type, checks in multiple instances
35 33 // for this type, and raises a Python `Exception` if the check does not pass.
36 34 // Because this type differs only in name from the regular Python tuple, it
37 35 // would be a good idea in the near future to remove it entirely to allow
38 36 // for a pure Python tuple of the same effective structure to be used,
39 37 // rendering this type and the capsule below useless.
40 38 py_capsule_fn!(
41 39 from mercurial.cext.parsers import make_dirstate_item_CAPI
42 40 as make_dirstate_item_capi
43 41 signature (
44 42 state: c_char,
45 43 mode: c_int,
46 44 size: c_int,
47 45 mtime: c_int,
48 46 ) -> *mut RawPyObject
49 47 );
50 48
51 49 pub fn make_dirstate_item(
52 50 py: Python,
53 51 entry: &DirstateEntry,
54 52 ) -> PyResult<PyObject> {
55 53 let &DirstateEntry {
56 54 state,
57 55 mode,
58 56 size,
59 57 mtime,
60 58 } = entry;
61 59 // Explicitly go through u8 first, then cast to platform-specific `c_char`
62 60 // because Into<u8> has a specific implementation while `as c_char` would
63 61 // just do a naive enum cast.
64 62 let state_code: u8 = state.into();
65 63 make_dirstate_item_raw(py, state_code, mode, size, mtime)
66 64 }
67 65
68 66 pub fn make_dirstate_item_raw(
69 67 py: Python,
70 68 state: u8,
71 69 mode: i32,
72 70 size: i32,
73 71 mtime: i32,
74 72 ) -> PyResult<PyObject> {
75 73 let make = make_dirstate_item_capi::retrieve(py)?;
76 74 let maybe_obj = unsafe {
77 75 let ptr = make(state as c_char, mode, size, mtime);
78 76 PyObject::from_owned_ptr_opt(py, ptr)
79 77 };
80 78 maybe_obj.ok_or_else(|| PyErr::fetch(py))
81 79 }
82 80
83 81 pub fn extract_dirstate(py: Python, dmap: &PyDict) -> Result<StateMap, PyErr> {
84 82 dmap.items(py)
85 83 .iter()
86 84 .map(|(filename, stats)| {
87 85 let stats = stats.extract::<PySequence>(py)?;
88 86 let state = stats.get_item(py, 0)?.extract::<PyBytes>(py)?;
89 87 let state =
90 88 EntryState::try_from(state.data(py)[0]).map_err(|e| {
91 89 PyErr::new::<exc::ValueError, _>(py, e.to_string())
92 90 })?;
93 91 let mode = stats.get_item(py, 1)?.extract(py)?;
94 92 let size = stats.get_item(py, 2)?.extract(py)?;
95 93 let mtime = stats.get_item(py, 3)?.extract(py)?;
96 94 let filename = filename.extract::<PyBytes>(py)?;
97 95 let filename = filename.data(py);
98 96 Ok((
99 97 HgPathBuf::from(filename.to_owned()),
100 98 DirstateEntry {
101 99 state,
102 100 mode,
103 101 size,
104 102 mtime,
105 103 },
106 104 ))
107 105 })
108 106 .collect()
109 107 }
110 108
111 109 /// Create the module, with `__package__` given from parent
112 110 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
113 111 let dotted_name = &format!("{}.dirstate", package);
114 112 let m = PyModule::new(py, dotted_name)?;
115 113
116 114 env_logger::init();
117 115
118 116 m.add(py, "__package__", package)?;
119 117 m.add(py, "__doc__", "Dirstate - Rust implementation")?;
120 118
121 119 m.add(
122 120 py,
123 121 "FallbackError",
124 122 py.get_type::<exceptions::FallbackError>(),
125 123 )?;
126 124 m.add_class::<Dirs>(py)?;
127 125 m.add_class::<DirstateMap>(py)?;
128 126 m.add(py, "V2_FORMAT_MARKER", PyBytes::new(py, V2_FORMAT_MARKER))?;
129 127 m.add(
130 128 py,
131 129 "status",
132 130 py_fn!(
133 131 py,
134 132 status_wrapper(
135 133 dmap: DirstateMap,
136 134 root_dir: PyObject,
137 135 matcher: PyObject,
138 136 ignorefiles: PyList,
139 137 check_exec: bool,
140 138 last_normal_time: i64,
141 139 list_clean: bool,
142 140 list_ignored: bool,
143 141 list_unknown: bool,
144 142 collect_traversed_dirs: bool
145 143 )
146 144 ),
147 145 )?;
148 146
149 147 let sys = PyModule::import(py, "sys")?;
150 148 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
151 149 sys_modules.set_item(py, dotted_name, &m)?;
152 150
153 151 Ok(m)
154 152 }
@@ -1,669 +1,679 b''
1 1 // dirstate_map.rs
2 2 //
3 3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 4 //
5 5 // This software may be used and distributed according to the terms of the
6 6 // GNU General Public License version 2 or any later version.
7 7
8 8 //! Bindings for the `hg::dirstate::dirstate_map` file provided by the
9 9 //! `hg-core` package.
10 10
11 11 use std::cell::{RefCell, RefMut};
12 12 use std::convert::TryInto;
13 13
14 14 use cpython::{
15 15 exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList,
16 16 PyObject, PyResult, PySet, PyString, Python, PythonObject, ToPyObject,
17 17 UnsafePyLeaked,
18 18 };
19 19
20 20 use crate::{
21 21 dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
22 22 dirstate::make_dirstate_item,
23 23 dirstate::make_dirstate_item_raw,
24 24 dirstate::non_normal_entries::{
25 25 NonNormalEntries, NonNormalEntriesIterator,
26 26 },
27 dirstate::owning::OwningDirstateMap,
28 27 parsers::dirstate_parents_to_pytuple,
28 pybytes_deref::PyBytesDeref,
29 29 };
30 30 use hg::{
31 31 dirstate::parsers::Timestamp,
32 32 dirstate::MTIME_UNSET,
33 33 dirstate::SIZE_NON_NORMAL,
34 dirstate_tree::dirstate_map::DirstateMap as TreeDirstateMap,
34 35 dirstate_tree::dispatch::DirstateMapMethods,
35 36 dirstate_tree::on_disk::DirstateV2ParseError,
37 dirstate_tree::owning::OwningDirstateMap,
36 38 revlog::Node,
37 39 utils::files::normalize_case,
38 40 utils::hg_path::{HgPath, HgPathBuf},
39 41 DirstateEntry, DirstateError, DirstateMap as RustDirstateMap,
40 42 DirstateParents, EntryState, StateMapIter,
41 43 };
42 44
43 45 // TODO
44 46 // This object needs to share references to multiple members of its Rust
45 47 // inner struct, namely `copy_map`, `dirs` and `all_dirs`.
46 48 // Right now `CopyMap` is done, but it needs to have an explicit reference
47 49 // to `RustDirstateMap` which itself needs to have an encapsulation for
48 50 // every method in `CopyMap` (copymapcopy, etc.).
49 51 // This is ugly and hard to maintain.
50 52 // The same logic applies to `dirs` and `all_dirs`, however the `Dirs`
51 53 // `py_class!` is already implemented and does not mention
52 54 // `RustDirstateMap`, rightfully so.
53 55 // All attributes also have to have a separate refcount data attribute for
54 56 // leaks, with all methods that go along for reference sharing.
55 57 py_class!(pub class DirstateMap |py| {
56 58 @shared data inner: Box<dyn DirstateMapMethods + Send>;
57 59
58 60 /// Returns a `(dirstate_map, parents)` tuple
59 61 @staticmethod
60 62 def new_v1(
61 63 use_dirstate_tree: bool,
62 64 on_disk: PyBytes,
63 65 ) -> PyResult<PyObject> {
64 66 let (inner, parents) = if use_dirstate_tree {
65 let (map, parents) = OwningDirstateMap::new_v1(py, on_disk)
67 let on_disk = PyBytesDeref::new(py, on_disk);
68 let mut map = OwningDirstateMap::new_empty(on_disk);
69 let (on_disk, map_placeholder) = map.get_mut_pair();
70
71 let (actual_map, parents) = TreeDirstateMap::new_v1(on_disk)
66 72 .map_err(|e| dirstate_error(py, e))?;
73 *map_placeholder = actual_map;
67 74 (Box::new(map) as _, parents)
68 75 } else {
69 76 let bytes = on_disk.data(py);
70 77 let mut map = RustDirstateMap::default();
71 78 let parents = map.read(bytes).map_err(|e| dirstate_error(py, e))?;
72 79 (Box::new(map) as _, parents)
73 80 };
74 81 let map = Self::create_instance(py, inner)?;
75 82 let parents = parents.map(|p| dirstate_parents_to_pytuple(py, &p));
76 83 Ok((map, parents).to_py_object(py).into_object())
77 84 }
78 85
79 86 /// Returns a DirstateMap
80 87 @staticmethod
81 88 def new_v2(
82 89 on_disk: PyBytes,
83 90 data_size: usize,
84 91 tree_metadata: PyBytes,
85 92 ) -> PyResult<PyObject> {
86 93 let dirstate_error = |e: DirstateError| {
87 94 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
88 95 };
89 let inner = OwningDirstateMap::new_v2(
90 py, on_disk, data_size, tree_metadata,
96 let on_disk = PyBytesDeref::new(py, on_disk);
97 let mut map = OwningDirstateMap::new_empty(on_disk);
98 let (on_disk, map_placeholder) = map.get_mut_pair();
99 *map_placeholder = TreeDirstateMap::new_v2(
100 on_disk, data_size, tree_metadata.data(py),
91 101 ).map_err(dirstate_error)?;
92 let map = Self::create_instance(py, Box::new(inner))?;
102 let map = Self::create_instance(py, Box::new(map))?;
93 103 Ok(map.into_object())
94 104 }
95 105
96 106 def clear(&self) -> PyResult<PyObject> {
97 107 self.inner(py).borrow_mut().clear();
98 108 Ok(py.None())
99 109 }
100 110
101 111 def get(
102 112 &self,
103 113 key: PyObject,
104 114 default: Option<PyObject> = None
105 115 ) -> PyResult<Option<PyObject>> {
106 116 let key = key.extract::<PyBytes>(py)?;
107 117 match self
108 118 .inner(py)
109 119 .borrow()
110 120 .get(HgPath::new(key.data(py)))
111 121 .map_err(|e| v2_error(py, e))?
112 122 {
113 123 Some(entry) => {
114 124 Ok(Some(make_dirstate_item(py, &entry)?))
115 125 },
116 126 None => Ok(default)
117 127 }
118 128 }
119 129
120 130 def set_v1(&self, path: PyObject, item: PyObject) -> PyResult<PyObject> {
121 131 let f = path.extract::<PyBytes>(py)?;
122 132 let filename = HgPath::new(f.data(py));
123 133 let state = item.getattr(py, "state")?.extract::<PyBytes>(py)?;
124 134 let state = state.data(py)[0];
125 135 let entry = DirstateEntry {
126 136 state: state.try_into().expect("state is always valid"),
127 137 mtime: item.getattr(py, "mtime")?.extract(py)?,
128 138 size: item.getattr(py, "size")?.extract(py)?,
129 139 mode: item.getattr(py, "mode")?.extract(py)?,
130 140 };
131 141 self.inner(py).borrow_mut().set_v1(filename, entry);
132 142 Ok(py.None())
133 143 }
134 144
135 145 def addfile(
136 146 &self,
137 147 f: PyObject,
138 148 mode: PyObject,
139 149 size: PyObject,
140 150 mtime: PyObject,
141 151 added: PyObject,
142 152 merged: PyObject,
143 153 from_p2: PyObject,
144 154 possibly_dirty: PyObject,
145 155 ) -> PyResult<PyObject> {
146 156 let f = f.extract::<PyBytes>(py)?;
147 157 let filename = HgPath::new(f.data(py));
148 158 let mode = if mode.is_none(py) {
149 159 // fallback default value
150 160 0
151 161 } else {
152 162 mode.extract(py)?
153 163 };
154 164 let size = if size.is_none(py) {
155 165 // fallback default value
156 166 SIZE_NON_NORMAL
157 167 } else {
158 168 size.extract(py)?
159 169 };
160 170 let mtime = if mtime.is_none(py) {
161 171 // fallback default value
162 172 MTIME_UNSET
163 173 } else {
164 174 mtime.extract(py)?
165 175 };
166 176 let entry = DirstateEntry {
167 177 // XXX Arbitrary default value since the value is determined later
168 178 state: EntryState::Normal,
169 179 mode: mode,
170 180 size: size,
171 181 mtime: mtime,
172 182 };
173 183 let added = added.extract::<PyBool>(py)?.is_true();
174 184 let merged = merged.extract::<PyBool>(py)?.is_true();
175 185 let from_p2 = from_p2.extract::<PyBool>(py)?.is_true();
176 186 let possibly_dirty = possibly_dirty.extract::<PyBool>(py)?.is_true();
177 187 self.inner(py).borrow_mut().add_file(
178 188 filename,
179 189 entry,
180 190 added,
181 191 merged,
182 192 from_p2,
183 193 possibly_dirty
184 194 ).and(Ok(py.None())).or_else(|e: DirstateError| {
185 195 Err(PyErr::new::<exc::ValueError, _>(py, e.to_string()))
186 196 })
187 197 }
188 198
189 199 def removefile(
190 200 &self,
191 201 f: PyObject,
192 202 in_merge: PyObject
193 203 ) -> PyResult<PyObject> {
194 204 self.inner(py).borrow_mut()
195 205 .remove_file(
196 206 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
197 207 in_merge.extract::<PyBool>(py)?.is_true(),
198 208 )
199 209 .or_else(|_| {
200 210 Err(PyErr::new::<exc::OSError, _>(
201 211 py,
202 212 "Dirstate error".to_string(),
203 213 ))
204 214 })?;
205 215 Ok(py.None())
206 216 }
207 217
208 218 def dropfile(
209 219 &self,
210 220 f: PyObject,
211 221 ) -> PyResult<PyBool> {
212 222 self.inner(py).borrow_mut()
213 223 .drop_file(
214 224 HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
215 225 )
216 226 .and_then(|b| Ok(b.to_py_object(py)))
217 227 .or_else(|e| {
218 228 Err(PyErr::new::<exc::OSError, _>(
219 229 py,
220 230 format!("Dirstate error: {}", e.to_string()),
221 231 ))
222 232 })
223 233 }
224 234
225 235 def clearambiguoustimes(
226 236 &self,
227 237 files: PyObject,
228 238 now: PyObject
229 239 ) -> PyResult<PyObject> {
230 240 let files: PyResult<Vec<HgPathBuf>> = files
231 241 .iter(py)?
232 242 .map(|filename| {
233 243 Ok(HgPathBuf::from_bytes(
234 244 filename?.extract::<PyBytes>(py)?.data(py),
235 245 ))
236 246 })
237 247 .collect();
238 248 self.inner(py)
239 249 .borrow_mut()
240 250 .clear_ambiguous_times(files?, now.extract(py)?)
241 251 .map_err(|e| v2_error(py, e))?;
242 252 Ok(py.None())
243 253 }
244 254
245 255 def other_parent_entries(&self) -> PyResult<PyObject> {
246 256 let mut inner_shared = self.inner(py).borrow_mut();
247 257 let set = PySet::empty(py)?;
248 258 for path in inner_shared.iter_other_parent_paths() {
249 259 let path = path.map_err(|e| v2_error(py, e))?;
250 260 set.add(py, PyBytes::new(py, path.as_bytes()))?;
251 261 }
252 262 Ok(set.into_object())
253 263 }
254 264
255 265 def non_normal_entries(&self) -> PyResult<NonNormalEntries> {
256 266 NonNormalEntries::from_inner(py, self.clone_ref(py))
257 267 }
258 268
259 269 def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> {
260 270 let key = key.extract::<PyBytes>(py)?;
261 271 self.inner(py)
262 272 .borrow_mut()
263 273 .non_normal_entries_contains(HgPath::new(key.data(py)))
264 274 .map_err(|e| v2_error(py, e))
265 275 }
266 276
267 277 def non_normal_entries_display(&self) -> PyResult<PyString> {
268 278 let mut inner = self.inner(py).borrow_mut();
269 279 let paths = inner
270 280 .iter_non_normal_paths()
271 281 .collect::<Result<Vec<_>, _>>()
272 282 .map_err(|e| v2_error(py, e))?;
273 283 let formatted = format!("NonNormalEntries: {}", hg::utils::join_display(paths, ", "));
274 284 Ok(PyString::new(py, &formatted))
275 285 }
276 286
277 287 def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> {
278 288 let key = key.extract::<PyBytes>(py)?;
279 289 let key = key.data(py);
280 290 let was_present = self
281 291 .inner(py)
282 292 .borrow_mut()
283 293 .non_normal_entries_remove(HgPath::new(key));
284 294 if !was_present {
285 295 let msg = String::from_utf8_lossy(key);
286 296 Err(PyErr::new::<exc::KeyError, _>(py, msg))
287 297 } else {
288 298 Ok(py.None())
289 299 }
290 300 }
291 301
292 302 def non_normal_entries_discard(&self, key: PyObject) -> PyResult<PyObject>
293 303 {
294 304 let key = key.extract::<PyBytes>(py)?;
295 305 self
296 306 .inner(py)
297 307 .borrow_mut()
298 308 .non_normal_entries_remove(HgPath::new(key.data(py)));
299 309 Ok(py.None())
300 310 }
301 311
302 312 def non_normal_entries_add(&self, key: PyObject) -> PyResult<PyObject> {
303 313 let key = key.extract::<PyBytes>(py)?;
304 314 self
305 315 .inner(py)
306 316 .borrow_mut()
307 317 .non_normal_entries_add(HgPath::new(key.data(py)));
308 318 Ok(py.None())
309 319 }
310 320
311 321 def non_normal_or_other_parent_paths(&self) -> PyResult<PyList> {
312 322 let mut inner = self.inner(py).borrow_mut();
313 323
314 324 let ret = PyList::new(py, &[]);
315 325 for filename in inner.non_normal_or_other_parent_paths() {
316 326 let filename = filename.map_err(|e| v2_error(py, e))?;
317 327 let as_pystring = PyBytes::new(py, filename.as_bytes());
318 328 ret.append(py, as_pystring.into_object());
319 329 }
320 330 Ok(ret)
321 331 }
322 332
323 333 def non_normal_entries_iter(&self) -> PyResult<NonNormalEntriesIterator> {
324 334 // Make sure the sets are defined before we no longer have a mutable
325 335 // reference to the dmap.
326 336 self.inner(py)
327 337 .borrow_mut()
328 338 .set_non_normal_other_parent_entries(false);
329 339
330 340 let leaked_ref = self.inner(py).leak_immutable();
331 341
332 342 NonNormalEntriesIterator::from_inner(py, unsafe {
333 343 leaked_ref.map(py, |o| {
334 344 o.iter_non_normal_paths_panic()
335 345 })
336 346 })
337 347 }
338 348
339 349 def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
340 350 let d = d.extract::<PyBytes>(py)?;
341 351 Ok(self.inner(py).borrow_mut()
342 352 .has_tracked_dir(HgPath::new(d.data(py)))
343 353 .map_err(|e| {
344 354 PyErr::new::<exc::ValueError, _>(py, e.to_string())
345 355 })?
346 356 .to_py_object(py))
347 357 }
348 358
349 359 def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
350 360 let d = d.extract::<PyBytes>(py)?;
351 361 Ok(self.inner(py).borrow_mut()
352 362 .has_dir(HgPath::new(d.data(py)))
353 363 .map_err(|e| {
354 364 PyErr::new::<exc::ValueError, _>(py, e.to_string())
355 365 })?
356 366 .to_py_object(py))
357 367 }
358 368
359 369 def write_v1(
360 370 &self,
361 371 p1: PyObject,
362 372 p2: PyObject,
363 373 now: PyObject
364 374 ) -> PyResult<PyBytes> {
365 375 let now = Timestamp(now.extract(py)?);
366 376
367 377 let mut inner = self.inner(py).borrow_mut();
368 378 let parents = DirstateParents {
369 379 p1: extract_node_id(py, &p1)?,
370 380 p2: extract_node_id(py, &p2)?,
371 381 };
372 382 let result = inner.pack_v1(parents, now);
373 383 match result {
374 384 Ok(packed) => Ok(PyBytes::new(py, &packed)),
375 385 Err(_) => Err(PyErr::new::<exc::OSError, _>(
376 386 py,
377 387 "Dirstate error".to_string(),
378 388 )),
379 389 }
380 390 }
381 391
382 392 /// Returns new data together with whether that data should be appended to
383 393 /// the existing data file whose content is at `self.on_disk` (True),
384 394 /// instead of written to a new data file (False).
385 395 def write_v2(
386 396 &self,
387 397 now: PyObject,
388 398 can_append: bool,
389 399 ) -> PyResult<PyObject> {
390 400 let now = Timestamp(now.extract(py)?);
391 401
392 402 let mut inner = self.inner(py).borrow_mut();
393 403 let result = inner.pack_v2(now, can_append);
394 404 match result {
395 405 Ok((packed, tree_metadata, append)) => {
396 406 let packed = PyBytes::new(py, &packed);
397 407 let tree_metadata = PyBytes::new(py, &tree_metadata);
398 408 let tuple = (packed, tree_metadata, append);
399 409 Ok(tuple.to_py_object(py).into_object())
400 410 },
401 411 Err(_) => Err(PyErr::new::<exc::OSError, _>(
402 412 py,
403 413 "Dirstate error".to_string(),
404 414 )),
405 415 }
406 416 }
407 417
408 418 def filefoldmapasdict(&self) -> PyResult<PyDict> {
409 419 let dict = PyDict::new(py);
410 420 for item in self.inner(py).borrow_mut().iter() {
411 421 let (path, entry) = item.map_err(|e| v2_error(py, e))?;
412 422 if entry.state != EntryState::Removed {
413 423 let key = normalize_case(path);
414 424 let value = path;
415 425 dict.set_item(
416 426 py,
417 427 PyBytes::new(py, key.as_bytes()).into_object(),
418 428 PyBytes::new(py, value.as_bytes()).into_object(),
419 429 )?;
420 430 }
421 431 }
422 432 Ok(dict)
423 433 }
424 434
425 435 def __len__(&self) -> PyResult<usize> {
426 436 Ok(self.inner(py).borrow().len())
427 437 }
428 438
429 439 def __contains__(&self, key: PyObject) -> PyResult<bool> {
430 440 let key = key.extract::<PyBytes>(py)?;
431 441 self.inner(py)
432 442 .borrow()
433 443 .contains_key(HgPath::new(key.data(py)))
434 444 .map_err(|e| v2_error(py, e))
435 445 }
436 446
437 447 def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
438 448 let key = key.extract::<PyBytes>(py)?;
439 449 let key = HgPath::new(key.data(py));
440 450 match self
441 451 .inner(py)
442 452 .borrow()
443 453 .get(key)
444 454 .map_err(|e| v2_error(py, e))?
445 455 {
446 456 Some(entry) => {
447 457 Ok(make_dirstate_item(py, &entry)?)
448 458 },
449 459 None => Err(PyErr::new::<exc::KeyError, _>(
450 460 py,
451 461 String::from_utf8_lossy(key.as_bytes()),
452 462 )),
453 463 }
454 464 }
455 465
456 466 def keys(&self) -> PyResult<DirstateMapKeysIterator> {
457 467 let leaked_ref = self.inner(py).leak_immutable();
458 468 DirstateMapKeysIterator::from_inner(
459 469 py,
460 470 unsafe { leaked_ref.map(py, |o| o.iter()) },
461 471 )
462 472 }
463 473
464 474 def items(&self) -> PyResult<DirstateMapItemsIterator> {
465 475 let leaked_ref = self.inner(py).leak_immutable();
466 476 DirstateMapItemsIterator::from_inner(
467 477 py,
468 478 unsafe { leaked_ref.map(py, |o| o.iter()) },
469 479 )
470 480 }
471 481
472 482 def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
473 483 let leaked_ref = self.inner(py).leak_immutable();
474 484 DirstateMapKeysIterator::from_inner(
475 485 py,
476 486 unsafe { leaked_ref.map(py, |o| o.iter()) },
477 487 )
478 488 }
479 489
480 490 // TODO all copymap* methods, see docstring above
481 491 def copymapcopy(&self) -> PyResult<PyDict> {
482 492 let dict = PyDict::new(py);
483 493 for item in self.inner(py).borrow().copy_map_iter() {
484 494 let (key, value) = item.map_err(|e| v2_error(py, e))?;
485 495 dict.set_item(
486 496 py,
487 497 PyBytes::new(py, key.as_bytes()),
488 498 PyBytes::new(py, value.as_bytes()),
489 499 )?;
490 500 }
491 501 Ok(dict)
492 502 }
493 503
494 504 def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
495 505 let key = key.extract::<PyBytes>(py)?;
496 506 match self
497 507 .inner(py)
498 508 .borrow()
499 509 .copy_map_get(HgPath::new(key.data(py)))
500 510 .map_err(|e| v2_error(py, e))?
501 511 {
502 512 Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())),
503 513 None => Err(PyErr::new::<exc::KeyError, _>(
504 514 py,
505 515 String::from_utf8_lossy(key.data(py)),
506 516 )),
507 517 }
508 518 }
509 519 def copymap(&self) -> PyResult<CopyMap> {
510 520 CopyMap::from_inner(py, self.clone_ref(py))
511 521 }
512 522
513 523 def copymaplen(&self) -> PyResult<usize> {
514 524 Ok(self.inner(py).borrow().copy_map_len())
515 525 }
516 526 def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
517 527 let key = key.extract::<PyBytes>(py)?;
518 528 self.inner(py)
519 529 .borrow()
520 530 .copy_map_contains_key(HgPath::new(key.data(py)))
521 531 .map_err(|e| v2_error(py, e))
522 532 }
523 533 def copymapget(
524 534 &self,
525 535 key: PyObject,
526 536 default: Option<PyObject>
527 537 ) -> PyResult<Option<PyObject>> {
528 538 let key = key.extract::<PyBytes>(py)?;
529 539 match self
530 540 .inner(py)
531 541 .borrow()
532 542 .copy_map_get(HgPath::new(key.data(py)))
533 543 .map_err(|e| v2_error(py, e))?
534 544 {
535 545 Some(copy) => Ok(Some(
536 546 PyBytes::new(py, copy.as_bytes()).into_object(),
537 547 )),
538 548 None => Ok(default),
539 549 }
540 550 }
541 551 def copymapsetitem(
542 552 &self,
543 553 key: PyObject,
544 554 value: PyObject
545 555 ) -> PyResult<PyObject> {
546 556 let key = key.extract::<PyBytes>(py)?;
547 557 let value = value.extract::<PyBytes>(py)?;
548 558 self.inner(py)
549 559 .borrow_mut()
550 560 .copy_map_insert(
551 561 HgPathBuf::from_bytes(key.data(py)),
552 562 HgPathBuf::from_bytes(value.data(py)),
553 563 )
554 564 .map_err(|e| v2_error(py, e))?;
555 565 Ok(py.None())
556 566 }
557 567 def copymappop(
558 568 &self,
559 569 key: PyObject,
560 570 default: Option<PyObject>
561 571 ) -> PyResult<Option<PyObject>> {
562 572 let key = key.extract::<PyBytes>(py)?;
563 573 match self
564 574 .inner(py)
565 575 .borrow_mut()
566 576 .copy_map_remove(HgPath::new(key.data(py)))
567 577 .map_err(|e| v2_error(py, e))?
568 578 {
569 579 Some(_) => Ok(None),
570 580 None => Ok(default),
571 581 }
572 582 }
573 583
574 584 def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
575 585 let leaked_ref = self.inner(py).leak_immutable();
576 586 CopyMapKeysIterator::from_inner(
577 587 py,
578 588 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
579 589 )
580 590 }
581 591
582 592 def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
583 593 let leaked_ref = self.inner(py).leak_immutable();
584 594 CopyMapItemsIterator::from_inner(
585 595 py,
586 596 unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
587 597 )
588 598 }
589 599
590 600 def tracked_dirs(&self) -> PyResult<PyList> {
591 601 let dirs = PyList::new(py, &[]);
592 602 for path in self.inner(py).borrow_mut().iter_tracked_dirs()
593 603 .map_err(|e |dirstate_error(py, e))?
594 604 {
595 605 let path = path.map_err(|e| v2_error(py, e))?;
596 606 let path = PyBytes::new(py, path.as_bytes());
597 607 dirs.append(py, path.into_object())
598 608 }
599 609 Ok(dirs)
600 610 }
601 611
602 612 def debug_iter(&self) -> PyResult<PyList> {
603 613 let dirs = PyList::new(py, &[]);
604 614 for item in self.inner(py).borrow().debug_iter() {
605 615 let (path, (state, mode, size, mtime)) =
606 616 item.map_err(|e| v2_error(py, e))?;
607 617 let path = PyBytes::new(py, path.as_bytes());
608 618 let item = make_dirstate_item_raw(py, state, mode, size, mtime)?;
609 619 dirs.append(py, (path, item).to_py_object(py).into_object())
610 620 }
611 621 Ok(dirs)
612 622 }
613 623 });
614 624
615 625 impl DirstateMap {
616 626 pub fn get_inner_mut<'a>(
617 627 &'a self,
618 628 py: Python<'a>,
619 629 ) -> RefMut<'a, Box<dyn DirstateMapMethods + Send>> {
620 630 self.inner(py).borrow_mut()
621 631 }
622 632 fn translate_key(
623 633 py: Python,
624 634 res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
625 635 ) -> PyResult<Option<PyBytes>> {
626 636 let (f, _entry) = res.map_err(|e| v2_error(py, e))?;
627 637 Ok(Some(PyBytes::new(py, f.as_bytes())))
628 638 }
629 639 fn translate_key_value(
630 640 py: Python,
631 641 res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
632 642 ) -> PyResult<Option<(PyBytes, PyObject)>> {
633 643 let (f, entry) = res.map_err(|e| v2_error(py, e))?;
634 644 Ok(Some((
635 645 PyBytes::new(py, f.as_bytes()),
636 646 make_dirstate_item(py, &entry)?,
637 647 )))
638 648 }
639 649 }
640 650
641 651 py_shared_iterator!(
642 652 DirstateMapKeysIterator,
643 653 UnsafePyLeaked<StateMapIter<'static>>,
644 654 DirstateMap::translate_key,
645 655 Option<PyBytes>
646 656 );
647 657
648 658 py_shared_iterator!(
649 659 DirstateMapItemsIterator,
650 660 UnsafePyLeaked<StateMapIter<'static>>,
651 661 DirstateMap::translate_key_value,
652 662 Option<(PyBytes, PyObject)>
653 663 );
654 664
655 665 fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<Node> {
656 666 let bytes = obj.extract::<PyBytes>(py)?;
657 667 match bytes.data(py).try_into() {
658 668 Ok(s) => Ok(s),
659 669 Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())),
660 670 }
661 671 }
662 672
663 673 pub(super) fn v2_error(py: Python<'_>, _: DirstateV2ParseError) -> PyErr {
664 674 PyErr::new::<exc::ValueError, _>(py, "corrupted dirstate-v2")
665 675 }
666 676
667 677 fn dirstate_error(py: Python<'_>, e: DirstateError) -> PyErr {
668 678 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
669 679 }
@@ -1,53 +1,56 b''
1 1 use cpython::{PyBytes, Python};
2 use stable_deref_trait::StableDeref;
2 3
3 4 /// Safe abstraction over a `PyBytes` together with the `&[u8]` slice
4 5 /// that borrows it. Implements `Deref<Target = [u8]>`.
5 6 ///
6 7 /// Calling `PyBytes::data` requires a GIL marker but we want to access the
7 8 /// data in a thread that (ideally) does not need to acquire the GIL.
8 9 /// This type allows separating the call an the use.
9 10 ///
10 11 /// It also enables using a (wrapped) `PyBytes` in GIL-unaware generic code.
11 12 pub struct PyBytesDeref {
12 13 #[allow(unused)]
13 14 keep_alive: PyBytes,
14 15
15 16 /// Borrows the buffer inside `self.keep_alive`,
16 17 /// but the borrow-checker cannot express self-referential structs.
17 18 data: *const [u8],
18 19 }
19 20
20 21 impl PyBytesDeref {
21 22 pub fn new(py: Python, bytes: PyBytes) -> Self {
22 23 Self {
23 24 data: bytes.data(py),
24 25 keep_alive: bytes,
25 26 }
26 27 }
27 28
28 29 pub fn unwrap(self) -> PyBytes {
29 30 self.keep_alive
30 31 }
31 32 }
32 33
33 34 impl std::ops::Deref for PyBytesDeref {
34 35 type Target = [u8];
35 36
36 37 fn deref(&self) -> &[u8] {
37 38 // Safety: the raw pointer is valid as long as the PyBytes is still
38 39 // alive, and the returned slice borrows `self`.
39 40 unsafe { &*self.data }
40 41 }
41 42 }
42 43
44 unsafe impl StableDeref for PyBytesDeref {}
45
43 46 fn require_send<T: Send>() {}
44 47
45 48 #[allow(unused)]
46 49 fn static_assert_pybytes_is_send() {
47 50 require_send::<PyBytes>;
48 51 }
49 52
50 53 // Safety: PyBytes is Send. Raw pointers are not by default,
51 54 // but here sending one to another thread is fine since we ensure it stays
52 55 // valid.
53 56 unsafe impl Send for PyBytesDeref {}
General Comments 0
You need to be logged in to leave comments. Login now