summaryrefslogtreecommitdiffstats
path: root/vendor/git2/src/signature.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/git2/src/signature.rs
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/git2/src/signature.rs')
-rw-r--r--vendor/git2/src/signature.rs189
1 files changed, 189 insertions, 0 deletions
diff --git a/vendor/git2/src/signature.rs b/vendor/git2/src/signature.rs
new file mode 100644
index 000000000..83fbbf593
--- /dev/null
+++ b/vendor/git2/src/signature.rs
@@ -0,0 +1,189 @@
+use libc;
+use std::ffi::CString;
+use std::fmt;
+use std::marker;
+use std::mem;
+use std::ptr;
+use std::str;
+
+use crate::util::Binding;
+use crate::{raw, Error, Time};
+
+/// A Signature is used to indicate authorship of various actions throughout the
+/// library.
+///
+/// Signatures contain a name, email, and timestamp. All fields can be specified
+/// with `new` while the `now` constructor omits the timestamp. The
+/// [`Repository::signature`] method can be used to create a default signature
+/// with name and email values read from the configuration.
+///
+/// [`Repository::signature`]: struct.Repository.html#method.signature
+pub struct Signature<'a> {
+ raw: *mut raw::git_signature,
+ _marker: marker::PhantomData<&'a str>,
+ owned: bool,
+}
+
+impl<'a> Signature<'a> {
+ /// Create a new action signature with a timestamp of 'now'.
+ ///
+ /// See `new` for more information
+ pub fn now(name: &str, email: &str) -> Result<Signature<'static>, Error> {
+ crate::init();
+ let mut ret = ptr::null_mut();
+ let name = CString::new(name)?;
+ let email = CString::new(email)?;
+ unsafe {
+ try_call!(raw::git_signature_now(&mut ret, name, email));
+ Ok(Binding::from_raw(ret))
+ }
+ }
+
+ /// Create a new action signature.
+ ///
+ /// The `time` specified is in seconds since the epoch, and the `offset` is
+ /// the time zone offset in minutes.
+ ///
+ /// Returns error if either `name` or `email` contain angle brackets.
+ pub fn new(name: &str, email: &str, time: &Time) -> Result<Signature<'static>, Error> {
+ crate::init();
+ let mut ret = ptr::null_mut();
+ let name = CString::new(name)?;
+ let email = CString::new(email)?;
+ unsafe {
+ try_call!(raw::git_signature_new(
+ &mut ret,
+ name,
+ email,
+ time.seconds() as raw::git_time_t,
+ time.offset_minutes() as libc::c_int
+ ));
+ Ok(Binding::from_raw(ret))
+ }
+ }
+
+ /// Gets the name on the signature.
+ ///
+ /// Returns `None` if the name is not valid utf-8
+ pub fn name(&self) -> Option<&str> {
+ str::from_utf8(self.name_bytes()).ok()
+ }
+
+ /// Gets the name on the signature as a byte slice.
+ pub fn name_bytes(&self) -> &[u8] {
+ unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() }
+ }
+
+ /// Gets the email on the signature.
+ ///
+ /// Returns `None` if the email is not valid utf-8
+ pub fn email(&self) -> Option<&str> {
+ str::from_utf8(self.email_bytes()).ok()
+ }
+
+ /// Gets the email on the signature as a byte slice.
+ pub fn email_bytes(&self) -> &[u8] {
+ unsafe { crate::opt_bytes(self, (*self.raw).email).unwrap() }
+ }
+
+ /// Get the `when` of this signature.
+ pub fn when(&self) -> Time {
+ unsafe { Binding::from_raw((*self.raw).when) }
+ }
+
+ /// Convert a signature of any lifetime into an owned signature with a
+ /// static lifetime.
+ pub fn to_owned(&self) -> Signature<'static> {
+ unsafe {
+ let me = mem::transmute::<&Signature<'a>, &Signature<'static>>(self);
+ me.clone()
+ }
+ }
+}
+
+impl<'a> Binding for Signature<'a> {
+ type Raw = *mut raw::git_signature;
+ unsafe fn from_raw(raw: *mut raw::git_signature) -> Signature<'a> {
+ Signature {
+ raw,
+ _marker: marker::PhantomData,
+ owned: true,
+ }
+ }
+ fn raw(&self) -> *mut raw::git_signature {
+ self.raw
+ }
+}
+
+/// Creates a new signature from the give raw pointer, tied to the lifetime
+/// of the given object.
+///
+/// This function is unsafe as there is no guarantee that `raw` is valid for
+/// `'a` nor if it's a valid pointer.
+pub unsafe fn from_raw_const<'b, T>(_lt: &'b T, raw: *const raw::git_signature) -> Signature<'b> {
+ Signature {
+ raw: raw as *mut raw::git_signature,
+ _marker: marker::PhantomData,
+ owned: false,
+ }
+}
+
+impl Clone for Signature<'static> {
+ fn clone(&self) -> Signature<'static> {
+ // TODO: can this be defined for 'a and just do a plain old copy if the
+ // lifetime isn't static?
+ let mut raw = ptr::null_mut();
+ let rc = unsafe { raw::git_signature_dup(&mut raw, &*self.raw) };
+ assert_eq!(rc, 0);
+ unsafe { Binding::from_raw(raw) }
+ }
+}
+
+impl<'a> Drop for Signature<'a> {
+ fn drop(&mut self) {
+ if self.owned {
+ unsafe { raw::git_signature_free(self.raw) }
+ }
+ }
+}
+
+impl<'a> fmt::Display for Signature<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{} <{}>",
+ String::from_utf8_lossy(self.name_bytes()),
+ String::from_utf8_lossy(self.email_bytes())
+ )
+ }
+}
+
+impl PartialEq for Signature<'_> {
+ fn eq(&self, other: &Self) -> bool {
+ self.when() == other.when()
+ && self.email_bytes() == other.email_bytes()
+ && self.name_bytes() == other.name_bytes()
+ }
+}
+
+impl Eq for Signature<'_> {}
+
+#[cfg(test)]
+mod tests {
+ use crate::{Signature, Time};
+
+ #[test]
+ fn smoke() {
+ Signature::new("foo", "bar", &Time::new(89, 0)).unwrap();
+ Signature::now("foo", "bar").unwrap();
+ assert!(Signature::new("<foo>", "bar", &Time::new(89, 0)).is_err());
+ assert!(Signature::now("<foo>", "bar").is_err());
+
+ let s = Signature::now("foo", "bar").unwrap();
+ assert_eq!(s.name(), Some("foo"));
+ assert_eq!(s.email(), Some("bar"));
+
+ drop(s.clone());
+ drop(s.to_owned());
+ }
+}