Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/revlog/manifest.rs @ 53040:cdd7bf612c7b stable tip
bundle-spec: properly format boolean parameter (issue6960)
This was breaking automatic clone bundle generation. This changeset fixes it and
add a test to catch it in the future.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 11 Mar 2025 02:29:42 +0100 |
parents | 7b4548a075ab |
children |
rev | line source |
---|---|
52061
0ea323b7e3b1
rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
1 use std::num::NonZeroU8; |
0ea323b7e3b1
rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
2 |
47991
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47985
diff
changeset
|
3 use crate::errors::HgError; |
52775
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
4 use crate::revlog::options::RevlogOpenOptions; |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
5 use crate::revlog::{Node, NodePrefix, Revlog, RevlogError}; |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
6 use crate::utils::hg_path::HgPath; |
52774
94e2547e6f3d
rust: move code from utils to utils::strings
Mitchell Kember <mkember@janestreet.com>
parents:
52326
diff
changeset
|
7 use crate::utils::strings::SliceExt; |
51906 | 8 use crate::vfs::VfsImpl; |
52775
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
9 use crate::{Graph, GraphError, Revision, UncheckedRevision, NULL_REVISION}; |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
10 |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
11 /// A specialized `Revlog` to work with `manifest` data format. |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
12 pub struct Manifestlog { |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
13 /// The generic `revlog` format. |
51212
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
14 pub(crate) revlog: Revlog, |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
15 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
16 |
50989
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
17 impl Graph for Manifestlog { |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
18 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> { |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
19 self.revlog.parents(rev) |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
20 } |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
21 } |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
22 |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
23 impl Manifestlog { |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
24 /// Open the `manifest` of a repository given by its root. |
51212
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
25 pub fn open( |
51906 | 26 store_vfs: &VfsImpl, |
51212
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
27 options: RevlogOpenOptions, |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
28 ) -> Result<Self, HgError> { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
29 let revlog = Revlog::open(store_vfs, "00manifest.i", None, options)?; |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
30 Ok(Self { revlog }) |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
31 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
32 |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
33 /// Return the `Manifest` for the given node ID. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
34 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
35 /// Note: this is a node ID in the manifestlog, typically found through |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
36 /// `ChangelogEntry::manifest_node`. It is *not* the node ID of any |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
37 /// changeset. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
38 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
39 /// See also `Repo::manifest_for_node` |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
40 pub fn data_for_node( |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
41 &self, |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
42 node: NodePrefix, |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
43 ) -> Result<Manifest, RevlogError> { |
47996
6f579618ea7b
rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
44 let rev = self.revlog.rev_from_node(node)?; |
52326
a3fa37bdb7ec
rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52316
diff
changeset
|
45 self.data(rev) |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
46 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
47 |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
48 /// Return the `Manifest` of a given revision number. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
49 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
50 /// Note: this is a revision number in the manifestlog, *not* of any |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
51 /// changeset. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
52 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
53 /// See also `Repo::manifest_for_rev` |
52326
a3fa37bdb7ec
rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52316
diff
changeset
|
54 pub fn data_for_unchecked_rev( |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
55 &self, |
50988
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
56 rev: UncheckedRevision, |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
57 ) -> Result<Manifest, RevlogError> { |
52326
a3fa37bdb7ec
rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52316
diff
changeset
|
58 let bytes = self.revlog.get_data_for_unchecked_rev(rev)?.into_owned(); |
50988
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
59 Ok(Manifest { bytes }) |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
60 } |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
61 |
52326
a3fa37bdb7ec
rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52316
diff
changeset
|
62 /// Same as [`Self::data_for_unchecked_rev`] for a checked [`Revision`] |
a3fa37bdb7ec
rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52316
diff
changeset
|
63 pub fn data(&self, rev: Revision) -> Result<Manifest, RevlogError> { |
a3fa37bdb7ec
rust: normalize `_for_unchecked_rev` naming among revlogs and the index
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52316
diff
changeset
|
64 let bytes = self.revlog.get_data(rev)?.into_owned(); |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
65 Ok(Manifest { bytes }) |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
66 } |
52775
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
67 |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
68 /// Returns a manifest containing entries for `rev` that are not in its |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
69 /// parents. It is inexact because it might return a superset of this. |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
70 /// Equivalent to `manifestctx.read_delta_parents(exact=False)` in Python. |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
71 pub fn inexact_data_delta_parents( |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
72 &self, |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
73 rev: Revision, |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
74 ) -> Result<Manifest, RevlogError> { |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
75 let delta_parent = self.revlog.delta_parent(rev); |
52784
7b4548a075ab
rust: refactor conversions from GraphError
Mitchell Kember <mkember@janestreet.com>
parents:
52775
diff
changeset
|
76 let parents = self.parents(rev).map_err(|err| { |
7b4548a075ab
rust: refactor conversions from GraphError
Mitchell Kember <mkember@janestreet.com>
parents:
52775
diff
changeset
|
77 RevlogError::corrupted(format!("rev {rev}: {err}")) |
52775
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
78 })?; |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
79 if delta_parent == NULL_REVISION || !parents.contains(&delta_parent) { |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
80 return self.data(rev); |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
81 } |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
82 let mut bytes = vec![]; |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
83 for chunk in self.revlog.get_data_incr(rev)?.as_patch_list()?.chunks { |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
84 bytes.extend_from_slice(chunk.data); |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
85 } |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
86 Ok(Manifest { bytes }) |
8497cfb0d76c
rust-manifest: add Manifestlog::inexact_data_delta_parents
Mitchell Kember <mkember@janestreet.com>
parents:
52774
diff
changeset
|
87 } |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
88 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
89 |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
90 /// `Manifestlog` entry which knows how to interpret the `manifest` data bytes. |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
91 #[derive(Debug)] |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
92 pub struct Manifest { |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
93 /// Format for a manifest: flat sequence of variable-size entries, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
94 /// sorted by path, each as: |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
95 /// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
96 /// ```text |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
97 /// <path> \0 <hex_node_id> <flags> \n |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
98 /// ``` |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
99 /// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
100 /// The last entry is also terminated by a newline character. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
101 /// Flags is one of `b""` (the empty string), `b"x"`, `b"l"`, or `b"t"`. |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
102 bytes: Vec<u8>, |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
103 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
104 |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
105 impl Manifest { |
52072
78fc666a3e94
rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52061
diff
changeset
|
106 /// Return a new empty manifest |
78fc666a3e94
rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52061
diff
changeset
|
107 pub fn empty() -> Self { |
78fc666a3e94
rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52061
diff
changeset
|
108 Self { bytes: vec![] } |
78fc666a3e94
rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52061
diff
changeset
|
109 } |
78fc666a3e94
rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52061
diff
changeset
|
110 |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
111 pub fn iter( |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
112 &self, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
113 ) -> impl Iterator<Item = Result<ManifestEntry, HgError>> { |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
114 self.bytes |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
115 .split(|b| b == &b'\n') |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
116 .filter(|line| !line.is_empty()) |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
117 .map(ManifestEntry::from_raw) |
45546
f2de24c2b1f6
hg-core: add `files_with_nodes` to `Manifest`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45539
diff
changeset
|
118 } |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
119 |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
120 /// If the given path is in this manifest, return its filelog node ID |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
121 pub fn find_by_path( |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
122 &self, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
123 path: &HgPath, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
124 ) -> Result<Option<ManifestEntry>, HgError> { |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
125 use std::cmp::Ordering::*; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
126 let path = path.as_bytes(); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
127 // Both boundaries of this `&[u8]` slice are always at the boundary of |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
128 // an entry |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
129 let mut bytes = &*self.bytes; |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
130 |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
131 // Binary search algorithm derived from `[T]::binary_search_by` |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
132 // <https://github.com/rust-lang/rust/blob/1.57.0/library/core/src/slice/mod.rs#L2221> |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
133 // except we don’t have a slice of entries. Instead we jump to the |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
134 // middle of the byte slice and look around for entry delimiters |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
135 // (newlines). |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
136 while let Some(entry_range) = Self::find_entry_near_middle_of(bytes)? { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
137 let (entry_path, rest) = |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
138 ManifestEntry::split_path(&bytes[entry_range.clone()])?; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
139 let cmp = entry_path.cmp(path); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
140 if cmp == Less { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
141 let after_newline = entry_range.end + 1; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
142 bytes = &bytes[after_newline..]; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
143 } else if cmp == Greater { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
144 bytes = &bytes[..entry_range.start]; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
145 } else { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
146 return Ok(Some(ManifestEntry::from_path_and_rest( |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
147 entry_path, rest, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
148 ))); |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
149 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
150 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
151 Ok(None) |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
152 } |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
153 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
154 /// If there is at least one, return the byte range of an entry *excluding* |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
155 /// the final newline. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
156 fn find_entry_near_middle_of( |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
157 bytes: &[u8], |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
158 ) -> Result<Option<std::ops::Range<usize>>, HgError> { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
159 let len = bytes.len(); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
160 if len > 0 { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
161 let middle = bytes.len() / 2; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
162 // Integer division rounds down, so `middle < len`. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
163 let (before, after) = bytes.split_at(middle); |
52316
f4aede0f01af
rust-manifest: use `memchr` crate for all byte-finding needs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
164 let entry_start = match memchr::memrchr(b'\n', before) { |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
165 Some(i) => i + 1, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
166 None => 0, // We choose the first entry in `bytes` |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
167 }; |
52316
f4aede0f01af
rust-manifest: use `memchr` crate for all byte-finding needs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52286
diff
changeset
|
168 let entry_end = match memchr::memchr(b'\n', after) { |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
169 Some(i) => { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
170 // No `+ 1` here to exclude this newline from the range |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
171 middle + i |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
172 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
173 None => { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
174 // In a well-formed manifest: |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
175 // |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
176 // * Since `len > 0`, `bytes` contains at least one entry |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
177 // * Every entry ends with a newline |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
178 // * Since `middle < len`, `after` contains at least the |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
179 // newline at the end of the last entry of `bytes`. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
180 // |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
181 // We didn’t find a newline, so this manifest is not |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
182 // well-formed. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
183 return Err(HgError::corrupted( |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
184 "manifest entry without \\n delimiter", |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
185 )); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
186 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
187 }; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
188 Ok(Some(entry_start..entry_end)) |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
189 } else { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
190 // len == 0 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
191 Ok(None) |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
192 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
193 } |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
194 } |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
195 |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
196 /// `Manifestlog` entry which knows how to interpret the `manifest` data bytes. |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
197 #[derive(Debug)] |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
198 pub struct ManifestEntry<'manifest> { |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
199 pub path: &'manifest HgPath, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
200 pub hex_node_id: &'manifest [u8], |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
201 |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
202 /// `Some` values are b'x', b'l', or 't' |
52061
0ea323b7e3b1
rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
203 pub flags: Option<NonZeroU8>, |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
204 } |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
205 |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
206 impl<'a> ManifestEntry<'a> { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
207 fn split_path(bytes: &[u8]) -> Result<(&[u8], &[u8]), HgError> { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
208 bytes.split_2(b'\0').ok_or_else(|| { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
209 HgError::corrupted("manifest entry without \\0 delimiter") |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
210 }) |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
211 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
212 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
213 fn from_path_and_rest(path: &'a [u8], rest: &'a [u8]) -> Self { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
214 let (hex_node_id, flags) = match rest.split_last() { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
215 Some((&b'x', rest)) => (rest, Some(b'x')), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
216 Some((&b'l', rest)) => (rest, Some(b'l')), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
217 Some((&b't', rest)) => (rest, Some(b't')), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
218 _ => (rest, None), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
219 }; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
220 Self { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
221 path: HgPath::new(path), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
222 hex_node_id, |
52061
0ea323b7e3b1
rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents:
51906
diff
changeset
|
223 flags: flags.map(|f| f.try_into().expect("invalid flag")), |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
224 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
225 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
226 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
227 fn from_raw(bytes: &'a [u8]) -> Result<Self, HgError> { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
228 let (path, rest) = Self::split_path(bytes)?; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
229 Ok(Self::from_path_and_rest(path, rest)) |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
230 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
231 |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
232 pub fn node_id(&self) -> Result<Node, HgError> { |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
233 Node::from_hex_for_repo(self.hex_node_id) |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
234 } |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
235 } |