Mercurial > public > mercurial-scm > hg
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 }) |