From 1423d1d9e45b2713b87be0b655d942466fe58526 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Sun, 1 Feb 2026 08:27:45 +0000 Subject: [PATCH] Add git repository analyzer module --- src/analyzers/git_repository.py | 81 +++++++++------------------------ 1 file changed, 21 insertions(+), 60 deletions(-) diff --git a/src/analyzers/git_repository.py b/src/analyzers/git_repository.py index 033df58..3772c6a 100644 --- a/src/analyzers/git_repository.py +++ b/src/analyzers/git_repository.py @@ -5,6 +5,8 @@ from src.models import Commit class GitRepository: + """Wrapper for git repository operations.""" + def __init__(self, path: str): self.path = path self._repo: Optional[Repo] = None @@ -19,18 +21,10 @@ class GitRepository: commits = [] try: - commit_iter = repo.iter_commits( - rev=None, - since=since.isoformat() if since else None, - until=until.isoformat() if until else None, - max_count=None, - ) - - for git_commit in commit_iter: + for git_commit in repo.iter_commits(): commit = self._convert_git_commit(git_commit) if commit: commits.append(commit) - except GitCommandError as e: raise ValueError(f"Error reading git repository: {e}") @@ -38,12 +32,8 @@ class GitRepository: def _convert_git_commit(self, git_commit) -> Optional[Commit]: try: - parents = [p.hexsha for p in git_commit.parents] - is_merge = len(parents) > 1 - - is_revert = False - if git_commit.message.lower().startswith(("revert", "reverted")): - is_revert = True + is_merge = len(git_commit.parents) > 1 + is_revert = git_commit.message.lower().startswith(("revert", "reverted")) file_changes = [] additions = 0 @@ -52,8 +42,7 @@ class GitRepository: try: if git_commit.stats and git_commit.stats.files: for filepath, stats in git_commit.stats.files.items(): - file_change = self._create_file_change(filepath, stats) - file_changes.append(file_change) + file_changes.append(filepath) additions += stats.get('insertions', 0) deletions += stats.get('deletions', 0) except Exception: @@ -62,56 +51,28 @@ class GitRepository: return Commit( sha=git_commit.hexsha, message=git_commit.message.strip(), - author_name=git_commit.author.name or "Unknown", + author=git_commit.author.name or "Unknown", author_email=git_commit.author.email or "", - committed_datetime=datetime.fromtimestamp(git_commit.committed_date), - author_datetime=datetime.fromtimestamp(git_commit.authored_date), - parents=parents, - additions=additions, - deletions=deletions, - files_changed=len(file_changes), - file_changes=file_changes, + timestamp=datetime.fromtimestamp(git_commit.committed_date), + lines_added=additions, + lines_deleted=deletions, + files_changed=file_changes, is_merge=is_merge, is_revert=is_revert, ) except Exception: return None - def _create_file_change(self, filepath: str, stats: dict) -> "FileChange": - from src.models import FileChange - return FileChange( - filepath=filepath, - additions=stats.get('insertions', 0), - deletions=stats.get('deletions', 0), - changes=stats.get('insertions', 0) + stats.get('deletions', 0), - ) - - def get_commit_count(self) -> int: - return sum(1 for _ in self.get_repo().iter_commits()) - - def get_unique_authors(self) -> set: - authors = set() - for commit in self.get_repo().iter_commits(): - if commit.author.name: - authors.add(commit.author.name) - return authors - - def get_authors(self): - from src.models import Author - authors = {} - for commit in self.get_repo().iter_commits(): - if commit.author.name and commit.author.email: - email = commit.author.email - if email not in authors: - authors[email] = Author( - name=commit.author.name, - email=email, - commit_count=0, - lines_added=0, - lines_deleted=0, - ) - authors[email].commit_count += 1 - return list(authors.values()) + def get_authors(self) -> List[Author]: + """Get list of authors from commits.""" + authors_dict = {} + for commit in self.get_commits(): + if commit.author_email not in authors_dict: + authors_dict[commit.author_email] = Author( + name=commit.author, + email=commit.author_email, + ) + return list(authors_dict.values()) def close(self): if self._repo: