293 } |
293 } |
294 NodeRef::OnDisk(node) => node.copy_source(on_disk), |
294 NodeRef::OnDisk(node) => node.copy_source(on_disk), |
295 } |
295 } |
296 } |
296 } |
297 |
297 |
298 pub(super) fn has_entry(&self) -> bool { |
|
299 match self { |
|
300 NodeRef::InMemory(_path, node) => node.entry.is_some(), |
|
301 NodeRef::OnDisk(node) => node.has_entry(), |
|
302 } |
|
303 } |
|
304 |
|
305 pub(super) fn entry( |
298 pub(super) fn entry( |
306 &self, |
299 &self, |
307 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> { |
300 ) -> Result<Option<DirstateEntry>, DirstateV2ParseError> { |
308 match self { |
301 match self { |
309 NodeRef::InMemory(_path, node) => Ok(node.entry), |
302 NodeRef::InMemory(_path, node) => { |
|
303 Ok(node.data.as_entry().copied()) |
|
304 } |
310 NodeRef::OnDisk(node) => node.entry(), |
305 NodeRef::OnDisk(node) => node.entry(), |
311 } |
306 } |
312 } |
307 } |
313 |
308 |
314 pub(super) fn state( |
309 pub(super) fn state( |
315 &self, |
310 &self, |
316 ) -> Result<Option<EntryState>, DirstateV2ParseError> { |
311 ) -> Result<Option<EntryState>, DirstateV2ParseError> { |
317 match self { |
312 match self { |
318 NodeRef::InMemory(_path, node) => { |
313 NodeRef::InMemory(_path, node) => { |
319 Ok(node.entry.as_ref().map(|entry| entry.state)) |
314 Ok(node.data.as_entry().map(|entry| entry.state)) |
320 } |
315 } |
321 NodeRef::OnDisk(node) => node.state(), |
316 NodeRef::OnDisk(node) => node.state(), |
322 } |
317 } |
323 } |
318 } |
324 |
319 |
331 } |
326 } |
332 |
327 |
333 /// Represents a file or a directory |
328 /// Represents a file or a directory |
334 #[derive(Default)] |
329 #[derive(Default)] |
335 pub(super) struct Node<'on_disk> { |
330 pub(super) struct Node<'on_disk> { |
336 /// `None` for directories |
331 pub(super) data: NodeData, |
337 pub(super) entry: Option<DirstateEntry>, |
|
338 |
332 |
339 pub(super) copy_source: Option<Cow<'on_disk, HgPath>>, |
333 pub(super) copy_source: Option<Cow<'on_disk, HgPath>>, |
340 |
334 |
341 pub(super) children: ChildNodes<'on_disk>, |
335 pub(super) children: ChildNodes<'on_disk>, |
342 |
336 |
343 /// How many (non-inclusive) descendants of this node are tracked files |
337 /// How many (non-inclusive) descendants of this node are tracked files |
344 pub(super) tracked_descendants_count: u32, |
338 pub(super) tracked_descendants_count: u32, |
|
339 } |
|
340 |
|
341 pub(super) enum NodeData { |
|
342 Entry(DirstateEntry), |
|
343 CachedDirectory { mtime: on_disk::Timestamp }, |
|
344 None, |
|
345 } |
|
346 |
|
347 impl Default for NodeData { |
|
348 fn default() -> Self { |
|
349 NodeData::None |
|
350 } |
|
351 } |
|
352 |
|
353 impl NodeData { |
|
354 fn has_entry(&self) -> bool { |
|
355 match self { |
|
356 NodeData::Entry(_) => true, |
|
357 _ => false, |
|
358 } |
|
359 } |
|
360 |
|
361 fn as_entry(&self) -> Option<&DirstateEntry> { |
|
362 match self { |
|
363 NodeData::Entry(entry) => Some(entry), |
|
364 _ => None, |
|
365 } |
|
366 } |
345 } |
367 } |
346 |
368 |
347 impl<'on_disk> DirstateMap<'on_disk> { |
369 impl<'on_disk> DirstateMap<'on_disk> { |
348 pub(super) fn empty(on_disk: &'on_disk [u8]) -> Self { |
370 pub(super) fn empty(on_disk: &'on_disk [u8]) -> Self { |
349 Self { |
371 Self { |
384 ancestor.tracked_descendants_count += 1 |
406 ancestor.tracked_descendants_count += 1 |
385 } |
407 } |
386 }, |
408 }, |
387 )?; |
409 )?; |
388 assert!( |
410 assert!( |
389 node.entry.is_none(), |
411 !node.data.has_entry(), |
390 "duplicate dirstate entry in read" |
412 "duplicate dirstate entry in read" |
391 ); |
413 ); |
392 assert!( |
414 assert!( |
393 node.copy_source.is_none(), |
415 node.copy_source.is_none(), |
394 "duplicate dirstate entry in read" |
416 "duplicate dirstate entry in read" |
395 ); |
417 ); |
396 node.entry = Some(*entry); |
418 node.data = NodeData::Entry(*entry); |
397 node.copy_source = copy_source.map(Cow::Borrowed); |
419 node.copy_source = copy_source.map(Cow::Borrowed); |
398 map.nodes_with_entry_count += 1; |
420 map.nodes_with_entry_count += 1; |
399 if copy_source.is_some() { |
421 if copy_source.is_some() { |
400 map.nodes_with_copy_source_count += 1 |
422 map.nodes_with_copy_source_count += 1 |
401 } |
423 } |
517 -1 => ancestor.tracked_descendants_count -= 1, |
539 -1 => ancestor.tracked_descendants_count -= 1, |
518 _ => {} |
540 _ => {} |
519 } |
541 } |
520 }, |
542 }, |
521 )?; |
543 )?; |
522 if node.entry.is_none() { |
544 if !node.data.has_entry() { |
523 self.nodes_with_entry_count += 1 |
545 self.nodes_with_entry_count += 1 |
524 } |
546 } |
525 node.entry = Some(new_entry); |
547 node.data = NodeData::Entry(new_entry); |
526 Ok(()) |
548 Ok(()) |
527 } |
549 } |
528 |
550 |
529 fn iter_nodes<'tree>( |
551 fn iter_nodes<'tree>( |
530 &'tree self, |
552 &'tree self, |
701 } |
723 } |
702 } else { |
724 } else { |
703 return Ok(None); |
725 return Ok(None); |
704 } |
726 } |
705 } else { |
727 } else { |
|
728 let had_entry = node.data.has_entry(); |
|
729 if had_entry { |
|
730 node.data = NodeData::None |
|
731 } |
706 dropped = Dropped { |
732 dropped = Dropped { |
707 was_tracked: node |
733 was_tracked: node |
708 .entry |
734 .data |
709 .as_ref() |
735 .as_entry() |
710 .map_or(false, |entry| entry.state.is_tracked()), |
736 .map_or(false, |entry| entry.state.is_tracked()), |
711 had_entry: node.entry.take().is_some(), |
737 had_entry, |
712 had_copy_source: node.copy_source.take().is_some(), |
738 had_copy_source: node.copy_source.take().is_some(), |
713 }; |
739 }; |
714 } |
740 } |
715 // After recursion, for both leaf (rest_of_path is None) nodes and |
741 // After recursion, for both leaf (rest_of_path is None) nodes and |
716 // parent nodes, remove a node if it just became empty. |
742 // parent nodes, remove a node if it just became empty. |
717 if node.entry.is_none() |
743 if !node.data.has_entry() |
718 && node.copy_source.is_none() |
744 && node.copy_source.is_none() |
719 && node.children.is_empty() |
745 && node.children.is_empty() |
720 { |
746 { |
721 nodes.make_mut(on_disk)?.remove(first_path_component); |
747 nodes.make_mut(on_disk)?.remove(first_path_component); |
722 } |
748 } |
744 ) -> Result<(), DirstateV2ParseError> { |
770 ) -> Result<(), DirstateV2ParseError> { |
745 for filename in filenames { |
771 for filename in filenames { |
746 if let Some(node) = |
772 if let Some(node) = |
747 Self::get_node_mut(self.on_disk, &mut self.root, &filename)? |
773 Self::get_node_mut(self.on_disk, &mut self.root, &filename)? |
748 { |
774 { |
749 if let Some(entry) = node.entry.as_mut() { |
775 if let NodeData::Entry(entry) = &mut node.data { |
750 entry.clear_ambiguous_mtime(now); |
776 entry.clear_ambiguous_mtime(now); |
751 } |
777 } |
752 } |
778 } |
753 } |
779 } |
754 Ok(()) |
780 Ok(()) |
813 directory: &HgPath, |
839 directory: &HgPath, |
814 ) -> Result<bool, DirstateError> { |
840 ) -> Result<bool, DirstateError> { |
815 if let Some(node) = self.get_node(directory)? { |
841 if let Some(node) = self.get_node(directory)? { |
816 // A node without a `DirstateEntry` was created to hold child |
842 // A node without a `DirstateEntry` was created to hold child |
817 // nodes, and is therefore a directory. |
843 // nodes, and is therefore a directory. |
818 Ok(!node.has_entry() && node.tracked_descendants_count() > 0) |
844 let state = node.state()?; |
|
845 Ok(state.is_none() && node.tracked_descendants_count() > 0) |
819 } else { |
846 } else { |
820 Ok(false) |
847 Ok(false) |
821 } |
848 } |
822 } |
849 } |
823 |
850 |
824 fn has_dir(&mut self, directory: &HgPath) -> Result<bool, DirstateError> { |
851 fn has_dir(&mut self, directory: &HgPath) -> Result<bool, DirstateError> { |
825 if let Some(node) = self.get_node(directory)? { |
852 if let Some(node) = self.get_node(directory)? { |
826 // A node without a `DirstateEntry` was created to hold child |
853 // A node without a `DirstateEntry` was created to hold child |
827 // nodes, and is therefore a directory. |
854 // nodes, and is therefore a directory. |
828 Ok(!node.has_entry()) |
855 Ok(node.state()?.is_none()) |
829 } else { |
856 } else { |
830 Ok(false) |
857 Ok(false) |
831 } |
858 } |
832 } |
859 } |
833 |
860 |