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 }