Skip to main content

git_disjoint/
issue_group.rs

1use std::{error::Error, fmt::Display};
2
3use git2::Commit;
4
5use crate::issue::Issue;
6
7#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct GitCommitSummary(pub String);
9
10impl Display for GitCommitSummary {
11    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
12        write!(f, "{}", self.0)
13    }
14}
15
16#[derive(Debug)]
17#[non_exhaustive]
18pub struct FromCommitError {
19    commit: git2::Oid,
20    kind: FromCommitErrorKind,
21}
22
23impl Display for FromCommitError {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        match &self.kind {
26            FromCommitErrorKind::InvalidUtf8 => {
27                write!(f, "summary for commit {:?} is not valid UTF-8", self.commit)
28            }
29        }
30    }
31}
32
33impl Error for FromCommitError {
34    fn source(&self) -> Option<&(dyn Error + 'static)> {
35        match &self.kind {
36            FromCommitErrorKind::InvalidUtf8 => None,
37        }
38    }
39}
40
41#[derive(Debug)]
42pub enum FromCommitErrorKind {
43    #[non_exhaustive]
44    InvalidUtf8,
45}
46
47impl TryFrom<&Commit<'_>> for GitCommitSummary {
48    type Error = FromCommitError;
49
50    fn try_from(commit: &Commit) -> Result<Self, Self::Error> {
51        Ok(Self(
52            commit
53                .summary()
54                .ok_or(FromCommitError {
55                    commit: commit.id(),
56                    kind: FromCommitErrorKind::InvalidUtf8,
57                })?
58                .to_owned(),
59        ))
60    }
61}
62
63#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
64pub enum IssueGroup {
65    Issue(Issue),
66    Commit(GitCommitSummary),
67}
68
69impl Display for IssueGroup {
70    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71        match self {
72            IssueGroup::Issue(issue) => write!(f, "{issue}"),
73            IssueGroup::Commit(commit) => write!(f, "{commit}"),
74        }
75    }
76}
77
78impl From<GitCommitSummary> for IssueGroup {
79    fn from(value: GitCommitSummary) -> Self {
80        Self::Commit(value)
81    }
82}
83
84impl From<Issue> for IssueGroup {
85    fn from(value: Issue) -> Self {
86        Self::Issue(value)
87    }
88}
89
90#[cfg(test)]
91mod test_display {
92    use crate::{issue::Issue, issue_group::GitCommitSummary};
93
94    use super::IssueGroup;
95
96    fn check<I: Into<IssueGroup>>(issue_group: I, displays_as: &str) {
97        assert_eq!(displays_as, format!("{}", issue_group.into()));
98    }
99
100    #[test]
101    fn display_human_readable_issue() {
102        check(Issue::Jira("COOL-123".to_string()), "Jira COOL-123");
103    }
104
105    #[test]
106    fn display_human_readable_commit() {
107        check(
108            GitCommitSummary(String::from("this is a cool summary")),
109            "this is a cool summary",
110        );
111    }
112}