55 lines
1.7 KiB
Rust
55 lines
1.7 KiB
Rust
use model::repos::RepoProtectModel;
|
|
|
|
use crate::ssh::ref_update::RefUpdate;
|
|
|
|
fn ref_matches_protection(ref_name: &str, protection_pattern: &str) -> bool {
|
|
ref_name == protection_pattern
|
|
|| ref_name.starts_with(&format!("{}/", protection_pattern))
|
|
}
|
|
|
|
pub fn check_branch_protection(
|
|
branch_protects: &[RepoProtectModel],
|
|
r#ref: &RefUpdate,
|
|
) -> Option<String> {
|
|
for protection in branch_protects {
|
|
if !ref_matches_protection(&r#ref.name, &protection.pattern) {
|
|
continue;
|
|
}
|
|
|
|
if r#ref.new_oid == "0000000000000000000000000000000000000000" {
|
|
if !protection.allow_deletions {
|
|
return Some(format!(
|
|
"protected branch rejected. Deletion of '{}' is forbidden. Create a PR or ask a maintainer to update branch protection.",
|
|
r#ref.name
|
|
));
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if r#ref.name.starts_with("refs/tags/") {
|
|
continue;
|
|
}
|
|
|
|
let is_new_branch =
|
|
r#ref.old_oid == "0000000000000000000000000000000000000000";
|
|
if !is_new_branch
|
|
&& r#ref.old_oid != r#ref.new_oid
|
|
&& r#ref.name.starts_with("refs/heads/")
|
|
&& !protection.allow_force_pushes
|
|
{
|
|
return Some(format!(
|
|
"protected branch rejected. Force push to '{}' is forbidden. Create a PR instead of rewriting protected history.",
|
|
r#ref.name
|
|
));
|
|
}
|
|
|
|
if protection.require_pull_request {
|
|
return Some(format!(
|
|
"protected branch rejected. Direct push to '{}' is forbidden. Please push to a feature branch and create a PR.",
|
|
r#ref.name
|
|
));
|
|
}
|
|
}
|
|
None
|
|
}
|