Skip to main content

AuthorId

Struct AuthorId 

Source
pub struct AuthorId { /* private fields */ }
Available on crate feature vcs-git only.
Expand description

A canonical author identity, keyed by lowercased email.

Falls back to the lowercased display name when the email is empty (some imported histories carry name-only authors). Compared and hashed by that key so author counts and ownership are stable across display-name variation.

The key is normally the plaintext canonical email; a from_digest identity instead holds the SHA-256 digest, used when an identity is reconstructed from the persistent VCS cache (issue #334), which never stores plaintext author keys on disk. Both forms share the same equality/hashing contract — distinct-author counts and ownership ratios are preserved either way because the digest is collision-free over the author set in practice (SHA-256 of distinct emails yields distinct hashes) — and within any one walk every identity is of the same form, so the is_digest flag never makes two keys-for-the-same-person compare unequal.

Implementations§

Source§

impl AuthorId

Source

pub fn new(name: &[u8], email: &[u8]) -> Self

Build a canonical identity from raw signature bytes.

Bytes are interpreted lossily as UTF-8: an identity is a map key and a hash pre-image, never re-emitted as a path, so a stray non-UTF-8 byte degrading to U+FFFD is acceptable and keeps the function total.

Source

pub fn has_identity(&self) -> bool

Whether this identity carries a usable key.

An author with neither a name nor an email trims to the empty key, which would otherwise collapse every keyless author into one phantom identity (the same Eq/Hash). Callers building a participant set drop keyless identities so they never anchor ownership or inflate edit counts (issue #817). A from_digest identity is never keyless (a SHA-256 hex is non-empty).

Source

pub fn from_digest(digest: String) -> Self

Reconstruct an identity from a previously-emitted SHA-256 hashed digest. The persistent VCS cache stores authors in this hashed form (never plaintext — see hashed for what that does and does not protect), and replaying it must reproduce the same author counts, ownership, and emitted hashes as a fresh walk — so a from_digest identity hashes to itself.

Source

pub fn hashed(&self) -> String

SHA-256 hex digest of the canonical key, for --emit-author-details. Stable across runs, so the same author carries the same pseudonym in every report and survives a cache round-trip.

§Privacy: pseudonym, not anonymization

The digest avoids emitting the plaintext email and deters casual disclosure, but it is not cryptographically irreversible. The pre-image is an email — low-entropy and enumerable — and commit histories are public, so an attacker with a candidate set of emails can recover the mapping by hashing each candidate or with a precomputed email→hash table (the Gravatar weakness). Treat published digests as pseudonymization that keeps plaintext emails out of output and caches, not as robust anonymization against a determined attacker. Hardening (a keyed HMAC / slow KDF) is tracked as a follow-up; it must be reconciled with the issue-#334 cache-replay invariant that replaying reproduces identical digests.

A from_digest identity already is the digest, so it is returned unchanged (re-hashing would double-hash and diverge from a fresh walk).

Source

pub fn emit_hashed(&self, key: Option<&AuthorHashKey>) -> String

The author digest emitted for --emit-author-details, optionally hardened with a caller-supplied AuthorHashKey.

Without a key this is exactly hashed — the bare SHA-256 — so default output is unchanged. With a key it is HMAC-SHA256(key, hashed_hex): an attacker holding a candidate set of emails can no longer recover the mapping by hashing each candidate, nor with a precomputed email→hash table (the Gravatar weakness hashed documents), because computing the digest for any candidate now requires the secret key they do not hold.

Keying the inner digest rather than the raw email is what preserves the issue-#334 cache-replay invariant: the persistent cache stores the unkeyed inner SHA-256 (a from_digest identity is that digest), so replaying a cached walk under any key reproduces the same emitted value as a fresh walk, and the same cached walk can be re-finalized under a different key without re-walking. The trade-off is that the on-disk cache still holds the unkeyed digest; it is local-only and never published, matching the cache’s existing threat model.

Trait Implementations§

Source§

impl Clone for AuthorId

Source§

fn clone(&self) -> AuthorId

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AuthorId

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for AuthorId

Source§

impl Hash for AuthorId

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for AuthorId

Source§

fn eq(&self, other: &AuthorId) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for AuthorId

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.