""" A package source module to import ebuilds and patches from bugzilla """ import xmlrpc.client from os import path from urllib.parse import urlparse from pomu.package import Package from pomu.source import dispatcher from pomu.util.iquery import EditSelectPrompt from pomu.util.misc import extract_urls from pomu.util.query import query from pomu.util.result import Result class BzEbuild(): """A class to represent a local ebuild""" __name__ = 'fs' def __init__(self, bug_id, filemap, category, name, version, slot='0'): self.bug_id = bug_id self.filemap = filemap self.category = category self.name = name self.version = version self.slot = slot def fetch(self): return Package(self.name, '/', self, self.category, self.version, filemap=self.filemap) @staticmethod def from_data_dir(pkgdir): with open(path.join(pkgdir, 'BZ_BUG_ID'), 'r') as f: return BugzillaSource.parse_bug(f.readline()).unwrap() def write_meta(self, pkgdir): with open(path.join(pkgdir, 'BZ_BUG_ID'), 'w') as f: f.write(self.bug_id + '\n') def __str__(self): return '{}/{}-{} (from {})'.format(self.category, self.name, self.version, self.path) CLIENT_BASE = 'https://bugs.gentoo.org/xmlrpc.cgi' @dispatcher.source class BugzillaSource(): """The source module responsible for importing ebuilds and patches from bugzilla tickets""" @dispatcher.handler(priority=1) def parse_bug(uri): if not uri.isdigit(): return Result.Err() uri = int(uri) proxy = xmlrpc.client.ServerProxy(CLIENT_BASE).Bug payload = {'ids': [uri]} try: bug = proxy.get(payload) except (xmlrpc.client.Fault, OverflowError) as err: return Result.Err(str(err)) attachments = proxy.attachments(payload)['bugs'][str(uri)] comments = proxy.comments(payload)['bugs'][str(uri)]['comments'] comment_links = [] for comment in comments: comment_links.extend(extract_urls(comment['text'])) items = [(x['file_name'], x['data'].data.decode('utf-8')) for x in attachments] + comment_links if not items: return Result.Err() p = EditSelectPrompt(items) files = p.run() if not files: return Result.Err() category = query('category', 'Please enter package category').expect() name = query('name', 'Please enter package name').expect() ver = query('version', 'Please specify package version for {}'.format(name)).expect() slot = query('slot', 'Please specify package slot', '0').expect() fmap = {path.join(category, name, x[2]): x[1] for x in files} return Result.Ok(BzEbuild(uri, fmap, category, name, ver, slot)) @dispatcher.handler(priority=2) def parse_link(uri): res = urlparse(uri) if res.netloc != 'bugs.gentoo.org': return Result.Err() if res.path == '/show_bugs.cgi': ps = [x.split('=') for x in res.params.split('&') if x.startswith('id=')][1] return BugzillaSource.parse_bug(ps) if res.path.lstrip('/').isdigit(): return BugzillaSource.parse_bug(res.path.lstrip('/')) return Result.Err() @dispatcher.handler() def parse_full(uri): if not uri.startswith('bug:'): return Result.Err() rem = uri[4:] if rem.isdigit(): return BugzillaSource.parse_bug(rem) return BugzillaSource.parse_link(rem) @classmethod def fetch_package(self, pkg): return pkg.fetch() @classmethod def from_meta_dir(cls, metadir): return BzEbuild.from_data_dir(cls, metadir)