annotate rust/hg-core/src/revlog/manifest.rs @ 52186:e6a44bc91bc2 stable

rust-update: make `update_from_null` respect `worker.numcpu` config option This was overlooked in the original series. This is important for tests (because we run many at once), and for the occasional end user that wants to keep their CPU usage in check. A future series should clean up this `worker` parameter tunelling business by rewriting the config in Rust, but doing so on stable would be a very bad idea.
author Rapha?l Gom?s <rgomes@octobus.net>
date Tue, 05 Nov 2024 15:21:09 +0100
parents 78fc666a3e94
children 039b7caeb4d9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
52033
0ea323b7e3b1 rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51864
diff changeset
1 use std::num::NonZeroU8;
0ea323b7e3b1 rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51864
diff changeset
2
47963
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47957
diff changeset
3 use crate::errors::HgError;
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
4 use crate::revlog::{Node, NodePrefix};
49937
750409505286 rust-clippy: merge "revlog" module definition and struct implementation
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49090
diff changeset
5 use crate::revlog::{Revlog, RevlogError};
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
6 use crate::utils::hg_path::HgPath;
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
7 use crate::utils::SliceExt;
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
8 use crate::vfs::VfsImpl;
51188
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
9 use crate::{
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
10 Graph, GraphError, Revision, RevlogOpenOptions, UncheckedRevision,
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
11 };
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
12
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
13 /// A specialized `Revlog` to work with `manifest` data format.
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
14 pub struct Manifestlog {
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
15 /// The generic `revlog` format.
51188
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
16 pub(crate) revlog: Revlog,
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
17 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
18
50975
27e773aa607d rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50974
diff changeset
19 impl Graph for Manifestlog {
27e773aa607d rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50974
diff changeset
20 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: 50974
diff changeset
21 self.revlog.parents(rev)
27e773aa607d rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50974
diff changeset
22 }
27e773aa607d rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50974
diff changeset
23 }
27e773aa607d rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50974
diff changeset
24
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
25 impl Manifestlog {
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
26 /// Open the `manifest` of a repository given by its root.
51188
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
27 pub fn open(
51864
db7dbe6f7bb2 rust: add Vfs trait
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51188
diff changeset
28 store_vfs: &VfsImpl,
51188
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
29 options: RevlogOpenOptions,
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
30 ) -> Result<Self, HgError> {
13f58ce70299 rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents: 50975
diff changeset
31 let revlog = Revlog::open(store_vfs, "00manifest.i", None, options)?;
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
32 Ok(Self { revlog })
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
33 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
34
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
35 /// 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: 47968
diff changeset
36 ///
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
37 /// 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: 47968
diff changeset
38 /// `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: 47968
diff changeset
39 /// changeset.
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
40 ///
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
41 /// 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: 47968
diff changeset
42 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: 47968
diff changeset
43 &self,
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
44 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: 47968
diff changeset
45 ) -> Result<Manifest, RevlogError> {
47968
6f579618ea7b rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents: 47964
diff changeset
46 let rev = self.revlog.rev_from_node(node)?;
50974
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
47 self.data_for_checked_rev(rev)
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
48 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
49
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
50 /// 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: 47968
diff changeset
51 ///
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
52 /// 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: 47968
diff changeset
53 /// changeset.
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
54 ///
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
55 /// See also `Repo::manifest_for_rev`
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
56 pub fn data_for_rev(
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
57 &self,
50974
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
58 rev: UncheckedRevision,
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
59 ) -> Result<Manifest, RevlogError> {
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
60 let bytes = self.revlog.get_rev_data(rev)?.into_owned();
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
61 Ok(Manifest { bytes })
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
62 }
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
63
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
64 pub fn data_for_checked_rev(
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
65 &self,
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
66 rev: Revision,
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
67 ) -> Result<Manifest, RevlogError> {
50974
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
68 let bytes =
1928b770e3e7 rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents: 49937
diff changeset
69 self.revlog.get_rev_data_for_checked_rev(rev)?.into_owned();
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
70 Ok(Manifest { bytes })
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
71 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
72 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
73
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
74 /// `Manifestlog` entry which knows how to interpret the `manifest` data bytes.
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
75 #[derive(Debug)]
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
76 pub struct Manifest {
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
77 /// 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: 48343
diff changeset
78 /// sorted by path, each as:
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
79 ///
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
80 /// ```text
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
81 /// <path> \0 <hex_node_id> <flags> \n
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
82 /// ```
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
83 ///
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
84 /// 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: 48343
diff changeset
85 /// Flags is one of `b""` (the empty string), `b"x"`, `b"l"`, or `b"t"`.
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
86 bytes: Vec<u8>,
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
87 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
88
47957
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
89 impl Manifest {
52044
78fc666a3e94 rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52033
diff changeset
90 /// Return a new empty manifest
78fc666a3e94 rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52033
diff changeset
91 pub fn empty() -> Self {
78fc666a3e94 rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52033
diff changeset
92 Self { bytes: vec![] }
78fc666a3e94 rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52033
diff changeset
93 }
78fc666a3e94 rust-files: check for empty manifests caused by narrow
Rapha?l Gom?s <rgomes@octobus.net>
parents: 52033
diff changeset
94
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
95 pub fn iter(
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
96 &self,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
97 ) -> impl Iterator<Item = Result<ManifestEntry, HgError>> {
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
98 self.bytes
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
99 .split(|b| b == &b'\n')
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
100 .filter(|line| !line.is_empty())
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
101 .map(ManifestEntry::from_raw)
45540
f2de24c2b1f6 hg-core: add `files_with_nodes` to `Manifest`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45533
diff changeset
102 }
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
103
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
104 /// If the given path is in this manifest, return its filelog node ID
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
105 pub fn find_by_path(
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
106 &self,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
107 path: &HgPath,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
108 ) -> Result<Option<ManifestEntry>, HgError> {
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
109 use std::cmp::Ordering::*;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
110 let path = path.as_bytes();
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
111 // 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: 48343
diff changeset
112 // an entry
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
113 let mut bytes = &*self.bytes;
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
114
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
115 // Binary search algorithm derived from `[T]::binary_search_by`
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
116 // <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: 48343
diff changeset
117 // 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: 48343
diff changeset
118 // 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: 48343
diff changeset
119 // (newlines).
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
120 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: 48343
diff changeset
121 let (entry_path, rest) =
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
122 ManifestEntry::split_path(&bytes[entry_range.clone()])?;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
123 let cmp = entry_path.cmp(path);
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
124 if cmp == Less {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
125 let after_newline = entry_range.end + 1;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
126 bytes = &bytes[after_newline..];
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
127 } else if cmp == Greater {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
128 bytes = &bytes[..entry_range.start];
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
129 } else {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
130 return Ok(Some(ManifestEntry::from_path_and_rest(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
131 entry_path, rest,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
132 )));
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
133 }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
134 }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
135 Ok(None)
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
136 }
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
137
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
138 /// 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: 48343
diff changeset
139 /// the final newline.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
140 fn find_entry_near_middle_of(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
141 bytes: &[u8],
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
142 ) -> Result<Option<std::ops::Range<usize>>, HgError> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
143 let len = bytes.len();
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
144 if len > 0 {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
145 let middle = bytes.len() / 2;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
146 // Integer division rounds down, so `middle < len`.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
147 let (before, after) = bytes.split_at(middle);
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
148 let is_newline = |&byte: &u8| byte == b'\n';
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
149 let entry_start = match before.iter().rposition(is_newline) {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
150 Some(i) => i + 1,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
151 None => 0, // We choose the first entry in `bytes`
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
152 };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
153 let entry_end = match after.iter().position(is_newline) {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
154 Some(i) => {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
155 // 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: 48343
diff changeset
156 middle + i
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
157 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
158 None => {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
159 // In a well-formed manifest:
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
160 //
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
161 // * Since `len > 0`, `bytes` contains at least one entry
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
162 // * Every entry ends with a newline
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
163 // * Since `middle < len`, `after` contains at least the
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
164 // 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: 48343
diff changeset
165 //
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
166 // 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: 48343
diff changeset
167 // well-formed.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
168 return Err(HgError::corrupted(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
169 "manifest entry without \\n delimiter",
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
170 ));
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
171 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
172 };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
173 Ok(Some(entry_start..entry_end))
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
174 } else {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
175 // len == 0
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
176 Ok(None)
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
177 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
178 }
45533
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
179 }
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
180
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
181 /// `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: 48342
diff changeset
182 #[derive(Debug)]
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
183 pub struct ManifestEntry<'manifest> {
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
184 pub path: &'manifest HgPath,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
185 pub hex_node_id: &'manifest [u8],
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
186
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
187 /// `Some` values are b'x', b'l', or 't'
52033
0ea323b7e3b1 rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51864
diff changeset
188 pub flags: Option<NonZeroU8>,
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
189 }
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
190
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
191 impl<'a> ManifestEntry<'a> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
192 fn split_path(bytes: &[u8]) -> Result<(&[u8], &[u8]), HgError> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
193 bytes.split_2(b'\0').ok_or_else(|| {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
194 HgError::corrupted("manifest entry without \\0 delimiter")
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
195 })
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
196 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
197
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
198 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: 48343
diff changeset
199 let (hex_node_id, flags) = match rest.split_last() {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
200 Some((&b'x', rest)) => (rest, Some(b'x')),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
201 Some((&b'l', rest)) => (rest, Some(b'l')),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
202 Some((&b't', rest)) => (rest, Some(b't')),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
203 _ => (rest, None),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
204 };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
205 Self {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
206 path: HgPath::new(path),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
207 hex_node_id,
52033
0ea323b7e3b1 rust-manifest: encode flags as `Option<NonZeroU8>`
Rapha?l Gom?s <rgomes@octobus.net>
parents: 51864
diff changeset
208 flags: flags.map(|f| f.try_into().expect("invalid flag")),
48495
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
209 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
210 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
211
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
212 fn from_raw(bytes: &'a [u8]) -> Result<Self, HgError> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
213 let (path, rest) = Self::split_path(bytes)?;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
214 Ok(Self::from_path_and_rest(path, rest))
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
215 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48343
diff changeset
216
48343
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
217 pub fn node_id(&self) -> Result<Node, HgError> {
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
218 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: 48342
diff changeset
219 }
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48342
diff changeset
220 }