##// END OF EJS Templates
rhg: support rhg files [FILE]...
Spencer Baugh -
r51760:788113f0 default
parent child Browse files
Show More
@@ -1,116 +1,149 b''
1 1 use crate::error::CommandError;
2 2 use crate::ui::{
3 3 print_narrow_sparse_warnings, relative_paths, RelativePaths, Ui,
4 4 };
5 5 use crate::utils::path_utils::RelativizePaths;
6 6 use clap::Arg;
7 use hg::filepatterns::parse_pattern_args;
8 use hg::matchers::IntersectionMatcher;
7 9 use hg::narrow;
8 10 use hg::operations::list_rev_tracked_files;
9 11 use hg::repo::Repo;
12 use hg::utils::files::get_bytes_from_os_str;
10 13 use hg::utils::filter_map_results;
11 14 use hg::utils::hg_path::HgPath;
12 15 use rayon::prelude::*;
13 16
14 17 pub const HELP_TEXT: &str = "
15 18 List tracked files.
16 19
17 20 Returns 0 on success.
18 21 ";
19 22
20 23 pub fn args() -> clap::Command {
21 24 clap::command!("files")
22 25 .arg(
23 26 Arg::new("rev")
24 27 .help("search the repository as it is in REV")
25 28 .short('r')
26 29 .long("revision")
27 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 38 .about(HELP_TEXT)
30 39 }
31 40
32 41 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
33 42 let relative_paths = match relative_paths(invocation.config)? {
34 43 RelativePaths::Legacy => true,
35 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 50 let repo = invocation.repo?;
41 51
42 52 // It seems better if this check is removed: this would correspond to
43 53 // automatically enabling the extension if the repo requires it.
44 54 // However we need this check to be in sync with vanilla hg so hg tests
45 55 // pass.
46 56 if repo.has_sparse()
47 57 && invocation.config.get(b"extensions", b"sparse").is_none()
48 58 {
49 59 return Err(CommandError::unsupported(
50 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 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 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 92 .map_err(|e| (e, rev.as_ref()))?;
60 93 display_files(invocation.ui, repo, relative_paths, files.iter())
61 94 } else {
62 95 // The dirstate always reflects the sparse narrowspec.
63 96 let dirstate = repo.dirstate_map()?;
64 97 let files_res: Result<Vec<_>, _> =
65 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 100 Some(path)
68 101 } else {
69 102 None
70 103 })
71 104 })
72 105 .collect();
73 106
74 107 let mut files = files_res?;
75 108 files.par_sort_unstable();
76 109
77 110 display_files(
78 111 invocation.ui,
79 112 repo,
80 113 relative_paths,
81 114 files.into_iter().map::<Result<_, CommandError>, _>(Ok),
82 115 )
83 116 }
84 117 }
85 118
86 119 fn display_files<'a, E>(
87 120 ui: &Ui,
88 121 repo: &Repo,
89 122 relative_paths: bool,
90 123 files: impl IntoIterator<Item = Result<&'a HgPath, E>>,
91 124 ) -> Result<(), CommandError>
92 125 where
93 126 CommandError: From<E>,
94 127 {
95 128 let mut stdout = ui.stdout_buffer();
96 129 let mut any = false;
97 130
98 131 let relativize = RelativizePaths::new(repo)?;
99 132 for result in files {
100 133 let path = result?;
101 134 if relative_paths {
102 135 stdout.write_all(&relativize.relativize(path))?;
103 136 } else {
104 137 stdout.write_all(path.as_bytes())?;
105 138 }
106 139 stdout.write_all(b"\n")?;
107 140 any = true;
108 141 }
109 142
110 143 stdout.flush()?;
111 144 if any {
112 145 Ok(())
113 146 } else {
114 147 Err(CommandError::Unsuccessful)
115 148 }
116 149 }
General Comments 0
You need to be logged in to leave comments. Login now