1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use std::collections::BTreeMap;
use bitflags::bitflags;
use git_repository as git;
pub mod conventional {
use git_repository as git;
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Message {
User {
markdown: String,
},
Generated {
id: git::ObjectId,
title: String,
body: Option<String>,
},
}
pub fn as_headline(kind: &str) -> Option<&'static str> {
Some(match kind {
"fix" => "Bug Fixes",
"add" | "added" => "Added",
"feat" => "New Features",
"revert" => "Reverted",
"remove" => "Removed",
"change" => "Changed",
"docs" => "Documentation",
"perf" => "Performance",
"chore" => "Chore",
"test" => "Test",
"refactor" => "Refactor",
"other" => "Other",
"style" => "Style",
_unknown => return None,
})
}
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct Conventional {
pub kind: &'static str,
pub is_breaking: bool,
pub removed: Vec<git::ObjectId>,
pub messages: Vec<conventional::Message>,
}
impl Conventional {
pub const REMOVED_HTML_PREFIX: &'static str = "<csr-id-";
pub const BREAKING_TITLE: &'static str = "BREAKING";
pub const BREAKING_TITLE_ENCLOSED: &'static str = "(BREAKING)";
}
pub mod details {
use std::fmt;
use git_repository as git;
#[derive(PartialEq, Eq, Ord, PartialOrd, Debug, Clone)]
pub enum Category {
Issue(String),
Uncategorized,
}
impl fmt::Display for Category {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Category::Uncategorized => f.write_str("Uncategorized"),
Category::Issue(issue) => write!(f, "#{}", issue),
}
}
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Message {
pub title: String,
pub id: git::ObjectId,
}
impl From<&crate::commit::history::Item> for Message {
fn from(v: &crate::commit::history::Item) -> Self {
Message {
title: v.message.title.to_owned(),
id: v.id,
}
}
}
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct Details {
pub commits_by_category: BTreeMap<details::Category, Vec<details::Message>>,
}
impl Details {
pub const TITLE: &'static str = "Commit Details";
pub const HTML_PREFIX: &'static str = "<details><summary>view details</summary>";
pub const HTML_PREFIX_END: &'static str = "</details>";
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct CommitStatistics {
pub count: usize,
pub duration: Option<time::Duration>,
pub conventional_count: usize,
pub unique_issues: Vec<details::Category>,
pub time_passed_since_last_release: Option<time::Duration>,
}
impl CommitStatistics {
pub const TITLE: &'static str = "Commit Statistics";
}
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ThanksClippy {
pub count: usize,
}
impl ThanksClippy {
pub const TITLE: &'static str = "Thanks Clippy";
}
bitflags! {
pub struct Selection: u8 {
const CLIPPY = 1<<0;
const COMMIT_DETAILS = 1<<1;
const COMMIT_STATISTICS = 1<<2;
const GIT_CONVENTIONAL = 1<<3;
}
}