Mercurial > hg
annotate rust/hg-core/src/revlog/changelog.rs @ 51397:b01e7d97e167
revlog: add a Rust implementation of `headrevsdiff`
Python implementation of `headrevsdiff` can be very slow in the worst
case compared with the `heads` computation it replaces, since the
latter is done in Rust.
Even the average case of this Python implementation is still
noticeable in the profiles.
This patch makes the computation much much faster by doing it in Rust.
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Mon, 12 Feb 2024 20:01:27 +0000 |
parents | 6603a1448f18 |
children | 918ceb5a3d25 |
rev | line source |
---|---|
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
1 use std::ascii::escape_default; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
2 use std::borrow::Cow; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
3 use std::collections::BTreeMap; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
4 use std::fmt::{Debug, Formatter}; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
5 use std::{iter, str}; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
6 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
7 use chrono::{DateTime, FixedOffset, NaiveDateTime}; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
8 use itertools::{Either, Itertools}; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
9 |
46443
43d63979a75e
rust: use HgError in RevlogError and Vfs
Simon Sapin <simon.sapin@octobus.net>
parents:
46433
diff
changeset
|
10 use crate::errors::HgError; |
50747
9865af7191d2
rust-changelog: removed now useless early conditional for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents:
50746
diff
changeset
|
11 use crate::revlog::Revision; |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
12 use crate::revlog::{Node, NodePrefix}; |
49937
750409505286
rust-clippy: merge "revlog" module definition and struct implementation
Raphaël Gomès <rgomes@octobus.net>
parents:
49930
diff
changeset
|
13 use crate::revlog::{Revlog, RevlogEntry, RevlogError}; |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
14 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
|
15 use crate::vfs::Vfs; |
51191
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
16 use crate::{Graph, GraphError, RevlogOpenOptions, UncheckedRevision}; |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
17 |
50409
b47a9316050a
rust-changelog: made doc-comments more consistent
Georges Racinet <georges.racinet@octobus.net>
parents:
49937
diff
changeset
|
18 /// 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
|
19 pub struct Changelog { |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
20 /// The generic `revlog` format. |
46433
4b381dbbf8b7
rhg: centralize parsing of `--rev` CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents:
46431
diff
changeset
|
21 pub(crate) revlog: Revlog, |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
22 } |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
23 |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
24 impl Changelog { |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
25 /// Open the `changelog` of a repository given by its root. |
51191
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
26 pub fn open( |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
27 store_vfs: &Vfs, |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
28 options: RevlogOpenOptions, |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
29 ) -> Result<Self, HgError> { |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
30 let revlog = Revlog::open(store_vfs, "00changelog.i", None, options)?; |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
31 Ok(Self { revlog }) |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
32 } |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
33 |
50409
b47a9316050a
rust-changelog: made doc-comments more consistent
Georges Racinet <georges.racinet@octobus.net>
parents:
49937
diff
changeset
|
34 /// 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
|
35 pub fn data_for_node( |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
36 &self, |
46431
645ee7225fab
rust: Make NodePrefix allocation-free and Copy, remove NodePrefixRef
Simon Sapin <simon.sapin@octobus.net>
parents:
46167
diff
changeset
|
37 node: NodePrefix, |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48198
diff
changeset
|
38 ) -> 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
|
39 let rev = self.revlog.rev_from_node(node)?; |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
40 self.entry_for_checked_rev(rev)?.data() |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
41 } |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
42 |
50411
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
43 /// 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
|
44 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
|
45 &self, |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
46 rev: UncheckedRevision, |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
47 ) -> Result<ChangelogEntry, RevlogError> { |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
48 let revlog_entry = self.revlog.get_entry(rev)?; |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
49 Ok(ChangelogEntry { revlog_entry }) |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
50 } |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
51 |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
52 /// Same as [`Self::entry_for_rev`] for checked revisions. |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
53 fn entry_for_checked_rev( |
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
54 &self, |
49065
5d205e476057
rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents:
49064
diff
changeset
|
55 rev: Revision, |
50411
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
56 ) -> Result<ChangelogEntry, RevlogError> { |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
57 let revlog_entry = self.revlog.get_entry_for_checked_rev(rev)?; |
50411
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
58 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
|
59 } |
5d205e476057
rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents:
49064
diff
changeset
|
60 |
50409
b47a9316050a
rust-changelog: made doc-comments more consistent
Georges Racinet <georges.racinet@octobus.net>
parents:
49937
diff
changeset
|
61 /// 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
|
62 /// |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
63 /// 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
|
64 /// generic revlog information (parents, hashes etc). Otherwise |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
65 /// consider taking a [`ChangelogEntry`] with |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
66 /// [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
|
67 pub fn data_for_rev( |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
68 &self, |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
69 rev: UncheckedRevision, |
48540
20d0d896183e
rhg: Rename some revlog-related types and methods
Simon Sapin <simon.sapin@octobus.net>
parents:
48198
diff
changeset
|
70 ) -> Result<ChangelogRevisionData, RevlogError> { |
50411
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
71 self.entry_for_rev(rev)?.data() |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
72 } |
46744
b1f2c2b336ec
rhg: `cat` command: print error messages for missing files
Simon Sapin <simon.sapin@octobus.net>
parents:
46443
diff
changeset
|
73 |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
74 pub fn node_from_rev(&self, rev: UncheckedRevision) -> Option<&Node> { |
47967
6c653d9d41b8
rust: Make private the `index` field of the `Revlog` struct
Simon Sapin <simon.sapin@octobus.net>
parents:
47964
diff
changeset
|
75 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
|
76 } |
49065
5d205e476057
rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents:
49064
diff
changeset
|
77 |
5d205e476057
rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents:
49064
diff
changeset
|
78 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
|
79 &self, |
5d205e476057
rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents:
49064
diff
changeset
|
80 node: NodePrefix, |
5d205e476057
rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents:
49064
diff
changeset
|
81 ) -> Result<Revision, RevlogError> { |
5d205e476057
rust-revlog: add methods for getting parent revs and entries
Martin von Zweigbergk <martinvonz@google.com>
parents:
49064
diff
changeset
|
82 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
|
83 } |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
84 } |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
85 |
50978
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Raphaël Gomès <rgomes@octobus.net>
parents:
50977
diff
changeset
|
86 impl Graph for Changelog { |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Raphaël Gomès <rgomes@octobus.net>
parents:
50977
diff
changeset
|
87 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError> { |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Raphaël Gomès <rgomes@octobus.net>
parents:
50977
diff
changeset
|
88 self.revlog.parents(rev) |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Raphaël Gomès <rgomes@octobus.net>
parents:
50977
diff
changeset
|
89 } |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Raphaël Gomès <rgomes@octobus.net>
parents:
50977
diff
changeset
|
90 } |
27e773aa607d
rust: implement the `Graph` trait for all revlogs
Raphaël Gomès <rgomes@octobus.net>
parents:
50977
diff
changeset
|
91 |
50411
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
92 /// A specialized `RevlogEntry` for `changelog` data format |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
93 /// |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
94 /// 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
|
95 /// 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
|
96 /// the fact that `data()` constructs a `ChangelogRevisionData`. |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
97 /// 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
|
98 #[derive(Clone)] |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
99 pub struct ChangelogEntry<'changelog> { |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
100 /// Same data, as a generic `RevlogEntry`. |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
101 pub(crate) revlog_entry: RevlogEntry<'changelog>, |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
102 } |
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 impl<'changelog> ChangelogEntry<'changelog> { |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
105 pub fn data<'a>( |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
106 &'a self, |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
107 ) -> Result<ChangelogRevisionData<'changelog>, RevlogError> { |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
108 let bytes = self.revlog_entry.data()?; |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
109 if bytes.is_empty() { |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
110 Ok(ChangelogRevisionData::null()) |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
111 } else { |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
112 Ok(ChangelogRevisionData::new(bytes).map_err(|err| { |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
113 RevlogError::Other(HgError::CorruptedRepository(format!( |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
114 "Invalid changelog data for revision {}: {:?}", |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
115 self.revlog_entry.revision(), |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
116 err |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
117 ))) |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
118 })?) |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
119 } |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
120 } |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
121 |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
122 /// Obtain a reference to the underlying `RevlogEntry`. |
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 /// 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
|
125 /// 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
|
126 pub fn as_revlog_entry(&self) -> &RevlogEntry { |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
127 &self.revlog_entry |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
128 } |
50414
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
129 |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
130 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
|
131 Ok(self |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
132 .revlog_entry |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
133 .p1_entry()? |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
134 .map(|revlog_entry| Self { revlog_entry })) |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
135 } |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
136 |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
137 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
|
138 Ok(self |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
139 .revlog_entry |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
140 .p2_entry()? |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
141 .map(|revlog_entry| Self { revlog_entry })) |
071a6c1d291e
rust-changelog: introduce ChangelogEntry parent entries accessors
Georges Racinet <georges.racinet@octobus.net>
parents:
50411
diff
changeset
|
142 } |
50411
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
143 } |
841b13e6e84c
rust-changelog: introducing an intermediate `ChangelogEntry`
Georges Racinet <georges.racinet@octobus.net>
parents:
50410
diff
changeset
|
144 |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
145 /// `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
|
146 #[derive(PartialEq)] |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
147 pub struct ChangelogRevisionData<'changelog> { |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
148 /// 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
|
149 bytes: Cow<'changelog, [u8]>, |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
150 /// 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
|
151 manifest_end: usize, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
152 /// 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
|
153 user_end: usize, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
154 /// 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
|
155 /// newline) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
156 timestamp_end: usize, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
157 /// 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
|
158 files_end: usize, |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
159 } |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
160 |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
161 impl<'changelog> ChangelogRevisionData<'changelog> { |
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
162 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
|
163 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
|
164 let manifest_end = line_iter |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
165 .next() |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
166 .expect("Empty iterator from split()?") |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
167 .len(); |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
168 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
|
169 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
|
170 })?; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
171 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
|
172 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
|
173 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
|
174 })?; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
175 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
|
176 let mut files_end = timestamp_end + 1; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
177 loop { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
178 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
|
179 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
|
180 })?; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
181 if line.is_empty() { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
182 if files_end == bytes.len() { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
183 // 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
|
184 // should be two) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
185 return Err(HgError::corrupted( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
186 "Changeset data truncated after files list", |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
187 )); |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
188 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
189 files_end -= 1; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
190 break; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
191 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
192 files_end += line.len() + 1; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
193 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
194 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
195 Ok(Self { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
196 bytes, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
197 manifest_end, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
198 user_end, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
199 timestamp_end, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
200 files_end, |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
201 }) |
49063
cc132255261b
rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents:
49062
diff
changeset
|
202 } |
cc132255261b
rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents:
49062
diff
changeset
|
203 |
cc132255261b
rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents:
49062
diff
changeset
|
204 fn null() -> Self { |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
205 Self::new(Cow::Borrowed( |
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
206 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
|
207 )) |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
208 .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
|
209 } |
cc132255261b
rust-changelog: remove special parsing of empty changelog data for null rev
Martin von Zweigbergk <martinvonz@google.com>
parents:
49062
diff
changeset
|
210 |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
211 /// 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
|
212 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
|
213 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
|
214 } |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
215 |
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
216 /// 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
|
217 /// entry. |
47964
796206e74b10
rhg: Reuse manifest when checking status of multiple ambiguous files
Simon Sapin <simon.sapin@octobus.net>
parents:
47963
diff
changeset
|
218 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
|
219 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
|
220 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
|
221 } |
49064
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 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
|
224 /// angle brackets) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
225 pub fn user(&self) -> &[u8] { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
226 &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
|
227 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
228 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
229 /// 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
|
230 /// possibly extras) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
231 // 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
|
232 pub fn timestamp_line(&self) -> &[u8] { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
233 &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
|
234 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
235 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
236 /// Parsed timestamp. |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
237 pub fn timestamp(&self) -> Result<DateTime<FixedOffset>, HgError> { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
238 parse_timestamp(self.timestamp_line()) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
239 } |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
240 |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
241 /// Optional commit extras. |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
242 pub fn extra(&self) -> Result<BTreeMap<String, Vec<u8>>, HgError> { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
243 parse_timestamp_line_extra(self.timestamp_line()) |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
244 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
245 |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
246 /// The files changed in this revision. |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
247 pub fn files(&self) -> impl Iterator<Item = &HgPath> { |
51363
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
248 if self.timestamp_end == self.files_end { |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
249 Either::Left(iter::empty()) |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
250 } else { |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
251 Either::Right( |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
252 self.bytes[self.timestamp_end + 1..self.files_end] |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
253 .split(|b| b == &b'\n') |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
254 .map(HgPath::new), |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
255 ) |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
256 } |
49064
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 /// The change description. |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
260 pub fn description(&self) -> &[u8] { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
261 &self.bytes[self.files_end + 2..] |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
262 } |
45532
c2317b7624fd
hg-core: add `Changlog` a specialized `Revlog`
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff
changeset
|
263 } |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
264 |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
265 impl Debug for ChangelogRevisionData<'_> { |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
266 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
|
267 f.debug_struct("ChangelogRevisionData") |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
268 .field("bytes", &debug_bytes(&self.bytes)) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
269 .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
|
270 .field( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
271 "user", |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
272 &debug_bytes( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
273 &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
|
274 ), |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
275 ) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
276 .field( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
277 "timestamp", |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
278 &debug_bytes( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
279 &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
|
280 ), |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
281 ) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
282 .field( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
283 "files", |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
284 &debug_bytes( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
285 &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
|
286 ), |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
287 ) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
288 .field( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
289 "description", |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
290 &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
|
291 ) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
292 .finish() |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
293 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
294 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
295 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
296 fn debug_bytes(bytes: &[u8]) -> String { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
297 String::from_utf8_lossy( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
298 &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
|
299 ) |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
300 .to_string() |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
301 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
302 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
303 /// Parse the raw bytes of the timestamp line from a changelog entry. |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
304 /// |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
305 /// According to the documentation in `hg help dates` and the |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
306 /// implementation in `changelog.py`, the format of the timestamp line |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
307 /// is `time tz extra\n` where: |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
308 /// |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
309 /// - `time` is an ASCII-encoded signed int or float denoting a UTC timestamp |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
310 /// as seconds since the UNIX epoch. |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
311 /// |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
312 /// - `tz` is the timezone offset as an ASCII-encoded signed integer denoting |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
313 /// seconds WEST of UTC (so negative for timezones east of UTC, which is the |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
314 /// opposite of the sign in ISO 8601 timestamps). |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
315 /// |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
316 /// - `extra` is an optional set of NUL-delimited key-value pairs, with the key |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
317 /// and value in each pair separated by an ASCII colon. Keys are limited to |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
318 /// ASCII letters, digits, hyphens, and underscores, whereas values can be |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
319 /// arbitrary bytes. |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
320 fn parse_timestamp( |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
321 timestamp_line: &[u8], |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
322 ) -> Result<DateTime<FixedOffset>, HgError> { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
323 let mut parts = timestamp_line.splitn(3, |c| *c == b' '); |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
324 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
325 let timestamp_bytes = parts |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
326 .next() |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
327 .ok_or_else(|| HgError::corrupted("missing timestamp"))?; |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
328 let timestamp_str = str::from_utf8(timestamp_bytes).map_err(|e| { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
329 HgError::corrupted(format!("timestamp is not valid UTF-8: {e}")) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
330 })?; |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
331 let timestamp_utc = timestamp_str |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
332 .parse() |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
333 .map_err(|e| { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
334 HgError::corrupted(format!("failed to parse timestamp: {e}")) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
335 }) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
336 .and_then(|secs| { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
337 NaiveDateTime::from_timestamp_opt(secs, 0).ok_or_else(|| { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
338 HgError::corrupted(format!( |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
339 "integer timestamp out of valid range: {secs}" |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
340 )) |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
341 }) |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
342 }) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
343 // Attempt to parse the timestamp as a float if we can't parse |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
344 // it as an int. It doesn't seem like float timestamps are actually |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
345 // used in practice, but the Python code supports them. |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
346 .or_else(|_| parse_float_timestamp(timestamp_str))?; |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
347 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
348 let timezone_bytes = parts |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
349 .next() |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
350 .ok_or_else(|| HgError::corrupted("missing timezone"))?; |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
351 let timezone_secs: i32 = str::from_utf8(timezone_bytes) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
352 .map_err(|e| { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
353 HgError::corrupted(format!("timezone is not valid UTF-8: {e}")) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
354 })? |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
355 .parse() |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
356 .map_err(|e| { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
357 HgError::corrupted(format!("timezone is not an integer: {e}")) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
358 })?; |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
359 let timezone = FixedOffset::west_opt(timezone_secs) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
360 .ok_or_else(|| HgError::corrupted("timezone offset out of bounds"))?; |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
361 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
362 Ok(DateTime::from_naive_utc_and_offset(timestamp_utc, timezone)) |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
363 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
364 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
365 /// Attempt to parse the given string as floating-point timestamp, and |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
366 /// convert the result into a `chrono::NaiveDateTime`. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
367 fn parse_float_timestamp( |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
368 timestamp_str: &str, |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
369 ) -> Result<NaiveDateTime, HgError> { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
370 let timestamp = timestamp_str.parse::<f64>().map_err(|e| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
371 HgError::corrupted(format!("failed to parse timestamp: {e}")) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
372 })?; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
373 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
374 // To construct a `NaiveDateTime` we'll need to convert the float |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
375 // into signed integer seconds and unsigned integer nanoseconds. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
376 let mut secs = timestamp.trunc() as i64; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
377 let mut subsecs = timestamp.fract(); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
378 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
379 // If the timestamp is negative, we need to express the fractional |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
380 // component as positive nanoseconds since the previous second. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
381 if timestamp < 0.0 { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
382 secs -= 1; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
383 subsecs += 1.0; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
384 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
385 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
386 // This cast should be safe because the fractional component is |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
387 // by definition less than 1.0, so this value should not exceed |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
388 // 1 billion, which is representable as an f64 without loss of |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
389 // precision and should fit into a u32 without overflowing. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
390 // |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
391 // (Any loss of precision in the fractional component will have |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
392 // already happened at the time of initial parsing; in general, |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
393 // f64s are insufficiently precise to provide nanosecond-level |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
394 // precision with present-day timestamps.) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
395 let nsecs = (subsecs * 1_000_000_000.0) as u32; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
396 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
397 NaiveDateTime::from_timestamp_opt(secs, nsecs).ok_or_else(|| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
398 HgError::corrupted(format!( |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
399 "float timestamp out of valid range: {timestamp}" |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
400 )) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
401 }) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
402 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
403 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
404 /// Decode changeset extra fields. |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
405 /// |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
406 /// Extras are null-delimited key-value pairs where the key consists of ASCII |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
407 /// alphanumeric characters plus hyphens and underscores, and the value can |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
408 /// contain arbitrary bytes. |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
409 fn decode_extra(extra: &[u8]) -> Result<BTreeMap<String, Vec<u8>>, HgError> { |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
410 extra |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
411 .split(|c| *c == b'\0') |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
412 .map(|pair| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
413 let pair = unescape_extra(pair); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
414 let mut iter = pair.splitn(2, |c| *c == b':'); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
415 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
416 let key_bytes = |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
417 iter.next().filter(|k| !k.is_empty()).ok_or_else(|| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
418 HgError::corrupted("empty key in changeset extras") |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
419 })?; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
420 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
421 let key = str::from_utf8(key_bytes) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
422 .ok() |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
423 .filter(|k| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
424 k.chars().all(|c| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
425 c.is_ascii_alphanumeric() || c == '_' || c == '-' |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
426 }) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
427 }) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
428 .ok_or_else(|| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
429 let key = String::from_utf8_lossy(key_bytes); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
430 HgError::corrupted(format!( |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
431 "invalid key in changeset extras: {key}", |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
432 )) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
433 })? |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
434 .to_string(); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
435 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
436 let value = iter.next().map(Into::into).ok_or_else(|| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
437 HgError::corrupted(format!( |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
438 "missing value for changeset extra: {key}" |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
439 )) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
440 })?; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
441 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
442 Ok((key, value)) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
443 }) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
444 .collect() |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
445 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
446 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
447 /// Parse the extra fields from a changeset's timestamp line. |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
448 fn parse_timestamp_line_extra( |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
449 timestamp_line: &[u8], |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
450 ) -> Result<BTreeMap<String, Vec<u8>>, HgError> { |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
451 Ok(timestamp_line |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
452 .splitn(3, |c| *c == b' ') |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
453 .nth(2) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
454 .map(decode_extra) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
455 .transpose()? |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
456 .unwrap_or_default()) |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
457 } |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
458 |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
459 /// Decode Mercurial's escaping for changelog extras. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
460 /// |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
461 /// The `_string_escape` function in `changelog.py` only escapes 4 characters |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
462 /// (null, backslash, newline, and carriage return) so we only decode those. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
463 /// |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
464 /// The Python code also includes a workaround for decoding escaped nuls |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
465 /// that are followed by an ASCII octal digit, since Python's built-in |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
466 /// `string_escape` codec will interpret that as an escaped octal byte value. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
467 /// That workaround is omitted here since we don't support decoding octal. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
468 fn unescape_extra(bytes: &[u8]) -> Vec<u8> { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
469 let mut output = Vec::with_capacity(bytes.len()); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
470 let mut input = bytes.iter().copied(); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
471 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
472 while let Some(c) = input.next() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
473 if c != b'\\' { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
474 output.push(c); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
475 continue; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
476 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
477 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
478 match input.next() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
479 Some(b'0') => output.push(b'\0'), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
480 Some(b'\\') => output.push(b'\\'), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
481 Some(b'n') => output.push(b'\n'), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
482 Some(b'r') => output.push(b'\r'), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
483 // The following cases should never occur in theory because any |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
484 // backslashes in the original input should have been escaped |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
485 // with another backslash, so it should not be possible to |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
486 // observe an escape sequence other than the 4 above. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
487 Some(c) => output.extend_from_slice(&[b'\\', c]), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
488 None => output.push(b'\\'), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
489 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
490 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
491 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
492 output |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
493 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
494 |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
495 #[cfg(test)] |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
496 mod tests { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
497 use super::*; |
50410
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
498 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
|
499 use crate::NULL_REVISION; |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
500 use pretty_assertions::assert_eq; |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
501 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
502 #[test] |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
503 fn test_create_changelogrevisiondata_invalid() { |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
504 // Completely empty |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
505 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
|
506 // No newline after manifest |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
507 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
|
508 // No newline after user |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
509 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
|
510 // No newline after timestamp |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
511 assert!( |
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
512 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
|
513 ); |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
514 // Missing newline after files |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
515 assert!(ChangelogRevisionData::new(Cow::Borrowed( |
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
516 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
|
517 )) |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
518 .is_err(),); |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
519 // Only one newline after files |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
520 assert!(ChangelogRevisionData::new(Cow::Borrowed( |
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
521 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
|
522 )) |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
523 .is_err(),); |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
524 } |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
525 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
526 #[test] |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
527 fn test_create_changelogrevisiondata() { |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
528 let data = ChangelogRevisionData::new(Cow::Borrowed( |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
529 b"0123456789abcdef0123456789abcdef01234567 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
530 Some One <someone@example.com> |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
531 0 0 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
532 file1 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
533 file2 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
534 |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
535 some |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
536 commit |
49096
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
537 message", |
07ec9f4f24bf
changelog: avoid copying changeset data into `ChangesetRevisionData`
Martin von Zweigbergk <martinvonz@google.com>
parents:
49090
diff
changeset
|
538 )) |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
539 .unwrap(); |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
540 assert_eq!( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
541 data.manifest_node().unwrap(), |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
542 Node::from_hex("0123456789abcdef0123456789abcdef01234567") |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
543 .unwrap() |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
544 ); |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
545 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
|
546 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
|
547 assert_eq!( |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
548 data.files().collect_vec(), |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
549 vec![HgPath::new("file1"), HgPath::new("file2")] |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
550 ); |
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
551 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
|
552 } |
50410
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
553 |
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
554 #[test] |
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
555 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
|
556 // 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
|
557 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
|
558 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
|
559 std::fs::write(temp.path().join("foo.i"), b"").unwrap(); |
51191
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
560 let revlog = |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
561 Revlog::open(&vfs, "foo.i", None, RevlogOpenOptions::new()) |
13f58ce70299
rust-revlog: teach the revlog opening code to read the repo options
Raphaël Gomès <rgomes@octobus.net>
parents:
50978
diff
changeset
|
562 .unwrap(); |
50410
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
563 |
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
564 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
|
565 assert_eq!( |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
566 changelog.data_for_rev(NULL_REVISION.into())?, |
50410
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
567 ChangelogRevisionData::null() |
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
568 ); |
50746
124c44b5cfad
rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents:
50414
diff
changeset
|
569 // 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
|
570 assert_eq!( |
50977
1928b770e3e7
rust: use the new `UncheckedRevision` everywhere applicable
Raphaël Gomès <rgomes@octobus.net>
parents:
50747
diff
changeset
|
571 changelog.entry_for_rev(NULL_REVISION.into())?.data()?, |
50746
124c44b5cfad
rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents:
50414
diff
changeset
|
572 ChangelogRevisionData::null() |
124c44b5cfad
rust-revlog: fix RevlogEntry.data() for NULL_REVISION
Georges Racinet <georges.racinet@octobus.net>
parents:
50414
diff
changeset
|
573 ); |
50410
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
574 Ok(()) |
b5dd6d6d6fa6
rust-changelog: added a test for `NULL_REVISION` special case
Georges Racinet <georges.racinet@octobus.net>
parents:
50409
diff
changeset
|
575 } |
51363
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
576 |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
577 #[test] |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
578 fn test_empty_files_list() { |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
579 assert!(ChangelogRevisionData::null() |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
580 .files() |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
581 .collect_vec() |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
582 .is_empty()); |
d626e5e7bbbe
rust-changelog: don't panic on empty file lists
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
50978
diff
changeset
|
583 } |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
584 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
585 #[test] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
586 fn test_unescape_basic() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
587 // '\0', '\\', '\n', and '\r' are correctly unescaped. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
588 let expected = b"AAA\0BBB\\CCC\nDDD\rEEE"; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
589 let escaped = br"AAA\0BBB\\CCC\nDDD\rEEE"; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
590 let unescaped = unescape_extra(escaped); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
591 assert_eq!(&expected[..], &unescaped[..]); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
592 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
593 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
594 #[test] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
595 fn test_unescape_unsupported_sequence() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
596 // Other escape sequences are left unaltered. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
597 for c in 0u8..255 { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
598 match c { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
599 b'0' | b'\\' | b'n' | b'r' => continue, |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
600 c => { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
601 let expected = &[b'\\', c][..]; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
602 let unescaped = unescape_extra(expected); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
603 assert_eq!(expected, &unescaped[..]); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
604 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
605 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
606 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
607 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
608 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
609 #[test] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
610 fn test_unescape_trailing_backslash() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
611 // Trailing backslashes are OK. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
612 let expected = br"hi\"; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
613 let unescaped = unescape_extra(expected); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
614 assert_eq!(&expected[..], &unescaped[..]); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
615 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
616 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
617 #[test] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
618 fn test_unescape_nul_followed_by_octal() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
619 // Escaped NUL chars followed by octal digits are decoded correctly. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
620 let expected = b"\012"; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
621 let escaped = br"\012"; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
622 let unescaped = unescape_extra(escaped); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
623 assert_eq!(&expected[..], &unescaped[..]); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
624 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
625 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
626 #[test] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
627 fn test_parse_float_timestamp() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
628 let test_cases = [ |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
629 // Zero should map to the UNIX epoch. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
630 ("0.0", "1970-01-01 00:00:00"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
631 // Negative zero should be the same as positive zero. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
632 ("-0.0", "1970-01-01 00:00:00"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
633 // Values without fractional components should work like integers. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
634 // (Assuming the timestamp is within the limits of f64 precision.) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
635 ("1115154970.0", "2005-05-03 21:16:10"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
636 // We expect some loss of precision in the fractional component |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
637 // when parsing arbitrary floating-point values. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
638 ("1115154970.123456789", "2005-05-03 21:16:10.123456716"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
639 // But representable f64 values should parse losslessly. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
640 ("1115154970.123456716", "2005-05-03 21:16:10.123456716"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
641 // Negative fractional components are subtracted from the epoch. |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
642 ("-1.333", "1969-12-31 23:59:58.667"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
643 ]; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
644 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
645 for (input, expected) in test_cases { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
646 let res = parse_float_timestamp(input).unwrap().to_string(); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
647 assert_eq!(res, expected); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
648 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
649 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
650 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
651 fn escape_extra(bytes: &[u8]) -> Vec<u8> { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
652 let mut output = Vec::with_capacity(bytes.len()); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
653 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
654 for c in bytes.iter().copied() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
655 output.extend_from_slice(match c { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
656 b'\0' => &b"\\0"[..], |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
657 b'\\' => &b"\\\\"[..], |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
658 b'\n' => &b"\\n"[..], |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
659 b'\r' => &b"\\r"[..], |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
660 _ => { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
661 output.push(c); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
662 continue; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
663 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
664 }); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
665 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
666 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
667 output |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
668 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
669 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
670 fn encode_extra<K, V>(pairs: impl IntoIterator<Item = (K, V)>) -> Vec<u8> |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
671 where |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
672 K: AsRef<[u8]>, |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
673 V: AsRef<[u8]>, |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
674 { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
675 let extras = pairs.into_iter().map(|(k, v)| { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
676 escape_extra(&[k.as_ref(), b":", v.as_ref()].concat()) |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
677 }); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
678 // Use fully-qualified syntax to avoid a future naming conflict with |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
679 // the standard library: https://github.com/rust-lang/rust/issues/79524 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
680 Itertools::intersperse(extras, b"\0".to_vec()).concat() |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
681 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
682 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
683 #[test] |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
684 fn test_decode_extra() { |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
685 let extra = [ |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
686 ("branch".into(), b"default".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
687 ("key-with-hyphens".into(), b"value1".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
688 ("key_with_underscores".into(), b"value2".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
689 ("empty-value".into(), b"".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
690 ("binary-value".into(), (0u8..=255).collect::<Vec<_>>()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
691 ] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
692 .into_iter() |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
693 .collect::<BTreeMap<String, Vec<u8>>>(); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
694 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
695 let encoded = encode_extra(&extra); |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
696 let decoded = decode_extra(&encoded).unwrap(); |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
697 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
698 assert_eq!(extra, decoded); |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
699 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
700 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
701 #[test] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
702 fn test_corrupt_extra() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
703 let test_cases = [ |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
704 (&b""[..], "empty input"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
705 (&b"\0"[..], "unexpected null byte"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
706 (&b":empty-key"[..], "empty key"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
707 (&b"\0leading-null:"[..], "leading null"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
708 (&b"trailing-null:\0"[..], "trailing null"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
709 (&b"missing-value"[..], "missing value"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
710 (&b"$!@# non-alphanum-key:"[..], "non-alphanumeric key"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
711 (&b"\xF0\x9F\xA6\x80 non-ascii-key:"[..], "non-ASCII key"), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
712 ]; |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
713 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
714 for (extra, msg) in test_cases { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
715 assert!( |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
716 decode_extra(&extra).is_err(), |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
717 "corrupt extra should have failed to parse: {}", |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
718 msg |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
719 ); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
720 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
721 } |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
722 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
723 #[test] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
724 fn test_parse_timestamp_line() { |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
725 let extra = [ |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
726 ("branch".into(), b"default".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
727 ("key-with-hyphens".into(), b"value1".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
728 ("key_with_underscores".into(), b"value2".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
729 ("empty-value".into(), b"".to_vec()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
730 ("binary-value".into(), (0u8..=255).collect::<Vec<_>>()), |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
731 ] |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
732 .into_iter() |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
733 .collect::<BTreeMap<String, Vec<u8>>>(); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
734 |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
735 let mut line: Vec<u8> = b"1115154970 28800 ".to_vec(); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
736 line.extend_from_slice(&encode_extra(&extra)); |
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
737 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
738 let timestamp = parse_timestamp(&line).unwrap(); |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
739 assert_eq!(×tamp.to_rfc3339(), "2005-05-03T13:16:10-08:00"); |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
740 |
51393
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
741 let parsed_extra = parse_timestamp_line_extra(&line).unwrap(); |
6603a1448f18
hg-core: separate timestamp and extra methods
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51391
diff
changeset
|
742 assert_eq!(extra, parsed_extra); |
51391
a96ed440450e
hg-core: implement timestamp line parsing
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents:
51369
diff
changeset
|
743 } |
49064
95da3e99cbd8
rust-changelog: start parsing changeset data
Martin von Zweigbergk <martinvonz@google.com>
parents:
49063
diff
changeset
|
744 } |