Skip to content

Commit 3888444

Browse files
committed
fix: Properly parse reflog messages with > in them.
Previously these confused the signature parser, who gladly took the entire message as part of the email.
1 parent 743b979 commit 3888444

File tree

2 files changed

+42
-20
lines changed

2 files changed

+42
-20
lines changed

gix-ref/src/store/file/log/line.rs

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ impl<'a> From<LineRef<'a>> for Line {
7373

7474
///
7575
pub mod decode {
76+
use crate::{file::log::LineRef, parse::hex_hash};
7677
use gix_object::bstr::{BStr, ByteSlice};
7778
use winnow::{
7879
combinator::{alt, eof, fail, opt, preceded, rest, terminated},
@@ -81,8 +82,6 @@ pub mod decode {
8182
token::take_while,
8283
};
8384

84-
use crate::{file::log::LineRef, parse::hex_hash};
85-
8685
///
8786
mod error {
8887
use gix_object::bstr::{BString, ByteSlice};
@@ -135,34 +134,57 @@ pub mod decode {
135134
fn one<'a, E: ParserError<&'a [u8]> + AddContext<&'a [u8], StrContext>>(
136135
bytes: &mut &'a [u8],
137136
) -> PResult<LineRef<'a>, E> {
138-
(
139-
(
137+
let mut tokens = bytes.splitn(2, |b| *b == b'\t');
138+
if let (Some(mut first), Some(mut second)) = (tokens.next(), tokens.next()) {
139+
let (old, new, signature) = (
140140
terminated(hex_hash, b" ").context(StrContext::Expected("<old-hexsha>".into())),
141141
terminated(hex_hash, b" ").context(StrContext::Expected("<new-hexsha>".into())),
142142
gix_actor::signature::decode.context(StrContext::Expected("<name> <<email>> <timestamp>".into())),
143143
)
144144
.context(StrContext::Expected(
145145
"<old-hexsha> <new-hexsha> <name> <<email>> <timestamp> <tz>\\t<message>".into(),
146-
)),
147-
alt((
148-
preceded(
149-
b'\t',
150-
message.context(StrContext::Expected("<optional message>".into())),
151-
),
152-
b'\n'.value(Default::default()),
153-
eof.value(Default::default()),
154-
fail.context(StrContext::Expected(
155-
"log message must be separated from signature with whitespace".into(),
156-
)),
157-
)),
158-
)
159-
.map(|((old, new, signature), message)| LineRef {
146+
))
147+
.parse_next(&mut first)?;
148+
149+
let message = message(&mut second)?;
150+
// forward the buffer🤦‍♂️
151+
rest.parse_next(bytes)?;
152+
Ok(LineRef {
160153
previous_oid: old,
161154
new_oid: new,
162155
signature,
163156
message,
164157
})
165-
.parse_next(bytes)
158+
} else {
159+
(
160+
(
161+
terminated(hex_hash, b" ").context(StrContext::Expected("<old-hexsha>".into())),
162+
terminated(hex_hash, b" ").context(StrContext::Expected("<new-hexsha>".into())),
163+
gix_actor::signature::decode.context(StrContext::Expected("<name> <<email>> <timestamp>".into())),
164+
)
165+
.context(StrContext::Expected(
166+
"<old-hexsha> <new-hexsha> <name> <<email>> <timestamp> <tz>\\t<message>".into(),
167+
)),
168+
alt((
169+
preceded(
170+
b'\t',
171+
message.context(StrContext::Expected("<optional message>".into())),
172+
),
173+
b'\n'.value(Default::default()),
174+
eof.value(Default::default()),
175+
fail.context(StrContext::Expected(
176+
"log message must be separated from signature with whitespace".into(),
177+
)),
178+
)),
179+
)
180+
.map(|((old, new, signature), message)| LineRef {
181+
previous_oid: old,
182+
new_oid: new,
183+
signature,
184+
message,
185+
})
186+
.parse_next(bytes)
187+
}
166188
}
167189

168190
#[cfg(test)]

gix-ref/tests/refs/file/log.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ mod iter {
221221

222222
let mut iter = gix_ref::file::log::iter::forward(log_first_broken.as_bytes());
223223
let err = iter.next().expect("error is not none").expect_err("the line is broken");
224-
assert_eq!(err.to_string(), "In line 1: \"134385fbroken7062102c6a483440bfda2a03 committer <[email protected]> 946771200 +0000\\tcommit\" did not match '<old-hexsha> <new-hexsha> <name> <<email>> <timestamp> <tz>\\t<message>'");
224+
assert_eq!(err.to_string(), "In line 1: \"0000000000000000000000000000000000000000 134385fbroken7062102c6a483440bfda2a03 committer <[email protected]> 946771200 +0000\\tcommit\" did not match '<old-hexsha> <new-hexsha> <name> <<email>> <timestamp> <tz>\\t<message>'");
225225
assert!(iter.next().expect("a second line").is_ok(), "line parses ok");
226226
assert!(iter.next().is_none(), "iterator exhausted");
227227
}

0 commit comments

Comments
 (0)