Files
Yiqun/gitea-shim/python/models/pull_request.py

266 lines
8.9 KiB
Python

"""Pull Request model that provides GitHub-compatible interface for Gitea pull requests."""
from typing import Optional, Dict, Any, List
class PullRequest:
"""
Pull Request wrapper that provides GitHub-compatible interface for Gitea pull requests.
"""
def __init__(self, gitea_pr, gitea_repo, gitea_client):
"""
Initialize pull request wrapper.
Args:
gitea_pr: The Gitea pull request object
gitea_repo: The Gitea repository object
gitea_client: The Gitea client instance
"""
self._pr = gitea_pr
self._repo = gitea_repo
self._gitea = gitea_client
# Map Gitea attributes to GitHub attributes
self.number = gitea_pr.number
self.state = gitea_pr.state
self.title = gitea_pr.title
self.body = gitea_pr.body
self.created_at = gitea_pr.created_at
self.updated_at = gitea_pr.updated_at
self.closed_at = gitea_pr.closed_at
self.merged_at = gitea_pr.merged_at
self.merge_commit_sha = gitea_pr.merge_commit_sha
self.html_url = gitea_pr.html_url
self.diff_url = gitea_pr.diff_url
self.patch_url = gitea_pr.patch_url
self.mergeable = gitea_pr.mergeable
self.merged = gitea_pr.merged
self.draft = getattr(gitea_pr, 'draft', False) # Gitea might not have draft PRs
# User information
self.user = self._create_user_object(gitea_pr.user)
self.assignee = self._create_user_object(gitea_pr.assignee) if gitea_pr.assignee else None
self.assignees = [self._create_user_object(a) for a in getattr(gitea_pr, 'assignees', [])]
# Branch information
self.base = self._create_branch_info(gitea_pr.base)
self.head = self._create_branch_info(gitea_pr.head)
# Labels and milestone
self.labels = [self._create_label_object(l) for l in getattr(gitea_pr, 'labels', [])]
self.milestone = self._create_milestone_object(gitea_pr.milestone) if gitea_pr.milestone else None
def _create_user_object(self, gitea_user) -> Dict[str, Any]:
"""Create a GitHub-compatible user object."""
if not gitea_user:
return None
return {
'login': gitea_user.login,
'id': gitea_user.id,
'avatar_url': gitea_user.avatar_url,
'type': 'User'
}
def _create_branch_info(self, gitea_branch) -> Dict[str, Any]:
"""Create a GitHub-compatible branch info object."""
return {
'ref': gitea_branch.ref,
'sha': gitea_branch.sha,
'repo': {
'name': gitea_branch.repo.name,
'full_name': gitea_branch.repo.full_name,
'owner': self._create_user_object(gitea_branch.repo.owner)
} if gitea_branch.repo else None
}
def _create_label_object(self, gitea_label) -> Dict[str, Any]:
"""Create a GitHub-compatible label object."""
return {
'name': gitea_label.name,
'color': gitea_label.color,
'description': gitea_label.description
}
def _create_milestone_object(self, gitea_milestone) -> Dict[str, Any]:
"""Create a GitHub-compatible milestone object."""
return {
'title': gitea_milestone.title,
'description': gitea_milestone.description,
'state': gitea_milestone.state,
'number': gitea_milestone.id,
'due_on': gitea_milestone.due_on
}
def update(self, **kwargs) -> 'PullRequest':
"""
Update the pull request.
Args:
**kwargs: Fields to update (title, body, state, base, etc.)
Returns:
Updated PullRequest object
"""
# Map GitHub parameters to Gitea parameters
update_params = {}
if 'title' in kwargs:
update_params['title'] = kwargs['title']
if 'body' in kwargs:
update_params['body'] = kwargs['body']
if 'state' in kwargs:
update_params['state'] = kwargs['state']
if 'assignee' in kwargs:
update_params['assignee'] = kwargs['assignee']
if 'assignees' in kwargs:
update_params['assignees'] = kwargs['assignees']
if 'labels' in kwargs:
update_params['labels'] = kwargs['labels']
if 'milestone' in kwargs:
update_params['milestone'] = kwargs['milestone']
# Update using Gitea API
updated_pr = self._pr.update(**update_params)
# Return new PullRequest instance with updated data
return PullRequest(updated_pr, self._repo, self._gitea)
def merge(self, commit_title: Optional[str] = None,
commit_message: Optional[str] = None,
sha: Optional[str] = None,
merge_method: str = 'merge') -> Dict[str, Any]:
"""
Merge the pull request.
Args:
commit_title: Title for the merge commit
commit_message: Message for the merge commit
sha: SHA that must match the HEAD of the PR
merge_method: Merge method ('merge', 'squash', 'rebase')
Returns:
Merge result information
"""
# Map GitHub merge methods to Gitea
gitea_merge_style = {
'merge': 'merge',
'squash': 'squash',
'rebase': 'rebase'
}.get(merge_method, 'merge')
# Merge using Gitea API
result = self._pr.merge(
style=gitea_merge_style,
title=commit_title,
message=commit_message
)
return {
'sha': result.sha if hasattr(result, 'sha') else None,
'merged': True,
'message': 'Pull Request successfully merged'
}
def get_commits(self) -> List[Dict[str, Any]]:
"""
Get commits in the pull request.
Returns:
List of commit objects
"""
gitea_commits = self._pr.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
}
},
'html_url': commit.html_url
})
return commits
def get_files(self) -> List[Dict[str, Any]]:
"""
Get files changed in the pull request.
Returns:
List of file objects
"""
gitea_files = self._pr.get_files()
files = []
for file in gitea_files:
files.append({
'filename': file.filename,
'status': file.status,
'additions': file.additions,
'deletions': file.deletions,
'changes': file.changes,
'patch': file.patch,
'sha': file.sha,
'blob_url': file.blob_url,
'raw_url': file.raw_url
})
return files
def create_review_comment(self, body: str, commit_id: str, path: str,
position: int) -> Dict[str, Any]:
"""
Create a review comment on the pull request.
Args:
body: Comment body
commit_id: Commit SHA to comment on
path: File path to comment on
position: Line position in the diff
Returns:
Comment object
"""
comment = self._pr.create_review_comment(
body=body,
commit_id=commit_id,
path=path,
position=position
)
return {
'id': comment.id,
'body': comment.body,
'path': comment.path,
'position': comment.position,
'commit_id': comment.commit_id,
'user': self._create_user_object(comment.user),
'created_at': comment.created_at,
'updated_at': comment.updated_at
}
def create_issue_comment(self, body: str) -> Dict[str, Any]:
"""
Create a general comment on the pull request.
Args:
body: Comment body
Returns:
Comment object
"""
comment = self._pr.create_comment(body=body)
return {
'id': comment.id,
'body': comment.body,
'user': self._create_user_object(comment.user),
'created_at': comment.created_at,
'updated_at': comment.updated_at
}