rust/hg-core/src/dirstate/dirs_multiset.rs
changeset 42608 717686c5e461
parent 42559 a80464e85ddd
child 42609 326fdce22fb2
equal deleted inserted replaced
42607:8f7c3f43e3ac 42608:717686c5e461
     9 //!
     9 //!
    10 //! Used to counts the references to directories in a manifest or dirstate.
    10 //! Used to counts the references to directories in a manifest or dirstate.
    11 use std::collections::hash_map::{Entry, Iter};
    11 use std::collections::hash_map::{Entry, Iter};
    12 use std::collections::HashMap;
    12 use std::collections::HashMap;
    13 use {DirsIterable, DirstateEntry, DirstateMapError};
    13 use {DirsIterable, DirstateEntry, DirstateMapError};
       
    14 use utils::files;
    14 
    15 
    15 #[derive(PartialEq, Debug)]
    16 #[derive(PartialEq, Debug)]
    16 pub struct DirsMultiset {
    17 pub struct DirsMultiset {
    17     inner: HashMap<Vec<u8>, u32>,
    18     inner: HashMap<Vec<u8>, u32>,
    18 }
    19 }
    47         }
    48         }
    48 
    49 
    49         multiset
    50         multiset
    50     }
    51     }
    51 
    52 
    52     /// Returns the slice up to the next directory name from right to left,
       
    53     /// without trailing slash
       
    54     fn find_dir(path: &[u8]) -> &[u8] {
       
    55         let mut path = path;
       
    56         loop {
       
    57             if let Some(new_pos) = path.len().checked_sub(1) {
       
    58                 if path[new_pos] == b'/' {
       
    59                     break &path[..new_pos];
       
    60                 }
       
    61                 path = &path[..new_pos];
       
    62             } else {
       
    63                 break &[];
       
    64             }
       
    65         }
       
    66     }
       
    67 
       
    68     /// Increases the count of deepest directory contained in the path.
    53     /// Increases the count of deepest directory contained in the path.
    69     ///
    54     ///
    70     /// If the directory is not yet in the map, adds its parents.
    55     /// If the directory is not yet in the map, adds its parents.
    71     pub fn add_path(&mut self, path: &[u8]) {
    56     pub fn add_path(&mut self, path: &[u8]) {
    72         let mut pos = path.len();
    57         for subpath in files::find_dirs(path) {
    73 
       
    74         loop {
       
    75             let subpath = Self::find_dir(&path[..pos]);
       
    76             if let Some(val) = self.inner.get_mut(subpath) {
    58             if let Some(val) = self.inner.get_mut(subpath) {
    77                 *val += 1;
    59                 *val += 1;
    78                 break;
    60                 break;
    79             }
    61             }
    80             self.inner.insert(subpath.to_owned(), 1);
    62             self.inner.insert(subpath.to_owned(), 1);
    81 
       
    82             pos = subpath.len();
       
    83             if pos == 0 {
       
    84                 break;
       
    85             }
       
    86         }
    63         }
    87     }
    64     }
    88 
    65 
    89     /// Decreases the count of deepest directory contained in the path.
    66     /// Decreases the count of deepest directory contained in the path.
    90     ///
    67     ///
    93     /// If the directory is not in the map, something horrible has happened.
    70     /// If the directory is not in the map, something horrible has happened.
    94     pub fn delete_path(
    71     pub fn delete_path(
    95         &mut self,
    72         &mut self,
    96         path: &[u8],
    73         path: &[u8],
    97     ) -> Result<(), DirstateMapError> {
    74     ) -> Result<(), DirstateMapError> {
    98         let mut pos = path.len();
    75         for subpath in files::find_dirs(path) {
    99 
       
   100         loop {
       
   101             let subpath = Self::find_dir(&path[..pos]);
       
   102             match self.inner.entry(subpath.to_owned()) {
    76             match self.inner.entry(subpath.to_owned()) {
   103                 Entry::Occupied(mut entry) => {
    77                 Entry::Occupied(mut entry) => {
   104                     let val = entry.get().clone();
    78                     let val = entry.get().clone();
   105                     if val > 1 {
    79                     if val > 1 {
   106                         entry.insert(val - 1);
    80                         entry.insert(val - 1);
   112                     return Err(DirstateMapError::PathNotFound(
    86                     return Err(DirstateMapError::PathNotFound(
   113                         path.to_owned(),
    87                         path.to_owned(),
   114                     ))
    88                     ))
   115                 }
    89                 }
   116             };
    90             };
   117 
       
   118             pos = subpath.len();
       
   119             if pos == 0 {
       
   120                 break;
       
   121             }
       
   122         }
    91         }
   123 
    92 
   124         Ok(())
    93         Ok(())
   125     }
    94     }
   126 
    95