Mercurial > public > mercurial-scm > hg
annotate rust/rhg/src/commands/cat.rs @ 50215:ae61851e6fe2 stable
dirstate: add a way to test races happening during status
We add the `devel.sync.status.pre-dirstate-write-file` config option to easily
test what happens when other operations happen during the window where
`hg status` is done working but has not updated the cache on disk yet.
We introduce the framework for testing such races too, actual tests will be
added in the next changesets. For now the test is only checking dirstate-v1. We
will extend the test coverage later too.
Check test documentation for details.
Code change from Rapha?l Gom?s <rgomes@octobus.net>
Test change from Pierre-Yves David <pierre-yves.david@octobus.net>
author | Rapha?l Gom?s <rgomes@octobus.net>, Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 28 Feb 2023 15:25:47 +0100 |
parents | 044e42ae45d9 |
children | c7fb9b74e753 |
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 } |
49375
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
70 let relative_path = working_directory |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
71 .strip_prefix(&cwd) |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
72 .unwrap_or(&working_directory); |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
73 let stripped = normalized |
46740
97ac588b6d9e
rhg: Don?t make repository path absolute too early
Simon Sapin <simon.sapin@octobus.net>
parents:
46666
diff
changeset
|
74 .strip_prefix(&working_directory) |
49375
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
75 .map_err(|_| { |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
76 CommandError::abort(format!( |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
77 "abort: {} not under root '{}'\n(consider using '--cwd {}')", |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
78 file, |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
79 working_directory.display(), |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
80 relative_path.display(), |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
81 )) |
044e42ae45d9
rhg: add error message for paths outside the repository when cwd != root
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48308
diff
changeset
|
82 })?; |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
83 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
|
84 .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
|
85 files.push(hg_file); |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
86 } |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
87 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
|
88 // 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
|
89 // 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
|
90 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
|
91 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
|
92 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
|
93 }; |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
94 |
48224
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48172
diff
changeset
|
95 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
|
96 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
|
97 invocation.ui.write_stdout(&contents)?; |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
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 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
|
100 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
|
101 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
|
102 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
|
103 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
|
104 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
|
105 short |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
106 ))?; |
46500
184e46550dc8
rhg: replace command structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46484
diff
changeset
|
107 } |
48072
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
108 } |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
109 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
|
110 Ok(()) |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
111 } else { |
d919b0ca8449
rhg: add support for calling `rhg cat` without a revision
Rapha?l Gom?s <rgomes@octobus.net>
parents:
46744
diff
changeset
|
112 Err(CommandError::Unsuccessful) |
45542
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
113 } |
33ded2d3f4fc
rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
114 } |