comparison rust/rhg/src/commands/files.rs @ 50864:788113f056d4

rhg: support rhg files [FILE] This comes mostly for free after the rhg status [FILE] implementation.
author Spencer Baugh <sbaugh@janestreet.com>
date Thu, 17 Aug 2023 15:53:32 -0400
parents 9db197c73138
children b7d99348ea36
comparison
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 })