-
-
Notifications
You must be signed in to change notification settings - Fork 399
fix!: store raw commit/tag actor headers and parse lazily (see #2177) #2253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,32 @@ use bstr::ByteSlice; | |
|
|
||
| use crate::{encode, encode::NL, Commit, CommitRef, Kind}; | ||
|
|
||
| fn parse_signature(raw: &bstr::BStr) -> gix_actor::SignatureRef<'_> { | ||
| gix_actor::SignatureRef::from_bytes::<()>(raw.as_ref()).expect("signatures were validated during parsing") | ||
| } | ||
|
|
||
| fn signature_requires_raw(raw: &bstr::BStr) -> bool { | ||
| let signature = parse_signature(raw); | ||
| signature.name.find_byteset(b"<>\n").is_some() || signature.email.find_byteset(b"<>\n").is_some() | ||
| } | ||
|
|
||
| fn signature_len(raw: &bstr::BStr) -> usize { | ||
| if signature_requires_raw(raw) { | ||
| raw.len() | ||
| } else { | ||
| parse_signature(raw).size() | ||
| } | ||
| } | ||
|
|
||
| fn write_signature(mut out: &mut dyn io::Write, field: &[u8], raw: &bstr::BStr) -> io::Result<()> { | ||
| if signature_requires_raw(raw) { | ||
|
||
| encode::trusted_header_field(field, raw.as_ref(), &mut out) | ||
| } else { | ||
| let signature = parse_signature(raw); | ||
| encode::trusted_header_signature(field, &signature, &mut out) | ||
| } | ||
| } | ||
|
|
||
| impl crate::WriteTo for Commit { | ||
| /// Serializes this instance to `out` in the git serialization format. | ||
| fn write_to(&self, mut out: &mut dyn io::Write) -> io::Result<()> { | ||
|
|
@@ -58,8 +84,8 @@ impl crate::WriteTo for CommitRef<'_> { | |
| for parent in self.parents() { | ||
| encode::trusted_header_id(b"parent", &parent, &mut out)?; | ||
| } | ||
| encode::trusted_header_signature(b"author", &self.author, &mut out)?; | ||
| encode::trusted_header_signature(b"committer", &self.committer, &mut out)?; | ||
| write_signature(&mut out, b"author", self.author)?; | ||
| write_signature(&mut out, b"committer", self.committer)?; | ||
| if let Some(encoding) = self.encoding.as_ref() { | ||
| encode::header_field(b"encoding", encoding, &mut out)?; | ||
| } | ||
|
|
@@ -78,8 +104,8 @@ impl crate::WriteTo for CommitRef<'_> { | |
| let hash_in_hex = self.tree().kind().len_in_hex(); | ||
| (b"tree".len() + 1 /* space */ + hash_in_hex + 1 /* nl */ | ||
| + self.parents.iter().count() * (b"parent".len() + 1 /* space */ + hash_in_hex + 1 /* nl */) | ||
| + b"author".len() + 1 /* space */ + self.author.size() + 1 /* nl */ | ||
| + b"committer".len() + 1 /* space */ + self.committer.size() + 1 /* nl */ | ||
| + b"author".len() + 1 /* space */ + signature_len(self.author) + 1 /* nl */ | ||
| + b"committer".len() + 1 /* space */ + signature_len(self.committer) + 1 /* nl */ | ||
| + self | ||
| .encoding | ||
| .as_ref() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,15 +7,20 @@ impl From<TagRef<'_>> for Tag { | |
| name, | ||
| target_kind, | ||
| message, | ||
| tagger: signature, | ||
| tagger, | ||
| pgp_signature, | ||
| } = other; | ||
| let tagger = tagger.map(|raw| { | ||
| gix_actor::SignatureRef::from_bytes::<()>(raw.as_ref()) | ||
| .expect("signatures were validated during parsing") | ||
|
||
| .into() | ||
| }); | ||
| Tag { | ||
| target: gix_hash::ObjectId::from_hex(target).expect("prior parser validation"), | ||
| name: name.to_owned(), | ||
| target_kind, | ||
| message: message.to_owned(), | ||
| tagger: signature.map(Into::into), | ||
| tagger, | ||
| pgp_signature: pgp_signature.map(ToOwned::to_owned), | ||
| } | ||
| } | ||
|
|
@@ -32,6 +37,10 @@ impl From<CommitRef<'_>> for Commit { | |
| message, | ||
| extra_headers, | ||
| } = other; | ||
| let author = gix_actor::SignatureRef::from_bytes::<()>(author.as_ref()) | ||
| .expect("signatures were validated during parsing"); | ||
| let committer = gix_actor::SignatureRef::from_bytes::<()>(committer.as_ref()) | ||
| .expect("signatures were validated during parsing"); | ||
| Commit { | ||
| tree: gix_hash::ObjectId::from_hex(tree).expect("prior parser validation"), | ||
| parents: parents | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,27 @@ | ||
| use std::io; | ||
|
|
||
| use bstr::BStr; | ||
| use bstr::{BStr, ByteSlice}; | ||
| use gix_date::parse::TimeBuf; | ||
|
|
||
| use crate::{encode, encode::NL, Kind, Tag, TagRef}; | ||
|
|
||
| fn parse_signature(raw: &BStr) -> gix_actor::SignatureRef<'_> { | ||
| gix_actor::SignatureRef::from_bytes::<()>(raw.as_ref()).expect("signatures were validated during parsing") | ||
| } | ||
|
|
||
| fn signature_requires_raw(raw: &BStr) -> bool { | ||
|
||
| let signature = parse_signature(raw); | ||
| signature.name.find_byteset(b"<>\n").is_some() || signature.email.find_byteset(b"<>\n").is_some() | ||
| } | ||
|
|
||
| fn signature_len(raw: &BStr) -> usize { | ||
| if signature_requires_raw(raw) { | ||
| raw.len() | ||
| } else { | ||
| parse_signature(raw).size() | ||
| } | ||
| } | ||
|
|
||
| /// An Error used in [`Tag::write_to()`][crate::WriteTo::write_to()]. | ||
| #[derive(Debug, thiserror::Error)] | ||
| #[allow(missing_docs)] | ||
|
|
@@ -64,8 +81,13 @@ impl crate::WriteTo for TagRef<'_> { | |
| encode::trusted_header_field(b"object", self.target, &mut out)?; | ||
| encode::trusted_header_field(b"type", self.target_kind.as_bytes(), &mut out)?; | ||
| encode::header_field(b"tag", validated_name(self.name)?, &mut out)?; | ||
| if let Some(tagger) = &self.tagger { | ||
| encode::trusted_header_signature(b"tagger", tagger, &mut out)?; | ||
| if let Some(tagger) = self.tagger { | ||
| if signature_requires_raw(tagger) { | ||
| encode::trusted_header_field(b"tagger", tagger.as_ref(), &mut out)?; | ||
| } else { | ||
| let signature = parse_signature(tagger); | ||
| encode::trusted_header_signature(b"tagger", &signature, &mut out)?; | ||
| } | ||
| } | ||
|
|
||
| if !self.message.iter().all(|b| *b == b'\n') { | ||
|
|
@@ -89,8 +111,7 @@ impl crate::WriteTo for TagRef<'_> { | |
| + b"tag".len() + 1 /* space */ + self.name.len() + 1 /* nl */ | ||
| + self | ||
| .tagger | ||
| .as_ref() | ||
| .map_or(0, |t| b"tagger".len() + 1 /* space */ + t.size() + 1 /* nl */) | ||
| .map_or(0, |raw| b"tagger".len() + 1 /* space */ + signature_len(raw) + 1 /* nl */) | ||
| + if self.message.iter().all(|b| *b == b'\n') { 0 } else { 1 /* nl */ } + self.message.len() | ||
| + self.pgp_signature.as_ref().map_or(0, |m| 1 /* nl */ + m.len())) as u64 | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These must be fallible, panics aren't allowed. It's OK to use the error type returned by
SignatureRef::from_bytes().