git_checks/
reject_merges.rs1use derive_builder::Builder;
10use git_checks_core::impl_prelude::*;
11
12#[derive(Builder, Debug, Default, Clone, Copy)]
14#[non_exhaustive]
15#[builder(field(private))]
16pub struct RejectMerges {}
17
18impl RejectMerges {
19 pub fn builder() -> RejectMergesBuilder {
21 Default::default()
22 }
23}
24
25impl Check for RejectMerges {
26 fn name(&self) -> &str {
27 "reject-merges"
28 }
29
30 fn check(&self, _: &CheckGitContext, commit: &Commit) -> Result<CheckResult, Box<dyn Error>> {
31 let mut result = CheckResult::new();
32
33 if commit.parents.len() > 1 {
34 result.add_error(format!(
35 "commit {} not allowed; it is a merge commit.",
36 commit.sha1,
37 ));
38 }
39
40 Ok(result)
41 }
42}
43
44#[cfg(feature = "config")]
45pub(crate) mod config {
46 use git_checks_config::{register_checks, CommitCheckConfig, IntoCheck};
47 use serde::Deserialize;
48 #[cfg(test)]
49 use serde_json::json;
50
51 use crate::RejectMerges;
52
53 #[derive(Deserialize, Debug)]
60 pub struct RejectMergesConfig {}
61
62 impl IntoCheck for RejectMergesConfig {
63 type Check = RejectMerges;
64
65 fn into_check(self) -> Self::Check {
66 Default::default()
67 }
68 }
69
70 register_checks! {
71 RejectMergesConfig {
72 "reject_merges" => CommitCheckConfig,
73 },
74 }
75
76 #[test]
77 fn test_reject_merges_config_empty() {
78 let json = json!({});
79 let check: RejectMergesConfig = serde_json::from_value(json).unwrap();
80
81 let _ = check.into_check();
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use git_checks_core::Check;
88
89 use crate::test::*;
90 use crate::RejectMerges;
91
92 const NO_MERGES_TOPIC: &str = "2fab950c4ace0584760e00caae1bb7913b07494e";
93 const WITH_MERGES_TOPIC: &str = "92f545fa6c9326fe11dfb69c3ee01af285b595f4";
94 const OCTOPUS_MERGES_TOPIC: &str = "4447a8eddbccac61daa6b55642e46156011d36cb";
95
96 #[test]
97 fn test_reject_merges_builder_default() {
98 assert!(RejectMerges::builder().build().is_ok());
99 }
100
101 #[test]
102 fn test_reject_merges_name_commit() {
103 let check = RejectMerges::default();
104 assert_eq!(Check::name(&check), "reject-merges");
105 }
106
107 #[test]
108 fn test_reject_merges_name_topic() {
109 let check = RejectMerges::default();
110 assert_eq!(Check::name(&check), "reject-merges");
111 }
112
113 #[test]
114 fn test_reject_merges_no_merges() {
115 let check = RejectMerges::default();
116 run_check_ok("test_reject_merges_no_merges", NO_MERGES_TOPIC, check);
117 }
118
119 #[test]
120 fn test_reject_merges_with_merges() {
121 let check = RejectMerges::default();
122 let result = run_check("test_reject_merges_with_merges", WITH_MERGES_TOPIC, check);
123 test_result_errors(result, &[
124 "commit 92f545fa6c9326fe11dfb69c3ee01af285b595f4 not allowed; it is a merge commit.",
125 ]);
126 }
127
128 #[test]
129 fn test_reject_merges_octopus_merges() {
130 let check = RejectMerges::default();
131 let result = run_check("test_reject_merges_no_merges", OCTOPUS_MERGES_TOPIC, check);
132 test_result_errors(result, &[
133 "commit 4447a8eddbccac61daa6b55642e46156011d36cb not allowed; it is a merge commit.",
134 ]);
135 }
136}