aboutsummaryrefslogtreecommitdiff
blob: 62916a3bb3dfb2ecd169ca85af5cd3468361eac8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
"""
A package source module to import ebuilds and patches from bugzilla
"""

import xmlrpc.client
from os import path
from urllib.parse import urlparse

from pbraw import grab

from pomu.package import Package
from pomu.source import dispatcher
from pomu.util.misc import extract_urls, parse_range
from pomu.util.pkg import cpv_split, ver_str
from pomu.util.query import query, QueryContext
from pomu.util.result import Result

class BzEbuild():
    """A class to represent a local ebuild"""
    __name__ = 'fs'

    # slots?
    def __init__(self, bug_id, category, name, version, filemap):
        self.bug_id = bug_id
        self.category = category
        self.name = name
        self.version = version
        self.filemap = filemap

    def fetch(self):
        return Package(self.name, '/', self, self.category, self.version, 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(text))
        items = attachments + comment_links
        if not items:
            return Result.Err()
        lines = ['Please select required items (ranges are accepted)']
        for idx, item in enumerate(items):
            if isinstance(item, str):
                lines.append('{} - {}'.format(idx, item))
            else:
                lines.append('{} - Attachment: {}'.format(idx, item['file_name']))
        lines.append('>>> ')
        rng = query('items', '\n'.join(lines), 1)
        idxs = parse_range(rng, len(items))
        if not idxs:
            return Result.Err()
        filtered = [x for idx, x in enumerate(items) if idx in idxs]
        files = []
        for idx, item in enumerate(idxs):
            if isinstance(item, str):
                files.extend([(x[0], x[1].encode('utf-8')) for x in grab(item)])
            else:
                files.append((item['file_name'], item['data']))
        if not files:
            return Result.Err()
        category = query('category', 'Please enter package category').expect()
        name = query('name', 'Please enter package name')
        ver = query('version', 'Please specify package version for {}'.format(name)).expect()
        # TODO: ???
        fmap = {}
        for fn, data in files:
            with QueryContext(path=None):
                fpath = query('path', 'Please enter path for {} file'.format(fn), path.join(category, name, fn))
                fmap[fpath] = data



        return Result.Ok(BzEbuild(uri, category, name, ver, uri))

    @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 from_meta_dir(cls, metadir):
        return BzEbuild.from_data_dir(cls, metadir)