Add source code files
This commit is contained in:
76
src/codeguard/git/hooks.py
Normal file
76
src/codeguard/git/hooks.py
Normal file
@@ -0,0 +1,76 @@
|
||||
"""Git hooks management for CodeGuard."""
|
||||
|
||||
import os
|
||||
import stat
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class HookManager:
|
||||
HOOK_SCRIPT = """#!/bin/bash
|
||||
# CodeGuard pre-commit hook
|
||||
# This hook runs CodeGuard security analysis before commit
|
||||
|
||||
set -e
|
||||
|
||||
# Get the root directory of the git repository
|
||||
GIT_DIR=$(git rev-parse --git-dir)
|
||||
REPO_ROOT=$(git rev-parse --show-toplevel)
|
||||
|
||||
# Change to repository root
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Run CodeGuard scan
|
||||
# Exit with error code if scan fails or finds critical issues
|
||||
exec codeguard scan --fail-level critical
|
||||
"""
|
||||
|
||||
def __init__(self, repo_path: str = "."):
|
||||
self.repo_path = Path(repo_path).resolve()
|
||||
self.git_dir = self.repo_path / ".git"
|
||||
self.hooks_dir = self.git_dir / "hooks"
|
||||
|
||||
def install(self, force: bool = False) -> bool:
|
||||
if not self.git_dir.exists():
|
||||
raise NotAGitRepository(f"Not a git repository: {self.repo_path}")
|
||||
|
||||
self.hooks_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
hook_path = self.hooks_dir / "pre-commit"
|
||||
|
||||
if hook_path.exists() and not force:
|
||||
existing_content = hook_path.read_text()
|
||||
if "codeguard" in existing_content.lower():
|
||||
return False
|
||||
|
||||
hook_content = self._generate_hook_script()
|
||||
hook_path.write_text(hook_content)
|
||||
|
||||
os.chmod(hook_path, hook_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
return True
|
||||
|
||||
def uninstall(self) -> None:
|
||||
hook_path = self.hooks_dir / "pre-commit"
|
||||
if hook_path.exists():
|
||||
hook_path.unlink()
|
||||
|
||||
def _generate_hook_script(self) -> str:
|
||||
return self.HOOK_SCRIPT
|
||||
|
||||
def check_installed(self) -> bool:
|
||||
hook_path = self.hooks_dir / "pre-commit"
|
||||
if not hook_path.exists():
|
||||
return False
|
||||
|
||||
content = hook_path.read_text()
|
||||
return "codeguard" in content.lower()
|
||||
|
||||
def get_hook_path(self) -> Path:
|
||||
return self.hooks_dir / "pre-commit"
|
||||
|
||||
|
||||
class NotAGitRepository(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class HookAlreadyInstalled(Exception):
|
||||
pass
|
||||
Reference in New Issue
Block a user