vxSDK/vxsdk/core/pkg/backend/gitea.py

171 lines
4.9 KiB
Python

"""
Vhex core backend for Gitea instance
"""
import os
import subprocess
import requests
from core.pkg.backend.core import VxRemoteBackendCore
from core.pkg.version import VxVersion
from core.logger import log
from core.config import config_get
__all__ = [
'VxBackendRemote'
]
class VxBackendRemote(VxRemoteBackendCore):
"""
Vhex Gitea backend class
"""
#---
# Public properties
#---
@property
def name(self):
return 'gitea'
@property
def url(self):
return self._url
@property
def package_list(self):
""" Return the list of all repository find in the remote instance.
This property is used to cache request's information and avoid big HTTP
quesring to the remote instance of Gitea.
"""
# if cached, avoid quering operation
if self._pkg_list:
return self._pkg_list
# raw HTTP request
resp = requests.get(
f'{self.url}/api/v1/repos/search',
params={
'q' : 'vxsdk',
'topic': 'True'
}
)
if not resp.ok:
log.warn(
f'[backend] gitea: remote package requests failed\n'
f'>>> {resp.status_code}'
)
self._pkg_list = []
return []
# generate the pacakge list
# @note
# - hide private repositories
self._pkg_list = []
for pkg in resp.json()['data']:
if pkg['private']:
continue
self._pkg_list.append({
'name' : pkg['name'],
'full_name' : pkg['full_name'],
'description' : pkg['description'],
'url' : pkg['clone_url'],
'created' : pkg['created_at'].split('T')[0],
'updated' : pkg['updated_at'].split('T')[0],
'author' : pkg['owner']['login'],
'default_branch' : pkg['default_branch'],
'versions' : []
})
return self._pkg_list
#---
# Private methods
#---
def package_fetch_versions(self, pkg):
""" Fetch package version information.
Same as the `package_list` property, we using cache to avoid too many
HTTP request.
"""
# if cached information, return it
if pkg['versions']:
return pkg['versions']
# request branches information
pkg['versions'] = []
url = f"{self.url}/api/v1/repos/{pkg['full_name']}"
resp = requests.get(f'{url}/branches')
if not resp.ok:
log.warn(
f'[pkg]: backend: gitea: branches requests error\n'
f'>>> url = {url}/branches\n'
f'>>> status = {resp.status_code}'
)
else:
for ver in resp.json():
pkg['versions'].append(
VxVersion(ver['name'], 'branch', 'remote')
)
# request tag information
resp = requests.get(f'{url}/tags')
if not resp.ok:
log.warn(
f'[pkg]: backend: gitea: tags requests error\n'
f'>>> url = {url}/tags\n'
f'>>> status = {resp.status_code}'
)
else:
for ver in resp.json():
pkg['versions'].append(VxVersion(ver['name'], 'tag', 'remote'))
return pkg['versions']
#---
# Public methods
#---
def package_clone(self, pkg, _=None):
""" Clone the package in global storage
@args
> pkg (dict) - package information returned by package_find()
@return
> Complet path for the package (str), or None if error
"""
# fetch global storage prefix
# @notes
# - create it if its doesn't exists
prefix = os.path.expanduser(config_get('path.packages'))
if not os.path.exists(prefix):
os.makedirs(prefix)
# generate clone information
# @note
# - create clone folder if not exists
pkg_ver = pkg['version']
pkg_name = f"{pkg['author']}@{pkg['name']}@{pkg_ver.name}@{pkg_ver.type}"
pkg_path = f"{prefix}/{pkg_name}"
if os.path.exists(pkg_path):
log.warn(f"[clone]: {pkg_name} already exists, skipped")
return pkg_path
# perform high-level git clone
cmd = [
'git',
'-c', 'advice.detachedHead=false',
'clone', '--branch', pkg_ver.name,
pkg['url'], pkg_path,
'--depth=1'
]
log.debug(f"[gitea] {cmd}")
status = subprocess.run(cmd, capture_output=True, check=False)
if status.returncode != 0:
log.error(f"[clone] : unable to clone {pkg_name}, abord")
return []
# return the package path
return pkg_path