This repository has no description
1use std::sync::Arc;
2
3use knot_cob::{CobHome, CobStore};
4use knot_git::Repo;
5use knot_messages::{Catalog, ErrorKey};
6use knot_types::{ActorId, RefName};
7
8use crate::{ReceiveCommand, ReceiveGuard, RefDecision};
9
10pub struct PushGuard {
11 pub cob_authority: ActorId,
12 pub home: CobHome,
13 pub messages: Arc<Catalog>,
14}
15
16impl ReceiveGuard for PushGuard {
17 fn authorize(&self, staged: &Repo, commands: &[ReceiveCommand]) -> Vec<RefDecision> {
18 commands
19 .iter()
20 .map(|command| self.decide(staged, command))
21 .collect()
22 }
23}
24
25impl PushGuard {
26 fn decide(&self, staged: &Repo, command: &ReceiveCommand) -> RefDecision {
27 match command.name() {
28 None => RefDecision::Reject(
29 self.messages
30 .reject
31 .cob_verification
32 .line(|ErrorKey::Error| crate::receive::invalid_refname(command.refname())),
33 ),
34 Some(name) if knot_git::is_public_ref(name) => RefDecision::Allow,
35 Some(name) if knot_git::is_reserved(name) => {
36 if command.is_delete() {
37 RefDecision::Reject(self.messages.reject.cob_delete.text())
38 } else {
39 self.verify_cob(staged, name)
40 }
41 }
42 Some(_) => RefDecision::Reject(self.messages.reject.hidden_reserved.text()),
43 }
44 }
45
46 fn verify_cob(&self, staged: &Repo, name: &RefName) -> RefDecision {
47 let store = CobStore::new(staged);
48 match knot_cobs::verify_cob_ref(&store, &self.home, name, &self.cob_authority) {
49 Ok(_) => RefDecision::Allow,
50 Err(error) => RefDecision::Reject(
51 self.messages
52 .reject
53 .cob_verification
54 .line(|ErrorKey::Error| error.to_string()),
55 ),
56 }
57 }
58}