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
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" |