rust/rhg/src/commands/files.rs
changeset 50864 788113f056d4
parent 50537 9db197c73138
child 52034 b7d99348ea36
equal deleted inserted replaced
50863:c112cc9effdc 50864:788113f056d4
     2 use crate::ui::{
     2 use crate::ui::{
     3     print_narrow_sparse_warnings, relative_paths, RelativePaths, Ui,
     3     print_narrow_sparse_warnings, relative_paths, RelativePaths, Ui,
     4 };
     4 };
     5 use crate::utils::path_utils::RelativizePaths;
     5 use crate::utils::path_utils::RelativizePaths;
     6 use clap::Arg;
     6 use clap::Arg;
       
     7 use hg::filepatterns::parse_pattern_args;
       
     8 use hg::matchers::IntersectionMatcher;
     7 use hg::narrow;
     9 use hg::narrow;
     8 use hg::operations::list_rev_tracked_files;
    10 use hg::operations::list_rev_tracked_files;
     9 use hg::repo::Repo;
    11 use hg::repo::Repo;
       
    12 use hg::utils::files::get_bytes_from_os_str;
    10 use hg::utils::filter_map_results;
    13 use hg::utils::filter_map_results;
    11 use hg::utils::hg_path::HgPath;
    14 use hg::utils::hg_path::HgPath;
    12 use rayon::prelude::*;
    15 use rayon::prelude::*;
    13 
    16 
    14 pub const HELP_TEXT: &str = "
    17 pub const HELP_TEXT: &str = "
    24                 .help("search the repository as it is in REV")
    27                 .help("search the repository as it is in REV")
    25                 .short('r')
    28                 .short('r')
    26                 .long("revision")
    29                 .long("revision")
    27                 .value_name("REV"),
    30                 .value_name("REV"),
    28         )
    31         )
       
    32         .arg(
       
    33             Arg::new("file")
       
    34                 .value_parser(clap::value_parser!(std::ffi::OsString))
       
    35                 .help("show only these files")
       
    36                 .action(clap::ArgAction::Append),
       
    37         )
    29         .about(HELP_TEXT)
    38         .about(HELP_TEXT)
    30 }
    39 }
    31 
    40 
    32 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
    41 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
    33     let relative_paths = match relative_paths(invocation.config)? {
    42     let relative_paths = match relative_paths(invocation.config)? {
    34         RelativePaths::Legacy => true,
    43         RelativePaths::Legacy => true,
    35         RelativePaths::Bool(v) => v,
    44         RelativePaths::Bool(v) => v,
    36     };
    45     };
    37 
    46 
    38     let rev = invocation.subcommand_args.get_one::<String>("rev");
    47     let args = invocation.subcommand_args;
       
    48     let rev = args.get_one::<String>("rev");
    39 
    49 
    40     let repo = invocation.repo?;
    50     let repo = invocation.repo?;
    41 
    51 
    42     // It seems better if this check is removed: this would correspond to
    52     // It seems better if this check is removed: this would correspond to
    43     // automatically enabling the extension if the repo requires it.
    53     // automatically enabling the extension if the repo requires it.
    49         return Err(CommandError::unsupported(
    59         return Err(CommandError::unsupported(
    50             "repo is using sparse, but sparse extension is not enabled",
    60             "repo is using sparse, but sparse extension is not enabled",
    51         ));
    61         ));
    52     }
    62     }
    53 
    63 
    54     let (narrow_matcher, narrow_warnings) = narrow::matcher(repo)?;
    64     let (matcher, narrow_warnings) = narrow::matcher(repo)?;
    55     print_narrow_sparse_warnings(&narrow_warnings, &[], invocation.ui, repo)?;
    65     print_narrow_sparse_warnings(&narrow_warnings, &[], invocation.ui, repo)?;
       
    66     let matcher = match args.get_many::<std::ffi::OsString>("file") {
       
    67         None => matcher,
       
    68         Some(files) => {
       
    69             let patterns: Vec<Vec<u8>> = files
       
    70                 .filter(|s| !s.is_empty())
       
    71                 .map(get_bytes_from_os_str)
       
    72                 .collect();
       
    73             for file in &patterns {
       
    74                 if file.starts_with(b"set:") {
       
    75                     return Err(CommandError::unsupported("fileset"));
       
    76                 }
       
    77             }
       
    78             let cwd = hg::utils::current_dir()?;
       
    79             let root = repo.working_directory_path();
       
    80             let ignore_patterns = parse_pattern_args(patterns, &cwd, root)?;
       
    81             let files_matcher =
       
    82                 hg::matchers::PatternMatcher::new(ignore_patterns)?;
       
    83             Box::new(IntersectionMatcher::new(
       
    84                 Box::new(files_matcher),
       
    85                 matcher,
       
    86             ))
       
    87         }
       
    88     };
    56 
    89 
    57     if let Some(rev) = rev {
    90     if let Some(rev) = rev {
    58         let files = list_rev_tracked_files(repo, rev, narrow_matcher)
    91         let files = list_rev_tracked_files(repo, rev, matcher)
    59             .map_err(|e| (e, rev.as_ref()))?;
    92             .map_err(|e| (e, rev.as_ref()))?;
    60         display_files(invocation.ui, repo, relative_paths, files.iter())
    93         display_files(invocation.ui, repo, relative_paths, files.iter())
    61     } else {
    94     } else {
    62         // The dirstate always reflects the sparse narrowspec.
    95         // The dirstate always reflects the sparse narrowspec.
    63         let dirstate = repo.dirstate_map()?;
    96         let dirstate = repo.dirstate_map()?;
    64         let files_res: Result<Vec<_>, _> =
    97         let files_res: Result<Vec<_>, _> =
    65             filter_map_results(dirstate.iter(), |(path, entry)| {
    98             filter_map_results(dirstate.iter(), |(path, entry)| {
    66                 Ok(if entry.tracked() && narrow_matcher.matches(path) {
    99                 Ok(if entry.tracked() && matcher.matches(path) {
    67                     Some(path)
   100                     Some(path)
    68                 } else {
   101                 } else {
    69                     None
   102                     None
    70                 })
   103                 })
    71             })
   104             })