1 use crate::errors::HgError; |
1 use crate::errors::HgError; |
2 use crate::revlog::Revision; |
|
3 use crate::revlog::{Node, NodePrefix}; |
2 use crate::revlog::{Node, NodePrefix}; |
|
3 use crate::revlog::{Revision, NULL_REVISION}; |
4 use crate::revlog::{Revlog, RevlogEntry, RevlogError}; |
4 use crate::revlog::{Revlog, RevlogEntry, RevlogError}; |
5 use crate::utils::hg_path::HgPath; |
5 use crate::utils::hg_path::HgPath; |
6 use crate::vfs::Vfs; |
6 use crate::vfs::Vfs; |
7 use itertools::Itertools; |
7 use itertools::Itertools; |
8 use std::ascii::escape_default; |
8 use std::ascii::escape_default; |
30 ) -> Result<ChangelogRevisionData, RevlogError> { |
30 ) -> Result<ChangelogRevisionData, RevlogError> { |
31 let rev = self.revlog.rev_from_node(node)?; |
31 let rev = self.revlog.rev_from_node(node)?; |
32 self.data_for_rev(rev) |
32 self.data_for_rev(rev) |
33 } |
33 } |
34 |
34 |
35 /// Return the `RevlogEntry` for the given revision number. |
35 /// Return the [`ChangelogEntry`] for the given revision number. |
36 pub fn entry_for_rev( |
36 pub fn entry_for_rev( |
37 &self, |
37 &self, |
38 rev: Revision, |
38 rev: Revision, |
39 ) -> Result<RevlogEntry, RevlogError> { |
39 ) -> Result<ChangelogEntry, RevlogError> { |
40 self.revlog.get_entry(rev) |
40 let revlog_entry = self.revlog.get_entry(rev)?; |
|
41 Ok(ChangelogEntry { revlog_entry }) |
41 } |
42 } |
42 |
43 |
43 /// Return the [`ChangelogRevisionData`] for the given revision number. |
44 /// Return the [`ChangelogRevisionData`] for the given revision number. |
|
45 /// |
|
46 /// This is a useful shortcut in case the caller does not need the |
|
47 /// generic revlog information (parents, hashes etc). Otherwise |
|
48 /// consider taking a [`ChangelogEntry`] with |
|
49 /// [entry_for_rev](`Self::entry_for_rev`) and doing everything from there. |
44 pub fn data_for_rev( |
50 pub fn data_for_rev( |
45 &self, |
51 &self, |
46 rev: Revision, |
52 rev: Revision, |
47 ) -> Result<ChangelogRevisionData, RevlogError> { |
53 ) -> Result<ChangelogRevisionData, RevlogError> { |
48 let bytes = self.revlog.get_rev_data(rev)?; |
54 if rev == NULL_REVISION { |
|
55 return Ok(ChangelogRevisionData::null()); |
|
56 } |
|
57 self.entry_for_rev(rev)?.data() |
|
58 } |
|
59 |
|
60 pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> { |
|
61 self.revlog.node_from_rev(rev) |
|
62 } |
|
63 |
|
64 pub fn rev_from_node( |
|
65 &self, |
|
66 node: NodePrefix, |
|
67 ) -> Result<Revision, RevlogError> { |
|
68 self.revlog.rev_from_node(node) |
|
69 } |
|
70 } |
|
71 |
|
72 /// A specialized `RevlogEntry` for `changelog` data format |
|
73 /// |
|
74 /// This is a `RevlogEntry` with the added semantics that the associated |
|
75 /// data should meet the requirements for `changelog`, materialized by |
|
76 /// the fact that `data()` constructs a `ChangelogRevisionData`. |
|
77 /// In case that promise would be broken, the `data` method returns an error. |
|
78 #[derive(Clone)] |
|
79 pub struct ChangelogEntry<'changelog> { |
|
80 /// Same data, as a generic `RevlogEntry`. |
|
81 pub(crate) revlog_entry: RevlogEntry<'changelog>, |
|
82 } |
|
83 |
|
84 impl<'changelog> ChangelogEntry<'changelog> { |
|
85 pub fn data<'a>( |
|
86 &'a self, |
|
87 ) -> Result<ChangelogRevisionData<'changelog>, RevlogError> { |
|
88 let bytes = self.revlog_entry.data()?; |
49 if bytes.is_empty() { |
89 if bytes.is_empty() { |
50 Ok(ChangelogRevisionData::null()) |
90 Ok(ChangelogRevisionData::null()) |
51 } else { |
91 } else { |
52 Ok(ChangelogRevisionData::new(bytes).map_err(|err| { |
92 Ok(ChangelogRevisionData::new(bytes).map_err(|err| { |
53 RevlogError::Other(HgError::CorruptedRepository(format!( |
93 RevlogError::Other(HgError::CorruptedRepository(format!( |
54 "Invalid changelog data for revision {}: {:?}", |
94 "Invalid changelog data for revision {}: {:?}", |
55 rev, err |
95 self.revlog_entry.revision(), |
|
96 err |
56 ))) |
97 ))) |
57 })?) |
98 })?) |
58 } |
99 } |
59 } |
100 } |
60 |
101 |
61 pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> { |
102 /// Obtain a reference to the underlying `RevlogEntry`. |
62 self.revlog.node_from_rev(rev) |
103 /// |
63 } |
104 /// This allows the caller to access the information that is common |
64 |
105 /// to all revlog entries: revision number, node id, parent revisions etc. |
65 pub fn rev_from_node( |
106 pub fn as_revlog_entry(&self) -> &RevlogEntry { |
66 &self, |
107 &self.revlog_entry |
67 node: NodePrefix, |
|
68 ) -> Result<Revision, RevlogError> { |
|
69 self.revlog.rev_from_node(node) |
|
70 } |
108 } |
71 } |
109 } |
72 |
110 |
73 /// `Changelog` entry which knows how to interpret the `changelog` data bytes. |
111 /// `Changelog` entry which knows how to interpret the `changelog` data bytes. |
74 #[derive(PartialEq)] |
112 #[derive(PartialEq)] |