forge
ExploreLog in

Tahinli/forge

public
0 watching
★ 0
3.5 KiB
1//! Pull request types. A pull request is an issue with `kind = 'pull'` plus a `pull_requests`
2//! row. The stored shape is in migrations/0007_pulls.sql; the store functions live in
3//! store/pulls.rs.
4
5use crate::error::{Error, Result};
6use crate::issues::Issue;
7use crate::model::Id;
8
9/// Mergeability of a pull request, as last computed.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Mergeable {
12 Unknown,
13 Clean,
14 Conflict,
15 Merged,
16 UpToDate,
17}
18
19impl Mergeable {
20 pub fn as_str(&self) -> &'static str {
21 match self {
22 Mergeable::Unknown => "unknown",
23 Mergeable::Clean => "clean",
24 Mergeable::Conflict => "conflict",
25 Mergeable::Merged => "merged",
26 Mergeable::UpToDate => "up_to_date",
27 }
28 }
29}
30
31impl std::str::FromStr for Mergeable {
32 type Err = Error;
33
34 fn from_str(s: &str) -> Result<Self> {
35 match s {
36 "unknown" => Ok(Mergeable::Unknown),
37 "clean" => Ok(Mergeable::Clean),
38 "conflict" => Ok(Mergeable::Conflict),
39 "merged" => Ok(Mergeable::Merged),
40 "up_to_date" => Ok(Mergeable::UpToDate),
41 other => Err(Error::Invalid(format!("mergeable {other:?}"))),
42 }
43 }
44}
45
46#[derive(Debug, Clone, PartialEq)]
47pub struct PullRequest {
48 /// The backing issue row (`kind = 'pull'`): number, title, state, author and so on.
49 pub issue: Issue,
50 pub base_branch: String,
51 /// `None` once the head repo has been deleted.
52 pub head_repo_id: Option<Id>,
53 pub head_branch: String,
54 /// Last known head commit (also `refs/pull/N/head` in the base repo).
55 pub head_oid: String,
56 /// Base branch tip when mergeability was last computed.
57 pub base_oid: String,
58 pub merge_base: Option<String>,
59 pub mergeable: Mergeable,
60 pub conflict_files: Vec<String>,
61 pub merged_at: Option<String>,
62 pub merged_by: Option<Id>,
63 pub merge_commit: Option<String>,
64}
65
66/// How a pull request is merged into its base branch.
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum MergeStyle {
69 Merge,
70 Squash,
71 FastForward,
72}
73
74impl MergeStyle {
75 /// The value used in forms and URLs.
76 pub fn as_str(&self) -> &'static str {
77 match self {
78 MergeStyle::Merge => "merge",
79 MergeStyle::Squash => "squash",
80 MergeStyle::FastForward => "ff",
81 }
82 }
83}
84
85impl std::str::FromStr for MergeStyle {
86 type Err = Error;
87
88 fn from_str(s: &str) -> Result<Self> {
89 match s {
90 "merge" => Ok(MergeStyle::Merge),
91 "squash" => Ok(MergeStyle::Squash),
92 "ff" => Ok(MergeStyle::FastForward),
93 other => Err(Error::Invalid(format!("merge style {other:?}"))),
94 }
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn mergeable_round_trips() {
104 for m in [
105 Mergeable::Unknown,
106 Mergeable::Clean,
107 Mergeable::Conflict,
108 Mergeable::Merged,
109 Mergeable::UpToDate,
110 ] {
111 assert_eq!(m.as_str().parse::<Mergeable>().ok(), Some(m));
112 }
113 assert!("Clean".parse::<Mergeable>().is_err());
114 }
115
116 #[test]
117 fn merge_style_round_trips() {
118 for s in [
119 MergeStyle::Merge,
120 MergeStyle::Squash,
121 MergeStyle::FastForward,
122 ] {
123 assert_eq!(s.as_str().parse::<MergeStyle>().ok(), Some(s));
124 }
125 assert_eq!(MergeStyle::FastForward.as_str(), "ff");
126 assert!("rebase".parse::<MergeStyle>().is_err());
127 }
128}