rust/hg-core/src/operations/cat.rs
changeset 48225 0cc69017d47f
parent 48224 6b5773f89183
child 48234 1837663ac216
equal deleted inserted replaced
48224:6b5773f89183 48225:0cc69017d47f
     7 
     7 
     8 use crate::repo::Repo;
     8 use crate::repo::Repo;
     9 use crate::revlog::revlog::RevlogError;
     9 use crate::revlog::revlog::RevlogError;
    10 use crate::revlog::Node;
    10 use crate::revlog::Node;
    11 
    11 
       
    12 use crate::utils::hg_path::HgPath;
    12 use crate::utils::hg_path::HgPathBuf;
    13 use crate::utils::hg_path::HgPathBuf;
    13 
    14 
    14 use itertools::EitherOrBoth::{Both, Left, Right};
    15 use itertools::put_back;
    15 use itertools::Itertools;
    16 use itertools::PutBack;
       
    17 use std::cmp::Ordering;
    16 
    18 
    17 pub struct CatOutput {
    19 pub struct CatOutput {
    18     /// Whether any file in the manifest matched the paths given as CLI
    20     /// Whether any file in the manifest matched the paths given as CLI
    19     /// arguments
    21     /// arguments
    20     pub found_any: bool,
    22     pub found_any: bool,
    22     pub concatenated: Vec<u8>,
    24     pub concatenated: Vec<u8>,
    23     /// Which of the CLI arguments did not match any manifest file
    25     /// Which of the CLI arguments did not match any manifest file
    24     pub missing: Vec<HgPathBuf>,
    26     pub missing: Vec<HgPathBuf>,
    25     /// The node ID that the given revset was resolved to
    27     /// The node ID that the given revset was resolved to
    26     pub node: Node,
    28     pub node: Node,
       
    29 }
       
    30 
       
    31 // Find an item in an iterator over a sorted collection.
       
    32 fn find_item<'a, 'b, 'c, D, I: Iterator<Item = (&'a HgPath, D)>>(
       
    33     i: &mut PutBack<I>,
       
    34     needle: &'b HgPath,
       
    35 ) -> Option<I::Item> {
       
    36     loop {
       
    37         match i.next() {
       
    38             None => return None,
       
    39             Some(val) => match needle.as_bytes().cmp(val.0.as_bytes()) {
       
    40                 Ordering::Less => {
       
    41                     i.put_back(val);
       
    42                     return None;
       
    43                 }
       
    44                 Ordering::Greater => continue,
       
    45                 Ordering::Equal => return Some(val),
       
    46             },
       
    47         }
       
    48     }
       
    49 }
       
    50 
       
    51 fn find_files_in_manifest<
       
    52     'a,
       
    53     'b,
       
    54     D,
       
    55     I: Iterator<Item = (&'a HgPath, D)>,
       
    56     J: Iterator<Item = &'b HgPath>,
       
    57 >(
       
    58     manifest: I,
       
    59     files: J,
       
    60 ) -> (Vec<(&'a HgPath, D)>, Vec<&'b HgPath>) {
       
    61     let mut manifest = put_back(manifest);
       
    62     let mut res = vec![];
       
    63     let mut missing = vec![];
       
    64 
       
    65     for file in files {
       
    66         match find_item(&mut manifest, file) {
       
    67             None => missing.push(file),
       
    68             Some(item) => res.push(item),
       
    69         }
       
    70     }
       
    71     return (res, missing);
    27 }
    72 }
    28 
    73 
    29 /// Output the given revision of files
    74 /// Output the given revision of files
    30 ///
    75 ///
    31 /// * `root`: Repository root
    76 /// * `root`: Repository root
    40     let manifest = repo.manifest_for_rev(rev)?;
    85     let manifest = repo.manifest_for_rev(rev)?;
    41     let node = *repo
    86     let node = *repo
    42         .changelog()?
    87         .changelog()?
    43         .node_from_rev(rev)
    88         .node_from_rev(rev)
    44         .expect("should succeed when repo.manifest did");
    89         .expect("should succeed when repo.manifest did");
    45     let mut bytes = vec![];
    90     let mut bytes: Vec<u8> = vec![];
    46     let mut found_any = false;
    91     let mut found_any = false;
       
    92 
    47     files.sort_unstable();
    93     files.sort_unstable();
    48 
    94 
    49     let mut missing = vec![];
    95     let (found, missing) = find_files_in_manifest(
       
    96         manifest.files_with_nodes(),
       
    97         files.iter().map(|f| f.as_ref()),
       
    98     );
    50 
    99 
    51     for entry in manifest
   100     for (manifest_file, node_bytes) in found {
    52         .files_with_nodes()
   101         found_any = true;
    53         .merge_join_by(files.iter(), |(manifest_file, _), file| {
   102         let file_log = repo.filelog(manifest_file)?;
    54             manifest_file.cmp(&file.as_ref())
   103         let file_node = Node::from_hex_for_repo(node_bytes)?;
    55         })
   104         bytes.extend(file_log.data_for_node(file_node)?.data()?);
    56     {
       
    57         match entry {
       
    58             Left(_) => (),
       
    59             Right(path) => missing.push(path),
       
    60             Both((manifest_file, node_bytes), _) => {
       
    61                 found_any = true;
       
    62                 let file_log = repo.filelog(manifest_file)?;
       
    63                 let file_node = Node::from_hex_for_repo(node_bytes)?;
       
    64                 let entry = file_log.data_for_node(file_node)?;
       
    65                 bytes.extend(entry.data()?)
       
    66             }
       
    67         }
       
    68     }
   105     }
    69 
   106 
    70     let missing: Vec<HgPathBuf> = missing
   107     let missing: Vec<HgPathBuf> = missing
    71         .iter()
   108         .iter()
    72         .map(|file| (*(file.as_ref())).to_owned())
   109         .map(|file| (*file).to_owned())
    73         .collect();
   110         .collect();
    74     Ok(CatOutput {
   111     Ok(CatOutput {
    75         found_any,
   112         found_any,
    76         concatenated: bytes,
   113         concatenated: bytes,
    77         missing,
   114         missing,