annotate rust/hg-core/src/revlog/manifest.rs @ 49210:34decbaf4da3

node: manually implement Debug I got too irritated today with the default Debug implementation of hg::revlog::Node while playing with a new parser. This isn't quite what I wanted, but it wasn't much code and it at least gives you output that's easy to visually compare to a node.hex()ed identifier from the Python side of things. Sadly, this doesn't influence the output in lldb or the VSCode debugger extension that uses lldb under the covers, but it at least means debug prints are a little more useful. Differential Revision: https://phab.mercurial-scm.org/D12608
author Augie Fackler <augie@google.com>
date Thu, 05 May 2022 14:47:26 -0400
parents a5ef50becea8
children 750409505286
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
47991
001d747c2baf rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents: 47985
diff changeset
1 use crate::errors::HgError;
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
2 use crate::revlog::revlog::{Revlog, RevlogError};
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
3 use crate::revlog::Revision;
47992
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
4 use crate::revlog::{Node, NodePrefix};
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
5 use crate::utils::hg_path::HgPath;
48392
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
6 use crate::utils::SliceExt;
49145
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49144
diff changeset
7 use crate::vfs::Vfs;
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
8
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
9 /// 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
10 pub struct Manifestlog {
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
11 /// The generic `revlog` format.
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
12 revlog: Revlog,
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
13 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
14
47985
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
15 impl Manifestlog {
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
16 /// Open the `manifest` of a repository given by its root.
49145
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49144
diff changeset
17 pub fn open(store_vfs: &Vfs, use_nodemap: bool) -> Result<Self, HgError> {
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49144
diff changeset
18 let revlog =
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49144
diff changeset
19 Revlog::open(store_vfs, "00manifest.i", None, use_nodemap)?;
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
20 Ok(Self { revlog })
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
21 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
22
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
23 /// 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
24 ///
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
25 /// 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
26 /// `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
27 /// 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
28 ///
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
29 /// 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
30 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
31 &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
32 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
33 ) -> 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
34 let rev = self.revlog.rev_from_node(node)?;
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
35 self.data_for_rev(rev)
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
36 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
37
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
38 /// 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
39 ///
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 /// 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
41 /// 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
42 ///
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 /// 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: 47996
diff changeset
44 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: 47996
diff changeset
45 &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
46 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: 47996
diff changeset
47 ) -> Result<Manifest, RevlogError> {
48570
f2f57724d4eb rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents: 48532
diff changeset
48 let bytes = self.revlog.get_rev_data(rev)?.into_owned();
47985
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
49 Ok(Manifest { bytes })
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
50 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
51 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
52
47985
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
53 /// `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
54 #[derive(Debug)]
47985
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
55 pub struct Manifest {
48532
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
56 /// 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
57 /// sorted by path, each as:
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
58 ///
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
59 /// ```text
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
60 /// <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
61 /// ```
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
62 ///
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
63 /// 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
64 /// 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
65 bytes: Vec<u8>,
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
66 }
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
67
47985
d44740725b95 rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents: 46499
diff changeset
68 impl Manifest {
48392
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
69 pub fn iter(
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
70 &self,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
71 ) -> impl Iterator<Item = Result<ManifestEntry, HgError>> {
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
72 self.bytes
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
73 .split(|b| b == &b'\n')
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
74 .filter(|line| !line.is_empty())
48532
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
75 .map(ManifestEntry::from_raw)
45546
f2de24c2b1f6 hg-core: add `files_with_nodes` to `Manifest`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45539
diff changeset
76 }
47992
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
77
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
78 /// 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
79 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
80 &self,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
81 path: &HgPath,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
82 ) -> Result<Option<ManifestEntry>, HgError> {
48532
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
83 use std::cmp::Ordering::*;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
84 let path = path.as_bytes();
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
85 // 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
86 // an entry
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
87 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
88
48532
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
89 // 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
90 // <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
91 // 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
92 // 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
93 // (newlines).
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
94 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
95 let (entry_path, rest) =
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
96 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
97 let cmp = entry_path.cmp(path);
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
98 if cmp == Less {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
99 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
100 bytes = &bytes[after_newline..];
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
101 } else if cmp == Greater {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
102 bytes = &bytes[..entry_range.start];
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
103 } else {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
104 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
105 entry_path, rest,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
106 )));
47992
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
107 }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
108 }
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
109 Ok(None)
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47991
diff changeset
110 }
48532
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
111
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
112 /// 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
113 /// the final newline.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
114 fn find_entry_near_middle_of(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
115 bytes: &[u8],
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
116 ) -> 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
117 let len = bytes.len();
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
118 if len > 0 {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
119 let middle = bytes.len() / 2;
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
120 // 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
121 let (before, after) = bytes.split_at(middle);
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
122 let is_newline = |&byte: &u8| byte == b'\n';
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
123 let entry_start = match before.iter().rposition(is_newline) {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
124 Some(i) => i + 1,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
125 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
126 };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
127 let entry_end = match after.iter().position(is_newline) {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
128 Some(i) => {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
129 // 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
130 middle + i
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
131 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
132 None => {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
133 // In a well-formed manifest:
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
134 //
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
135 // * 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
136 // * Every entry ends with a newline
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
137 // * 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
138 // 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
139 //
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
140 // 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
141 // well-formed.
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
142 return Err(HgError::corrupted(
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
143 "manifest entry without \\n delimiter",
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
144 ));
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
145 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
146 };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
147 Ok(Some(entry_start..entry_end))
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
148 } else {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
149 // len == 0
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
150 Ok(None)
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
151 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
152 }
45539
89ac95bd4993 hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
153 }
48392
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
154
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
155 /// `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
156 #[derive(Debug)]
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
157 pub struct ManifestEntry<'manifest> {
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
158 pub path: &'manifest HgPath,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
159 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
160
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
161 /// `Some` values are b'x', b'l', or 't'
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
162 pub flags: Option<u8>,
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
163 }
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
164
48532
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
165 impl<'a> ManifestEntry<'a> {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
166 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
167 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
168 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
169 })
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
170 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
171
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
172 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
173 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
174 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
175 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
176 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
177 _ => (rest, None),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
178 };
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
179 Self {
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
180 path: HgPath::new(path),
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
181 hex_node_id,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
182 flags,
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
183 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
184 }
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 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
187 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
188 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
189 }
e293ff808a05 rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents: 48392
diff changeset
190
48392
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
191 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
192 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
193 }
eb428010aad2 rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents: 48391
diff changeset
194 }