rust/hg-core/src/dirstate_tree/dirstate_map.rs
changeset 47280 1766130fe9ba
parent 47193 47ccab19bf9f
child 47282 ce41ee53263f
equal deleted inserted replaced
47279:40b51c28b242 47280:1766130fe9ba
     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();
   496         } else {
   510         } else {
   497             Ok(false)
   511             Ok(false)
   498         }
   512         }
   499     }
   513     }
   500 
   514 
   501     fn pack(
   515     #[timed]
       
   516     fn pack_v1(
   502         &mut self,
   517         &mut self,
   503         parents: DirstateParents,
   518         parents: DirstateParents,
   504         now: Timestamp,
   519         now: Timestamp,
   505     ) -> Result<Vec<u8>, DirstateError> {
   520     ) -> Result<Vec<u8>, DirstateError> {
   506         // Optizimation (to be measured?): pre-compute size to avoid `Vec`
   521         // Optizimation (to be measured?): pre-compute size to avoid `Vec`
   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     }