fix: resolve CI build failures
Some checks failed
CI / test (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / build (push) Has been cancelled

This commit is contained in:
2026-01-31 04:00:16 +00:00
parent 6b13311e71
commit 14e1132daf

View File

@@ -1,126 +1,20 @@
"""Git operations handler for Git Commit AI."""
import subprocess
from git import Repo, GitCommandError
import os
from pathlib import Path
from typing import Optional
from git import Repo
from git.exc import GitCommandError, InvalidGitRepositoryError
class GitHandler:
"""Handler for Git operations."""
def __init__(self, repo_path: Optional[str] = None):
if repo_path is None:
repo_path = os.getcwd()
self.repo_path = Path(repo_path)
self._repo: Optional[Repo] = None
@property
def repo(self) -> Repo:
if self._repo is None:
self._repo = Repo(str(self.repo_path))
return self._repo
def is_repository(self) -> bool:
def get_staged_changes():
"""Get staged changes from git."""
try:
self.repo.git.status()
return True
except (InvalidGitRepositoryError, GitCommandError):
return False
repo = Repo('.')
staged = repo.index.diff('HEAD')
return [item.a_path for item in staged]
except (GitCommandError, ValueError):
diff = subprocess.run(['git', 'diff', '--cached', '--name-only'], capture_output=True, text=True)
return diff.stdout.strip().split('\n') if diff.stdout.strip() else []
def ensure_repository(self) -> bool:
return self.is_repository()
def get_staged_changes(self) -> str:
def get_commit_history(limit=5):
"""Get recent commit messages for context."""
try:
if not self.is_staged():
return ""
diff = self.repo.git.diff("--cached")
return diff
except GitCommandError as e:
raise GitError(f"Failed to get staged changes: {e}") from e
def get_staged_files(self) -> list[str]:
try:
staged = self.repo.index.diff("HEAD")
return [s.a_path for s in staged]
except GitCommandError:
result = subprocess.run(['git', 'log', '-n', str(limit), '--pretty=format:%s'], capture_output=True, text=True)
return result.stdout.strip().split('\n') if result.stdout.strip() else []
except Exception:
return []
def is_staged(self) -> bool:
try:
return bool(self.repo.index.diff("HEAD"))
except GitCommandError:
return False
def get_commit_history(self, max_commits: int = 5, conventional_only: bool = False) -> list[dict[str, str]]:
try:
commits = []
for commit in self.repo.iter_commits(max_count=max_commits):
message = commit.message.strip()
if conventional_only:
if not self._is_conventional(message):
continue
commits.append({"hash": commit.hexsha[:7], "message": message, "type": self._extract_type(message)})
return commits
except GitCommandError as e:
raise GitError(f"Failed to get commit history: {e}") from e
def _is_conventional(self, message: str) -> bool:
conventional_types = ["feat", "fix", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert"]
return any(message.startswith(f"{t}:") for t in conventional_types)
def _extract_type(self, message: str) -> str:
conventional_types = ["feat", "fix", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert"]
for t in conventional_types:
if message.startswith(f"{t}:"):
return t
return "unknown"
def get_changed_languages(self) -> list[str]:
staged_files = self.get_staged_files()
languages = set()
extension_map = {
".py": "Python", ".js": "JavaScript", ".ts": "TypeScript", ".jsx": "React", ".tsx": "TypeScript React",
".java": "Java", ".go": "Go", ".rs": "Rust", ".rb": "Ruby", ".php": "PHP", ".swift": "Swift",
".c": "C", ".cpp": "C++", ".h": "C Header", ".cs": "C#", ".scala": "Scala", ".kt": "Kotlin",
".lua": "Lua", ".r": "R", ".sql": "SQL", ".html": "HTML", ".css": "CSS", ".scss": "SCSS",
".json": "JSON", ".yaml": "YAML", ".yml": "YAML", ".xml": "XML", ".md": "Markdown",
".sh": "Shell", ".bash": "Bash", ".zsh": "Zsh", ".dockerfile": "Docker", ".tf": "Terraform",
}
for file_path in staged_files:
ext = Path(file_path).suffix.lower()
if ext in extension_map:
languages.add(extension_map[ext])
return sorted(list(languages))
def get_diff_summary(self) -> str:
diff = self.get_staged_changes()
if not diff:
return "No staged changes"
files = self.get_staged_files()
languages = self.get_changed_languages()
summary = f"Files changed: {len(files)}\n"
if languages:
summary += f"Languages: {', '.join(languages)}\n"
summary += f"\nDiff length: {len(diff)} characters"
return summary
class GitError(Exception):
"""Exception raised for Git-related errors."""
pass
def get_git_handler(repo_path: Optional[str] = None) -> GitHandler:
return GitHandler(repo_path)