/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
0.431.5 by Jelmer Vernooij
Initial work on gitlab 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 GitLab."""
18
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
19
from __future__ import absolute_import
20
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
21
from ... import (
0.431.33 by Jelmer Vernooij
Fix URLs from gitlab.
22
    branch as _mod_branch,
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
23
    controldir,
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
24
    errors,
25
    urlutils,
26
    )
0.432.4 by Jelmer Vernooij
Some work on gitlab.
27
from ...config import AuthenticationConfig
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
28
from ...git.urls import git_url_to_bzr_url
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
29
from ...sixish import PY3
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
30
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
31
from .propose import (
0.432.2 by Jelmer Vernooij
Publish command sort of works.
32
    Hoster,
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
33
    MergeProposal,
0.432.2 by Jelmer Vernooij
Publish command sort of works.
34
    MergeProposalBuilder,
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
35
    MergeProposalExists,
0.431.38 by Jelmer Vernooij
Add NoSuchProject.
36
    NoSuchProject,
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
37
    PrerequisiteBranchUnsupported,
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
38
    UnsupportedHoster,
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
39
    )
40
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
41
def mp_status_to_status(status):
42
    return {
43
        'all': 'all',
44
        'open': 'opened',
45
        'merged': 'merged',
46
        'closed': 'closed'}[status]
47
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
48
0.431.17 by Jelmer Vernooij
Try harder to avoid detecting any URL as a GitLab URL.
49
class NotGitLabUrl(errors.BzrError):
50
51
    _fmt = "Not a GitLab URL: %(url)s"
52
53
    def __init__(self, url):
54
        errors.BzrError.__init__(self)
55
        self.url = url
56
57
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
58
class DifferentGitLabInstances(errors.BzrError):
59
60
    _fmt = ("Can't create merge proposals across GitLab instances: "
61
            "%(source_host)s and %(target_host)s")
62
63
    def __init__(self, source_host, target_host):
64
        self.source_host = source_host
65
        self.target_host = target_host
66
67
0.432.10 by Jelmer Vernooij
More test fixes.
68
class GitLabLoginMissing(errors.BzrError):
69
70
    _fmt = ("Please log into GitLab")
71
72
0.431.59 by Jelmer Vernooij
Add gitlab-login command.
73
def default_config_path():
74
    from breezy.config import config_dir
75
    import os
76
    return os.path.join(config_dir(), 'gitlab.conf')
77
78
79
def store_gitlab_token(name, url, private_token):
80
    """Store a GitLab token in a configuration file."""
81
    import configparser
82
    config = configparser.ConfigParser()
83
    path = default_config_path()
84
    config.read([path])
85
    config.add_section(name)
86
    config[name]['url'] = url
87
    config[name]['private_token'] = private_token
88
    with open(path, 'w') as f:
89
        config.write(f)
90
91
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
92
def iter_tokens():
93
    import configparser
94
    from gitlab.config import _DEFAULT_FILES
95
    config = configparser.ConfigParser()
96
    config.read(_DEFAULT_FILES + [default_config_path()])
97
    for name, section in config.items():
98
        yield name, section
99
100
0.432.10 by Jelmer Vernooij
More test fixes.
101
def connect_gitlab(host):
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
102
    from gitlab import Gitlab, GitlabGetError
0.432.4 by Jelmer Vernooij
Some work on gitlab.
103
    auth = AuthenticationConfig()
104
0.432.10 by Jelmer Vernooij
More test fixes.
105
    url = 'https://%s' % host
106
    credentials = auth.get_credentials('https', host)
0.432.4 by Jelmer Vernooij
Some work on gitlab.
107
    if credentials is None:
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
108
        for name, section in iter_tokens():
0.432.10 by Jelmer Vernooij
More test fixes.
109
            if section.get('url') == url:
110
                credentials = section
111
                break
112
        else:
0.431.10 by Jelmer Vernooij
Various other fixes.
113
            try:
114
                return Gitlab(url)
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
115
            except GitlabGetError:
0.431.10 by Jelmer Vernooij
Various other fixes.
116
                raise GitLabLoginMissing()
0.432.10 by Jelmer Vernooij
More test fixes.
117
    else:
118
        credentials['url'] = url
119
    return Gitlab(**credentials)
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
120
121
122
def parse_gitlab_url(branch):
123
    url = urlutils.split_segment_parameters(branch.user_url)[0]
124
    (scheme, user, password, host, port, path) = urlutils.parse_url(
125
        url)
0.431.17 by Jelmer Vernooij
Try harder to avoid detecting any URL as a GitLab URL.
126
    if scheme not in ('git+ssh', 'https', 'http'):
127
        raise NotGitLabUrl(branch.user_url)
128
    if not host:
129
        raise NotGitLabUrl(branch.user_url)
0.432.10 by Jelmer Vernooij
More test fixes.
130
    path = path.strip('/')
0.432.11 by Jelmer Vernooij
Fix some tests.
131
    if path.endswith('.git'):
132
        path = path[:-4]
0.432.10 by Jelmer Vernooij
More test fixes.
133
    return host, path, branch.name
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
134
135
0.431.39 by Jelmer Vernooij
Extend the merge proposal abstraction a bit.
136
class GitLabMergeProposal(MergeProposal):
137
138
    def __init__(self, mr):
139
        self._mr = mr
140
141
    @property
142
    def url(self):
143
        return self._mr.web_url
144
145
    def get_description(self):
146
        return self._mr.description
147
148
    def set_description(self, description):
149
        self._mr.description = description
150
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
151
    def _branch_url_from_project(self, project_id, branch_name):
152
        project = self._mr.manager.gitlab.projects.get(project_id)
153
        return gitlab_url_to_bzr_url(project.http_url_to_repo, branch_name)
154
155
    def get_source_branch_url(self):
156
        return self._branch_url_from_project(
157
            self._mr.source_project_id, self._mr.source_branch)
158
159
    def get_target_branch_url(self):
160
        return self._branch_url_from_project(
161
            self._mr.target_project_id, self._mr.target_branch)
162
0.431.46 by Jelmer Vernooij
Add MergeProposal.is_merged.
163
    def is_merged(self):
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
164
        return (self._mr.state == 'merged')
0.431.46 by Jelmer Vernooij
Add MergeProposal.is_merged.
165
0.431.39 by Jelmer Vernooij
Extend the merge proposal abstraction a bit.
166
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
167
def gitlab_url_to_bzr_url(url, name):
168
    if not PY3:
169
        name = name.encode('utf-8')
170
    return urlutils.join_segment_parameters(
7211.13.7 by Jelmer Vernooij
Fix formatting.
171
        git_url_to_bzr_url(url), {"branch": name})
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
172
173
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
174
class GitLab(Hoster):
175
    """GitLab hoster implementation."""
176
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
177
    supports_merge_proposal_labels = True
178
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
179
    def __repr__(self):
180
        return "<GitLab(%r)>" % self.gl.url
181
7260.1.1 by Jelmer Vernooij
Add .base_url property to Hoster.
182
    @property
183
    def base_url(self):
184
        return self.gl.url
185
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
186
    def __init__(self, gl):
187
        self.gl = gl
188
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
189
    def get_push_url(self, branch):
190
        (host, project_name, branch_name) = parse_gitlab_url(branch)
191
        project = self.gl.projects.get(project_name)
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
192
        return gitlab_url_to_bzr_url(
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
193
            project.ssh_url_to_repo, branch_name)
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
194
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
195
    def publish_derived(self, local_branch, base_branch, name, project=None,
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
196
                        owner=None, revision_id=None, overwrite=False,
197
                        allow_lossy=True):
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
198
        import gitlab
0.432.4 by Jelmer Vernooij
Some work on gitlab.
199
        (host, base_project, base_branch_name) = parse_gitlab_url(base_branch)
0.432.10 by Jelmer Vernooij
More test fixes.
200
        self.gl.auth()
0.431.38 by Jelmer Vernooij
Add NoSuchProject.
201
        try:
202
            base_project = self.gl.projects.get(base_project)
203
        except gitlab.GitlabGetError as e:
204
            if e.response_code == 404:
205
                raise NoSuchProject(base_project)
206
            else:
207
                raise
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
208
        if owner is None:
0.432.10 by Jelmer Vernooij
More test fixes.
209
            owner = self.gl.user.username
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
210
        if project is None:
0.431.30 by Jelmer Vernooij
s/name/path.
211
            project = base_project.path
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
212
        try:
0.432.10 by Jelmer Vernooij
More test fixes.
213
            target_project = self.gl.projects.get('%s/%s' % (owner, project))
0.431.30 by Jelmer Vernooij
s/name/path.
214
        except gitlab.GitlabGetError as e:
215
            if e.response_code == 404:
216
                target_project = base_project.forks.create({})
217
            else:
218
                raise
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
219
        remote_repo_url = git_url_to_bzr_url(target_project.ssh_url_to_repo)
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
220
        remote_dir = controldir.ControlDir.open(remote_repo_url)
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
221
        try:
7211.13.7 by Jelmer Vernooij
Fix formatting.
222
            push_result = remote_dir.push_branch(
223
                local_branch, revision_id=revision_id, overwrite=overwrite,
224
                name=name)
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
225
        except errors.NoRoundtrippingSupport:
226
            if not allow_lossy:
227
                raise
7211.13.7 by Jelmer Vernooij
Fix formatting.
228
            push_result = remote_dir.push_branch(
229
                local_branch, revision_id=revision_id, overwrite=overwrite,
230
                name=name, lossy=True)
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
231
        public_url = gitlab_url_to_bzr_url(
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
232
            target_project.http_url_to_repo, name)
0.432.5 by Jelmer Vernooij
Fix publishing to gitlab.
233
        return push_result.target_branch, public_url
0.432.4 by Jelmer Vernooij
Some work on gitlab.
234
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
235
    def get_derived_branch(self, base_branch, name, project=None, owner=None):
236
        import gitlab
237
        (host, base_project, base_branch_name) = parse_gitlab_url(base_branch)
238
        self.gl.auth()
0.431.38 by Jelmer Vernooij
Add NoSuchProject.
239
        try:
240
            base_project = self.gl.projects.get(base_project)
241
        except gitlab.GitlabGetError as e:
242
            if e.response_code == 404:
243
                raise NoSuchProject(base_project)
244
            else:
245
                raise
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
246
        if owner is None:
247
            owner = self.gl.user.username
248
        if project is None:
0.431.30 by Jelmer Vernooij
s/name/path.
249
            project = base_project.path
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
250
        try:
251
            target_project = self.gl.projects.get('%s/%s' % (owner, project))
252
        except gitlab.GitlabGetError as e:
253
            if e.response_code == 404:
254
                raise errors.NotBranchError('%s/%s/%s' % (self.gl.url, owner, project))
255
            raise
0.433.3 by Jelmer Vernooij
Some python 3 compatibility.
256
        return _mod_branch.Branch.open(gitlab_url_to_bzr_url(
7233.3.2 by Jelmer Vernooij
Merge lp:brz-propose.
257
            target_project.ssh_url_to_repo, name))
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
258
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
259
    def get_proposer(self, source_branch, target_branch):
260
        return GitlabMergeProposalBuilder(self.gl, source_branch, target_branch)
261
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
262
    def iter_proposals(self, source_branch, target_branch, status):
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
263
        import gitlab
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
264
        (source_host, source_project_name, source_branch_name) = (
265
            parse_gitlab_url(source_branch))
266
        (target_host, target_project_name, target_branch_name) = (
267
            parse_gitlab_url(target_branch))
268
        if source_host != target_host:
269
            raise DifferentGitLabInstances(source_host, target_host)
270
        self.gl.auth()
271
        source_project = self.gl.projects.get(source_project_name)
272
        target_project = self.gl.projects.get(target_project_name)
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
273
        state = mp_status_to_status(status)
0.431.43 by Jelmer Vernooij
Handle 403s during proposal listing.
274
        try:
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
275
            for mr in target_project.mergerequests.list(state=state):
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
276
                if (mr.source_project_id != source_project.id or
7233.3.2 by Jelmer Vernooij
Merge lp:brz-propose.
277
                        mr.source_branch != source_branch_name or
278
                        mr.target_project_id != target_project.id or
279
                        mr.target_branch != target_branch_name):
0.431.43 by Jelmer Vernooij
Handle 403s during proposal listing.
280
                    continue
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
281
                yield GitLabMergeProposal(mr)
0.431.43 by Jelmer Vernooij
Handle 403s during proposal listing.
282
        except gitlab.GitlabListError as e:
283
            if e.response_code == 403:
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
284
                raise errors.PermissionDenied(e.error_message)
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
285
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
286
    def hosts(self, branch):
287
        try:
288
            (host, project, branch_name) = parse_gitlab_url(branch)
289
        except NotGitLabUrl:
290
            return False
291
        return (self.gl.url == ('https://%s' % host))
292
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
293
    @classmethod
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
294
    def probe(cls, branch):
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
295
        try:
296
            (host, project, branch_name) = parse_gitlab_url(branch)
0.431.17 by Jelmer Vernooij
Try harder to avoid detecting any URL as a GitLab URL.
297
        except NotGitLabUrl:
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
298
            raise UnsupportedHoster(branch)
0.432.4 by Jelmer Vernooij
Some work on gitlab.
299
        import gitlab
0.431.43 by Jelmer Vernooij
Handle 403s during proposal listing.
300
        import requests.exceptions
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
301
        try:
0.432.4 by Jelmer Vernooij
Some work on gitlab.
302
            gl = connect_gitlab(host)
0.431.10 by Jelmer Vernooij
Various other fixes.
303
            gl.auth()
0.431.43 by Jelmer Vernooij
Handle 403s during proposal listing.
304
        except requests.exceptions.SSLError:
7211.13.7 by Jelmer Vernooij
Fix formatting.
305
            # Well, I guess it could be..
0.431.43 by Jelmer Vernooij
Handle 403s during proposal listing.
306
            raise UnsupportedHoster(branch)
0.432.4 by Jelmer Vernooij
Some work on gitlab.
307
        except gitlab.GitlabGetError:
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
308
            raise UnsupportedHoster(branch)
0.431.10 by Jelmer Vernooij
Various other fixes.
309
        except gitlab.GitlabHttpError as e:
0.431.27 by Jelmer Vernooij
Catch 503 errors.
310
            if e.response_code in (404, 405, 503):
0.431.10 by Jelmer Vernooij
Various other fixes.
311
                raise UnsupportedHoster(branch)
312
            else:
313
                raise
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
314
        return cls(gl)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
315
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
316
    @classmethod
317
    def iter_instances(cls):
318
        from gitlab import Gitlab
319
        for name, credentials in iter_tokens():
320
            if 'url' not in credentials:
321
                continue
322
            gl = Gitlab(**credentials)
323
            yield cls(gl)
324
0.431.66 by Jelmer Vernooij
Add support for status argument.
325
    def iter_my_proposals(self, status='open'):
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
326
        state = mp_status_to_status(status)
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
327
        self.gl.auth()
0.431.66 by Jelmer Vernooij
Add support for status argument.
328
        for mp in self.gl.mergerequests.list(
329
                owner=self.gl.user.username, state=state):
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
330
            yield GitLabMergeProposal(mp)
331
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
332
0.432.2 by Jelmer Vernooij
Publish command sort of works.
333
class GitlabMergeProposalBuilder(MergeProposalBuilder):
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
334
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
335
    def __init__(self, gl, source_branch, target_branch):
336
        self.gl = gl
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
337
        self.source_branch = source_branch
338
        (self.source_host, self.source_project_name, self.source_branch_name) = (
339
            parse_gitlab_url(source_branch))
340
        self.target_branch = target_branch
341
        (self.target_host, self.target_project_name, self.target_branch_name) = (
342
            parse_gitlab_url(target_branch))
343
        if self.source_host != self.target_host:
344
            raise DifferentGitLabInstances(self.source_host, self.target_host)
345
346
    def get_infotext(self):
347
        """Determine the initial comment for the merge proposal."""
348
        info = []
349
        info.append("Gitlab instance: %s\n" % self.target_host)
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
350
        info.append("Source: %s\n" % self.source_branch.user_url)
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
351
        info.append("Target: %s\n" % self.target_branch.user_url)
352
        return ''.join(info)
353
354
    def get_initial_body(self):
355
        """Get a body for the proposal for the user to modify.
