/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
7408.3.1 by Jelmer Vernooij
Move propose module into core.
1
# Copyright (C) 2018-2019 Breezy Developers
0.431.1 by Jelmer Vernooij
Start work on propose command.
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
17
"""Helper functions for proposing merges."""
18
19
from __future__ import absolute_import
20
7408.3.1 by Jelmer Vernooij
Move propose module into core.
21
from . import (
0.431.1 by Jelmer Vernooij
Start work on propose command.
22
    errors,
23
    hooks,
24
    registry,
7268.12.3 by Jelmer Vernooij
Add missing import.
25
    urlutils,
0.431.1 by Jelmer Vernooij
Start work on propose command.
26
    )
27
28
0.431.38 by Jelmer Vernooij
Add NoSuchProject.
29
class NoSuchProject(errors.BzrError):
30
31
    _fmt = "Project does not exist: %(project)s."
32
33
    def __init__(self, project):
34
        errors.BzrError.__init__(self)
35
        self.project = project
36
37
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
38
class MergeProposalExists(errors.BzrError):
39
40
    _fmt = "A merge proposal already exists: %(url)s."
41
42
    def __init__(self, url):
43
        errors.BzrError.__init__(self)
44
        self.url = url
45
46
0.432.2 by Jelmer Vernooij
Publish command sort of works.
47
class UnsupportedHoster(errors.BzrError):
48
49
    _fmt = "No supported hoster for %(branch)s."
50
51
    def __init__(self, branch):
52
        errors.BzrError.__init__(self)
53
        self.branch = branch
54
55
7381.5.1 by Jelmer Vernooij
Several more fixes for merge proposals. Add functions for reopening merge proposals.
56
class ReopenFailed(errors.BzrError):
57
58
    _fmt = "Reopening the merge proposal failed: %(error)s."
59
60
0.431.1 by Jelmer Vernooij
Start work on propose command.
61
class ProposeMergeHooks(hooks.Hooks):
62
    """Hooks for proposing a merge on Launchpad."""
63
64
    def __init__(self):
65
        hooks.Hooks.__init__(self, __name__, "Proposer.hooks")
0.431.57 by Jelmer Vernooij
Cleanups.
66
        self.add_hook(
67
            'get_prerequisite',
0.431.1 by Jelmer Vernooij
Start work on propose command.
68
            "Return the prerequisite branch for proposing as merge.", (3, 0))
0.431.57 by Jelmer Vernooij
Cleanups.
69
        self.add_hook(
70
            'merge_proposal_body',
0.431.1 by Jelmer Vernooij
Start work on propose command.
71
            "Return an initial body for the merge proposal message.", (3, 0))
72
73
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
74
class LabelsUnsupported(errors.BzrError):
75
    """Labels not supported by this hoster."""
76
77
    _fmt = "Labels are not supported by %(hoster)r."
78
79
    def __init__(self, hoster):
80
        errors.BzrError.__init__(self)
81
        self.hoster = hoster
82
83
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
84
class PrerequisiteBranchUnsupported(errors.BzrError):
85
    """Prerequisite branch not supported by this hoster."""
86
87
    def __init__(self, hoster):
88
        errors.BzrError.__init__(self)
89
        self.hoster = hoster
90
91
7268.8.1 by Jelmer Vernooij
Add HosterLoginRequired exception.
92
class HosterLoginRequired(errors.BzrError):
93
    """Action requires hoster login credentials."""
94
7268.8.2 by Jelmer Vernooij
Handle GitHub errors.
95
    _fmt = "Action requires credentials for hosting site %(hoster)r."""
96
7268.8.1 by Jelmer Vernooij
Add HosterLoginRequired exception.
97
    def __init__(self, hoster):
98
        errors.BzrError.__init__(self)
99
        self.hoster = hoster
100
101
0.431.3 by Jelmer Vernooij
Add a MergeProposal object.
102
class MergeProposal(object):
103
    """A merge proposal.
104
105
    :ivar url: URL for the merge proposal
106
    """
107
108
    def __init__(self, url=None):
109
        self.url = url
110
0.431.39 by Jelmer Vernooij
Extend the merge proposal abstraction a bit.
111
    def get_description(self):
112
        """Get the description of the merge proposal."""
113
        raise NotImplementedError(self.get_description)
114
115
    def set_description(self, description):
116
        """Set the description of the merge proposal."""
117
        raise NotImplementedError(self.set_description)
118
7296.8.2 by Jelmer Vernooij
Add feature flag for commit message.
119
    def get_commit_message(self):
