forge
ExploreLog in

Tahinli/forge

public
0 watching
★ 0
3.3 KiB
1//! Pull request reviews and line comments. The stored shape is in migrations/0008_reviews.sql;
2//! the store functions live in store/reviews.rs.
3
4use crate::error::{Error, Result};
5use crate::model::Id;
6
7/// State of a review. `Pending` is a draft visible only to its author.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ReviewState {
10 Pending,
11 Commented,
12 Approved,
13 ChangesRequested,
14 Dismissed,
15}
16
17impl ReviewState {
18 pub fn as_str(&self) -> &'static str {
19 match self {
20 ReviewState::Pending => "pending",
21 ReviewState::Commented => "commented",
22 ReviewState::Approved => "approved",
23 ReviewState::ChangesRequested => "changes_requested",
24 ReviewState::Dismissed => "dismissed",
25 }
26 }
27}
28
29impl std::str::FromStr for ReviewState {
30 type Err = Error;
31
32 fn from_str(s: &str) -> Result<Self> {
33 match s {
34 "pending" => Ok(ReviewState::Pending),
35 "commented" => Ok(ReviewState::Commented),
36 "approved" => Ok(ReviewState::Approved),
37 "changes_requested" => Ok(ReviewState::ChangesRequested),
38 "dismissed" => Ok(ReviewState::Dismissed),
39 other => Err(Error::Invalid(format!("review state {other:?}"))),
40 }
41 }
42}
43
44/// Which side of the diff a comment is on: `Old` for deleted lines, `New` for added and context
45/// lines.
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
47pub enum Side {
48 Old,
49 New,
50}
51
52impl Side {
53 pub fn as_str(&self) -> &'static str {
54 match self {
55 Side::Old => "old",
56 Side::New => "new",
57 }
58 }
59}
60
61impl std::str::FromStr for Side {
62 type Err = Error;
63
64 fn from_str(s: &str) -> Result<Self> {
65 match s {
66 "old" => Ok(Side::Old),
67 "new" => Ok(Side::New),
68 other => Err(Error::Invalid(format!("diff side {other:?}"))),
69 }
70 }
71}
72
73#[derive(Debug, Clone, PartialEq)]
74pub struct Review {
75 pub id: Id,
76 pub issue_id: Id,
77 pub author_id: Id,
78 pub author_name: String,
79 pub state: ReviewState,
80 pub body: String,
81 pub commit_oid: String,
82 pub dismissed_reason: Option<String>,
83 /// The state the review had before it was dismissed (`Approved` or `ChangesRequested`). None
84 /// for reviews dismissed before this was recorded, and for reviews that were not dismissed.
85 pub dismissed_from: Option<ReviewState>,
86 pub created_at: String,
87 pub submitted_at: Option<String>,
88}
89
90#[derive(Debug, Clone, PartialEq)]
91pub struct ReviewComment {
92 pub id: Id,
93 pub review_id: Id,
94 pub author_id: Id,
95 pub author_name: String,
96 pub path: String,
97 pub side: Side,
98 pub line: u32,
99 pub commit_oid: String,
100 pub diff_hunk: String,
101 pub reply_to: Option<Id>,
102 pub body: String,
103 pub outdated: bool,
104 pub resolved: bool,
105 pub created_at: String,
106 pub updated_at: String,
107 /// True when the review this comment belongs to is still pending.
108 pub pending: bool,
109}
110
111/// A root comment and its replies, oldest first.
112#[derive(Debug, Clone, PartialEq)]
113pub struct Thread {
114 pub root: ReviewComment,
115 pub replies: Vec<ReviewComment>,
116}
117
118/// Who currently approves and who requests changes, by username.
119#[derive(Debug, Clone, Default, PartialEq, Eq)]
120pub struct ReviewSummary {
121 pub approved_by: Vec<String>,
122 pub changes_requested_by: Vec<String>,
123}