356
357
        :return: a str or None.
358
        """
359
        return None
360
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
361
    def create_proposal(self, description, reviewers=None, labels=None,
362
                        prerequisite_branch=None):
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
363
        """Perform the submission."""
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
364
        if prerequisite_branch is not None:
365
            raise PrerequisiteBranchUnsupported(self)
0.431.16 by Jelmer Vernooij
gitlab: Report when a merge proposal already exists.
366
        import gitlab
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
367
        # TODO(jelmer): Support reviewers
0.432.10 by Jelmer Vernooij
More test fixes.
368
        self.gl.auth()
369
        source_project = self.gl.projects.get(self.source_project_name)
370
        target_project = self.gl.projects.get(self.target_project_name)
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
371
        # TODO(jelmer): Allow setting title explicitly
372
        title = description.splitlines()[0]
373
        # TODO(jelmer): Allow setting allow_collaboration field
374
        # TODO(jelmer): Allow setting milestone field
375
        # TODO(jelmer): Allow setting squash field
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
376
        kwargs = {
0.431.6 by Jelmer Vernooij
Initial gitlab support works.
377
            'title': title,
378
            'target_project_id': target_project.id,
379
            'source_branch': self.source_branch_name,
380
            'target_branch': self.target_branch_name,
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
381
            'description': description}
382
        if labels:
383
            kwargs['labels'] = ','.join(labels)
0.431.16 by Jelmer Vernooij
gitlab: Report when a merge proposal already exists.
384
        try:
385
            merge_request = source_project.mergerequests.create(kwargs)
386
        except gitlab.GitlabCreateError as e:
0.431.34 by Jelmer Vernooij
Cope with gitlab 403.
387
            if e.response_code == 403:
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
388
                raise errors.PermissionDenied(e.error_message)
0.431.16 by Jelmer Vernooij
gitlab: Report when a merge proposal already exists.
389
            if e.response_code == 409:
390
                raise MergeProposalExists(self.source_branch.user_url)
391
            raise
0.431.39 by Jelmer Vernooij
Extend the merge proposal abstraction a bit.
392
        return GitLabMergeProposal(merge_request)
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
393
394
395
def register_gitlab_instance(shortname, url):
396
    """Register a gitlab instance.
397
398
    :param shortname: Short name (e.g. "gitlab")
399
    :param url: URL to the gitlab instance
400
    """
401
    from breezy.bugtracker import (
402
        tracker_registry,
403
        ProjectIntegerBugTracker,
404
        )
405
    tracker_registry.register(
406
        shortname, ProjectIntegerBugTracker(
407
            shortname, url + '/{project}/issues/{id}'))