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 { 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 }