rust/hg-core/src/operations/status_rev_rev.rs
changeset 51155 ac3859a8b796
equal deleted inserted replaced
51154:aba622c7dc7e 51155:ac3859a8b796
       
     1 use crate::errors::HgError;
       
     2 use crate::matchers::Matcher;
       
     3 use crate::repo::Repo;
       
     4 use crate::revlog::manifest::Manifest;
       
     5 use crate::utils::filter_map_results;
       
     6 use crate::utils::hg_path::HgPath;
       
     7 use crate::utils::merge_join_results_by;
       
     8 
       
     9 use crate::Revision;
       
    10 
       
    11 use itertools::EitherOrBoth;
       
    12 
       
    13 #[derive(Debug, Copy, Clone)]
       
    14 pub enum DiffStatus {
       
    15     Removed,
       
    16     Added,
       
    17     Matching,
       
    18     Modified,
       
    19 }
       
    20 
       
    21 pub struct StatusRevRev {
       
    22     manifest1: Manifest,
       
    23     manifest2: Manifest,
       
    24     narrow_matcher: Box<dyn Matcher>,
       
    25 }
       
    26 
       
    27 fn manifest_for_rev(repo: &Repo, rev: Revision) -> Result<Manifest, HgError> {
       
    28     repo.manifest_for_rev(rev.into()).map_err(|e| {
       
    29         HgError::corrupted(format!(
       
    30             "manifest lookup failed for revision {}: {}",
       
    31             rev, e
       
    32         ))
       
    33     })
       
    34 }
       
    35 
       
    36 pub fn status_rev_rev_no_copies(
       
    37     repo: &Repo,
       
    38     rev1: Revision,
       
    39     rev2: Revision,
       
    40     narrow_matcher: Box<dyn Matcher>,
       
    41 ) -> Result<StatusRevRev, HgError> {
       
    42     let manifest1 = manifest_for_rev(repo, rev1)?;
       
    43     let manifest2 = manifest_for_rev(repo, rev2)?;
       
    44     Ok(StatusRevRev {
       
    45         manifest1,
       
    46         manifest2,
       
    47         narrow_matcher,
       
    48     })
       
    49 }
       
    50 
       
    51 impl StatusRevRev {
       
    52     pub fn iter(
       
    53         &self,
       
    54     ) -> impl Iterator<Item = Result<(&HgPath, DiffStatus), HgError>> {
       
    55         let iter1 = self.manifest1.iter();
       
    56         let iter2 = self.manifest2.iter();
       
    57 
       
    58         let merged =
       
    59             merge_join_results_by(iter1, iter2, |i1, i2| i1.path.cmp(i2.path));
       
    60 
       
    61         filter_map_results(merged, |entry| {
       
    62             let (path, status) = match entry {
       
    63                 EitherOrBoth::Left(entry) => {
       
    64                     let path = entry.path;
       
    65                     (path, DiffStatus::Removed)
       
    66                 }
       
    67                 EitherOrBoth::Right(entry) => {
       
    68                     let path = entry.path;
       
    69                     (path, DiffStatus::Added)
       
    70                 }
       
    71                 EitherOrBoth::Both(entry1, entry2) => {
       
    72                     let path = entry1.path;
       
    73                     if entry1.node_id().unwrap() == entry2.node_id().unwrap()
       
    74                         && entry1.flags == entry2.flags
       
    75                     {
       
    76                         (path, DiffStatus::Matching)
       
    77                     } else {
       
    78                         (path, DiffStatus::Modified)
       
    79                     }
       
    80                 }
       
    81             };
       
    82             Ok(if self.narrow_matcher.matches(path) {
       
    83                 Some((path, status))
       
    84             } else {
       
    85                 None
       
    86             })
       
    87         })
       
    88     }
       
    89 }