This commit is contained in:
Vinícius Moreira
2020-04-13 11:49:28 -03:00
parent 83aab1ff55
commit 01a60ea686
165 changed files with 12778 additions and 6171 deletions

View File

@@ -1,17 +1,19 @@
import logging
import os
import re
from typing import Set, List
import urllib.parse
from typing import Set, List, Iterable, Dict
import requests
from bauh.api.http import HttpClient
import urllib.parse
from bauh.gems.arch import pacman, AUR_INDEX_FILE
from bauh.gems.arch.exceptions import PackageNotFoundException
URL_INFO = 'https://aur.archlinux.org/rpc/?v=5&type=info&'
URL_SRC_INFO = 'https://aur.archlinux.org/cgit/aur.git/plain/.SRCINFO?h='
URL_SEARCH = 'https://aur.archlinux.org/rpc/?v=5&type=search&arg='
URL_INDEX = 'https://aur.archlinux.org/packages.gz'
RE_SRCINFO_KEYS = re.compile(r'(\w+)\s+=\s+(.+)\n')
RE_SPLIT_DEP = re.compile(r'[<>]?=')
@@ -33,7 +35,9 @@ KNOWN_LIST_FIELDS = ('validpgpkeys',
'source_i686',
'makedepends',
'makedepends_x86_64',
'makedepends_i686')
'makedepends_i686',
'provides',
'conflicts')
def map_pkgbuild(pkgbuild: str) -> dict:
@@ -70,19 +74,30 @@ class AURClient:
self.http_client = http_client
self.logger = logger
self.x86_64 = x86_64
self.srcinfo_cache = {}
def search(self, words: str) -> dict:
return self.http_client.get_json(URL_SEARCH + words)
def get_info(self, names: Set[str]) -> List[dict]:
def get_info(self, names: Iterable[str]) -> List[dict]:
res = self.http_client.get_json(URL_INFO + self._map_names_as_queries(names))
return res['results'] if res and res.get('results') else []
def get_src_info(self, name: str) -> dict:
srcinfo = self.srcinfo_cache.get(name)
if srcinfo:
return srcinfo
res = self.http_client.get(URL_SRC_INFO + urllib.parse.quote(name))
if res and res.text:
return map_srcinfo(res.text)
srcinfo = map_srcinfo(res.text)
if srcinfo:
self.srcinfo_cache[name] = srcinfo
return srcinfo
self.logger.warning('No .SRCINFO found for {}'.format(name))
self.logger.info('Checking if {} is based on another package'.format(name))
@@ -96,7 +111,12 @@ class AURClient:
info_base = info.get('PackageBase')
if info_name and info_base and info_name != info_base:
self.logger.info('{p} is based on {b}. Retrieving {b} .SRCINFO'.format(p=info_name, b=info_base))
return self.get_src_info(info_base)
srcinfo = self.get_src_info(info_base)
if srcinfo:
self.srcinfo_cache[name] = srcinfo
return srcinfo
def extract_required_dependencies(self, srcinfo: dict) -> Set[str]:
deps = set()
@@ -123,7 +143,7 @@ class AURClient:
return '&'.join(['arg[{}]={}'.format(i, urllib.parse.quote(n)) for i, n in enumerate(names)])
def read_local_index(self) -> dict:
self.logger.info('Checking if the AUR index file exists')
self.logger.info('Checking if the cached AUR index file exists')
if os.path.exists(AUR_INDEX_FILE):
self.logger.info('Reading AUR index file from {}'.format(AUR_INDEX_FILE))
index = {}
@@ -135,3 +155,57 @@ class AURClient:
self.logger.info("AUR index file read")
return index
self.logger.warning('The AUR index file was not found')
def download_names(self) -> Set[str]:
self.logger.info('Downloading AUR index')
try:
res = self.http_client.get(URL_INDEX)
if res and res.text:
return {n.strip() for n in res.text.split('\n') if n and not n.startswith('#')}
else:
self.logger.warning('No data returned from: {}'.format(URL_INDEX))
except requests.exceptions.ConnectionError:
self.logger.warning('No internet connection: could not pre-index packages')
self.logger.info("Finished")
def read_index(self) -> Iterable[str]:
index = self.read_local_index()
if not index:
self.logger.warning("Cached AUR index file not found")
pkgnames = self.download_names()
if pkgnames:
return pkgnames
else:
self.logger.warning("Could not load AUR index on the context")
else:
return index.values()
def clean_caches(self):
self.srcinfo_cache.clear()
def map_update_data(self, pkgname: str, latest_version: str, srcinfo: dict = None) -> dict:
info = self.get_src_info(pkgname) if not srcinfo else srcinfo
provided = set()
provided.add(pkgname)
if info:
provided.add('{}={}'.format(pkgname, info['pkgver']))
if info.get('provides'):
provided.update(info.get('provides'))
return {'c': info.get('conflicts'), 's': None, 'p': provided, 'r': 'arch',
'v': info['pkgver'], 'd': self.extract_required_dependencies(info)}
else:
if latest_version:
provided.add('{}={}'.format(pkgname, latest_version))
return {'c': None, 's': None, 'p': provided, 'r': 'arch', 'v': latest_version, 'd': set()}
def fill_update_data(self, output: Dict[str, dict], pkgname: str, latest_version: str, srcinfo: dict = None):
data = self.map_update_data(pkgname=pkgname, latest_version=latest_version, srcinfo=srcinfo)
output[pkgname] = data