291 lines
9.5 KiB
Python
291 lines
9.5 KiB
Python
"""Repository model that provides GitHub-compatible interface for Gitea repositories."""
|
|
|
|
from typing import Optional, List, Dict, Any
|
|
|
|
try:
|
|
# When running tests or using as a module
|
|
from models.pull_request import PullRequest
|
|
except ImportError:
|
|
# When using as a package
|
|
from .pull_request import PullRequest
|
|
|
|
|
|
class Repository:
|
|
"""
|
|
Repository wrapper that provides GitHub-compatible interface for Gitea repositories.
|
|
"""
|
|
|
|
def __init__(self, gitea_repo, gitea_client):
|
|
"""
|
|
Initialize repository wrapper.
|
|
|
|
Args:
|
|
gitea_repo: The Gitea repository object
|
|
gitea_client: The Gitea client instance
|
|
"""
|
|
self._repo = gitea_repo
|
|
self._gitea = gitea_client
|
|
|
|
# Map Gitea attributes to GitHub attributes
|
|
self.name = gitea_repo.name
|
|
self.full_name = gitea_repo.full_name
|
|
self.description = gitea_repo.description
|
|
self.private = gitea_repo.private
|
|
self.fork = gitea_repo.fork
|
|
self.created_at = gitea_repo.created_at
|
|
self.updated_at = gitea_repo.updated_at
|
|
self.pushed_at = gitea_repo.updated_at # Gitea doesn't have pushed_at
|
|
self.size = gitea_repo.size
|
|
self.stargazers_count = gitea_repo.stars_count
|
|
self.watchers_count = gitea_repo.watchers_count
|
|
self.forks_count = gitea_repo.forks_count
|
|
self.open_issues_count = gitea_repo.open_issues_count
|
|
self.default_branch = gitea_repo.default_branch
|
|
self.archived = gitea_repo.archived
|
|
self.html_url = gitea_repo.html_url
|
|
self.clone_url = gitea_repo.clone_url
|
|
self.ssh_url = gitea_repo.ssh_url
|
|
|
|
# Owner information
|
|
self.owner = self._create_owner_object(gitea_repo.owner)
|
|
|
|
def _create_owner_object(self, gitea_owner) -> Dict[str, Any]:
|
|
"""Create a GitHub-compatible owner object."""
|
|
return {
|
|
'login': gitea_owner.login,
|
|
'id': gitea_owner.id,
|
|
'avatar_url': gitea_owner.avatar_url,
|
|
'type': 'User' if not getattr(gitea_owner, 'is_organization', False) else 'Organization'
|
|
}
|
|
|
|
def get_pull(self, number: int) -> PullRequest:
|
|
"""
|
|
Get a pull request by number.
|
|
|
|
Args:
|
|
number: Pull request number
|
|
|
|
Returns:
|
|
PullRequest object
|
|
"""
|
|
gitea_pr = self._repo.get_pull(number)
|
|
return PullRequest(gitea_pr, self._repo, self._gitea)
|
|
|
|
def get_pulls(self, state: str = 'open', sort: str = 'created',
|
|
direction: str = 'desc', base: Optional[str] = None,
|
|
head: Optional[str] = None) -> List[PullRequest]:
|
|
"""
|
|
Get pull requests for the repository.
|
|
|
|
Args:
|
|
state: State of PRs to return ('open', 'closed', 'all')
|
|
sort: Sort field ('created', 'updated', 'popularity')
|
|
direction: Sort direction ('asc', 'desc')
|
|
base: Filter by base branch
|
|
head: Filter by head branch
|
|
|
|
Returns:
|
|
List of PullRequest objects
|
|
"""
|
|
# Map GitHub state to Gitea state
|
|
gitea_state = state
|
|
if state == 'all':
|
|
gitea_state = None # Gitea uses None for all
|
|
|
|
gitea_prs = self._repo.get_pulls(state=gitea_state)
|
|
|
|
# Convert to PullRequest objects
|
|
pulls = [PullRequest(pr, self._repo, self._gitea) for pr in gitea_prs]
|
|
|
|
# Apply additional filters if needed
|
|
if base:
|
|
pulls = [pr for pr in pulls if pr.base.ref == base]
|
|
if head:
|
|
pulls = [pr for pr in pulls if pr.head.ref == head]
|
|
|
|
return pulls
|
|
|
|
def create_pull(self, title: str, body: str, head: str, base: str,
|
|
draft: bool = False, **kwargs) -> PullRequest:
|
|
"""
|
|
Create a new pull request.
|
|
|
|
Args:
|
|
title: PR title
|
|
body: PR description
|
|
head: Source branch
|
|
base: Target branch
|
|
draft: Whether PR is a draft
|
|
**kwargs: Additional parameters
|
|
|
|
Returns:
|
|
PullRequest object
|
|
"""
|
|
# Create PR using Gitea API
|
|
gitea_pr = self._repo.create_pull_request(
|
|
title=title,
|
|
body=body,
|
|
head=head,
|
|
base=base
|
|
# Note: Gitea might not support draft PRs
|
|
)
|
|
|
|
return PullRequest(gitea_pr, self._repo, self._gitea)
|
|
|
|
def get_contents(self, path: str, ref: Optional[str] = None) -> Any:
|
|
"""
|
|
Get file contents from repository.
|
|
|
|
Args:
|
|
path: File path
|
|
ref: Git ref (branch, tag, commit SHA)
|
|
|
|
Returns:
|
|
File contents object
|
|
"""
|
|
# Get file contents using Gitea API
|
|
contents = self._repo.get_file_contents(path, ref=ref)
|
|
|
|
# Create GitHub-compatible response
|
|
return {
|
|
'name': contents.name,
|
|
'path': contents.path,
|
|
'sha': contents.sha,
|
|
'size': contents.size,
|
|
'type': contents.type,
|
|
'content': contents.content,
|
|
'encoding': contents.encoding,
|
|
'download_url': contents.download_url,
|
|
'html_url': contents.html_url
|
|
}
|
|
|
|
def get_branches(self) -> List[Dict[str, Any]]:
|
|
"""
|
|
Get all branches in the repository.
|
|
|
|
Returns:
|
|
List of branch objects
|
|
"""
|
|
gitea_branches = self._repo.get_branches()
|
|
|
|
branches = []
|
|
for branch in gitea_branches:
|
|
branches.append({
|
|
'name': branch.name,
|
|
'commit': {
|
|
'sha': branch.commit.id,
|
|
'url': branch.commit.url
|
|
},
|
|
'protected': branch.protected
|
|
})
|
|
|
|
return branches
|
|
|
|
def get_branch(self, branch: str) -> Dict[str, Any]:
|
|
"""
|
|
Get a specific branch.
|
|
|
|
Args:
|
|
branch: Branch name
|
|
|
|
Returns:
|
|
Branch object
|
|
"""
|
|
gitea_branch = self._repo.get_branch(branch)
|
|
|
|
return {
|
|
'name': gitea_branch.name,
|
|
'commit': {
|
|
'sha': gitea_branch.commit.id,
|
|
'url': gitea_branch.commit.url
|
|
},
|
|
'protected': gitea_branch.protected
|
|
}
|
|
|
|
def create_fork(self, organization: Optional[str] = None) -> 'Repository':
|
|
"""
|
|
Create a fork of the repository.
|
|
|
|
Args:
|
|
organization: Organization to fork to (optional)
|
|
|
|
Returns:
|
|
Repository object for the fork
|
|
"""
|
|
gitea_fork = self._repo.create_fork(organization=organization)
|
|
return Repository(gitea_fork, self._gitea)
|
|
|
|
def get_commits(self, sha: Optional[str] = None, path: Optional[str] = None,
|
|
since: Optional[str] = None, until: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
"""
|
|
Get commits from the repository.
|
|
|
|
Args:
|
|
sha: Starting commit SHA or branch
|
|
path: Only commits containing this path
|
|
since: Only commits after this date
|
|
until: Only commits before this date
|
|
|
|
Returns:
|
|
List of commit objects
|
|
"""
|
|
# Note: Gitea API might have different parameters
|
|
gitea_commits = self._repo.get_commits()
|
|
|
|
commits = []
|
|
for commit in gitea_commits:
|
|
commits.append({
|
|
'sha': commit.sha,
|
|
'commit': {
|
|
'message': commit.commit.message,
|
|
'author': {
|
|
'name': commit.commit.author.name,
|
|
'email': commit.commit.author.email,
|
|
'date': commit.commit.author.date
|
|
},
|
|
'committer': {
|
|
'name': commit.commit.committer.name,
|
|
'email': commit.commit.committer.email,
|
|
'date': commit.commit.committer.date
|
|
}
|
|
},
|
|
'html_url': commit.html_url,
|
|
'author': commit.author,
|
|
'committer': commit.committer
|
|
})
|
|
|
|
return commits
|
|
|
|
def get_commit(self, sha: str) -> Dict[str, Any]:
|
|
"""
|
|
Get a specific commit.
|
|
|
|
Args:
|
|
sha: Commit SHA
|
|
|
|
Returns:
|
|
Commit object
|
|
"""
|
|
gitea_commit = self._repo.get_commit(sha)
|
|
|
|
return {
|
|
'sha': gitea_commit.sha,
|
|
'commit': {
|
|
'message': gitea_commit.commit.message,
|
|
'author': {
|
|
'name': gitea_commit.commit.author.name,
|
|
'email': gitea_commit.commit.author.email,
|
|
'date': gitea_commit.commit.author.date
|
|
},
|
|
'committer': {
|
|
'name': gitea_commit.commit.committer.name,
|
|
'email': gitea_commit.commit.committer.email,
|
|
'date': gitea_commit.commit.committer.date
|
|
}
|
|
},
|
|
'html_url': gitea_commit.html_url,
|
|
'author': gitea_commit.author,
|
|
'committer': gitea_commit.committer,
|
|
'stats': gitea_commit.stats,
|
|
'files': gitea_commit.files
|
|
} |