120
        """Get the proposed commit message."""
121
        raise NotImplementedError(self.get_commit_message)
122
123
    def set_commit_message(self, commit_message):
124
        """Set the propose commit message."""
125
        raise NotImplementedError(self.set_commit_message)
126
0.431.64 by Jelmer Vernooij
Add get_source_branch_url/get_target_branch_url methods.
127
    def get_source_branch_url(self):
128
        """Return the source branch."""
129
        raise NotImplementedError(self.get_source_branch_url)
130
131
    def get_target_branch_url(self):
132
        """Return the target branch."""
133
        raise NotImplementedError(self.get_target_branch_url)
134
7414.5.1 by Jelmer Vernooij
Add functions for managing projects.
135
    def get_source_project(self):
136
        raise NotImplementedError(self.get_source_project)
137
138
    def get_target_project(self):
139
        raise NotImplementedError(self.get_target_project)
140
0.431.39 by Jelmer Vernooij
Extend the merge proposal abstraction a bit.
141
    def close(self):
142
        """Close the merge proposal (without merging it)."""
143
        raise NotImplementedError(self.close)
144
0.431.46 by Jelmer Vernooij
Add MergeProposal.is_merged.
145
    def is_merged(self):
146
        """Check whether this merge proposal has been merged."""
147
        raise NotImplementedError(self.is_merged)
148
7381.5.1 by Jelmer Vernooij
Several more fixes for merge proposals. Add functions for reopening merge proposals.
149
    def is_closed(self):
150
        """Check whether this merge proposal is closed
151
152
        This can either mean that it is merged or rejected.
153
        """
154
        raise NotImplementedError(self.is_closed)
155
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
156
    def merge(self, commit_message=None):
157
        """Merge this merge proposal."""
158
        raise NotImplementedError(self.merge)
159
7380.1.1 by Jelmer Vernooij
Several more fixes for git merge proposals.
160
    def can_be_merged(self):
161
        """Can this merge proposal be merged?
162
163
        The answer to this can be no if e.g. it has conflics.
164
        """
165
        raise NotImplementedError(self.can_be_merged)
166
7414.4.1 by Jelmer Vernooij
Add a MergeProposal.get_merged_by method.
167
    def get_merged_by(self):
168
        """If this proposal was merged, who merged it.
169
        """
170
        raise NotImplementedError(self.get_merged_by)
171
7414.4.3 by Jelmer Vernooij
Add MergeProposal.get_merged_at.
172
    def get_merged_at(self):
173
        """If this proposal was merged, when it was merged.
174
        """
175
        raise NotImplementedError(self.get_merged_at)
176
0.431.3 by Jelmer Vernooij
Add a MergeProposal object.
177
0.432.2 by Jelmer Vernooij
Publish command sort of works.
178
class MergeProposalBuilder(object):
0.431.1 by Jelmer Vernooij
Start work on propose command.
179
    """Merge proposal creator.
180
181
    :param source_branch: Branch to propose for merging
182
    :param target_branch: Target branch
183
    """
184
185
    hooks = ProposeMergeHooks()
186
187
    def __init__(self, source_branch, target_branch):
188
        self.source_branch = source_branch
189
        self.target_branch = target_branch
190
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
191
    def get_initial_body(self):
192
        """Get a body for the proposal for the user to modify.
193
194
        :return: a str or None.
195
        """
196
        raise NotImplementedError(self.get_initial_body)
197
198
    def get_infotext(self):
199
        """Determine the initial comment for the merge proposal.
200
        """
201
        raise NotImplementedError(self.get_infotext)
202
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
203
    def create_proposal(self, description, reviewers=None, labels=None,
7296.8.1 by Jelmer Vernooij
Add commit-message option to 'brz propose'.
204
                        prerequisite_branch=None, commit_message=None):
0.431.1 by Jelmer Vernooij
Start work on propose command.
205
        """Create a proposal to merge a branch for merging.
0.431.2 by Jelmer Vernooij
Add launchpad implementation.
206
207
        :param description: Description for the merge proposal
0.431.5 by Jelmer Vernooij
Initial work on gitlab support.
208
        :param reviewers: Optional list of people to ask reviews from
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
209
        :param labels: Labels to attach to the proposal
0.431.56 by Jelmer Vernooij
Add support for prerequisite branches.
210
        :param prerequisite_branch: Optional prerequisite branch
7296.8.1 by Jelmer Vernooij
Add commit-message option to 'brz propose'.
211
        :param commit_message: Optional commit message
0.431.3 by Jelmer Vernooij
Add a MergeProposal object.
212
        :return: A `MergeProposal` object
0.431.1 by Jelmer Vernooij
Start work on propose command.
213
        """
