/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
1
# Copyright (C) 2018 Breezy Developers
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
0.434.1 by Jelmer Vernooij
Use absolute_import.
17
"""Support for GitHub."""
18
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
19
from __future__ import absolute_import
20
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
21
import os
22
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
23
from .propose import (
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
24
    Hoster,
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
25
    HosterLoginRequired,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
26
    MergeProposal,
0.432.2 by Jelmer Vernooij
Publish command sort of works.
27
    MergeProposalBuilder,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
28
    MergeProposalExists,
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
29
    NoSuchProject,
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
30
    PrerequisiteBranchUnsupported,
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
31
    UnsupportedHoster,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
32
    )
33
34
from ... import (
0.431.33 by Jelmer Vernooij
Fix URLs from gitlab.
35
    branch as _mod_branch,
0.432.3 by Jelmer Vernooij
Publish command works for github.
36
    controldir,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
37
    errors,
38
    hooks,
39
    urlutils,
0.432.3 by Jelmer Vernooij
Publish command works for github.
40
    version_string as breezy_version,
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
41
    )
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
42
from ...config import AuthenticationConfig, GlobalStack, config_dir
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
43
from ...errors import InvalidHttpResponse
0.431.32 by Jelmer Vernooij
Properly resolve git+ssh URLs.
44
from ...git.urls import git_url_to_bzr_url
0.432.3 by Jelmer Vernooij
Publish command works for github.
45
from ...i18n import gettext
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
46
from ...sixish import PY3
0.432.3 by Jelmer Vernooij
Publish command works for github.
47
from ...trace import note
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
48
from ...transport import get_transport
7296.10.5 by Jelmer Vernooij
use default_user_agent function.
49
from ...transport.http import default_user_agent
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
50
51
52
GITHUB_HOST = 'github.com'
53
WEB_GITHUB_URL = 'https://github.com'
54
API_GITHUB_URL = 'https://api.github.com'
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
55
56
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
57
def store_github_token(scheme, host, token):
58
    with open(os.path.join(config_dir(), 'github.conf'), 'w') as f:
59
        f.write(token)
60
61
62
def retrieve_github_token(scheme, host):
63
    path = os.path.join(config_dir(), 'github.conf')
64
    if not os.path.exists(path):
65
        return None
0.435.1 by Jelmer Vernooij
Fix reading github credentials.
66
    with open(path, 'r') as f:
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
67
        return f.read().strip()
68
69
0.431.44 by Jelmer Vernooij
Support get/set description.
70
def determine_title(description):
71
    return description.splitlines()[0]
72
73
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
74
class NotGitHubUrl(errors.BzrError):
75
76
    _fmt = "Not a GitHub URL: %(url)s"
77
78
    def __init__(self, url):
79
        errors.BzrError.__init__(self)
80
        self.url = url
81
82
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
83
class GitHubLoginRequired(HosterLoginRequired):
84
85
    _fmt = "Action requires GitHub login."
86
87
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
88
def connect_github():
7211.13.7 by Jelmer Vernooij
Fix formatting.
89
    """Connect to GitHub.
90
    """
7296.10.5 by Jelmer Vernooij
use default_user_agent function.
91
    user_agent = default_user_agent()
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
92
    auth = AuthenticationConfig()
93
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
94
    credentials = auth.get_credentials('https', GITHUB_HOST)
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
95
    if credentials is not None:
0.432.3 by Jelmer Vernooij
Publish command works for github.
96
        return Github(credentials['user'], credentials['password'],
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
97
                      user_agent=user_agent)
98
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
99
    # TODO(jelmer): token = auth.get_token('https', GITHUB_HOST)
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
100
    if token is not None:
0.431.61 by Jelmer Vernooij
Fix token login.
101
        return Github(token, user_agent=user_agent)
0.431.49 by Jelmer Vernooij
Store GitHub tokens in a magic file, for now.
102
    else:
103
        note('Accessing GitHub anonymously. To log in, run \'brz gh-login\'.')
