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