##// END OF EJS Templates
rhg: simplify split_metadata...
Arseniy Alekseyev -
r49064:e9faae0f default
parent child Browse files
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((metadata, data)))
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((_metadata, data)) = self.split_metadata()? {
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