214
        raise NotImplementedError(self.create_proposal)
215
216
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
217
class Hoster(object):
218
    """A hosting site manager.
219
    """
220
7260.1.1 by Jelmer Vernooij
Add .base_url property to Hoster.
221
    # Does this hoster support arbitrary labels being attached to merge
222
    # proposals?
0.431.13 by Jelmer Vernooij
Add support for labels on merge proposals.
223
    supports_merge_proposal_labels = None
224
7296.8.2 by Jelmer Vernooij
Add feature flag for commit message.
225
    # Does this hoster support suggesting a commit message in the
226
    # merge proposal?
227
    supports_merge_proposal_commit_message = None
228
7260.1.1 by Jelmer Vernooij
Add .base_url property to Hoster.
229
    # The base_url that would be visible to users. I.e. https://github.com/
230
    # rather than https://api.github.com/
231
    base_url = None
232
0.431.20 by Jelmer Vernooij
publish -> publish_derived.
233
    def publish_derived(self, new_branch, base_branch, name, project=None,
0.431.51 by Jelmer Vernooij
Allow fallback to lossy by default.
234
                        owner=None, revision_id=None, overwrite=False,
235
                        allow_lossy=True):
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
236
        """Publish a branch to the site, derived from base_branch.
237
238
        :param base_branch: branch to derive the new branch from
239
        :param new_branch: branch to publish
0.432.3 by Jelmer Vernooij
Publish command works for github.
240
        :return: resulting branch, public URL
7268.8.1 by Jelmer Vernooij
Add HosterLoginRequired exception.
241
        :raise HosterLoginRequired: Action requires a hoster login, but none is
242
            known.
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
243
        """
244
        raise NotImplementedError(self.publish)
245
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
246
    def get_derived_branch(self, base_branch, name, project=None, owner=None):
0.431.31 by Jelmer Vernooij
Drop autopropose command.
247
        """Get a derived branch ('a fork').
248
        """
0.431.22 by Jelmer Vernooij
Add Hoster.get_derived_branch.
249
        raise NotImplementedError(self.get_derived_branch)
250
0.431.28 by Jelmer Vernooij
Implement Hoster.get_push_url.
251
    def get_push_url(self, branch):
252
        """Get the push URL for a branch."""
253
        raise NotImplementedError(self.get_push_url)
254
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
255
    def get_proposer(self, source_branch, target_branch):
256
        """Get a merge proposal creator.
257
0.431.31 by Jelmer Vernooij
Drop autopropose command.
258
        :note: source_branch does not have to be hosted by the hoster.
259
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
260
        :param source_branch: Source branch
261
        :param target_branch: Target branch
0.432.2 by Jelmer Vernooij
Publish command sort of works.
262
        :return: A MergeProposalBuilder object
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
263
        """
264
        raise NotImplementedError(self.get_proposer)
265
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
266
    def iter_proposals(self, source_branch, target_branch, status='open'):
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
267
        """Get the merge proposals for a specified branch tuple.
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
268
269
        :param source_branch: Source branch
270
        :param target_branch: Target branch
0.431.68 by Jelmer Vernooij
Add status to other Hosters.
271
        :param status: Status of proposals to iterate over
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
272
        :return: Iterate over MergeProposal object
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
273
        """
0.431.67 by Jelmer Vernooij
Support multiple merge proposals per branch.
274
        raise NotImplementedError(self.iter_proposals)
0.431.35 by Jelmer Vernooij
Add Hoster.get_proposal.
275
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
276
    def get_proposal_by_url(self, url):
277
        """Retrieve a branch proposal by URL.
278
279
        :param url: Merge proposal URL.
280
        :return: MergeProposal object
281
        :raise UnsupportedHoster: Hoster does not support this URL
282
        """
283
        raise NotImplementedError(self.get_proposal_by_url)
284
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
285
    def hosts(self, branch):
286
        """Return true if this hoster hosts given branch."""
287
        raise NotImplementedError(self.hosts)
288
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
289
    @classmethod
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
290
    def probe_from_branch(cls, branch):
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
291
        """Create a Hoster object if this hoster knows about a branch."""
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
292
        url = urlutils.split_segment_parameters(branch.user_url)[0]
