from __future__ import annotations import base64 import logging from dataclasses import dataclass from github import GithubException, UnknownObjectException from github.ContentFile import ContentFile from github.Repository import Repository from vuln_scan.github.base_client import GitHubBaseClient logger = logging.getLogger(__name__) @dataclass class GitHubRepoClient(GitHubBaseClient): owner: str repo: str def __post_init__(self) -> None: super().__post_init__() self._repo: Repository = self._gh.get_repo(f"{self.owner}/{self.repo}") def get_default_branch(self) -> str: return self._repo.default_branch def get_file_content(self, path: str, ref: str) -> str | None: try: content = self._repo.get_contents(path, ref=ref) except UnknownObjectException: logger.debug("File not found: %s@%s", path, ref) return None except GithubException as exc: logger.error( "GitHub API error fetching %s@%s: %s %s", path, ref, exc.status, exc.data, ) raise # ---------------------------------------- # Handle directory case (list returned) # ---------------------------------------- if isinstance(content, list): return None # ---------------------------------------- # Handle file case # ---------------------------------------- if not isinstance(content, ContentFile): return None if content.content is None: return None return base64.b64decode(content.content).decode()