//! Plain data types shared by ingestion, storage and the static site. use serde::{Deserialize, Serialize}; /// What relationship an identity has to the person this service is about. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum IdentityKind { /// A handle the person speaks as: permadeath.com, lance.blue, ... Personal, /// An account on a GitHub installation. Github, /// An agent account operated through a didbot PDS. Bot, /// Anyone else seen in the global Tangled index. External, } impl IdentityKind { pub fn as_str(self) -> &'static str { match self { Self::Personal => "personal", Self::Github => "github", Self::Bot => "bot", Self::External => "external", } } pub fn parse(value: &str) -> Self { match value { "personal" => Self::Personal, "github" => Self::Github, "bot" => Self::Bot, _ => Self::External, } } } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Identity { pub did: String, pub handle: String, pub kind: IdentityKind, pub operator_did: Option, pub color: String, pub active: bool, /// The PDS this bot identity was discovered on, when applicable. pub pds: Option, /// Tangled collections present on the identity's repository, comma separated. pub collections: String, /// Last time the directory resolved this identity. pub checked_at: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Repo { pub repo_did: String, pub owner_did: String, pub name: String, pub knot: String, pub url: String, /// Optional public homepage. Used only to find a project favicon; never /// fetched by the server. pub website: Option, pub fork: bool, pub created_at: Option, pub active: bool, pub last_scanned: Option, pub last_error: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Branch { pub repo_did: String, pub name: String, pub head_sha: String, pub indexed: bool, /// The head an unfinished walk reads from, and how many commits of its /// log that walk has been through. pub walk_head: Option, pub walk_offset: u64, } /// One commit, as it should be counted. The SHA is the identity of the commit; /// a commit reachable from several branches or mirrored on two forges is still /// one row here. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Commit { pub sha: String, /// `Change-Id:` trailer when the commit carries one. atgc writes this, so a /// rebase keeps the same logical-change identity even though the SHA /// changes. pub change_id: String, /// Resolved DID or a stable GitHub identity key. Empty when no identity /// matched. pub author_did: String, pub author_email: String, pub author_name: String, /// RFC 3339, author date. This is the date a contribution graph should use; /// Tangled's committer date is the time of the push. pub authored_at: String, pub committed_at: String, pub message: String, } /// Extract a Gerrit-style `Change-Id:` trailer from a commit message. It may /// be followed by other trailers, so scan every line rather than assuming it /// is last. pub fn change_id_from_message(message: &str) -> String { for line in message.lines().rev() { if let Some(rest) = line.trim().strip_prefix("Change-Id:") { let value = rest.trim(); if !value.is_empty() { return value.to_string(); } } } String::new() } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CommitRef { pub sha: String, /// `tangled` or `github`. pub source: String, /// `tangled:` or `github:/`. pub repo_key: String, pub url: String, /// Seen on the repository's default branch: walked there by the Tangled /// or GitHub crawler, or marked so by the GitHub report script. pub on_default: bool, } #[derive(Debug, Clone, Copy, Default)] pub struct ScanReport { pub repos_seen: usize, pub repos_scanned: usize, pub repos_skipped: usize, pub repos_failed: usize, pub branches_seen: usize, pub branches_scanned: usize, pub commits_seen: usize, pub commits_new: usize, } impl ScanReport { pub fn merge(&mut self, other: Self) { self.repos_seen += other.repos_seen; self.repos_scanned += other.repos_scanned; self.repos_skipped += other.repos_skipped; self.repos_failed += other.repos_failed; self.branches_seen += other.branches_seen; self.branches_scanned += other.branches_scanned; self.commits_seen += other.commits_seen; self.commits_new += other.commits_new; } }