104
        return Github(user_agent=user_agent)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
105
106
0.431.44 by Jelmer Vernooij
Support get/set description.
107
class GitHubMergeProposal(MergeProposal):
108
109
    def __init__(self, pr):
110
        self._pr = pr
111
112
    @property
113
    def url(self):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
114
        return self._pr['html_url']
0.431.44 by Jelmer Vernooij
Support get/set description.
115
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
116
    def _branch_from_part(self, part):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
117
        return github_url_to_bzr_url(part['repo']['html_url'], part['ref'])
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
118
119
    def get_source_branch_url(self):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
120
        return self._branch_from_part(self._pr['head'])
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
121
122
    def get_target_branch_url(self):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
123
        return self._branch_from_part(self._pr['base'])
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
124
0.431.44 by Jelmer Vernooij
Support get/set description.
125
    def get_description(self):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
126
        return self._pr['body']
0.431.44 by Jelmer Vernooij
Support get/set description.
127
7296.8.2 by Jelmer Vernooij
Add feature flag for commit message.
128
    def get_commit_message(self):
129
        return None
130
0.431.44 by Jelmer Vernooij
Support get/set description.
131
    def set_description(self, description):
132
        self._pr.edit(body=description, title=determine_title(description))
133
0.431.46 by Jelmer Vernooij
Add MergeProposal.is_merged.
134
    def is_merged(self):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
135
        return self._pr['merged']
0.431.46 by Jelmer Vernooij
Add MergeProposal.is_merged.
136
7260.2.1 by Jelmer Vernooij
Implement .close on merge proposals.
137
    def close(self):
138
        self._pr.edit(state='closed')
139
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
140
    def merge(self, commit_message=None):
141
        # https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-button
142
        self._pr.merge(commit_message=commit_message)
143
0.431.44 by Jelmer Vernooij
Support get/set description.
144
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
145
def parse_github_url(url):
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
146
    (scheme, user, password, host, port, path) = urlutils.parse_url(
147
        url)
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
148
    if host != GITHUB_HOST:
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
149
        raise NotGitHubUrl(url)
150
    (owner, repo_name) = path.strip('/').split('/')
0.432.12 by Jelmer Vernooij
Fix .git ends.
151
    if repo_name.endswith('.git'):
152
        repo_name = repo_name[:-4]
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
153
    return owner, repo_name
154
155
156
def parse_github_branch_url(branch):
157
    url = urlutils.split_segment_parameters(branch.user_url)[0]
158
    owner, repo_name = parse_github_url(url)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
159
    return owner, repo_name, branch.name
160
161
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
162
def github_url_to_bzr_url(url, branch_name):
163
    if not PY3:
164
        branch_name = branch_name.encode('utf-8')
165
    return urlutils.join_segment_parameters(
7211.13.7 by Jelmer Vernooij
Fix formatting.
166
        git_url_to_bzr_url(url), {"branch": branch_name})
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
167
168
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
169
class GitHub(Hoster):
170
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
171
    name = 'github'
172
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
173
    supports_merge_proposal_labels = True
7296.8.2 by Jelmer Vernooij
Add feature flag for commit message.
174
    supports_merge_proposal_commit_message = False
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
175
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
176
    def __repr__(self):
177
        return "GitHub()"
178
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
179
    def _api_request(self, method, path):
180
        headers = {
181
            'Accept': 'application/vnd.github.v3+json'}
182
        if self._token:
183
            headers['Authorization'] = 'token %s' % self._token
184
        response = self.transport.request(
185
            method, urlutils.join(self.transport.base, path),
186
            headers=headers)
187
        if response.status == 401:
188
            raise GitHubLoginRequired(self)
189
        return response
190
191
    def _get_repo(self, path):
192
        path = 'repos/' + path
193
        response = self._api_request('GET', path)
194
        if response.status == 404:
195
            raise NoSuchProject(path)
196
        if response.status == 200:
197
            return response.json
