from distgit.hooks import Hook, HookResult, CommitMsg, Update
import re
from sys import stderr
import pygit2

"""
Commit-Msg Pattern Hook (Client-side)
Validates the commit message against a regular expression.
"""
class CommitMsgPattern(CommitMsg):
    def __init__(self, repo: pygit2.Repository, pattern: str):
        super().__init__(repo)
        self.exp = re.compile(pattern)

    def run(self, message_file: str) -> HookResult:
        with open(message_file, "r") as f:
            message = f.read()
        if not self.exp.match(message):
            stderr.write(f"Commit message does not match pattern: {self.exp.pattern}\n")
            return HookResult.FAILURE
        return HookResult.SUCCESS

"""
Update Pattern Hook (Server-side)
Invoked by git-receive-pack once per ref being updated, before the ref is updated.
Use this hook to:
- Enforce fast-forward only (reject non-FF updates)
- Implement per-ref access control
- Log or validate old → new for specific refs
Takes three parameters: ref name, old object name, new object name.
"""
class UpdatePattern(Hook):
    def __init__(self, repo: pygit2.Repository, ref_pattern: str, msg_pattern: str):
        super().__init__(repo)
        self.ref_exp = re.compile(ref_pattern)
        self.msg_exp = re.compile(msg_pattern)

    def run(self, ref_name: str, old_oid: str, new_oid: str) -> HookResult:
        if self.ref_exp.match(ref_name):
            commit = self.repo.revparse_single(new_oid).peel(pygit2.Commit)
            if not self.msg_exp.match(commit.message):
                stderr.write(f"Commit message does not match pattern: {self.msg_exp.pattern}\n")
                return HookResult.FAILURE
        return HookResult.SUCCESS