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