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