266 lines
8.9 KiB
Python
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
|
|
} |