Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/operations/cat.rs @ 52160:e01e84e5e426
rust-revlog: add a Rust-only `InnerRevlog`
This mirrors the Python `InnerRevlog` and will be used in a future patch
to replace said Python implementation. This allows us to start doing more
things in pure Rust, in particular reading and writing operations.
A lot of changes have to be introduced all at once, it wouldn't be very
useful to separate this patch IMO since all of them are either interlocked
or only useful with the rest.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Thu, 10 Oct 2024 10:34:51 +0200 |
parents | 1928b770e3e7 |
children | bd8081e9fd62 |
rev | line source |
---|---|
45541
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
1 // list_tracked_files.rs |
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
2 // |
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
3 // Copyright 2020 Antoine Cezar <antoine.cezar@octobus.net> |
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
4 // |
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
5 // This software may be used and distributed according to the terms of the |
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
6 // GNU General Public License version 2 or any later version. |
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
7 |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
46135
diff
changeset
|
8 use crate::repo::Repo; |
46033
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46032
diff
changeset
|
9 use crate::revlog::Node; |
49937
750409505286
rust-clippy: merge "revlog" module definition and struct implementation
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49930
diff
changeset
|
10 use crate::revlog::RevlogError; |
47961
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47960
diff
changeset
|
11 |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
12 use crate::utils::hg_path::HgPath; |
45541
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
13 |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
14 use crate::errors::HgError; |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
15 use crate::manifest::Manifest; |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
16 use crate::manifest::ManifestEntry; |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
17 use itertools::put_back; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
18 use itertools::PutBack; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
19 use std::cmp::Ordering; |
48224
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
20 |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
21 pub struct CatOutput<'a> { |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
22 /// Whether any file in the manifest matched the paths given as CLI |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
23 /// arguments |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
24 pub found_any: bool, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
25 /// The contents of matching files, in manifest order |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
26 pub results: Vec<(&'a HgPath, Vec<u8>)>, |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
27 /// Which of the CLI arguments did not match any manifest file |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
28 pub missing: Vec<&'a HgPath>, |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
29 /// The node ID that the given revset was resolved to |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
30 pub node: Node, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
31 } |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
32 |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
33 // Find an item in an iterator over a sorted collection. |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
34 fn find_item<'a>( |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
35 i: &mut PutBack<impl Iterator<Item = Result<ManifestEntry<'a>, HgError>>>, |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
36 needle: &HgPath, |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
37 ) -> Result<Option<Node>, HgError> { |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
38 loop { |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
39 match i.next() { |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
40 None => return Ok(None), |
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
41 Some(result) => { |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
42 let entry = result?; |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
43 match needle.as_bytes().cmp(entry.path.as_bytes()) { |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
44 Ordering::Less => { |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
45 i.put_back(Ok(entry)); |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
46 return Ok(None); |
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
47 } |
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
48 Ordering::Greater => continue, |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
49 Ordering::Equal => return Ok(Some(entry.node_id()?)), |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
50 } |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
51 } |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
52 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
53 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
54 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
55 |
49925
49131579db62
rust-clippy: refactor complex type
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48540
diff
changeset
|
56 // Tuple of (missing, found) paths in the manifest |
49131579db62
rust-clippy: refactor complex type
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48540
diff
changeset
|
57 type ManifestQueryResponse<'a> = (Vec<(&'a HgPath, Node)>, Vec<&'a HgPath>); |
49131579db62
rust-clippy: refactor complex type
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48540
diff
changeset
|
58 |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
59 fn find_files_in_manifest<'query>( |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
60 manifest: &Manifest, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
61 query: impl Iterator<Item = &'query HgPath>, |
49925
49131579db62
rust-clippy: refactor complex type
Rapha?l Gom?s <rgomes@octobus.net>
parents:
48540
diff
changeset
|
62 ) -> Result<ManifestQueryResponse<'query>, HgError> { |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
63 let mut manifest = put_back(manifest.iter()); |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
64 let mut res = vec![]; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
65 let mut missing = vec![]; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
66 |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
67 for file in query { |
48342
10c32e1b892a
rhg: Propogate manifest parse errors instead of panicking
Simon Sapin <simon.sapin@octobus.net>
parents:
48237
diff
changeset
|
68 match find_item(&mut manifest, file)? { |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
69 None => missing.push(file), |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
70 Some(item) => res.push((file, item)), |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
71 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
72 } |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49925
diff
changeset
|
73 Ok((res, missing)) |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
74 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
75 |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
76 /// Output the given revision of files |
46135
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46134
diff
changeset
|
77 /// |
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46134
diff
changeset
|
78 /// * `root`: Repository root |
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46134
diff
changeset
|
79 /// * `rev`: The revision to cat the files from. |
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46134
diff
changeset
|
80 /// * `files`: The files to output. |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
81 pub fn cat<'a>( |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
46135
diff
changeset
|
82 repo: &Repo, |
46433
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
83 revset: &str, |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
84 mut files: Vec<&'a HgPath>, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
85 ) -> Result<CatOutput<'a>, RevlogError> { |
46433
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
86 let rev = crate::revset::resolve_single(revset, repo)?; |
50974
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49937
diff
changeset
|
87 let manifest = repo.manifest_for_rev(rev.into())?; |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
88 let node = *repo |
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
89 .changelog()? |
50974
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49937
diff
changeset
|
90 .node_from_rev(rev.into()) |
47960
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47959
diff
changeset
|
91 .expect("should succeed when repo.manifest did"); |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
92 let mut results: Vec<(&'a HgPath, Vec<u8>)> = vec![]; |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
93 let mut found_any = false; |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
94 |
48224
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
95 files.sort_unstable(); |
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47969
diff
changeset
|
96 |
49930
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49925
diff
changeset
|
97 let (found, missing) = |
e98fd81bb151
rust-clippy: fix most warnings in `hg-core`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49925
diff
changeset
|
98 find_files_in_manifest(&manifest, files.into_iter())?; |
45541
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
99 |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
100 for (file_path, file_node) in found { |
48225
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48224
diff
changeset
|
101 found_any = true; |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
102 let file_log = repo.filelog(file_path)?; |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
103 results.push(( |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
104 file_path, |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
105 file_log.data_for_node(file_node)?.into_file_data()?, |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
106 )); |
45541
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
107 } |
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
108 |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
109 Ok(CatOutput { |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
110 found_any, |
48237
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48234
diff
changeset
|
111 results, |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
112 missing, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
113 node, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
114 }) |
45541
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
115 } |