/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/propose.py

  • Committer: Breezy landing bot
  • Author(s): Jelmer Vernooij
  • Date: 2020-06-01 21:57:00 UTC
  • mfrom: (7490.39.3 move-launchpad)
  • Revision ID: breezy.the.bot@gmail.com-20200601215700-joxuzo6w172gq74v
Move launchpad hoster support to the launchpad plugin.

Merged from https://code.launchpad.net/~jelmer/brz/move-launchpad/+merge/384931

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Helper functions for proposing merges."""
18
18
 
19
 
import re
20
 
 
21
19
from . import (
22
20
    errors,
23
21
    hooks,
39
37
 
40
38
    _fmt = "A merge proposal already exists: %(url)s."
41
39
 
42
 
    def __init__(self, url, existing_proposal=None):
 
40
    def __init__(self, url):
43
41
        errors.BzrError.__init__(self)
44
42
        self.url = url
45
 
        self.existing_proposal = existing_proposal
46
43
 
47
44
 
48
45
class UnsupportedHoster(errors.BzrError):
100
97
        self.hoster = hoster
101
98
 
102
99
 
103
 
class SourceNotDerivedFromTarget(errors.BzrError):
104
 
    """Source branch is not derived from target branch."""
105
 
 
106
 
    _fmt = ("Source %(source_branch)r not derived from "
107
 
            "target %(target_branch)r.")
108
 
 
109
 
    def __init__(self, source_branch, target_branch):
110
 
        errors.BzrError.__init__(
111
 
            self, source_branch=source_branch,
112
 
            target_branch=target_branch)
113
 
 
114
 
 
115
100
class MergeProposal(object):
116
101
    """A merge proposal.
117
102
 
141
126
        """Return the source branch."""
142
127
        raise NotImplementedError(self.get_source_branch_url)
143
128
 
144
 
    def get_source_revision(self):
145
 
        """Return the latest revision for the source branch."""
146
 
        raise NotImplementedError(self.get_source_revision)
147
 
 
148
129
    def get_target_branch_url(self):
149
130
        """Return the target branch."""
150
131
        raise NotImplementedError(self.get_target_branch_url)
191
172
        """
192
173
        raise NotImplementedError(self.get_merged_at)
193
174
 
194
 
    def post_comment(self, body):
195
 
        """Post a comment on the merge proposal.
196
 
 
197
 
        Args:
198
 
          body: Body of the comment
199
 
        """
200
 
        raise NotImplementedError(self.post_comment)
201
 
 
202
175
 
203
176
class MergeProposalBuilder(object):
204
177
    """Merge proposal creator.
253
226
    # proposals?
254
227
    supports_merge_proposal_labels = None
255
228
 
256
 
    @property
257
 
    def name(self):
258
 
        """Name of this instance."""
259
 
        return "%s at %s" % (type(self).__name__, self.base_url)
260
 
 
261
229
    # Does this hoster support suggesting a commit message in the
262
230
    # merge proposal?
263
231
    supports_merge_proposal_commit_message = None
284
252
        :raise HosterLoginRequired: Action requires a hoster login, but none is
285
253
            known.
286
254
        """
287
 
        raise NotImplementedError(self.publish_derived)
 
255
        raise NotImplementedError(self.publish)
288
256
 
289
257
    def get_derived_branch(self, base_branch, name, project=None, owner=None):
290
258
        """Get a derived branch ('a fork').
341
309
        """Create a Hoster object if this hoster knows about a URL."""
342
310
        raise NotImplementedError(cls.probe_from_url)
343
311
 
344
 
    def iter_my_proposals(self, status='open', author=None):
 
312
    def iter_my_proposals(self, status='open'):
345
313
        """Iterate over the proposals created by the currently logged in user.
346
314
 
347
315
        :param status: Only yield proposals with this status
348
316
            (one of: 'open', 'closed', 'merged', 'all')
349
 
        :param author: Name of author to query (defaults to current user)
350
317
        :return: Iterator over MergeProposal objects
351
318
        :raise HosterLoginRequired: Action requires a hoster login, but none is
352
319
            known.
353
320
        """
354
321
        raise NotImplementedError(self.iter_my_proposals)
355
322
 
356
 
    def iter_my_forks(self, owner=None):
 
323
    def iter_my_forks(self):
357
324
        """Iterate over the currently logged in users' forks.
358
325
 
359
 
        :param owner: Name of owner to query (defaults to current user)
360
326
        :return: Iterator over project_name
361
327
        """
362
328
        raise NotImplementedError(self.iter_my_forks)
374
340
        """
375
341
        raise NotImplementedError(cls.iter_instances)
376
342
 
377
 
    def get_current_user(self):
378
 
        """Retrieve the name of the currently logged in user.
379
 
 
380
 
        :return: Username or None if not logged in
381
 
        """
382
 
        raise NotImplementedError(self.get_current_user)
383
 
 
384
 
    def get_user_url(self, user):
385
 
        """Rerieve the web URL for a user."""
386
 
        raise NotImplementedError(self.get_user_url)
387
 
 
388
343
 
389
344
def determine_title(description):
390
345
    """Determine the title for a merge proposal based on full description."""
391
 
    firstline = description.splitlines()[0]
392
 
    try:
393
 
        i = firstline.index('. ')
394
 
    except ValueError:
395
 
        return firstline.rstrip('.')
396
 
    else:
397
 
        return firstline[:i]
 
346
    return description.splitlines()[0].split('.')[0]
398
347
 
399
348
 
400
349
def get_hoster(branch, possible_hosters=None):
421
370
    raise UnsupportedHoster(branch)
422
371
 
423
372
 
424
 
def iter_hoster_instances(hoster=None):
425
 
    """Iterate over all known hoster instances.
426
 
 
427
 
    :return: Iterator over Hoster instances
428
 
    """
429
 
    if hoster is None:
430
 
        hoster_clses = [hoster_cls for name, hoster_cls in hosters.items()]
431
 
    else:
432
 
        hoster_clses = [hoster]
433
 
    for hoster_cls in hoster_clses:
434
 
        for instance in hoster_cls.iter_instances():
435
 
            yield instance
436
 
 
437
 
 
438
373
def get_proposal_by_url(url):
439
374
    """Get the proposal object associated with a URL.
440
375
 
442
377
    :raise UnsupportedHoster: if there is no hoster that supports the URL
443
378
    :return: A `MergeProposal` object
444
379
    """
445
 
    for instance in iter_hoster_instances():
446
 
        try:
447
 
            return instance.get_proposal_by_url(url)
448
 
        except UnsupportedHoster:
449
 
            pass
 
380
    for name, hoster_cls in hosters.items():
 
381
        for instance in hoster_cls.iter_instances():
 
382
            try:
 
383
                return instance.get_proposal_by_url(url)
 
384
            except UnsupportedHoster:
 
385
                pass
450
386
    raise UnsupportedHoster(url)
451
387
 
452
388