198
        raise InvalidHttpResponse(path, response.text)
199
200
    def _get_user(self, username=None):
201
        if username:
202
            path = 'users/:%s' % username
203
        else:
204
            path = 'user'
205
        response = self._api_request('GET', path)
206
        if response.status != 200:
207
            raise InvalidHttpResponse(path, response.text)
208
        return response.json
209
210
    def _get_organization(self, name):
211
        path = 'orgs/:%s' % name
212
        response = self._api_request('GET', path)
213
        if response.status != 200:
214
            raise InvalidHttpResponse(path, response.text)
215
        return response.json
216
217
    def _search_issues(self, query):
218
        path = 'search/issues'
219
        response = self._api_request(
220
            'GET', path + '?q=' + urlutils.quote(query))
221
        if response.status != 200:
222
            raise InvalidHttpResponse(path, response.text)
223
        return response.json
224
225
    def _create_fork(self, repo, owner=None):
226
        (orig_owner, orig_repo) = repo.split('/')
227
        path = '/repos/:%s/:%s/forks' % (orig_owner, orig_repo)
228
        if owner:
229
            path += '?organization=%s' % owner
230
        response = self._api_request('POST', path)
231
        if response != 202:
232
            raise InvalidHttpResponse(path, response.text)
233
        return response.json
234
7260.1.1 by Jelmer Vernooij
Add .base_url property to Hoster.
235
    @property
236
    def base_url(self):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
237
        return WEB_GITHUB_URL
238
239
    def __init__(self, transport):
240
        self._token = retrieve_github_token('https', GITHUB_HOST)
241
        self.transport = transport
242
        self._current_user = self._get_user()
243
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
244
    def publish_derived(self, local_branch, base_branch, name, project=None,
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
245
                        owner=None, revision_id=None, overwrite=False,
246
                        allow_lossy=True):
0.432.12 by Jelmer Vernooij
Fix .git ends.
247
        import github
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
248
        base_owner, base_project, base_branch_name = parse_github_branch_url(base_branch)
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
249
        base_repo = self._get_repo('%s/%s' % (base_owner, base_project))
0.432.3 by Jelmer Vernooij
Publish command works for github.
250
        if owner is None:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
251
            owner = self._current_user['login']
0.432.3 by Jelmer Vernooij
Publish command works for github.
252
        if project is None:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
253
            project = base_repo['name']
0.432.3 by Jelmer Vernooij
Publish command works for github.
254
        try:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
255
            remote_repo = self._get_repo('%s/%s' % (owner, project))
0.432.12 by Jelmer Vernooij
Fix .git ends.
256
        except github.UnknownObjectException:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
257
            base_repo = self._get_repo('%s/%s' % (base_owner, base_project))
258
            remote_repo = self._create_fork(base_repo, owner)
0.432.3 by Jelmer Vernooij
Publish command works for github.
259
            note(gettext('Forking new repository %s from %s') %
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
260
                 (remote_repo['html_url'], base_repo['html_url']))
0.432.3 by Jelmer Vernooij
Publish command works for github.
261
        else:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
262
            note(gettext('Reusing existing repository %s') % remote_repo['html_url'])
263
        remote_dir = controldir.ControlDir.open(git_url_to_bzr_url(remote_repo['ssh_url']))
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
264
        try:
7211.13.7 by Jelmer Vernooij
Fix formatting.
265
            push_result = remote_dir.push_branch(
266
                local_branch, revision_id=revision_id, overwrite=overwrite,
267
                name=name)
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
268
        except errors.NoRoundtrippingSupport:
269
            if not allow_lossy:
270
                raise
7211.13.7 by Jelmer Vernooij
Fix formatting.
271
            push_result = remote_dir.push_branch(
272
                local_branch, revision_id=revision_id,
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
273
                overwrite=overwrite, name=name, lossy=True)
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
274
        return push_result.target_branch, github_url_to_bzr_url(
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
275
            remote_repo['html_url'], name)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
