from pathlib import Path from typing import List, Optional from git import Repo, GitCommandError class GitRepo: def __init__(self, repo_path: Path): self.repo_path = Path(repo_path) self.repo = Repo(str(self.repo_path)) def get_repo_name(self) -> str: return self.repo.remote().url.split("/")[-1].replace(".git", "") def get_repo_url(self) -> Optional[str]: try: return self.repo.remote().url except GitCommandError: return None def get_staged_files(self) -> List[str]: staged_files = [] diff_index = self.repo.index.diff("HEAD") for diff in diff_index: staged_files.append(diff.a_path) if not staged_files: for item in self.repo.index.diff("HEAD"): staged_files.append(item.a_path) return staged_files def get_tracked_files(self) -> List[str]: return list(self.repo.git.ls_files().split("\n")) def get_untracked_files(self) -> List[str]: return self.repo.untracked_files def get_all_files(self) -> List[str]: return self.get_tracked_files() + self.get_untracked_files() def get_changed_files(self) -> List[str]: changed_files = [] for item in self.repo.index.diff(None): changed_files.append(item.a_path) return changed_files def get_commit_hash(self, short: bool = True) -> str: return self.repo.head.commit.hexsha[:7] if short else self.repo.head.commit.hexsha def get_current_branch(self) -> str: return self.repo.active_branch.name def is_clean(self) -> bool: return not self.repo.is_dirty() def get_file_content(self, file_path: str, commit_hash: Optional[str] = None) -> str: if commit_hash: return self.repo.git.show(f"{commit_hash}:{file_path}") return (self.repo_path / file_path).read_text()