Show More
@@ -1,98 +1,88 b'' | |||
|
1 | 1 | use crate::errors::HgError; |
|
2 | 2 | use crate::repo::Repo; |
|
3 | 3 | use crate::revlog::path_encode::path_encode; |
|
4 | 4 | use crate::revlog::revlog::{Revlog, RevlogError}; |
|
5 | 5 | use crate::revlog::NodePrefix; |
|
6 | 6 | use crate::revlog::Revision; |
|
7 | 7 | use crate::utils::files::get_path_from_bytes; |
|
8 | 8 | use crate::utils::hg_path::HgPath; |
|
9 | 9 | use crate::utils::SliceExt; |
|
10 | 10 | use std::path::PathBuf; |
|
11 | 11 | |
|
12 | 12 | /// A specialized `Revlog` to work with file data logs. |
|
13 | 13 | pub struct Filelog { |
|
14 | 14 | /// The generic `revlog` format. |
|
15 | 15 | revlog: Revlog, |
|
16 | 16 | } |
|
17 | 17 | |
|
18 | 18 | impl Filelog { |
|
19 | 19 | pub fn open(repo: &Repo, file_path: &HgPath) -> Result<Self, HgError> { |
|
20 | 20 | let index_path = store_path(file_path, b".i"); |
|
21 | 21 | let data_path = store_path(file_path, b".d"); |
|
22 | 22 | let revlog = Revlog::open(repo, index_path, Some(&data_path))?; |
|
23 | 23 | Ok(Self { revlog }) |
|
24 | 24 | } |
|
25 | 25 | |
|
26 | 26 | /// The given node ID is that of the file as found in a manifest, not of a |
|
27 | 27 | /// changeset. |
|
28 | 28 | pub fn data_for_node( |
|
29 | 29 | &self, |
|
30 | 30 | file_node: impl Into<NodePrefix>, |
|
31 | 31 | ) -> Result<FilelogEntry, RevlogError> { |
|
32 | 32 | let file_rev = self.revlog.rev_from_node(file_node.into())?; |
|
33 | 33 | self.data_for_rev(file_rev) |
|
34 | 34 | } |
|
35 | 35 | |
|
36 | 36 | /// The given revision is that of the file as found in a manifest, not of a |
|
37 | 37 | /// changeset. |
|
38 | 38 | pub fn data_for_rev( |
|
39 | 39 | &self, |
|
40 | 40 | file_rev: Revision, |
|
41 | 41 | ) -> Result<FilelogEntry, RevlogError> { |
|
42 | 42 | let data: Vec<u8> = self.revlog.get_rev_data(file_rev)?; |
|
43 | 43 | Ok(FilelogEntry(data.into())) |
|
44 | 44 | } |
|
45 | 45 | } |
|
46 | 46 | |
|
47 | 47 | fn store_path(hg_path: &HgPath, suffix: &[u8]) -> PathBuf { |
|
48 | 48 | let encoded_bytes = |
|
49 | 49 | path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat()); |
|
50 | 50 | get_path_from_bytes(&encoded_bytes).into() |
|
51 | 51 | } |
|
52 | 52 | |
|
53 | 53 | pub struct FilelogEntry(Vec<u8>); |
|
54 | 54 | |
|
55 | 55 | impl FilelogEntry { |
|
56 | 56 | /// Split into metadata and data |
|
57 | /// Returns None if there is no metadata, so the entire entry is data. | |
|
58 | fn split_metadata(&self) -> Result<Option<(&[u8], &[u8])>, HgError> { | |
|
57 | pub fn split(&self) -> Result<(Option<&[u8]>, &[u8]), HgError> { | |
|
59 | 58 | const DELIMITER: &[u8; 2] = &[b'\x01', b'\n']; |
|
60 | 59 | |
|
61 | 60 | if let Some(rest) = self.0.drop_prefix(DELIMITER) { |
|
62 | 61 | if let Some((metadata, data)) = rest.split_2_by_slice(DELIMITER) { |
|
63 |
Ok(Some( |
|
|
62 | Ok((Some(metadata), data)) | |
|
64 | 63 | } else { |
|
65 | 64 | Err(HgError::corrupted( |
|
66 | 65 | "Missing metadata end delimiter in filelog entry", |
|
67 | 66 | )) |
|
68 | 67 | } |
|
69 | 68 | } else { |
|
70 | Ok(None) | |
|
71 | } | |
|
72 | } | |
|
73 | ||
|
74 | /// Split into metadata and data | |
|
75 | pub fn split(&self) -> Result<(Option<&[u8]>, &[u8]), HgError> { | |
|
76 | if let Some((metadata, data)) = self.split_metadata()? { | |
|
77 | Ok((Some(metadata), data)) | |
|
78 | } else { | |
|
79 | 69 | Ok((None, &self.0)) |
|
80 | 70 | } |
|
81 | 71 | } |
|
82 | 72 | |
|
83 | 73 | /// Returns the file contents at this revision, stripped of any metadata |
|
84 | 74 | pub fn data(&self) -> Result<&[u8], HgError> { |
|
85 | 75 | let (_metadata, data) = self.split()?; |
|
86 | 76 | Ok(data) |
|
87 | 77 | } |
|
88 | 78 | |
|
89 | 79 | /// Consume the entry, and convert it into data, discarding any metadata, |
|
90 | 80 | /// if present. |
|
91 | 81 | pub fn into_data(self) -> Result<Vec<u8>, HgError> { |
|
92 |
if let Some( |
|
|
82 | if let (Some(_metadata), data) = self.split()? { | |
|
93 | 83 | Ok(data.to_owned()) |
|
94 | 84 | } else { |
|
95 | 85 | Ok(self.0) |
|
96 | 86 | } |
|
97 | 87 | } |
|
98 | 88 | } |
General Comments 0
You need to be logged in to leave comments.
Login now