Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-core/src/revlog/manifest.rs @ 51906:db7dbe6f7bb2
rust: add Vfs trait
This will allow for the use of multiple vfs like in the Python implementation,
as well as hiding the details of the upcoming Python vfs wrapper to hg-core.
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Wed, 19 Jun 2024 14:49:35 +0200 |
parents | 13f58ce70299 |
children | 0ea323b7e3b1 |
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; |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
2 use crate::revlog::{Node, NodePrefix}; |
50010
750409505286
rust-clippy: merge "revlog" module definition and struct implementation
Rapha?l Gom?s <rgomes@octobus.net>
parents:
49145
diff
changeset
|
3 use crate::revlog::{Revlog, RevlogError}; |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
4 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
|
5 use crate::utils::SliceExt; |
51906 | 6 use crate::vfs::VfsImpl; |
51212
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
7 use crate::{ |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
8 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:
50989
diff
changeset
|
9 }; |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
10 |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
11 /// A specialized `Revlog` to work with `manifest` data format. |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
12 pub struct Manifestlog { |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
13 /// The generic `revlog` format. |
51212
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
14 pub(crate) revlog: Revlog, |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
15 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
16 |
50989
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
17 impl Graph for Manifestlog { |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
18 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> { |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
19 self.revlog.parents(rev) |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
20 } |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
21 } |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50988
diff
changeset
|
22 |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
23 impl Manifestlog { |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
24 /// Open the `manifest` of a repository given by its root. |
51212
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
25 pub fn open( |
51906 | 26 store_vfs: &VfsImpl, |
51212
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
27 options: RevlogOpenOptions, |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
28 ) -> Result<Self, HgError> { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50989
diff
changeset
|
29 let revlog = Revlog::open(store_vfs, "00manifest.i", None, options)?; |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
30 Ok(Self { revlog }) |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
31 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
32 |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
33 /// Return the `Manifest` for the given node ID. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
34 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
35 /// Note: this is a node ID in the manifestlog, typically found through |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
36 /// `ChangelogEntry::manifest_node`. It is *not* the node ID of any |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
37 /// changeset. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
38 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
39 /// See also `Repo::manifest_for_node` |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
40 pub fn data_for_node( |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
41 &self, |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
42 node: NodePrefix, |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
43 ) -> Result<Manifest, RevlogError> { |
47996
6f579618ea7b
rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents:
47992
diff
changeset
|
44 let rev = self.revlog.rev_from_node(node)?; |
50988
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
45 self.data_for_checked_rev(rev) |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
46 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
47 |
47997
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
48 /// Return the `Manifest` of a given revision number. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
49 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
50 /// Note: this is a revision number in the manifestlog, *not* of any |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
51 /// changeset. |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
52 /// |
87e3f878e65f
rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents:
47996
diff
changeset
|
53 /// See also `Repo::manifest_for_rev` |
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
|
54 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
|
55 &self, |
50988
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
56 rev: UncheckedRevision, |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
57 ) -> Result<Manifest, RevlogError> { |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
58 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:
50010
diff
changeset
|
59 Ok(Manifest { bytes }) |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
60 } |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
61 |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
62 pub fn data_for_checked_rev( |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
63 &self, |
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
|
64 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
|
65 ) -> Result<Manifest, RevlogError> { |
50988
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
66 let bytes = |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Rapha?l Gom?s <rgomes@octobus.net>
parents:
50010
diff
changeset
|
67 self.revlog.get_rev_data_for_checked_rev(rev)?.into_owned(); |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
68 Ok(Manifest { bytes }) |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
69 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
70 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
71 |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
72 /// `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
|
73 #[derive(Debug)] |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
74 pub struct Manifest { |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
75 /// 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
|
76 /// sorted by path, each as: |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
77 /// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
78 /// ```text |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
79 /// <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
|
80 /// ``` |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
81 /// |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
82 /// 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
|
83 /// 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
|
84 bytes: Vec<u8>, |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
85 } |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
86 |
47985
d44740725b95
rust: Rename Manifest to Manifestlog, ManifestEntry to Manifest
Simon Sapin <simon.sapin@octobus.net>
parents:
46499
diff
changeset
|
87 impl Manifest { |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
88 pub fn iter( |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
89 &self, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
90 ) -> impl Iterator<Item = Result<ManifestEntry, HgError>> { |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
91 self.bytes |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
92 .split(|b| b == &b'\n') |
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
93 .filter(|line| !line.is_empty()) |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
94 .map(ManifestEntry::from_raw) |
45546
f2de24c2b1f6
hg-core: add `files_with_nodes` to `Manifest`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
45539
diff
changeset
|
95 } |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
96 |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
97 /// 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
|
98 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
|
99 &self, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
100 path: &HgPath, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
101 ) -> Result<Option<ManifestEntry>, HgError> { |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
102 use std::cmp::Ordering::*; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
103 let path = path.as_bytes(); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
104 // 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
|
105 // an entry |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
106 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
|
107 |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
108 // 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
|
109 // <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
|
110 // 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
|
111 // 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
|
112 // (newlines). |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
113 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
|
114 let (entry_path, rest) = |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
115 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
|
116 let cmp = entry_path.cmp(path); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
117 if cmp == Less { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
118 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
|
119 bytes = &bytes[after_newline..]; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
120 } else if cmp == Greater { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
121 bytes = &bytes[..entry_range.start]; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
122 } else { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
123 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
|
124 entry_path, rest, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
125 ))); |
47992
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
126 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
127 } |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
128 Ok(None) |
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47991
diff
changeset
|
129 } |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
130 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
131 /// 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
|
132 /// the final newline. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
133 fn find_entry_near_middle_of( |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
134 bytes: &[u8], |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
135 ) -> 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
|
136 let len = bytes.len(); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
137 if len > 0 { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
138 let middle = bytes.len() / 2; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
139 // 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
|
140 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
|
141 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
|
142 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
|
143 Some(i) => i + 1, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
144 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
|
145 }; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
146 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
|
147 Some(i) => { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
148 // 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
|
149 middle + i |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
150 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
151 None => { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
152 // In a well-formed manifest: |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
153 // |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
154 // * 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
|
155 // * Every entry ends with a newline |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
156 // * 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
|
157 // 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
|
158 // |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
159 // 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
|
160 // well-formed. |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
161 return Err(HgError::corrupted( |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
162 "manifest entry without \\n delimiter", |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
163 )); |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
164 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
165 }; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
166 Ok(Some(entry_start..entry_end)) |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
167 } else { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
168 // len == 0 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
169 Ok(None) |
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 } |
45539
89ac95bd4993
hg-core: add `Manifest` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
172 } |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
173 |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
174 /// `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
|
175 #[derive(Debug)] |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
176 pub struct ManifestEntry<'manifest> { |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
177 pub path: &'manifest HgPath, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
178 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
|
179 |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
180 /// `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
|
181 pub flags: Option<u8>, |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
182 } |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
183 |
48532
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
184 impl<'a> ManifestEntry<'a> { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
185 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
|
186 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
|
187 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
|
188 }) |
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 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
191 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
|
192 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
|
193 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
|
194 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
|
195 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
|
196 _ => (rest, None), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
197 }; |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
198 Self { |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
199 path: HgPath::new(path), |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
200 hex_node_id, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
201 flags, |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
202 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
203 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
204 |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
205 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
|
206 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
|
207 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
|
208 } |
e293ff808a05
rhg: Use binary search in manifest lookup
Simon Sapin <simon.sapin@octobus.net>
parents:
48392
diff
changeset
|
209 |
48392
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
210 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
|
211 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
|
212 } |
eb428010aad2
rhg: Also parse flags in the manifest parser
Simon Sapin <simon.sapin@octobus.net>
parents:
48391
diff
changeset
|
213 } |