Show More
@@ -573,11 +573,15 b' if rustmod is not None:' | |||||
573 | testing.wait_on_cfg(self._ui, b'dirstate.post-docket-read-file') |
|
573 | testing.wait_on_cfg(self._ui, b'dirstate.post-docket-read-file') | |
574 | if not self.docket.uuid: |
|
574 | if not self.docket.uuid: | |
575 | data = b'' |
|
575 | data = b'' | |
|
576 | self._map = rustmod.DirstateMap.new_empty() | |||
576 | else: |
|
577 | else: | |
577 | data = self._read_v2_data() |
|
578 | data = self._read_v2_data() | |
578 | self._map = rustmod.DirstateMap.new_v2( |
|
579 | self._map = rustmod.DirstateMap.new_v2( | |
579 | data, self.docket.data_size, self.docket.tree_metadata |
|
580 | data, | |
580 | ) |
|
581 | self.docket.data_size, | |
|
582 | self.docket.tree_metadata, | |||
|
583 | self.docket.uuid, | |||
|
584 | ) | |||
581 | parents = self.docket.parents |
|
585 | parents = self.docket.parents | |
582 | else: |
|
586 | else: | |
583 | self._set_identity() |
|
587 | self._set_identity() |
@@ -66,9 +66,16 b" pub struct DirstateMap<'on_disk> {" | |||||
66 | pub(super) unreachable_bytes: u32, |
|
66 | pub(super) unreachable_bytes: u32, | |
67 |
|
67 | |||
68 | /// Size of the data used to first load this `DirstateMap`. Used in case |
|
68 | /// Size of the data used to first load this `DirstateMap`. Used in case | |
69 |
/// we need to write some new metadata, but no new data on disk |
|
69 | /// we need to write some new metadata, but no new data on disk, | |
|
70 | /// as well as to detect writes that have happened in another process | |||
|
71 | /// since first read. | |||
70 | pub(super) old_data_size: usize, |
|
72 | pub(super) old_data_size: usize, | |
71 |
|
73 | |||
|
74 | /// UUID used when first loading this `DirstateMap`. Used to check if | |||
|
75 | /// the UUID has been changed by another process since first read. | |||
|
76 | /// Can be `None` if using dirstate v1 or if it's a brand new dirstate. | |||
|
77 | pub(super) old_uuid: Option<Vec<u8>>, | |||
|
78 | ||||
72 | pub(super) dirstate_version: DirstateVersion, |
|
79 | pub(super) dirstate_version: DirstateVersion, | |
73 |
|
80 | |||
74 | /// Controlled by config option `devel.dirstate.v2.data_update_mode` |
|
81 | /// Controlled by config option `devel.dirstate.v2.data_update_mode` | |
@@ -460,6 +467,7 b" impl<'on_disk> DirstateMap<'on_disk> {" | |||||
460 | ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN], |
|
467 | ignore_patterns_hash: [0; on_disk::IGNORE_PATTERNS_HASH_LEN], | |
461 | unreachable_bytes: 0, |
|
468 | unreachable_bytes: 0, | |
462 | old_data_size: 0, |
|
469 | old_data_size: 0, | |
|
470 | old_uuid: None, | |||
463 | dirstate_version: DirstateVersion::V1, |
|
471 | dirstate_version: DirstateVersion::V1, | |
464 | write_mode: DirstateMapWriteMode::Auto, |
|
472 | write_mode: DirstateMapWriteMode::Auto, | |
465 | } |
|
473 | } | |
@@ -470,9 +478,10 b" impl<'on_disk> DirstateMap<'on_disk> {" | |||||
470 | on_disk: &'on_disk [u8], |
|
478 | on_disk: &'on_disk [u8], | |
471 | data_size: usize, |
|
479 | data_size: usize, | |
472 | metadata: &[u8], |
|
480 | metadata: &[u8], | |
|
481 | uuid: Vec<u8>, | |||
473 | ) -> Result<Self, DirstateError> { |
|
482 | ) -> Result<Self, DirstateError> { | |
474 | if let Some(data) = on_disk.get(..data_size) { |
|
483 | if let Some(data) = on_disk.get(..data_size) { | |
475 | Ok(on_disk::read(data, metadata)?) |
|
484 | Ok(on_disk::read(data, metadata, uuid)?) | |
476 | } else { |
|
485 | } else { | |
477 | Err(DirstateV2ParseError::new("not enough bytes on disk").into()) |
|
486 | Err(DirstateV2ParseError::new("not enough bytes on disk").into()) | |
478 | } |
|
487 | } | |
@@ -1843,6 +1852,7 b' mod tests {' | |||||
1843 | packed, |
|
1852 | packed, | |
1844 | packed_len, |
|
1853 | packed_len, | |
1845 | metadata.as_bytes(), |
|
1854 | metadata.as_bytes(), | |
|
1855 | vec![], | |||
1846 | )?; |
|
1856 | )?; | |
1847 |
|
1857 | |||
1848 | // Check that everything is accounted for |
|
1858 | // Check that everything is accounted for |
@@ -290,6 +290,7 b' pub fn read_docket(' | |||||
290 | pub(super) fn read<'on_disk>( |
|
290 | pub(super) fn read<'on_disk>( | |
291 | on_disk: &'on_disk [u8], |
|
291 | on_disk: &'on_disk [u8], | |
292 | metadata: &[u8], |
|
292 | metadata: &[u8], | |
|
293 | uuid: Vec<u8>, | |||
293 | ) -> Result<DirstateMap<'on_disk>, DirstateV2ParseError> { |
|
294 | ) -> Result<DirstateMap<'on_disk>, DirstateV2ParseError> { | |
294 | if on_disk.is_empty() { |
|
295 | if on_disk.is_empty() { | |
295 | let mut map = DirstateMap::empty(on_disk); |
|
296 | let mut map = DirstateMap::empty(on_disk); | |
@@ -312,6 +313,7 b" pub(super) fn read<'on_disk>(" | |||||
312 | ignore_patterns_hash: meta.ignore_patterns_hash, |
|
313 | ignore_patterns_hash: meta.ignore_patterns_hash, | |
313 | unreachable_bytes: meta.unreachable_bytes.get(), |
|
314 | unreachable_bytes: meta.unreachable_bytes.get(), | |
314 | old_data_size: on_disk.len(), |
|
315 | old_data_size: on_disk.len(), | |
|
316 | old_uuid: Some(uuid), | |||
315 | dirstate_version: DirstateVersion::V2, |
|
317 | dirstate_version: DirstateVersion::V2, | |
316 | write_mode: DirstateMapWriteMode::Auto, |
|
318 | write_mode: DirstateMapWriteMode::Auto, | |
317 | }; |
|
319 | }; |
@@ -57,6 +57,7 b' impl OwningDirstateMap {' | |||||
57 | on_disk: OnDisk, |
|
57 | on_disk: OnDisk, | |
58 | data_size: usize, |
|
58 | data_size: usize, | |
59 | metadata: &[u8], |
|
59 | metadata: &[u8], | |
|
60 | uuid: Vec<u8>, | |||
60 | ) -> Result<Self, DirstateError> |
|
61 | ) -> Result<Self, DirstateError> | |
61 | where |
|
62 | where | |
62 | OnDisk: Deref<Target = [u8]> + Send + 'static, |
|
63 | OnDisk: Deref<Target = [u8]> + Send + 'static, | |
@@ -66,7 +67,7 b' impl OwningDirstateMap {' | |||||
66 | OwningDirstateMapTryBuilder { |
|
67 | OwningDirstateMapTryBuilder { | |
67 | on_disk, |
|
68 | on_disk, | |
68 | map_builder: |bytes| { |
|
69 | map_builder: |bytes| { | |
69 | DirstateMap::new_v2(&bytes, data_size, metadata) |
|
70 | DirstateMap::new_v2(&bytes, data_size, metadata, uuid) | |
70 | }, |
|
71 | }, | |
71 | } |
|
72 | } | |
72 | .try_build() |
|
73 | .try_build() | |
@@ -86,4 +87,12 b' impl OwningDirstateMap {' | |||||
86 | pub fn on_disk(&self) -> &[u8] { |
|
87 | pub fn on_disk(&self) -> &[u8] { | |
87 | self.borrow_on_disk() |
|
88 | self.borrow_on_disk() | |
88 | } |
|
89 | } | |
|
90 | ||||
|
91 | pub fn old_uuid(&self) -> Option<&[u8]> { | |||
|
92 | self.get_map().old_uuid.as_deref() | |||
|
93 | } | |||
|
94 | ||||
|
95 | pub fn old_data_size(&self) -> usize { | |||
|
96 | self.get_map().old_data_size | |||
|
97 | } | |||
89 | } |
|
98 | } |
@@ -383,6 +383,7 b' impl Repo {' | |||||
383 | self.dirstate_parents.set(docket.parents()); |
|
383 | self.dirstate_parents.set(docket.parents()); | |
384 | self.dirstate_data_file_uuid |
|
384 | self.dirstate_data_file_uuid | |
385 | .set(Some(docket.uuid.to_owned())); |
|
385 | .set(Some(docket.uuid.to_owned())); | |
|
386 | let uuid = docket.uuid.to_owned(); | |||
386 | let data_size = docket.data_size(); |
|
387 | let data_size = docket.data_size(); | |
387 |
|
388 | |||
388 | let context = "between reading dirstate docket and data file"; |
|
389 | let context = "between reading dirstate docket and data file"; | |
@@ -415,16 +416,16 b' impl Repo {' | |||||
415 | } |
|
416 | } | |
416 | Err(e) => return Err(e.into()), |
|
417 | Err(e) => return Err(e.into()), | |
417 | }; |
|
418 | }; | |
418 | OwningDirstateMap::new_v2(contents, data_size, metadata) |
|
419 | OwningDirstateMap::new_v2(contents, data_size, metadata, uuid) | |
419 | } else { |
|
420 | } else { | |
420 | match self |
|
421 | match self | |
421 | .hg_vfs() |
|
422 | .hg_vfs() | |
422 | .mmap_open(docket.data_filename()) |
|
423 | .mmap_open(docket.data_filename()) | |
423 | .io_not_found_as_none() |
|
424 | .io_not_found_as_none() | |
424 | { |
|
425 | { | |
425 |
Ok(Some(data_mmap)) => |
|
426 | Ok(Some(data_mmap)) => OwningDirstateMap::new_v2( | |
426 |
|
|
427 | data_mmap, data_size, metadata, uuid, | |
427 |
|
|
428 | ), | |
428 | Ok(None) => { |
|
429 | Ok(None) => { | |
429 | // Race where the data file was deleted right after we |
|
430 | // Race where the data file was deleted right after we | |
430 | // read the docket, try again |
|
431 | // read the docket, try again |
@@ -66,18 +66,28 b' py_class!(pub class DirstateMap |py| {' | |||||
66 | on_disk: PyBytes, |
|
66 | on_disk: PyBytes, | |
67 | data_size: usize, |
|
67 | data_size: usize, | |
68 | tree_metadata: PyBytes, |
|
68 | tree_metadata: PyBytes, | |
|
69 | uuid: PyBytes, | |||
69 | ) -> PyResult<PyObject> { |
|
70 | ) -> PyResult<PyObject> { | |
70 | let dirstate_error = |e: DirstateError| { |
|
71 | let dirstate_error = |e: DirstateError| { | |
71 | PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e)) |
|
72 | PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e)) | |
72 | }; |
|
73 | }; | |
73 | let on_disk = PyBytesDeref::new(py, on_disk); |
|
74 | let on_disk = PyBytesDeref::new(py, on_disk); | |
|
75 | let uuid = uuid.data(py); | |||
74 | let map = OwningDirstateMap::new_v2( |
|
76 | let map = OwningDirstateMap::new_v2( | |
75 | on_disk, data_size, tree_metadata.data(py), |
|
77 | on_disk, data_size, tree_metadata.data(py), uuid.to_owned(), | |
76 | ).map_err(dirstate_error)?; |
|
78 | ).map_err(dirstate_error)?; | |
77 | let map = Self::create_instance(py, map)?; |
|
79 | let map = Self::create_instance(py, map)?; | |
78 | Ok(map.into_object()) |
|
80 | Ok(map.into_object()) | |
79 | } |
|
81 | } | |
80 |
|
82 | |||
|
83 | /// Returns an empty DirstateMap. Only used for a new dirstate. | |||
|
84 | @staticmethod | |||
|
85 | def new_empty() -> PyResult<PyObject> { | |||
|
86 | let map = OwningDirstateMap::new_empty(vec![]); | |||
|
87 | let map = Self::create_instance(py, map)?; | |||
|
88 | Ok(map.into_object()) | |||
|
89 | } | |||
|
90 | ||||
81 | def clear(&self) -> PyResult<PyObject> { |
|
91 | def clear(&self) -> PyResult<PyObject> { | |
82 | self.inner(py).borrow_mut().clear(); |
|
92 | self.inner(py).borrow_mut().clear(); | |
83 | Ok(py.None()) |
|
93 | Ok(py.None()) |
General Comments 0
You need to be logged in to leave comments.
Login now