##// END OF EJS Templates
dirstate-v2: Add a zero-size error type for dirstate v2 parse errors...
Simon Sapin -
r48125:18b3060f default
parent child Browse files
Show More
@@ -228,7 +228,7 b" impl<'on_disk> DirstateMap<'on_disk> {"
228 228 pub fn new_v2(
229 229 on_disk: &'on_disk [u8],
230 230 ) -> Result<(Self, Option<DirstateParents>), DirstateError> {
231 on_disk::read(on_disk)
231 Ok(on_disk::read(on_disk)?)
232 232 }
233 233
234 234 #[timed]
@@ -108,14 +108,32 b' fn _static_assert_size_of() {'
108 108 let _ = std::mem::transmute::<Node, [u8; 57]>;
109 109 }
110 110
111 /// Unexpected file format found in `.hg/dirstate` with the "v2" format.
112 pub(crate) struct DirstateV2ParseError;
113
114 impl From<DirstateV2ParseError> for HgError {
115 fn from(_: DirstateV2ParseError) -> Self {
116 HgError::corrupted("dirstate-v2 parse error")
117 }
118 }
119
120 impl From<DirstateV2ParseError> for crate::DirstateError {
121 fn from(error: DirstateV2ParseError) -> Self {
122 HgError::from(error).into()
123 }
124 }
125
111 126 pub(super) fn read<'on_disk>(
112 127 on_disk: &'on_disk [u8],
113 ) -> Result<(DirstateMap<'on_disk>, Option<DirstateParents>), DirstateError> {
128 ) -> Result<
129 (DirstateMap<'on_disk>, Option<DirstateParents>),
130 DirstateV2ParseError,
131 > {
114 132 if on_disk.is_empty() {
115 133 return Ok((DirstateMap::empty(on_disk), None));
116 134 }
117 let (header, _) = Header::from_bytes(on_disk)
118 .map_err(|_| HgError::corrupted("truncated dirstate-v2"))?;
135 let (header, _) =
136 Header::from_bytes(on_disk).map_err(|_| DirstateV2ParseError)?;
119 137 let Header {
120 138 marker,
121 139 parents,
@@ -124,7 +142,7 b" pub(super) fn read<'on_disk>("
124 142 nodes_with_copy_source_count,
125 143 } = header;
126 144 if marker != V2_FORMAT_MARKER {
127 return Err(HgError::corrupted("missing dirstated-v2 marker").into());
145 return Err(DirstateV2ParseError);
128 146 }
129 147 let dirstate_map = DirstateMap {
130 148 on_disk,
@@ -140,7 +158,7 b' impl Node {'
140 158 pub(super) fn path<'on_disk>(
141 159 &self,
142 160 on_disk: &'on_disk [u8],
143 ) -> Result<dirstate_map::NodeKey<'on_disk>, HgError> {
161 ) -> Result<dirstate_map::NodeKey<'on_disk>, DirstateV2ParseError> {
144 162 let full_path = read_hg_path(on_disk, self.full_path)?;
145 163 let base_name_start = usize::try_from(self.base_name_start.get())
146 164 // u32 -> usize, could only panic on a 16-bit CPU
@@ -148,16 +166,14 b' impl Node {'
148 166 if base_name_start < full_path.len() {
149 167 Ok(WithBasename::from_raw_parts(full_path, base_name_start))
150 168 } else {
151 Err(HgError::corrupted(
152 "dirstate-v2 base_name_start out of bounds",
153 ))
169 Err(DirstateV2ParseError)
154 170 }
155 171 }
156 172
157 173 pub(super) fn copy_source<'on_disk>(
158 174 &self,
159 175 on_disk: &'on_disk [u8],
160 ) -> Result<Option<Cow<'on_disk, HgPath>>, HgError> {
176 ) -> Result<Option<Cow<'on_disk, HgPath>>, DirstateV2ParseError> {
161 177 Ok(if self.copy_source.start.get() != 0 {
162 178 Some(read_hg_path(on_disk, self.copy_source)?)
163 179 } else {
@@ -165,10 +181,16 b' impl Node {'
165 181 })
166 182 }
167 183
168 pub(super) fn entry(&self) -> Result<Option<DirstateEntry>, HgError> {
184 pub(super) fn entry(
185 &self,
186 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> {
169 187 Ok(if self.entry.state != b'\0' {
170 188 Some(DirstateEntry {
171 state: self.entry.state.try_into()?,
189 state: self
190 .entry
191 .state
192 .try_into()
193 .map_err(|_| DirstateV2ParseError)?,
172 194 mode: self.entry.mode.get(),
173 195 mtime: self.entry.mtime.get(),
174 196 size: self.entry.size.get(),
@@ -181,7 +203,7 b' impl Node {'
181 203 pub(super) fn to_in_memory_node<'on_disk>(
182 204 &self,
183 205 on_disk: &'on_disk [u8],
184 ) -> Result<dirstate_map::Node<'on_disk>, HgError> {
206 ) -> Result<dirstate_map::Node<'on_disk>, DirstateV2ParseError> {
185 207 Ok(dirstate_map::Node {
186 208 children: read_nodes(on_disk, self.children)?,
187 209 copy_source: self.copy_source(on_disk)?,
@@ -194,7 +216,7 b' impl Node {'
194 216 fn read_nodes(
195 217 on_disk: &[u8],
196 218 slice: ChildNodes,
197 ) -> Result<dirstate_map::ChildNodes, HgError> {
219 ) -> Result<dirstate_map::ChildNodes, DirstateV2ParseError> {
198 220 read_slice::<Node>(on_disk, slice)?
199 221 .iter()
200 222 .map(|node| {
@@ -204,12 +226,18 b' fn read_nodes('
204 226 .map(dirstate_map::ChildNodes::InMemory)
205 227 }
206 228
207 fn read_hg_path(on_disk: &[u8], slice: Slice) -> Result<Cow<HgPath>, HgError> {
229 fn read_hg_path(
230 on_disk: &[u8],
231 slice: Slice,
232 ) -> Result<Cow<HgPath>, DirstateV2ParseError> {
208 233 let bytes = read_slice::<u8>(on_disk, slice)?;
209 234 Ok(Cow::Borrowed(HgPath::new(bytes)))
210 235 }
211 236
212 fn read_slice<T>(on_disk: &[u8], slice: Slice) -> Result<&[T], HgError>
237 fn read_slice<T>(
238 on_disk: &[u8],
239 slice: Slice,
240 ) -> Result<&[T], DirstateV2ParseError>
213 241 where
214 242 T: BytesCast,
215 243 {
@@ -221,9 +249,7 b' where'
221 249 .get(start..)
222 250 .and_then(|bytes| T::slice_from_bytes(bytes, len).ok())
223 251 .map(|(slice, _rest)| slice)
224 .ok_or_else(|| {
225 HgError::corrupted("dirstate v2 slice is out of bounds")
226 })
252 .ok_or_else(|| DirstateV2ParseError)
227 253 }
228 254
229 255 pub(super) fn write(
General Comments 0
You need to be logged in to leave comments. Login now