//! Pull request reviews and line comments. The stored shape is in migrations/0008_reviews.sql; //! the store functions live in store/reviews.rs. use crate::error::{Error, Result}; use crate::model::Id; /// State of a review. `Pending` is a draft visible only to its author. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ReviewState { Pending, Commented, Approved, ChangesRequested, Dismissed, } impl ReviewState { pub fn as_str(&self) -> &'static str { match self { ReviewState::Pending => "pending", ReviewState::Commented => "commented", ReviewState::Approved => "approved", ReviewState::ChangesRequested => "changes_requested", ReviewState::Dismissed => "dismissed", } } } impl std::str::FromStr for ReviewState { type Err = Error; fn from_str(s: &str) -> Result { match s { "pending" => Ok(ReviewState::Pending), "commented" => Ok(ReviewState::Commented), "approved" => Ok(ReviewState::Approved), "changes_requested" => Ok(ReviewState::ChangesRequested), "dismissed" => Ok(ReviewState::Dismissed), other => Err(Error::Invalid(format!("review state {other:?}"))), } } } /// Which side of the diff a comment is on: `Old` for deleted lines, `New` for added and context /// lines. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Side { Old, New, } impl Side { pub fn as_str(&self) -> &'static str { match self { Side::Old => "old", Side::New => "new", } } } impl std::str::FromStr for Side { type Err = Error; fn from_str(s: &str) -> Result { match s { "old" => Ok(Side::Old), "new" => Ok(Side::New), other => Err(Error::Invalid(format!("diff side {other:?}"))), } } } #[derive(Debug, Clone, PartialEq)] pub struct Review { pub id: Id, pub issue_id: Id, pub author_id: Id, pub author_name: String, pub state: ReviewState, pub body: String, pub commit_oid: String, pub dismissed_reason: Option, /// The state the review had before it was dismissed (`Approved` or `ChangesRequested`). None /// for reviews dismissed before this was recorded, and for reviews that were not dismissed. pub dismissed_from: Option, pub created_at: String, pub submitted_at: Option, } #[derive(Debug, Clone, PartialEq)] pub struct ReviewComment { pub id: Id, pub review_id: Id, pub author_id: Id, pub author_name: String, pub path: String, pub side: Side, pub line: u32, pub commit_oid: String, pub diff_hunk: String, pub reply_to: Option, pub body: String, pub outdated: bool, pub resolved: bool, pub created_at: String, pub updated_at: String, /// True when the review this comment belongs to is still pending. pub pending: bool, } /// A root comment and its replies, oldest first. #[derive(Debug, Clone, PartialEq)] pub struct Thread { pub root: ReviewComment, pub replies: Vec, } /// Who currently approves and who requests changes, by username. #[derive(Debug, Clone, Default, PartialEq, Eq)] pub struct ReviewSummary { pub approved_by: Vec, pub changes_requested_by: Vec, }