2 use micro_timer::timed; |
2 use micro_timer::timed; |
3 use std::borrow::Cow; |
3 use std::borrow::Cow; |
4 use std::convert::TryInto; |
4 use std::convert::TryInto; |
5 use std::path::PathBuf; |
5 use std::path::PathBuf; |
6 |
6 |
|
7 use super::on_disk::V2_FORMAT_MARKER; |
7 use super::path_with_basename::WithBasename; |
8 use super::path_with_basename::WithBasename; |
8 use crate::dirstate::parsers::clear_ambiguous_mtime; |
9 use crate::dirstate::parsers::clear_ambiguous_mtime; |
9 use crate::dirstate::parsers::pack_entry; |
10 use crate::dirstate::parsers::pack_entry; |
10 use crate::dirstate::parsers::packed_entry_size; |
11 use crate::dirstate::parsers::packed_entry_size; |
11 use crate::dirstate::parsers::parse_dirstate_entries; |
12 use crate::dirstate::parsers::parse_dirstate_entries; |
12 use crate::dirstate::parsers::Timestamp; |
13 use crate::dirstate::parsers::Timestamp; |
|
14 use crate::errors::HgError; |
13 use crate::matchers::Matcher; |
15 use crate::matchers::Matcher; |
14 use crate::utils::hg_path::{HgPath, HgPathBuf}; |
16 use crate::utils::hg_path::{HgPath, HgPathBuf}; |
|
17 use crate::utils::SliceExt; |
15 use crate::CopyMapIter; |
18 use crate::CopyMapIter; |
16 use crate::DirstateEntry; |
19 use crate::DirstateEntry; |
17 use crate::DirstateError; |
20 use crate::DirstateError; |
18 use crate::DirstateMapError; |
21 use crate::DirstateMapError; |
19 use crate::DirstateParents; |
22 use crate::DirstateParents; |
73 &'tree mut Option<DirstateEntry>, |
76 &'tree mut Option<DirstateEntry>, |
74 &'tree mut Option<Cow<'on_disk, HgPath>>, |
77 &'tree mut Option<Cow<'on_disk, HgPath>>, |
75 ); |
78 ); |
76 |
79 |
77 impl<'on_disk> DirstateMap<'on_disk> { |
80 impl<'on_disk> DirstateMap<'on_disk> { |
78 pub fn new( |
81 #[timed] |
|
82 pub fn new_v2( |
|
83 on_disk: &'on_disk [u8], |
|
84 ) -> Result<(Self, Option<DirstateParents>), DirstateError> { |
|
85 if let Some(rest) = on_disk.drop_prefix(V2_FORMAT_MARKER) { |
|
86 Self::new_v1(rest) |
|
87 } else if on_disk.is_empty() { |
|
88 Self::new_v1(on_disk) |
|
89 } else { |
|
90 return Err(HgError::corrupted( |
|
91 "missing dirstate-v2 magic number", |
|
92 ) |
|
93 .into()); |
|
94 } |
|
95 } |
|
96 |
|
97 #[timed] |
|
98 pub fn new_v1( |
79 on_disk: &'on_disk [u8], |
99 on_disk: &'on_disk [u8], |
80 ) -> Result<(Self, Option<DirstateParents>), DirstateError> { |
100 ) -> Result<(Self, Option<DirstateParents>), DirstateError> { |
81 let mut map = Self { |
101 let mut map = Self { |
82 on_disk, |
102 on_disk, |
83 root: ChildNodes::default(), |
103 root: ChildNodes::default(), |
84 nodes_with_entry_count: 0, |
104 nodes_with_entry_count: 0, |
85 nodes_with_copy_source_count: 0, |
105 nodes_with_copy_source_count: 0, |
86 }; |
106 }; |
87 let parents = map.read()?; |
107 if map.on_disk.is_empty() { |
88 Ok((map, parents)) |
108 return Ok((map, None)); |
89 } |
|
90 |
|
91 /// Should only be called in `new` |
|
92 #[timed] |
|
93 fn read(&mut self) -> Result<Option<DirstateParents>, DirstateError> { |
|
94 if self.on_disk.is_empty() { |
|
95 return Ok(None); |
|
96 } |
109 } |
97 |
110 |
98 let parents = parse_dirstate_entries( |
111 let parents = parse_dirstate_entries( |
99 self.on_disk, |
112 map.on_disk, |
100 |path, entry, copy_source| { |
113 |path, entry, copy_source| { |
101 let tracked = entry.state.is_tracked(); |
114 let tracked = entry.state.is_tracked(); |
102 let node = Self::get_or_insert_node( |
115 let node = Self::get_or_insert_node( |
103 &mut self.root, |
116 &mut map.root, |
104 path, |
117 path, |
105 WithBasename::to_cow_borrowed, |
118 WithBasename::to_cow_borrowed, |
106 |ancestor| { |
119 |ancestor| { |
107 if tracked { |
120 if tracked { |
108 ancestor.tracked_descendants_count += 1 |
121 ancestor.tracked_descendants_count += 1 |
117 node.copy_source.is_none(), |
130 node.copy_source.is_none(), |
118 "duplicate dirstate entry in read" |
131 "duplicate dirstate entry in read" |
119 ); |
132 ); |
120 node.entry = Some(*entry); |
133 node.entry = Some(*entry); |
121 node.copy_source = copy_source.map(Cow::Borrowed); |
134 node.copy_source = copy_source.map(Cow::Borrowed); |
122 self.nodes_with_entry_count += 1; |
135 map.nodes_with_entry_count += 1; |
123 if copy_source.is_some() { |
136 if copy_source.is_some() { |
124 self.nodes_with_copy_source_count += 1 |
137 map.nodes_with_copy_source_count += 1 |
125 } |
138 } |
126 }, |
139 }, |
127 )?; |
140 )?; |
128 |
141 let parents = Some(parents.clone()); |
129 Ok(Some(parents.clone())) |
142 |
|
143 Ok((map, parents)) |
130 } |
144 } |
131 |
145 |
132 fn get_node(&self, path: &HgPath) -> Option<&Node> { |
146 fn get_node(&self, path: &HgPath) -> Option<&Node> { |
133 let mut children = &self.root; |
147 let mut children = &self.root; |
134 let mut components = path.components(); |
148 let mut components = path.components(); |
531 } |
546 } |
532 } |
547 } |
533 Ok(packed) |
548 Ok(packed) |
534 } |
549 } |
535 |
550 |
|
551 #[timed] |
|
552 fn pack_v2( |
|
553 &mut self, |
|
554 parents: DirstateParents, |
|
555 now: Timestamp, |
|
556 ) -> Result<Vec<u8>, DirstateError> { |
|
557 // Inefficient but temporary |
|
558 let mut v2 = V2_FORMAT_MARKER.to_vec(); |
|
559 v2.append(&mut self.pack_v1(parents, now)?); |
|
560 Ok(v2) |
|
561 } |
|
562 |
536 fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> { |
563 fn set_all_dirs(&mut self) -> Result<(), DirstateMapError> { |
537 // Do nothing, this `DirstateMap` does not a separate `all_dirs` that |
564 // Do nothing, this `DirstateMap` does not a separate `all_dirs` that |
538 // needs to be recomputed |
565 // needs to be recomputed |
539 Ok(()) |
566 Ok(()) |
540 } |
567 } |