Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/operations/cat.rs @ 48249:027ebad952ac
rhg: internally, return a structured representation from hg cat
The purpose of this change is to make it possible to support limited templating in `hg cat`, so we could print separators between files etc.
The templating itself is not implemented yet, so this functionality is unused in `rhg cat`.
However, in our fork of hg we're implementing a slightly different command `hg jscat` which makes use of this.
So accepting this change will let us minimize the size of the patch we're maintaining on our side.
Differential Revision: https://phab.mercurial-scm.org/D11679
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Fri, 15 Oct 2021 14:05:20 +0100 |
parents | 1837663ac216 |
children | 10c32e1b892a |
rev | line source |
---|---|
45547
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:
46136
diff
changeset
|
8 use crate::repo::Repo; |
45547
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
9 use crate::revlog::revlog::RevlogError; |
46037
88e741bf2d93
rust: use NodePrefix::from_hex instead of hex::decode directly
Simon Sapin <simon-commits@exyr.org>
parents:
46036
diff
changeset
|
10 use crate::revlog::Node; |
47989
4d2a5ca060e3
rust: Add a Filelog struct that wraps Revlog
Simon Sapin <simon.sapin@octobus.net>
parents:
47988
diff
changeset
|
11 |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
12 use crate::utils::hg_path::HgPath; |
45547
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
13 |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
14 use itertools::put_back; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
15 use itertools::PutBack; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
16 use std::cmp::Ordering; |
48236
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47997
diff
changeset
|
17 |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
18 pub struct CatOutput<'a> { |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
19 /// 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:
46511
diff
changeset
|
20 /// arguments |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
21 pub found_any: bool, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
22 /// The contents of matching files, in manifest order |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
23 pub results: Vec<(&'a HgPath, Vec<u8>)>, |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
24 /// Which of the CLI arguments did not match any manifest file |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
25 pub missing: Vec<&'a HgPath>, |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
26 /// 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:
46511
diff
changeset
|
27 pub node: Node, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
28 } |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
29 |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
30 // Find an item in an iterator over a sorted collection. |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
31 fn find_item<'a, 'b, 'c, D, I: Iterator<Item = (&'a HgPath, D)>>( |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
32 i: &mut PutBack<I>, |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
33 needle: &'b HgPath, |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
34 ) -> Option<D> { |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
35 loop { |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
36 match i.next() { |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
37 None => return None, |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
38 Some(val) => match needle.as_bytes().cmp(val.0.as_bytes()) { |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
39 Ordering::Less => { |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
40 i.put_back(val); |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
41 return None; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
42 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
43 Ordering::Greater => continue, |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
44 Ordering::Equal => return Some(val.1), |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
45 }, |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
46 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
47 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
48 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
49 |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
50 fn find_files_in_manifest< |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
51 'manifest, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
52 'query, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
53 Data, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
54 Manifest: Iterator<Item = (&'manifest HgPath, Data)>, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
55 Query: Iterator<Item = &'query HgPath>, |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
56 >( |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
57 manifest: Manifest, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
58 query: Query, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
59 ) -> (Vec<(&'query HgPath, Data)>, Vec<&'query HgPath>) { |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
60 let mut manifest = put_back(manifest); |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
61 let mut res = vec![]; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
62 let mut missing = vec![]; |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
63 |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
64 for file in query { |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
65 match find_item(&mut manifest, file) { |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
66 None => missing.push(file), |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
67 Some(item) => res.push((file, item)), |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
68 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
69 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
70 return (res, missing); |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
71 } |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
72 |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
73 /// Output the given revision of files |
46136
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46135
diff
changeset
|
74 /// |
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46135
diff
changeset
|
75 /// * `root`: Repository root |
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46135
diff
changeset
|
76 /// * `rev`: The revision to cat the files from. |
dca9cb99971c
rust: replace most "operation" structs with functions
Simon Sapin <simon.sapin@octobus.net>
parents:
46135
diff
changeset
|
77 /// * `files`: The files to output. |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
78 pub fn cat<'a>( |
46167
8a4914397d02
rust: introduce Repo and Vfs types for filesystem abstraction
Simon Sapin <simon.sapin@octobus.net>
parents:
46136
diff
changeset
|
79 repo: &Repo, |
46501
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
80 revset: &str, |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
81 mut files: Vec<&'a HgPath>, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
82 ) -> Result<CatOutput<'a>, RevlogError> { |
46501
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
83 let rev = crate::revset::resolve_single(revset, repo)?; |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47989
diff
changeset
|
84 let manifest = repo.manifest_for_rev(rev)?; |
47988
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
85 let node = *repo |
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
86 .changelog()? |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
87 .node_from_rev(rev) |
47988
cfb6e6699b25
rust: Add Repo::manifest(revision)
Simon Sapin <simon.sapin@octobus.net>
parents:
47987
diff
changeset
|
88 .expect("should succeed when repo.manifest did"); |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
89 let mut results: Vec<(&'a HgPath, Vec<u8>)> = vec![]; |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
90 let mut found_any = false; |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
91 |
48236
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47997
diff
changeset
|
92 files.sort_unstable(); |
6b5773f89183
rhg: faster hg cat when many files are requested
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
47997
diff
changeset
|
93 |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
94 let (found, missing) = find_files_in_manifest( |
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
95 manifest.files_with_nodes(), |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
96 files.into_iter().map(|f| f.as_ref()), |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
97 ); |
45547
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
98 |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
99 for (file_path, node_bytes) in found { |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
100 found_any = true; |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
101 let file_log = repo.filelog(file_path)?; |
48237
0cc69017d47f
rhg: stop manifest traversal when no more files are needed
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48236
diff
changeset
|
102 let file_node = Node::from_hex_for_repo(node_bytes)?; |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
103 results.push(( |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
104 file_path, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
105 file_log.data_for_node(file_node)?.into_data()?, |
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
106 )); |
45547
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 |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
109 Ok(CatOutput { |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
110 found_any, |
48249
027ebad952ac
rhg: internally, return a structured representation from hg cat
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
48246
diff
changeset
|
111 results, |
46757
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
112 missing, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
113 node, |
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46511
diff
changeset
|
114 }) |
45547
522ec3dc44b9
hg-core: add a `CatRev` operation
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
115 } |