Mercurial > hg
comparison rust/hg-core/src/dirstate_tree/on_disk.rs @ 49366:288de6f5d724 stable 6.2rc0
branching: merge default into stable
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Thu, 16 Jun 2022 15:28:54 +0200 |
parents | a932cad26d37 6cd249556e20 |
children | f8ec7b16c98f |
comparison
equal
deleted
inserted
replaced
49364:e8ea403b1c46 | 49366:288de6f5d724 |
---|---|
1 //! The "version 2" disk representation of the dirstate | 1 //! The "version 2" disk representation of the dirstate |
2 //! | 2 //! |
3 //! See `mercurial/helptext/internals/dirstate-v2.txt` | 3 //! See `mercurial/helptext/internals/dirstate-v2.txt` |
4 | 4 |
5 use crate::dirstate::TruncatedTimestamp; | 5 use crate::dirstate::{DirstateV2Data, TruncatedTimestamp}; |
6 use crate::dirstate_tree::dirstate_map::DirstateVersion; | 6 use crate::dirstate_tree::dirstate_map::DirstateVersion; |
7 use crate::dirstate_tree::dirstate_map::{self, DirstateMap, NodeRef}; | 7 use crate::dirstate_tree::dirstate_map::{self, DirstateMap, NodeRef}; |
8 use crate::dirstate_tree::path_with_basename::WithBasename; | 8 use crate::dirstate_tree::path_with_basename::WithBasename; |
9 use crate::errors::HgError; | 9 use crate::errors::HgError; |
10 use crate::utils::hg_path::HgPath; | 10 use crate::utils::hg_path::HgPath; |
83 ignore_patterns_hash: IgnorePatternsHash, | 83 ignore_patterns_hash: IgnorePatternsHash, |
84 } | 84 } |
85 | 85 |
86 /// Fields are documented in the *The data file format* | 86 /// Fields are documented in the *The data file format* |
87 /// section of `mercurial/helptext/internals/dirstate-v2.txt` | 87 /// section of `mercurial/helptext/internals/dirstate-v2.txt` |
88 #[derive(BytesCast)] | 88 #[derive(BytesCast, Debug)] |
89 #[repr(C)] | 89 #[repr(C)] |
90 pub(super) struct Node { | 90 pub(super) struct Node { |
91 full_path: PathSlice, | 91 full_path: PathSlice, |
92 | 92 |
93 /// In bytes from `self.full_path.start` | 93 /// In bytes from `self.full_path.start` |
123 const ALL_IGNORED_RECORDED = 1 <<15; | 123 const ALL_IGNORED_RECORDED = 1 <<15; |
124 } | 124 } |
125 } | 125 } |
126 | 126 |
127 /// Duration since the Unix epoch | 127 /// Duration since the Unix epoch |
128 #[derive(BytesCast, Copy, Clone)] | 128 #[derive(BytesCast, Copy, Clone, Debug)] |
129 #[repr(C)] | 129 #[repr(C)] |
130 struct PackedTruncatedTimestamp { | 130 struct PackedTruncatedTimestamp { |
131 truncated_seconds: U32Be, | 131 truncated_seconds: U32Be, |
132 nanoseconds: U32Be, | 132 nanoseconds: U32Be, |
133 } | 133 } |
151 /// of either some other node or of the repository root. | 151 /// of either some other node or of the repository root. |
152 /// | 152 /// |
153 /// Always sorted by ascending `full_path`, to allow binary search. | 153 /// Always sorted by ascending `full_path`, to allow binary search. |
154 /// Since nodes with the same parent nodes also have the same parent path, | 154 /// Since nodes with the same parent nodes also have the same parent path, |
155 /// only the `base_name`s need to be compared during binary search. | 155 /// only the `base_name`s need to be compared during binary search. |
156 #[derive(BytesCast, Copy, Clone)] | 156 #[derive(BytesCast, Copy, Clone, Debug)] |
157 #[repr(C)] | 157 #[repr(C)] |
158 struct ChildNodes { | 158 struct ChildNodes { |
159 start: Offset, | 159 start: Offset, |
160 len: Size, | 160 len: Size, |
161 } | 161 } |
162 | 162 |
163 /// A `HgPath` of `len` bytes | 163 /// A `HgPath` of `len` bytes |
164 #[derive(BytesCast, Copy, Clone)] | 164 #[derive(BytesCast, Copy, Clone, Debug)] |
165 #[repr(C)] | 165 #[repr(C)] |
166 struct PathSlice { | 166 struct PathSlice { |
167 start: Offset, | 167 start: Offset, |
168 len: PathSize, | 168 len: PathSize, |
169 } | 169 } |
415 Ok(m) | 415 Ok(m) |
416 } | 416 } |
417 | 417 |
418 fn assume_entry(&self) -> Result<DirstateEntry, DirstateV2ParseError> { | 418 fn assume_entry(&self) -> Result<DirstateEntry, DirstateV2ParseError> { |
419 // TODO: convert through raw bits instead? | 419 // TODO: convert through raw bits instead? |
420 let wdir_tracked = self.flags().contains(Flags::WDIR_TRACKED); | 420 let wc_tracked = self.flags().contains(Flags::WDIR_TRACKED); |
421 let p1_tracked = self.flags().contains(Flags::P1_TRACKED); | 421 let p1_tracked = self.flags().contains(Flags::P1_TRACKED); |
422 let p2_info = self.flags().contains(Flags::P2_INFO); | 422 let p2_info = self.flags().contains(Flags::P2_INFO); |
423 let mode_size = if self.flags().contains(Flags::HAS_MODE_AND_SIZE) | 423 let mode_size = if self.flags().contains(Flags::HAS_MODE_AND_SIZE) |
424 && !self.flags().contains(Flags::EXPECTED_STATE_IS_MODIFIED) | 424 && !self.flags().contains(Flags::EXPECTED_STATE_IS_MODIFIED) |
425 { | 425 { |
445 if self.flags().contains(Flags::HAS_FALLBACK_SYMLINK) { | 445 if self.flags().contains(Flags::HAS_FALLBACK_SYMLINK) { |
446 Some(self.flags().contains(Flags::FALLBACK_SYMLINK)) | 446 Some(self.flags().contains(Flags::FALLBACK_SYMLINK)) |
447 } else { | 447 } else { |
448 None | 448 None |
449 }; | 449 }; |
450 Ok(DirstateEntry::from_v2_data( | 450 Ok(DirstateEntry::from_v2_data(DirstateV2Data { |
451 wdir_tracked, | 451 wc_tracked, |
452 p1_tracked, | 452 p1_tracked, |
453 p2_info, | 453 p2_info, |
454 mode_size, | 454 mode_size, |
455 mtime, | 455 mtime, |
456 fallback_exec, | 456 fallback_exec, |
457 fallback_symlink, | 457 fallback_symlink, |
458 )) | 458 })) |
459 } | 459 } |
460 | 460 |
461 pub(super) fn entry( | 461 pub(super) fn entry( |
462 &self, | 462 &self, |
463 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> { | 463 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> { |
493 } | 493 } |
494 | 494 |
495 fn from_dirstate_entry( | 495 fn from_dirstate_entry( |
496 entry: &DirstateEntry, | 496 entry: &DirstateEntry, |
497 ) -> (Flags, U32Be, PackedTruncatedTimestamp) { | 497 ) -> (Flags, U32Be, PackedTruncatedTimestamp) { |
498 let ( | 498 let DirstateV2Data { |
499 wdir_tracked, | 499 wc_tracked, |
500 p1_tracked, | 500 p1_tracked, |
501 p2_info, | 501 p2_info, |
502 mode_size_opt, | 502 mode_size: mode_size_opt, |
503 mtime_opt, | 503 mtime: mtime_opt, |
504 fallback_exec, | 504 fallback_exec, |
505 fallback_symlink, | 505 fallback_symlink, |
506 ) = entry.v2_data(); | 506 } = entry.v2_data(); |
507 // TODO: convert throug raw flag bits instead? | 507 // TODO: convert through raw flag bits instead? |
508 let mut flags = Flags::empty(); | 508 let mut flags = Flags::empty(); |
509 flags.set(Flags::WDIR_TRACKED, wdir_tracked); | 509 flags.set(Flags::WDIR_TRACKED, wc_tracked); |
510 flags.set(Flags::P1_TRACKED, p1_tracked); | 510 flags.set(Flags::P1_TRACKED, p1_tracked); |
511 flags.set(Flags::P2_INFO, p2_info); | 511 flags.set(Flags::P2_INFO, p2_info); |
512 let size = if let Some((m, s)) = mode_size_opt { | 512 let size = if let Some((m, s)) = mode_size_opt { |
513 let exec_perm = m & (libc::S_IXUSR as u32) != 0; | 513 let exec_perm = m & (libc::S_IXUSR as u32) != 0; |
514 let is_symlink = m & (libc::S_IFMT as u32) == libc::S_IFLNK as u32; | 514 let is_symlink = m & (libc::S_IFMT as u32) == libc::S_IFLNK as u32; |
590 nodes: ChildNodes, | 590 nodes: ChildNodes, |
591 f: &mut impl FnMut(&'on_disk HgPath), | 591 f: &mut impl FnMut(&'on_disk HgPath), |
592 ) -> Result<(), DirstateV2ParseError> { | 592 ) -> Result<(), DirstateV2ParseError> { |
593 for node in read_nodes(on_disk, nodes)? { | 593 for node in read_nodes(on_disk, nodes)? { |
594 if let Some(entry) = node.entry()? { | 594 if let Some(entry) = node.entry()? { |
595 if entry.state().is_tracked() { | 595 if entry.tracked() { |
596 f(node.full_path(on_disk)?) | 596 f(node.full_path(on_disk)?) |
597 } | 597 } |
598 } | 598 } |
599 recur(on_disk, node.children, f)? | 599 recur(on_disk, node.children, f)? |
600 } | 600 } |