|
1 use crate::revlog::revlog::{Revlog, RevlogError}; |
|
2 use crate::revlog::Revision; |
|
3 use crate::utils::hg_path::HgPath; |
|
4 use std::path::PathBuf; |
|
5 |
|
6 /// A specialized `Revlog` to work with `manifest` data format. |
|
7 pub struct Manifest { |
|
8 /// The generic `revlog` format. |
|
9 revlog: Revlog, |
|
10 } |
|
11 |
|
12 impl Manifest { |
|
13 /// Open the `manifest` of a repository given by its root. |
|
14 pub fn open(root: &PathBuf) -> Result<Self, RevlogError> { |
|
15 let index_file = root.join(".hg/store/00manifest.i"); |
|
16 let revlog = Revlog::open(&index_file)?; |
|
17 Ok(Self { revlog }) |
|
18 } |
|
19 |
|
20 /// Return the `ManifestEntry` of a given node id. |
|
21 pub fn get_node(&self, node: &[u8]) -> Result<ManifestEntry, RevlogError> { |
|
22 let rev = self.revlog.get_node_rev(node)?; |
|
23 self.get_rev(rev) |
|
24 } |
|
25 |
|
26 /// Return the `ManifestEntry` of a given node revision. |
|
27 pub fn get_rev( |
|
28 &self, |
|
29 rev: Revision, |
|
30 ) -> Result<ManifestEntry, RevlogError> { |
|
31 let bytes = self.revlog.get_rev_data(rev)?; |
|
32 Ok(ManifestEntry { bytes }) |
|
33 } |
|
34 } |
|
35 |
|
36 /// `Manifest` entry which knows how to interpret the `manifest` data bytes. |
|
37 #[derive(Debug)] |
|
38 pub struct ManifestEntry { |
|
39 bytes: Vec<u8>, |
|
40 } |
|
41 |
|
42 impl ManifestEntry { |
|
43 /// Return an iterator over the lines of the entry. |
|
44 pub fn lines(&self) -> impl Iterator<Item = &[u8]> { |
|
45 self.bytes |
|
46 .split(|b| b == &b'\n') |
|
47 .filter(|line| !line.is_empty()) |
|
48 } |
|
49 |
|
50 /// Return an iterator over the files of the entry. |
|
51 pub fn files(&self) -> impl Iterator<Item = &HgPath> { |
|
52 self.lines().filter(|line| !line.is_empty()).map(|line| { |
|
53 let pos = line |
|
54 .iter() |
|
55 .position(|x| x == &b'\0') |
|
56 .expect("manifest line should contain \\0"); |
|
57 HgPath::new(&line[..pos]) |
|
58 }) |
|
59 } |
|
60 } |