| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- """Abstract base class for Git hosting provider backends."""
- import hashlib
- from abc import ABC, abstractmethod
- import httpx
- class GitProviderBackend(ABC):
- """Abstract base for Git hosting provider API backends."""
- @staticmethod
- def _blob_sha(content_bytes: bytes) -> str:
- """Compute the git blob SHA for content_bytes (sha1("blob {len}\\0" + data))."""
- return hashlib.sha1(
- f"blob {len(content_bytes)}\0".encode() + content_bytes, usedforsecurity=False
- ).hexdigest()
- @staticmethod
- def _truncated_response_text(response: httpx.Response, max_length: int = 200) -> str:
- """Return a bounded response body for errors surfaced to logs/UI."""
- text = response.text
- if len(text) <= max_length:
- return text
- return f"{text[: max_length - 3]}..."
- def get_headers(self, token: str) -> dict:
- """Return HTTP headers for authenticated API requests."""
- return {
- "Authorization": f"token {token}",
- "Accept": "application/vnd.github.v3+json",
- "User-Agent": "Bambuddy-Backup",
- }
- @abstractmethod
- def parse_repo_url(self, url: str) -> tuple[str, str]:
- """Return (owner, repo) extracted from the repository URL."""
- @abstractmethod
- def get_api_base(self, repo_url: str) -> str:
- """Return the API base URL for this provider instance."""
- @abstractmethod
- async def test_connection(self, repo_url: str, token: str, client: httpx.AsyncClient) -> dict:
- """Test API connectivity and push permissions. Returns success/message/repo_name/permissions."""
- @abstractmethod
- async def push_files(
- self,
- repo_url: str,
- token: str,
- branch: str,
- files: dict,
- client: httpx.AsyncClient,
- ) -> dict:
- """Push files to the repository. Returns status/message/commit_sha/files_changed."""
|