author | Raphaël Gomès <rgomes@octobus.net> |
Tue, 10 Jan 2023 11:20:54 +0100 | |
changeset 49937 | 750409505286 |
parent 49090 | a5ef50becea8 |
child 50977 | 1928b770e3e7 |
permissions | -rw-r--r-- |
47963
001d747c2baf
rust: Return HgError instead of RevlogError in revlog constructors
Simon Sapin <simon.sapin@octobus.net>
parents:
47957
diff
changeset
|
1 |
use crate::errors::HgError; |
45533
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
2 |
use crate::revlog::Revision; |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
3 |
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
|
4 |
use crate::revlog::{Revlog, RevlogError}; |
45533
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
5 |
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
|
6 |
use crate::utils::SliceExt; |
49090
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49089
diff
changeset
|
7 |
use crate::vfs::Vfs; |
45533
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. |
47957
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
10 |
pub struct Manifestlog { |
45533
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 |
|
47957
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
15 |
impl Manifestlog { |
45533
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. |
49090
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49089
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:
49089
diff
changeset
|
18 |
let revlog = |
a5ef50becea8
rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49089
diff
changeset
|
19 |
Revlog::open(store_vfs, "00manifest.i", None, use_nodemap)?; |
45533
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 |
|
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
|
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
diff
changeset
|
33 |
) -> 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
|
34 |
let rev = self.revlog.rev_from_node(node)?; |
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 |
self.data_for_rev(rev) |
45533
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 |
|
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
|
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
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:
47968
diff
changeset
|
47 |
) -> Result<Manifest, RevlogError> { |
48541
f2f57724d4eb
rhg: Add RevlogEntry::data that does delta resolution
Simon Sapin <simon.sapin@octobus.net>
parents:
48495
diff
changeset
|
48 |
let bytes = self.revlog.get_rev_data(rev)?.into_owned(); |
47957
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
49 |
Ok(Manifest { bytes }) |
45533
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 |
|
47957
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
53 |
/// `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
|
54 |
#[derive(Debug)] |
47957
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
55 |
pub struct Manifest { |
48495
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
57 |
/// sorted by path, each as: |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
58 |
/// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
59 |
/// ```text |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
61 |
/// ``` |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
62 |
/// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
64 |
/// 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
|
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 |
|
47957
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
68 |
impl Manifest { |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
69 |
pub fn iter( |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
70 |
&self, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
71 |
) -> impl Iterator<Item = Result<ManifestEntry, HgError>> { |
45533
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()) |
48495
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
75 |
.map(ManifestEntry::from_raw) |
45540
f2de24c2b1f6
hg-core: add `files_with_nodes` to `Manifest`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45533
diff
changeset
|
76 |
} |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
77 |
|
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
78 |
/// 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
|
79 |
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
|
80 |
&self, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
81 |
path: &HgPath, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
82 |
) -> Result<Option<ManifestEntry>, HgError> { |
48495
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
83 |
use std::cmp::Ordering::*; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
84 |
let path = path.as_bytes(); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
86 |
// an entry |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
87 |
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
|
88 |
|
48495
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
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:
48343
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:
48343
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:
48343
diff
changeset
|
93 |
// (newlines). |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
95 |
let (entry_path, rest) = |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
97 |
let cmp = entry_path.cmp(path); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
98 |
if cmp == Less { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
100 |
bytes = &bytes[after_newline..]; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
101 |
} else if cmp == Greater { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
102 |
bytes = &bytes[..entry_range.start]; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
103 |
} else { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
105 |
entry_path, rest, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
106 |
))); |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
107 |
} |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
108 |
} |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
109 |
Ok(None) |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
110 |
} |
48495
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
111 |
|
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
113 |
/// the final newline. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
114 |
fn find_entry_near_middle_of( |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
115 |
bytes: &[u8], |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
117 |
let len = bytes.len(); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
118 |
if len > 0 { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
119 |
let middle = bytes.len() / 2; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
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:
48343
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:
48343
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:
48343
diff
changeset
|
124 |
Some(i) => i + 1, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
126 |
}; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
128 |
Some(i) => { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
130 |
middle + i |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
131 |
} |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
132 |
None => { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
133 |
// In a well-formed manifest: |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
134 |
// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
136 |
// * Every entry ends with a newline |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
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:
48343
diff
changeset
|
139 |
// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
diff
changeset
|
141 |
// well-formed. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
142 |
return Err(HgError::corrupted( |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
143 |
"manifest entry without \\n delimiter", |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
144 |
)); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
145 |
} |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
146 |
}; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
147 |
Ok(Some(entry_start..entry_end)) |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
148 |
} else { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
149 |
// len == 0 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
150 |
Ok(None) |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
151 |
} |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
152 |
} |
45533
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
153 |
} |
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
154 |
|
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
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:
48342
diff
changeset
|
156 |
#[derive(Debug)] |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
157 |
pub struct ManifestEntry<'manifest> { |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
158 |
pub path: &'manifest HgPath, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
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:
48342
diff
changeset
|
160 |
|
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
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:
48342
diff
changeset
|
162 |
pub flags: Option<u8>, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
163 |
} |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
164 |
|
48495
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
165 |
impl<'a> ManifestEntry<'a> { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
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:
48343
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:
48343
diff
changeset
|
169 |
}) |
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 |
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
|
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:
48343
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:
48343
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:
48343
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:
48343
diff
changeset
|
177 |
_ => (rest, None), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
178 |
}; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
179 |
Self { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
180 |
path: HgPath::new(path), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
181 |
hex_node_id, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
182 |
flags, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
183 |
} |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
184 |
} |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
185 |
|
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
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:
48343
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:
48343
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:
48343
diff
changeset
|
189 |
} |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48343
diff
changeset
|
190 |
|
48343
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
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:
48342
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:
48342
diff
changeset
|
193 |
} |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48342
diff
changeset
|
194 |
} |