Mercurial > public > mercurial-scm > hg
annotate rust/rhg/src/commands/cat.rs @ 48471:b005d07ded7d
rhg: Skip reading the contents of ambiguous files in some cases
If the size of the file in the working directory does not match the length of
the filelog data, we know its contents will be different and don?t need to
read it.
rhg still decodes the filelog revision, which is not needed in some cases.
Differential Revision: https://phab.mercurial-scm.org/D11910
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Tue, 14 Dec 2021 20:36:36 +0100 |
parents | 698b70b9e8ea |
children | 044e42ae45d9 |
rev | line source |
---|---|
46434
3e2d539d0d1a
rust: remove `FooError` structs with only `kind: FooErrorKind` enum field
Simon Sapin <simon.sapin@octobus.net>
parents:
46167
diff
changeset
|
1 use crate::error::CommandError; |
46501
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
2 use clap::Arg; |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46740
diff
changeset
|
3 use format_bytes::format_bytes; |
46436
252d1bdba33d
rhg: replace `map_*_error` functions with `From` impls
Simon Sapin <simon.sapin@octobus.net>
parents:
46434
diff
changeset
|
4 use hg::operations::cat; |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
5 use hg::utils::hg_path::HgPathBuf; |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
6 use micro_timer::timed; |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
7 use std::convert::TryFrom; |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
8 |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
9 pub const HELP_TEXT: &str = " |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
10 Output the current or given revision of files |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
11 "; |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
12 |
46501
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
13 pub fn args() -> clap::App<'static, 'static> { |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
14 clap::SubCommand::with_name("cat") |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
15 .arg( |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
16 Arg::with_name("rev") |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
17 .help("search the repository as it is in REV") |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
18 .short("-r") |
48172
08c8cd2527bc
rhg: in rhg cat cli, fix the long name of the --rev flag
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48074
diff
changeset
|
19 .long("--rev") |
46501
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
20 .value_name("REV") |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
21 .takes_value(true), |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
22 ) |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
23 .arg( |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
24 clap::Arg::with_name("files") |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
25 .required(true) |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
26 .multiple(true) |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
27 .empty_values(false) |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
28 .value_name("FILE") |
48172
08c8cd2527bc
rhg: in rhg cat cli, fix the long name of the --rev flag
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48074
diff
changeset
|
29 .help("Files to output"), |
46501
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
30 ) |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
31 .about(HELP_TEXT) |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
32 } |
1ecaf09d9964
rhg: Move subcommand CLI arguments definitions to respective modules
Simon Sapin <simon.sapin@octobus.net>
parents:
46500
diff
changeset
|
33 |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
34 #[timed] |
46592
80840b651721
rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
35 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { |
48308
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
36 let cat_enabled_default = true; |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
37 let cat_enabled = invocation.config.get_option(b"rhg", b"cat")?; |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
38 if !cat_enabled.unwrap_or(cat_enabled_default) { |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
39 return Err(CommandError::unsupported( |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
40 "cat is disabled in rhg (enable it with 'rhg.cat = true' \ |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
41 or enable fallback with 'rhg.on-unsupported = fallback')", |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
42 )); |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
43 } |
698b70b9e8ea
rhg: make it possible to opt out of `rhg cat`
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48237
diff
changeset
|
44 |
46592
80840b651721
rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
45 let rev = invocation.subcommand_args.value_of("rev"); |
80840b651721
rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents:
46503
diff
changeset
|
46 let file_args = match invocation.subcommand_args.values_of("files") { |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
47 Some(files) => files.collect(), |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
48 None => vec![], |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
49 }; |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
50 |
46593
5ce2aa7c2ad5
rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents:
46592
diff
changeset
|
51 let repo = invocation.repo?; |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
52 let cwd = hg::utils::current_dir()?; |
46740
97ac588b6d9e
rhg: Don?t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents:
46666
diff
changeset
|
53 let working_directory = repo.working_directory_path(); |
97ac588b6d9e
rhg: Don?t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents:
46666
diff
changeset
|
54 let working_directory = cwd.join(working_directory); // Make it absolute |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
55 |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
56 let mut files = vec![]; |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
57 for file in file_args.iter() { |
48074
4a6fa6b6f079
rhg-cat: fallback in presence of a fileset
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48073
diff
changeset
|
58 if file.starts_with("set:") { |
4a6fa6b6f079
rhg-cat: fallback in presence of a fileset
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48073
diff
changeset
|
59 let message = "fileset"; |
4a6fa6b6f079
rhg-cat: fallback in presence of a fileset
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48073
diff
changeset
|
60 return Err(CommandError::unsupported(message)); |
4a6fa6b6f079
rhg-cat: fallback in presence of a fileset
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48073
diff
changeset
|
61 } |
4a6fa6b6f079
rhg-cat: fallback in presence of a fileset
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48073
diff
changeset
|
62 |
48073
1e00834491a5
rhg-cat: fallback when detecting `.` or `..` path segments
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48072
diff
changeset
|
63 let normalized = cwd.join(&file); |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
64 // TODO: actually normalize `..` path segments etc? |
48073
1e00834491a5
rhg-cat: fallback when detecting `.` or `..` path segments
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48072
diff
changeset
|
65 let dotted = normalized.components().any(|c| c.as_os_str() == ".."); |
1e00834491a5
rhg-cat: fallback when detecting `.` or `..` path segments
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48072
diff
changeset
|
66 if file == &"." || dotted { |
1e00834491a5
rhg-cat: fallback when detecting `.` or `..` path segments
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48072
diff
changeset
|
67 let message = "`..` or `.` path segment"; |
1e00834491a5
rhg-cat: fallback when detecting `.` or `..` path segments
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48072
diff
changeset
|
68 return Err(CommandError::unsupported(message)); |
1e00834491a5
rhg-cat: fallback when detecting `.` or `..` path segments
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48072
diff
changeset
|
69 } |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
70 let stripped = normalized |
46740
97ac588b6d9e
rhg: Don?t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents:
46666
diff
changeset
|
71 .strip_prefix(&working_directory) |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
72 // TODO: error message for path arguments outside of the repo |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
73 .map_err(|_| CommandError::abort(""))?; |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
74 let hg_file = HgPathBuf::try_from(stripped.to_path_buf()) |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
75 .map_err(|e| CommandError::abort(e.to_string()))?; |
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
76 files.push(hg_file); |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
77 } |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
78 let files = files.iter().map(|file| file.as_ref()).collect(); |
48072
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
79 // TODO probably move this to a util function like `repo.default_rev` or |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
80 // something when it's used somewhere else |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
81 let rev = match rev { |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
82 Some(r) => r.to_string(), |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
83 None => format!("{:x}", repo.dirstate_parents()?.p1), |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
84 }; |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
85 |
48224
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48172
diff
changeset
|
86 let output = cat(&repo, &rev, files).map_err(|e| (e, rev.as_str()))?; |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
87 for (_file, contents) in output.results { |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
88 invocation.ui.write_stdout(&contents)?; |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
89 } |
48072
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
90 if !output.missing.is_empty() { |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
91 let short = format!("{:x}", output.node.short()).into_bytes(); |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
92 for path in &output.missing { |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
93 invocation.ui.write_stderr(&format_bytes!( |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
94 b"{}: no such file in rev {}\n", |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
95 path.as_bytes(), |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
96 short |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
97 ))?; |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
98 } |
48072
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
99 } |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
100 if output.found_any { |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
101 Ok(()) |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
102 } else { |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
103 Err(CommandError::Unsuccessful) |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
104 } |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
105 } |