7296.10.1 by Jelmer Vernooij
Initial work making gitlab just directly use ReST.
293
        return cls.probe_from_url(
7296.10.2 by Jelmer Vernooij
More fixes.
294
            url, possible_transports=[branch.control_transport])
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
295
296
    @classmethod
7296.10.1 by Jelmer Vernooij
Initial work making gitlab just directly use ReST.
297
    def probe_from_url(cls, url, possible_hosters=None):
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
298
        """Create a Hoster object if this hoster knows about a URL."""
299
        raise NotImplementedError(cls.probe_from_url)
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
300
0.431.66 by Jelmer Vernooij
Add support for status argument.
301
    def iter_my_proposals(self, status='open'):
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
302
        """Iterate over the proposals created by the currently logged in user.
303
0.431.66 by Jelmer Vernooij
Add support for status argument.
304
        :param status: Only yield proposals with this status
305
            (one of: 'open', 'closed', 'merged', 'all')
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
306
        :return: Iterator over MergeProposal objects
7268.8.1 by Jelmer Vernooij
Add HosterLoginRequired exception.
307
        :raise HosterLoginRequired: Action requires a hoster login, but none is
308
            known.
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
309
        """
310
        raise NotImplementedError(self.iter_my_proposals)
311
7414.5.2 by Jelmer Vernooij
Change iter_my_projects to iter_my_forks.
312
    def iter_my_forks(self):
313
        """Iterate over the currently logged in users' forks.
7414.5.1 by Jelmer Vernooij
Add functions for managing projects.
314
7414.5.2 by Jelmer Vernooij
Change iter_my_projects to iter_my_forks.
315
        :return: Iterator over project_name
7414.5.1 by Jelmer Vernooij
Add functions for managing projects.
316
        """
7414.5.2 by Jelmer Vernooij
Change iter_my_projects to iter_my_forks.
317
        raise NotImplementedError(self.iter_my_forks)
7414.5.1 by Jelmer Vernooij
Add functions for managing projects.
318
319
    def delete_project(self, name):
320
        """Delete a project.
321
        """
322
        raise NotImplementedError(self.delete_project)
323
0.431.63 by Jelmer Vernooij
Add 'brz my-proposals' command.
324
    @classmethod
325
    def iter_instances(cls):
326
        """Iterate instances.
327
328
        :return: Hoster instances
329
        """
330
        raise NotImplementedError(cls.iter_instances)
331
0.432.1 by Jelmer Vernooij
Initial work on hoster support.
332
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
333
def get_hoster(branch, possible_hosters=None):
7408.3.2 by Jelmer Vernooij
Add some tests.
334
    """Find the hoster for a branch.
335
336
    :param branch: Branch to find hoster for
337
    :param possible_hosters: Optional list of hosters to reuse
338
    :raise UnsupportedHoster: if there is no hoster that supports `branch`
339
    :return: A `Hoster` object
340
    """
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
341
    if possible_hosters:
342
        for hoster in possible_hosters:
343
            if hoster.hosts(branch):
344
                return hoster
0.432.2 by Jelmer Vernooij
Publish command sort of works.
345
    for name, hoster_cls in hosters.items():
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
346
        try:
7268.12.1 by Jelmer Vernooij
Split out probe_from_url.
347
            hoster = hoster_cls.probe_from_branch(branch)
0.432.9 by Jelmer Vernooij
Drop is_compatible nonesense.
348
        except UnsupportedHoster:
349
            pass
0.433.1 by Jelmer Vernooij
Add Hoster.hosts.
350
        else:
351
            if possible_hosters is not None:
352
                possible_hosters.append(hoster)
353
            return hoster
0.432.2 by Jelmer Vernooij
Publish command sort of works.
354
    raise UnsupportedHoster(branch)
355
356
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
357
def get_proposal_by_url(url):
7408.3.2 by Jelmer Vernooij
Add some tests.
358
    """Get the proposal object associated with a URL.
359
360
    :param url: URL of the proposal
361
    :raise UnsupportedHoster: if there is no hoster that supports the URL
362
    :return: A `MergeProposal` object
363
    """
7296.9.1 by Jelmer Vernooij
Add 'brz land' subcommand.
364
    for name, hoster_cls in hosters.items():
365
        for instance in hoster_cls.iter_instances():
366
            try:
367
                return instance.get_proposal_by_url(url)
368
            except UnsupportedHoster:
369
                pass
370
    raise UnsupportedHoster(url)
371
372
0.432.2 by Jelmer Vernooij
Publish command sort of works.
373
hosters = registry.Registry()