You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
3.7 KiB

"""
Gitea destination provider implementation
"""
import logging
import requests
from typing import Dict
from ..base import DestinationProvider, Repository, ProviderError, ConfigurationError
logger = logging.getLogger(__name__)
class GiteaDestinationProvider(DestinationProvider):
"""Gitea destination provider implementation"""
def _validate_config(self) -> None:
"""Validate Gitea-specific configuration"""
required_keys = ['url', 'token', 'username']
missing = [key for key in required_keys if not self.config.get(key)]
if missing:
raise ConfigurationError(f"Missing Gitea configuration: {', '.join(missing)}")
self.base_url = self.config['url'].rstrip('/')
self.token = self.config['token']
self.username = self.config['username']
# Setup HTTP session
self.session = requests.Session()
self.session.headers.update({
'Authorization': f'token {self.token}',
'Content-Type': 'application/json'
})
# Verify authentication
try:
response = self.session.get(f"{self.base_url}/api/v1/user")
response.raise_for_status()
except requests.RequestException as e:
raise ConfigurationError(f"Failed to authenticate with Gitea: {e}")
def create_repository(self, repository: Repository, target_name: str) -> bool:
"""Create a new repository on Gitea"""
response = None
try:
# Check if repository already exists
if self.repository_exists(target_name):
logger.warning(f"Repository {target_name} already exists on Gitea")
return True
repo_data = {
'name': target_name,
'description': repository.description or '',
'private': repository.private,
'auto_init': False # Don't auto-init since we'll push existing content
}
response = self.session.post(
f"{self.base_url}/api/v1/user/repos",
json=repo_data
)
response.raise_for_status()
logger.info(f"Created repository: {target_name}")
return True
except requests.RequestException as e:
logger.error(f"Failed to create repository {target_name}: {e}")
if response and response.status_code == 409:
# Conflict - repository already exists
logger.warning(f"Repository {target_name} already exists (conflict)")
return True
elif response and response.status_code == 422:
# Unprocessable Entity - might already exist or name is invalid
logger.warning(f"Repository creation failed, possibly already exists: {target_name}")
return self.repository_exists(target_name)
raise ProviderError(f"Failed to create Gitea repository: {e}")
except Exception as e:
logger.error(f"Unexpected error creating repository {target_name}: {e}")
return False
def repository_exists(self, name: str) -> bool:
"""Check if a repository exists"""
try:
response = self.session.get(f"{self.base_url}/api/v1/repos/{self.username}/{name}")
return response.status_code == 200
except requests.RequestException:
return False
def get_authenticated_push_url(self, name: str) -> str:
"""Get authenticated URL for pushing to repository"""
base_url = self.base_url.replace('https://', '').replace('http://', '')
return f"https://{self.username}:{self.token}@{base_url}/{self.username}/{name}.git"