Show More
@@ -1,5 +1,7 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" |
@@ -396,6 +398,7 b' dependencies = [' | |||
|
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", |
@@ -411,6 +414,7 b' dependencies = [' | |||
|
411 | 414 | "hg-core", |
|
412 | 415 | "libc", |
|
413 | 416 | "log", |
|
417 | "stable_deref_trait", | |
|
414 | 418 | ] |
|
415 | 419 | |
|
416 | 420 | [[package]] |
@@ -865,6 +869,12 b' dependencies = [' | |||
|
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" |
@@ -24,6 +24,7 b' 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" |
@@ -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,11 +1,9 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 |
@@ -13,11 +11,11 b' use hg::DirstateParents;' | |||
|
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 |
|
|
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. |
@@ -28,12 +26,13 b' pub(super) struct OwningDirstateMap {' | |||
|
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`. |
@@ -42,30 +41,12 b' impl OwningDirstateMap {' | |||
|
42 | 41 | // Erase the pointed type entirely in order to erase the lifetime. |
|
43 | 42 | let ptr: *mut () = ptr.cast(); |
|
44 | 43 | |
|
45 |
|
|
|
44 | Self { on_disk, ptr } | |
|
46 | 45 | } |
|
47 | 46 | |
|
48 |
pub fn |
|
|
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 |
@@ -76,7 +57,11 b' impl OwningDirstateMap {' | |||
|
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> { |
@@ -84,6 +69,10 b' impl OwningDirstateMap {' | |||
|
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 { |
@@ -105,13 +94,12 b' impl Drop for OwningDirstateMap {' | |||
|
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` |
|
|
116 |
// |
|
|
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,18 +1,18 b'' | |||
|
1 |
use crate::dirstate:: |
|
|
2 | use hg::dirstate::parsers::Timestamp; | |
|
3 |
use |
|
|
4 |
use |
|
|
5 |
use |
|
|
6 |
use |
|
|
7 |
use |
|
|
8 |
use |
|
|
9 |
use |
|
|
10 |
use |
|
|
11 |
use |
|
|
12 |
use |
|
|
13 |
use |
|
|
14 |
use |
|
|
15 |
use |
|
|
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 { |
@@ -26,6 +26,7 b' 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" |
@@ -12,9 +12,7 b'' | |||
|
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::{ |
@@ -24,15 +24,17 b' use crate::{' | |||
|
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}, |
@@ -62,8 +64,13 b' py_class!(pub class DirstateMap |py| {' | |||
|
62 | 64 | on_disk: PyBytes, |
|
63 | 65 | ) -> PyResult<PyObject> { |
|
64 | 66 | let (inner, parents) = if use_dirstate_tree { |
|
65 |
let |
|
|
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); |
@@ -86,10 +93,13 b' py_class!(pub class DirstateMap |py| {' | |||
|
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( |
|
|
102 | let map = Self::create_instance(py, Box::new(map))?; | |
|
93 | 103 | Ok(map.into_object()) |
|
94 | 104 | } |
|
95 | 105 |
@@ -1,4 +1,5 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]>`. |
@@ -40,6 +41,8 b' impl std::ops::Deref for PyBytesDeref {' | |||
|
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)] |
General Comments 0
You need to be logged in to leave comments.
Login now