276
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
277
    def get_push_url(self, branch):
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
278
        owner, project, branch_name = parse_github_branch_url(branch)
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
279
        repo = self._get_repo('%s/%s' % (owner, project))
280
        return github_url_to_bzr_url(repo['ssh_url'], branch_name)
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
281
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
282
    def get_derived_branch(self, base_branch, name, project=None, owner=None):
283
        import github
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
284
        base_owner, base_project, base_branch_name = parse_github_branch_url(base_branch)
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
285
        base_repo = self._get_repo('%s/%s' % (base_owner, base_project))
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
286
        if owner is None:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
287
            owner = self._current_user['login']
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
288
        if project is None:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
289
            project = base_repo['name']
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
290
        try:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
291
            remote_repo = self._get_repo('%s/%s' % (owner, project))
292
            full_url = github_url_to_bzr_url(remote_repo['ssh_url'], name)
0.431.33 by Jelmer Vernooij
Fix URLs from gitlab.
293
            return _mod_branch.Branch.open(full_url)
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
294
        except github.UnknownObjectException:
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
295
            raise errors.NotBranchError('%s/%s/%s' % (WEB_GITHUB_URL, owner, project))
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
296
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
297
    def get_proposer(self, source_branch, target_branch):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
298
        return GitHubMergeProposalBuilder(self, source_branch, target_branch)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
299
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
300
    def iter_proposals(self, source_branch, target_branch, status='open'):
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
301
        (source_owner, source_repo_name, source_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
302
            parse_github_branch_url(source_branch))
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
303
        (target_owner, target_repo_name, target_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
304
            parse_github_branch_url(target_branch))
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
305
        target_repo = self._get_repo(
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
306
            "%s/%s" % (target_owner, target_repo_name))
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
307
        state = {
308
            'open': 'open',
309
            'merged': 'closed',
310
            'closed': 'closed',
311
            'all': 'all'}
312
        for pull in target_repo.get_pulls(
313
                head=target_branch_name,
314
                state=state[status]):
315
            if (status == 'closed' and pull.merged or
316
                    status == 'merged' and not pull.merged):
317
                continue
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
318
            if pull.head.ref != source_branch_name:
319
                continue
7268.4.1 by Jelmer Vernooij
Don't attempt to resolve None when repo has gone away.
320
            if pull.head.repo is None:
321
                # Repo has gone the way of the dodo
322
                continue
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
323
            if (pull.head.repo.owner.login != source_owner or
7211.13.7 by Jelmer Vernooij
Fix formatting.
324
                    pull.head.repo.name != source_repo_name):
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
325
                continue
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
326
            yield GitHubMergeProposal(pull)
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
327
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
328
    def hosts(self, branch):
329
        try:
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
330
            parse_github_branch_url(branch)
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
331
        except NotGitHubUrl:
332
            return False
333
        else:
334
            return True
335
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
336
    @classmethod
7296.10.1 by Jelmer Vernooij
Initial work making gitlab just directly use ReST.
337
    def probe_from_url(cls, url, possible_transports=None):
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
338
        try:
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
339
            parse_github_url(url)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
340
        except NotGitHubUrl:
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
341
            raise UnsupportedHoster(url)
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
342
        transport = get_transport(
343
            API_GITHUB_URL, possible_transports=possible_transports)
344
        return cls(transport)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
345
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
346
    @classmethod
347
    def iter_instances(cls):
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
348
        yield cls(get_transport(API_GITHUB_URL))
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
349
0.431.66 by Jelmer Vernooij
Add support for status argument.
350
    def iter_my_proposals(self, status='open'):
351
        query = ['is:pr']
352
        if status == 'open':
353
            query.append('is:open')
354
        elif status == 'closed':
355
            query.append('is:unmerged')
7268.2.1 by Jelmer Vernooij
Don't include open unmerged pull requests in 'closed'.
356
            # Also use "is:closed" otherwise unmerged open pull requests are
357
            # also included.
358
            query.append('is:closed')
