summaryrefslogtreecommitdiffstats
path: root/vendor/gix-actor
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-actor')
-rw-r--r--vendor/gix-actor/.cargo-checksum.json1
-rw-r--r--vendor/gix-actor/Cargo.toml81
-rw-r--r--vendor/gix-actor/src/lib.rs45
-rw-r--r--vendor/gix-actor/src/signature/decode.rs159
-rw-r--r--vendor/gix-actor/src/signature/mod.rs136
5 files changed, 422 insertions, 0 deletions
diff --git a/vendor/gix-actor/.cargo-checksum.json b/vendor/gix-actor/.cargo-checksum.json
new file mode 100644
index 000000000..722a61e21
--- /dev/null
+++ b/vendor/gix-actor/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"09f0d7585b773608c4209e13eb877201036010f9d005789fc35e49f7655ac940","src/lib.rs":"b5de3d3c223fa9423386353b077ac179d6a27358d14b04b0be625f46b1f16794","src/signature/decode.rs":"68d44b6c899dc19da3d7a327b26fc50bfe612a7c34216fb51ae52e8e72247e67","src/signature/mod.rs":"861191a680568abeaa79d9989f01eb249cad1e360a8824464cf8974502d929a8"},"package":"dc22b0cdc52237667c301dd7cdc6ead8f8f73c9f824e9942c8ebd6b764f6c0bf"} \ No newline at end of file
diff --git a/vendor/gix-actor/Cargo.toml b/vendor/gix-actor/Cargo.toml
new file mode 100644
index 000000000..b4585ce58
--- /dev/null
+++ b/vendor/gix-actor/Cargo.toml
@@ -0,0 +1,81 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2021"
+rust-version = "1.64"
+name = "gix-actor"
+version = "0.19.0"
+authors = ["Sebastian Thiel <sebastian.thiel@icloud.com>"]
+include = ["src/**/*"]
+description = "A way to identify git actors"
+license = "MIT/Apache-2.0"
+repository = "https://github.com/Byron/gitoxide"
+
+[package.metadata.docs.rs]
+all-features = true
+features = ["document-features"]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[lib]
+doctest = false
+
+[dependencies.bstr]
+version = "1.3.0"
+features = [
+ "std",
+ "unicode",
+]
+default-features = false
+
+[dependencies.btoi]
+version = "0.4.2"
+
+[dependencies.document-features]
+version = "0.2.0"
+optional = true
+
+[dependencies.gix-date]
+version = "^0.4.3"
+
+[dependencies.gix-features]
+version = "^0.28.0"
+optional = true
+
+[dependencies.itoa]
+version = "1.0.1"
+
+[dependencies.nom]
+version = "7"
+features = ["std"]
+default-features = false
+
+[dependencies.serde]
+version = "1.0.114"
+features = ["derive"]
+optional = true
+default-features = false
+
+[dependencies.thiserror]
+version = "1.0.38"
+
+[dev-dependencies.pretty_assertions]
+version = "1.0.0"
+
+[features]
+serde1 = [
+ "serde",
+ "bstr/serde",
+ "gix-date/serde1",
+]
diff --git a/vendor/gix-actor/src/lib.rs b/vendor/gix-actor/src/lib.rs
new file mode 100644
index 000000000..182f0beee
--- /dev/null
+++ b/vendor/gix-actor/src/lib.rs
@@ -0,0 +1,45 @@
+//! This crate provides ways of identifying an actor within the git repository both in shared/mutable and mutable variants.
+//!
+//! ## Feature Flags
+#![cfg_attr(
+ feature = "document-features",
+ cfg_attr(doc, doc = ::document_features::document_features!())
+)]
+#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
+#![deny(missing_docs, rust_2018_idioms)]
+#![forbid(unsafe_code)]
+
+use bstr::{BStr, BString};
+pub use gix_date::{time::Sign, Time};
+
+///
+pub mod signature;
+
+/// A mutable signature is created by an actor at a certain time.
+///
+/// Note that this is not a cryptographical signature.
+#[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
+#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
+pub struct Signature {
+ /// The actors name.
+ pub name: BString,
+ /// The actor's email.
+ pub email: BString,
+ /// The time stamp at which the signature is performed.
+ pub time: Time,
+}
+
+/// A immutable signature is created by an actor at a certain time.
+///
+/// Note that this is not a cryptographical signature.
+#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy, Default)]
+#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
+pub struct SignatureRef<'a> {
+ /// The actor's name.
+ #[cfg_attr(feature = "serde1", serde(borrow))]
+ pub name: &'a BStr,
+ /// The actor's email.
+ pub email: &'a BStr,
+ /// The time stamp at which the signature was performed.
+ pub time: gix_date::Time,
+}
diff --git a/vendor/gix-actor/src/signature/decode.rs b/vendor/gix-actor/src/signature/decode.rs
new file mode 100644
index 000000000..5483d1651
--- /dev/null
+++ b/vendor/gix-actor/src/signature/decode.rs
@@ -0,0 +1,159 @@
+use bstr::ByteSlice;
+use btoi::btoi;
+use nom::{
+ branch::alt,
+ bytes::complete::{tag, take, take_until, take_while_m_n},
+ character::is_digit,
+ error::{context, ContextError, ParseError},
+ sequence::{terminated, tuple},
+ IResult,
+};
+
+use crate::{Sign, SignatureRef, Time};
+
+const SPACE: &[u8] = b" ";
+
+/// Parse a signature from the bytes input `i` using `nom`.
+pub fn decode<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(
+ i: &'a [u8],
+) -> IResult<&'a [u8], SignatureRef<'a>, E> {
+ let (i, (name, email, time, tzsign, hours, minutes)) = context(
+ "<name> <<email>> <timestamp> <+|-><HHMM>",
+ tuple((
+ context("<name>", terminated(take_until(&b" <"[..]), take(2usize))),
+ context("<email>", terminated(take_until(&b"> "[..]), take(2usize))),
+ context("<timestamp>", |i| {
+ terminated(take_until(SPACE), take(1usize))(i).and_then(|(i, v)| {
+ btoi::<u32>(v)
+ .map(|v| (i, v))
+ .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes)))
+ })
+ }),
+ context("+|-", alt((tag(b"-"), tag(b"+")))),
+ context("HH", |i| {
+ take_while_m_n(2usize, 2, is_digit)(i).and_then(|(i, v)| {
+ btoi::<i32>(v)
+ .map(|v| (i, v))
+ .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes)))
+ })
+ }),
+ context("MM", |i| {
+ take_while_m_n(2usize, 2, is_digit)(i).and_then(|(i, v)| {
+ btoi::<i32>(v)
+ .map(|v| (i, v))
+ .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes)))
+ })
+ }),
+ )),
+ )(i)?;
+
+ debug_assert!(tzsign[0] == b'-' || tzsign[0] == b'+', "parser assure it's +|- only");
+ let sign = if tzsign[0] == b'-' { Sign::Minus } else { Sign::Plus }; //
+ let offset = (hours * 3600 + minutes * 60) * if sign == Sign::Minus { -1 } else { 1 };
+
+ Ok((
+ i,
+ SignatureRef {
+ name: name.as_bstr(),
+ email: email.as_bstr(),
+ time: Time {
+ seconds_since_unix_epoch: time,
+ offset_in_seconds: offset,
+ sign,
+ },
+ },
+ ))
+}
+
+#[cfg(test)]
+mod tests {
+ mod parse_signature {
+ use bstr::ByteSlice;
+ use gix_testtools::to_bstr_err;
+ use nom::IResult;
+
+ use crate::{signature, Sign, SignatureRef, Time};
+
+ fn decode(i: &[u8]) -> IResult<&[u8], SignatureRef<'_>, nom::error::VerboseError<&[u8]>> {
+ signature::decode(i)
+ }
+
+ fn signature(
+ name: &'static str,
+ email: &'static str,
+ time: u32,
+ sign: Sign,
+ offset: i32,
+ ) -> SignatureRef<'static> {
+ SignatureRef {
+ name: name.as_bytes().as_bstr(),
+ email: email.as_bytes().as_bstr(),
+ time: Time {
+ seconds_since_unix_epoch: time,
+ offset_in_seconds: offset,
+ sign,
+ },
+ }
+ }
+
+ #[test]
+ fn tz_minus() {
+ assert_eq!(
+ decode(b"Sebastian Thiel <byronimo@gmail.com> 1528473343 -0230")
+ .expect("parse to work")
+ .1,
+ signature("Sebastian Thiel", "byronimo@gmail.com", 1528473343, Sign::Minus, -9000)
+ );
+ }
+
+ #[test]
+ fn tz_plus() {
+ assert_eq!(
+ decode(b"Sebastian Thiel <byronimo@gmail.com> 1528473343 +0230")
+ .expect("parse to work")
+ .1,
+ signature("Sebastian Thiel", "byronimo@gmail.com", 1528473343, Sign::Plus, 9000)
+ );
+ }
+
+ #[test]
+ fn negative_offset_0000() {
+ assert_eq!(
+ decode(b"Sebastian Thiel <byronimo@gmail.com> 1528473343 -0000")
+ .expect("parse to work")
+ .1,
+ signature("Sebastian Thiel", "byronimo@gmail.com", 1528473343, Sign::Minus, 0)
+ );
+ }
+
+ #[test]
+ fn empty_name_and_email() {
+ assert_eq!(
+ decode(b" <> 12345 -1215").expect("parse to work").1,
+ signature("", "", 12345, Sign::Minus, -44100)
+ );
+ }
+
+ #[test]
+ fn invalid_signature() {
+ assert_eq!(
+ decode(b"hello < 12345 -1215")
+ .map_err(to_bstr_err)
+ .expect_err("parse fails as > is missing")
+ .to_string(),
+ "Parse error:\nTakeUntil at: 12345 -1215\nin section '<email>', at: 12345 -1215\nin section '<name> <<email>> <timestamp> <+|-><HHMM>', at: hello < 12345 -1215\n"
+ );
+ }
+
+ #[test]
+ fn invalid_time() {
+ assert_eq!(
+ decode(b"hello <> abc -1215")
+ .map_err(to_bstr_err)
+ .expect_err("parse fails as > is missing")
+ .to_string(),
+ "Parse error:\nMapRes at: -1215\nin section '<timestamp>', at: abc -1215\nin section '<name> <<email>> <timestamp> <+|-><HHMM>', at: hello <> abc -1215\n"
+ );
+ }
+ }
+}
diff --git a/vendor/gix-actor/src/signature/mod.rs b/vendor/gix-actor/src/signature/mod.rs
new file mode 100644
index 000000000..fa5fb8470
--- /dev/null
+++ b/vendor/gix-actor/src/signature/mod.rs
@@ -0,0 +1,136 @@
+mod _ref {
+ use bstr::{BStr, ByteSlice};
+
+ use crate::{signature::decode, Signature, SignatureRef};
+
+ impl<'a> SignatureRef<'a> {
+ /// Deserialize a signature from the given `data`.
+ pub fn from_bytes<E>(data: &'a [u8]) -> Result<SignatureRef<'a>, nom::Err<E>>
+ where
+ E: nom::error::ParseError<&'a [u8]> + nom::error::ContextError<&'a [u8]>,
+ {
+ decode(data).map(|(_, t)| t)
+ }
+
+ /// Create an owned instance from this shared one.
+ pub fn to_owned(&self) -> Signature {
+ Signature {
+ name: self.name.to_owned(),
+ email: self.email.to_owned(),
+ time: self.time,
+ }
+ }
+
+ /// Trim whitespace surrounding the name and email and return a new signature.
+ pub fn trim(&self) -> SignatureRef<'a> {
+ SignatureRef {
+ name: self.name.trim().as_bstr(),
+ email: self.email.trim().as_bstr(),
+ time: self.time,
+ }
+ }
+
+ /// Return the actor's name and email, effectively excluding the time stamp of this signature.
+ pub fn actor(&self) -> (&BStr, &BStr) {
+ (self.name, self.email)
+ }
+ }
+}
+
+mod convert {
+ use crate::{Signature, SignatureRef};
+
+ impl Signature {
+ /// An empty signature, similar to 'null'.
+ pub fn empty() -> Self {
+ Signature::default()
+ }
+
+ /// Borrow this instance as immutable
+ pub fn to_ref(&self) -> SignatureRef<'_> {
+ SignatureRef {
+ name: self.name.as_ref(),
+ email: self.email.as_ref(),
+ time: self.time,
+ }
+ }
+ }
+
+ impl From<SignatureRef<'_>> for Signature {
+ fn from(other: SignatureRef<'_>) -> Signature {
+ let SignatureRef { name, email, time } = other;
+ Signature {
+ name: name.to_owned(),
+ email: email.to_owned(),
+ time,
+ }
+ }
+ }
+
+ impl<'a> From<&'a Signature> for SignatureRef<'a> {
+ fn from(other: &'a Signature) -> SignatureRef<'a> {
+ other.to_ref()
+ }
+ }
+}
+
+mod write {
+ use std::io;
+
+ use bstr::{BStr, ByteSlice};
+
+ use crate::{Signature, SignatureRef};
+
+ /// The Error produced by [`Signature::write_to()`].
+ #[derive(Debug, thiserror::Error)]
+ #[allow(missing_docs)]
+ enum Error {
+ #[error("Signature name or email must not contain '<', '>' or \\n")]
+ IllegalCharacter,
+ }
+
+ impl From<Error> for io::Error {
+ fn from(err: Error) -> Self {
+ io::Error::new(io::ErrorKind::Other, err)
+ }
+ }
+
+ /// Output
+ impl Signature {
+ /// Serialize this instance to `out` in the git serialization format for actors.
+ pub fn write_to(&self, out: impl io::Write) -> io::Result<()> {
+ self.to_ref().write_to(out)
+ }
+ /// Computes the number of bytes necessary to serialize this signature
+ pub fn size(&self) -> usize {
+ self.to_ref().size()
+ }
+ }
+
+ impl<'a> SignatureRef<'a> {
+ /// Serialize this instance to `out` in the git serialization format for actors.
+ pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> {
+ out.write_all(validated_token(self.name)?)?;
+ out.write_all(b" ")?;
+ out.write_all(b"<")?;
+ out.write_all(validated_token(self.email)?)?;
+ out.write_all(b"> ")?;
+ self.time.write_to(out)
+ }
+ /// Computes the number of bytes necessary to serialize this signature
+ pub fn size(&self) -> usize {
+ self.name.len() + 2 /* space <*/ + self.email.len() + 2 /* > space */ + self.time.size()
+ }
+ }
+
+ fn validated_token(name: &BStr) -> Result<&BStr, Error> {
+ if name.find_byteset(b"<>\n").is_some() {
+ return Err(Error::IllegalCharacter);
+ }
+ Ok(name)
+ }
+}
+
+///
+mod decode;
+pub use decode::decode;