annotate rust/hg-core/src/revlog/changelog.rs @ 50746:124c44b5cfad stable

rust-revlog: fix RevlogEntry.data() for NULL_REVISION Before this change, the pseudo-entry returned by `Revlog.get_entry` for `NULL_REVISION` would trigger errors in application code using it. For example, this fixes a crash spotted with changelog data while implementing RHGitaly: `Changelog.data_for_rev(-1)` was already returning the pseudo content as expected, e.g., for `hg log`, but `Changelog.entry_for_rev(-1).data()` would still crash with "corrupted revlog, hash check failed for revision -1". There is an added test for this scenario.
author Georges Racinet <georges.racinet@octobus.net>
date Thu, 06 Jul 2023 11:53:40 +0200
parents 071a6c1d291e
children 9865af7191d2
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
46443
43d63979a75e rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents: 46433
diff changeset
1 use crate::errors::HgError;
46744
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
2 use crate::revlog::{Node, NodePrefix};
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
3 use crate::revlog::{Revision, NULL_REVISION};
49937
750409505286 rust-clippy: merge "revlog" module definition and struct implementation
Raphaël Gomès <rgomes@octobus.net>
parents: 49930
diff changeset
4 use crate::revlog::{Revlog, RevlogEntry, RevlogError};
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
5 use crate::utils::hg_path::HgPath;
49090
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
6 use crate::vfs::Vfs;
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
7 use itertools::Itertools;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
8 use std::ascii::escape_default;
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
9 use std::borrow::Cow;
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
10 use std::fmt::{Debug, Formatter};
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
11
50409
b47a9316050a rust-changelog: made doc-comments more consistent
Georges Racinet <georges.racinet@octobus.net>
parents: 49937
diff changeset
12 /// A specialized `Revlog` to work with changelog data format.
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
13 pub struct Changelog {
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
14 /// The generic `revlog` format.
46433
4b381dbbf8b7 rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46431
diff changeset
15 pub(crate) revlog: Revlog,
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
16 }
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
17
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
18 impl Changelog {
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
19 /// Open the `changelog` of a repository given by its root.
49090
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
20 pub fn open(store_vfs: &Vfs, use_nodemap: bool) -> Result<Self, HgError> {
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
21 let revlog =
a5ef50becea8 rust-revlog: make `Changelog` and `ManifestLog` unaware of `Repo`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49089
diff changeset
22 Revlog::open(store_vfs, "00changelog.i", None, use_nodemap)?;
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
23 Ok(Self { revlog })
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
24 }
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
25
50409
b47a9316050a rust-changelog: made doc-comments more consistent
Georges Racinet <georges.racinet@octobus.net>
parents: 49937
diff changeset
26 /// Return the `ChangelogRevisionData` for the given node ID.
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
27 pub fn data_for_node(
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
28 &self,
46431
645ee7225fab rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents: 46167
diff changeset
29 node: NodePrefix,
48540
20d0d896183e rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents: 48198
diff changeset
30 ) -> Result<ChangelogRevisionData, RevlogError> {
47968
6f579618ea7b rust: Rename the `Revlog::get_node_rev` method to `rev_from_node`
Simon Sapin <simon.sapin@octobus.net>
parents: 47967
diff changeset
31 let rev = self.revlog.rev_from_node(node)?;
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
32 self.data_for_rev(rev)
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
33 }
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
34
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
35 /// Return the [`ChangelogEntry`] for the given revision number.
49065
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
36 pub fn entry_for_rev(
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
37 &self,
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
38 rev: Revision,
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
39 ) -> Result<ChangelogEntry, RevlogError> {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
40 let revlog_entry = self.revlog.get_entry(rev)?;
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
41 Ok(ChangelogEntry { revlog_entry })
49065
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
42 }
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
43
50409
b47a9316050a rust-changelog: made doc-comments more consistent
Georges Racinet <georges.racinet@octobus.net>
parents: 49937
diff changeset
44 /// Return the [`ChangelogRevisionData`] for the given revision number.
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
45 ///
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
46 /// This is a useful shortcut in case the caller does not need the
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
47 /// generic revlog information (parents, hashes etc). Otherwise
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
48 /// consider taking a [`ChangelogEntry`] with
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
49 /// [entry_for_rev](`Self::entry_for_rev`) and doing everything from there.
47969
87e3f878e65f rust: Rename get_node methods to data_for_node, get_rev to data_for_rev
Simon Sapin <simon.sapin@octobus.net>
parents: 47968
diff changeset
50 pub fn data_for_rev(
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
51 &self,
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
52 rev: Revision,
48540
20d0d896183e rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents: 48198
diff changeset
53 ) -> Result<ChangelogRevisionData, RevlogError> {
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
54 if rev == NULL_REVISION {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
55 return Ok(ChangelogRevisionData::null());
49063
cc132255261b rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents: 49062
diff changeset
56 }
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
57 self.entry_for_rev(rev)?.data()
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
58 }
46744
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
59
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
60 pub fn node_from_rev(&self, rev: Revision) -> Option<&Node> {
47967
6c653d9d41b8 rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents: 47964
diff changeset
61 self.revlog.node_from_rev(rev)
46744
b1f2c2b336ec rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents: 46443
diff changeset
62 }
49065
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
63
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
64 pub fn rev_from_node(
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
65 &self,
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
66 node: NodePrefix,
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
67 ) -> Result<Revision, RevlogError> {
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
68 self.revlog.rev_from_node(node)
5d205e476057 rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents: 49064
diff changeset
69 }
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
70 }
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
71
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
72 /// A specialized `RevlogEntry` for `changelog` data format
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
73 ///
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
74 /// This is a `RevlogEntry` with the added semantics that the associated
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
75 /// data should meet the requirements for `changelog`, materialized by
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
76 /// the fact that `data()` constructs a `ChangelogRevisionData`.
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
77 /// In case that promise would be broken, the `data` method returns an error.
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
78 #[derive(Clone)]
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
79 pub struct ChangelogEntry<'changelog> {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
80 /// Same data, as a generic `RevlogEntry`.
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
81 pub(crate) revlog_entry: RevlogEntry<'changelog>,
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
82 }
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
83
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
84 impl<'changelog> ChangelogEntry<'changelog> {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
85 pub fn data<'a>(
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
86 &'a self,
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
87 ) -> Result<ChangelogRevisionData<'changelog>, RevlogError> {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
88 let bytes = self.revlog_entry.data()?;
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
89 if bytes.is_empty() {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
90 Ok(ChangelogRevisionData::null())
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
91 } else {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
92 Ok(ChangelogRevisionData::new(bytes).map_err(|err| {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
93 RevlogError::Other(HgError::CorruptedRepository(format!(
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
94 "Invalid changelog data for revision {}: {:?}",
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
95 self.revlog_entry.revision(),
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
96 err
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
97 )))
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
98 })?)
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
99 }
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
100 }
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
101
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
102 /// Obtain a reference to the underlying `RevlogEntry`.
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
103 ///
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
104 /// This allows the caller to access the information that is common
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
105 /// to all revlog entries: revision number, node id, parent revisions etc.
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
106 pub fn as_revlog_entry(&self) -> &RevlogEntry {
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
107 &self.revlog_entry
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
108 }
50414
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
109
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
110 pub fn p1_entry(&self) -> Result<Option<ChangelogEntry>, RevlogError> {
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
111 Ok(self
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
112 .revlog_entry
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
113 .p1_entry()?
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
114 .map(|revlog_entry| Self { revlog_entry }))
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
115 }
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
116
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
117 pub fn p2_entry(&self) -> Result<Option<ChangelogEntry>, RevlogError> {
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
118 Ok(self
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
119 .revlog_entry
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
120 .p2_entry()?
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
121 .map(|revlog_entry| Self { revlog_entry }))
071a6c1d291e rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents: 50411
diff changeset
122 }
50411
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
123 }
841b13e6e84c rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents: 50410
diff changeset
124
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
125 /// `Changelog` entry which knows how to interpret the `changelog` data bytes.
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
126 #[derive(PartialEq)]
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
127 pub struct ChangelogRevisionData<'changelog> {
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
128 /// The data bytes of the `changelog` entry.
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
129 bytes: Cow<'changelog, [u8]>,
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
130 /// The end offset for the hex manifest (not including the newline)
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
131 manifest_end: usize,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
132 /// The end offset for the user+email (not including the newline)
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
133 user_end: usize,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
134 /// The end offset for the timestamp+timezone+extras (not including the
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
135 /// newline)
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
136 timestamp_end: usize,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
137 /// The end offset for the file list (not including the newline)
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
138 files_end: usize,
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
139 }
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
140
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
141 impl<'changelog> ChangelogRevisionData<'changelog> {
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
142 fn new(bytes: Cow<'changelog, [u8]>) -> Result<Self, HgError> {
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
143 let mut line_iter = bytes.split(|b| b == &b'\n');
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
144 let manifest_end = line_iter
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
145 .next()
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
146 .expect("Empty iterator from split()?")
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
147 .len();
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
148 let user_slice = line_iter.next().ok_or_else(|| {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
149 HgError::corrupted("Changeset data truncated after manifest line")
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
150 })?;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
151 let user_end = manifest_end + 1 + user_slice.len();
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
152 let timestamp_slice = line_iter.next().ok_or_else(|| {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
153 HgError::corrupted("Changeset data truncated after user line")
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
154 })?;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
155 let timestamp_end = user_end + 1 + timestamp_slice.len();
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
156 let mut files_end = timestamp_end + 1;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
157 loop {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
158 let line = line_iter.next().ok_or_else(|| {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
159 HgError::corrupted("Changeset data truncated in files list")
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
160 })?;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
161 if line.is_empty() {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
162 if files_end == bytes.len() {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
163 // The list of files ended with a single newline (there
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
164 // should be two)
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
165 return Err(HgError::corrupted(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
166 "Changeset data truncated after files list",
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
167 ));
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
168 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
169 files_end -= 1;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
170 break;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
171 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
172 files_end += line.len() + 1;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
173 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
174
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
175 Ok(Self {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
176 bytes,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
177 manifest_end,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
178 user_end,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
179 timestamp_end,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
180 files_end,
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
181 })
49063
cc132255261b rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents: 49062
diff changeset
182 }
cc132255261b rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents: 49062
diff changeset
183
cc132255261b rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents: 49062
diff changeset
184 fn null() -> Self {
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
185 Self::new(Cow::Borrowed(
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
186 b"0000000000000000000000000000000000000000\n\n0 0\n\n",
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
187 ))
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
188 .unwrap()
49063
cc132255261b rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents: 49062
diff changeset
189 }
cc132255261b rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents: 49062
diff changeset
190
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
191 /// Return an iterator over the lines of the entry.
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
192 pub fn lines(&self) -> impl Iterator<Item = &[u8]> {
49062
fb82b5cb8301 rust-changelog: don't skip empty lines when iterating over changeset lines
Martin von Zweigbergk <martinvonz@google.com>
parents: 48541
diff changeset
193 self.bytes.split(|b| b == &b'\n')
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
194 }
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
195
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
196 /// Return the node id of the `manifest` referenced by this `changelog`
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
197 /// entry.
47964
796206e74b10 rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents: 47963
diff changeset
198 pub fn manifest_node(&self) -> Result<Node, HgError> {
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
199 let manifest_node_hex = &self.bytes[..self.manifest_end];
49063
cc132255261b rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents: 49062
diff changeset
200 Node::from_hex_for_repo(manifest_node_hex)
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
201 }
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
202
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
203 /// The full user string (usually a name followed by an email enclosed in
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
204 /// angle brackets)
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
205 pub fn user(&self) -> &[u8] {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
206 &self.bytes[self.manifest_end + 1..self.user_end]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
207 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
208
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
209 /// The full timestamp line (timestamp in seconds, offset in seconds, and
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
210 /// possibly extras)
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
211 // TODO: We should expose this in a more useful way
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
212 pub fn timestamp_line(&self) -> &[u8] {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
213 &self.bytes[self.user_end + 1..self.timestamp_end]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
214 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
215
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
216 /// The files changed in this revision.
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
217 pub fn files(&self) -> impl Iterator<Item = &HgPath> {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
218 self.bytes[self.timestamp_end + 1..self.files_end]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
219 .split(|b| b == &b'\n')
49930
e98fd81bb151 rust-clippy: fix most warnings in `hg-core`
Raphaël Gomès <rgomes@octobus.net>
parents: 49096
diff changeset
220 .map(HgPath::new)
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
221 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
222
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
223 /// The change description.
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
224 pub fn description(&self) -> &[u8] {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
225 &self.bytes[self.files_end + 2..]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
226 }
45532
c2317b7624fd hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
227 }
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
228
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
229 impl Debug for ChangelogRevisionData<'_> {
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
230 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
231 f.debug_struct("ChangelogRevisionData")
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
232 .field("bytes", &debug_bytes(&self.bytes))
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
233 .field("manifest", &debug_bytes(&self.bytes[..self.manifest_end]))
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
234 .field(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
235 "user",
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
236 &debug_bytes(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
237 &self.bytes[self.manifest_end + 1..self.user_end],
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
238 ),
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
239 )
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
240 .field(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
241 "timestamp",
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
242 &debug_bytes(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
243 &self.bytes[self.user_end + 1..self.timestamp_end],
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
244 ),
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
245 )
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
246 .field(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
247 "files",
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
248 &debug_bytes(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
249 &self.bytes[self.timestamp_end + 1..self.files_end],
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
250 ),
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
251 )
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
252 .field(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
253 "description",
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
254 &debug_bytes(&self.bytes[self.files_end + 2..]),
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
255 )
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
256 .finish()
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
257 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
258 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
259
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
260 fn debug_bytes(bytes: &[u8]) -> String {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
261 String::from_utf8_lossy(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
262 &bytes.iter().flat_map(|b| escape_default(*b)).collect_vec(),
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
263 )
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
264 .to_string()
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
265 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
266
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
267 #[cfg(test)]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
268 mod tests {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
269 use super::*;
50410
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
270 use crate::vfs::Vfs;
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
271 use crate::NULL_REVISION;
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
272 use pretty_assertions::assert_eq;
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
273
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
274 #[test]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
275 fn test_create_changelogrevisiondata_invalid() {
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
276 // Completely empty
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
277 assert!(ChangelogRevisionData::new(Cow::Borrowed(b"abcd")).is_err());
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
278 // No newline after manifest
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
279 assert!(ChangelogRevisionData::new(Cow::Borrowed(b"abcd")).is_err());
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
280 // No newline after user
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
281 assert!(ChangelogRevisionData::new(Cow::Borrowed(b"abcd\n")).is_err());
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
282 // No newline after timestamp
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
283 assert!(
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
284 ChangelogRevisionData::new(Cow::Borrowed(b"abcd\n\n0 0")).is_err()
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
285 );
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
286 // Missing newline after files
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
287 assert!(ChangelogRevisionData::new(Cow::Borrowed(
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
288 b"abcd\n\n0 0\nfile1\nfile2"
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
289 ))
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
290 .is_err(),);
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
291 // Only one newline after files
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
292 assert!(ChangelogRevisionData::new(Cow::Borrowed(
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
293 b"abcd\n\n0 0\nfile1\nfile2\n"
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
294 ))
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
295 .is_err(),);
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
296 }
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
297
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
298 #[test]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
299 fn test_create_changelogrevisiondata() {
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
300 let data = ChangelogRevisionData::new(Cow::Borrowed(
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
301 b"0123456789abcdef0123456789abcdef01234567
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
302 Some One <someone@example.com>
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
303 0 0
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
304 file1
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
305 file2
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
306
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
307 some
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
308 commit
49096
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
309 message",
07ec9f4f24bf changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents: 49090
diff changeset
310 ))
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
311 .unwrap();
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
312 assert_eq!(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
313 data.manifest_node().unwrap(),
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
314 Node::from_hex("0123456789abcdef0123456789abcdef01234567")
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
315 .unwrap()
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
316 );
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
317 assert_eq!(data.user(), b"Some One <someone@example.com>");
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
318 assert_eq!(data.timestamp_line(), b"0 0");
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
319 assert_eq!(
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
320 data.files().collect_vec(),
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
321 vec![HgPath::new("file1"), HgPath::new("file2")]
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
322 );
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
323 assert_eq!(data.description(), b"some\ncommit\nmessage");
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
324 }
50410
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
325
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
326 #[test]
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
327 fn test_data_from_rev_null() -> Result<(), RevlogError> {
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
328 // an empty revlog will be enough for this case
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
329 let temp = tempfile::tempdir().unwrap();
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
330 let vfs = Vfs { base: temp.path() };
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
331 std::fs::write(temp.path().join("foo.i"), b"").unwrap();
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
332 let revlog = Revlog::open(&vfs, "foo.i", None, false).unwrap();
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
333
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
334 let changelog = Changelog { revlog };
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
335 assert_eq!(
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
336 changelog.data_for_rev(NULL_REVISION)?,
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
337 ChangelogRevisionData::null()
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
338 );
50746
124c44b5cfad rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents: 50414
diff changeset
339 // same with the intermediate entry object
124c44b5cfad rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents: 50414
diff changeset
340 assert_eq!(
124c44b5cfad rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents: 50414
diff changeset
341 changelog.entry_for_rev(NULL_REVISION)?.data()?,
124c44b5cfad rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents: 50414
diff changeset
342 ChangelogRevisionData::null()
124c44b5cfad rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents: 50414
diff changeset
343 );
50410
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
344 Ok(())
b5dd6d6d6fa6 rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents: 50409
diff changeset
345 }
49064
95da3e99cbd8 rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents: 49063
diff changeset
346 }