0.431.66 by Jelmer Vernooij
Add support for status argument.
359
        elif status == 'merged':
360
            query.append('is:merged')
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
361
        query.append('author:%s' % self._current_user['login'])
362
        for issue in self._search_issues(query=' '.join(query))['items']:
363
            yield GitHubMergeProposal(
364
                self.transport.request('GET', issue['pull_request']['url']).json)
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
365
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
366
    @convert_github_error
367
    def get_proposal_by_url(self, url):
368
        raise UnsupportedHoster(url)
369
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
370
0.432.2 by Jelmer Vernooij
Publish command sort of works.
371
class GitHubMergeProposalBuilder(MergeProposalBuilder):
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
372
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
373
    def __init__(self, gh, source_branch, target_branch):
374
        self.gh = gh
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
375
        self.source_branch = source_branch
376
        self.target_branch = target_branch
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
377
        (self.target_owner, self.target_repo_name, self.target_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
378
            parse_github_branch_url(self.target_branch))
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
379
        (self.source_owner, self.source_repo_name, self.source_branch_name) = (
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
380
            parse_github_branch_url(self.source_branch))
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
381
382
    def get_infotext(self):
383
        """Determine the initial comment for the merge proposal."""
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
384
        info = []
385
        info.append("Merge %s into %s:%s\n" % (
386
            self.source_branch_name, self.target_owner,
387
            self.target_branch_name))
388
        info.append("Source: %s\n" % self.source_branch.user_url)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
389
        info.append("Target: %s\n" % self.target_branch.user_url)
390
        return ''.join(info)
391
392
    def get_initial_body(self):
393
        """Get a body for the proposal for the user to modify.
394
395
        :return: a str or None.
396
        """
397
        return None
398
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
399
    def create_proposal(self, description, reviewers=None, labels=None,
7296.8.1 by Jelmer Vernooij
Add commit-message option to 'brz propose'.
400
                        prerequisite_branch=None, commit_message=None):
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
401
        """Perform the submission."""
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
402
        if prerequisite_branch is not None:
403
            raise PrerequisiteBranchUnsupported(self)
7296.8.1 by Jelmer Vernooij
Add commit-message option to 'brz propose'.
404
        # Note that commit_message is ignored, since github doesn't support it.
0.432.10 by Jelmer Vernooij
More test fixes.
405
        import github
0.432.7 by Jelmer Vernooij
propose works \o/
406
        # TODO(jelmer): Probe for right repo name
0.432.12 by Jelmer Vernooij
Fix .git ends.
407
        if self.target_repo_name.endswith('.git'):
408
            self.target_repo_name = self.target_repo_name[:-4]
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
409
        target_repo = self.gh._get_repo("%s/%s" % (self.target_owner, self.target_repo_name))
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
410
        # TODO(jelmer): Allow setting title explicitly?
0.431.44 by Jelmer Vernooij
Support get/set description.
411
        title = determine_title(description)
0.431.4 by Jelmer Vernooij
Add basic GitHub support.
412
        # TOOD(jelmer): Set maintainers_can_modify?
0.432.10 by Jelmer Vernooij
More test fixes.
413
        try:
414
            pull_request = target_repo.create_pull(
415
                title=title, body=description,
416
                head="%s:%s" % (self.source_owner, self.source_branch_name),
417
                base=self.target_branch_name)
418
        except github.GithubException as e:
419
            if e.status == 422:
420
                raise MergeProposalExists(self.source_branch.user_url)
421
            raise
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
422
        if reviewers:
423
            for reviewer in reviewers:
424
                pull_request.assignees.append(
7296.11.1 by Jelmer Vernooij
Initial work migrating GitHub away from library.
425
                    self.gh._get_user(reviewer)['login'])
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
426
        if labels:
427
            for label in labels:
428
                pull_request.issue.labels.append(label)
0.431.44 by Jelmer Vernooij
Support get/set description.
429
        return GitHubMergeProposal(pull_request)