/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: Gustav Hartvigsson
  • Date: 2021-01-11 20:19:38 UTC
  • mfrom: (7526.3.2 work)
  • Revision ID: gustav.hartvigsson@gmail.com-20210111201938-omr9wjz3qdgyxe8k
MergedĀ lp:brz

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
 
19
21
from . import (
20
22
    errors,
21
23
    hooks,
37
39
 
38
40
    _fmt = "A merge proposal already exists: %(url)s."
39
41
 
40
 
    def __init__(self, url):
 
42
    def __init__(self, url, existing_proposal=None):
41
43
        errors.BzrError.__init__(self)
42
44
        self.url = url
 
45
        self.existing_proposal = existing_proposal
43
46
 
44
47
 
45
48
class UnsupportedHoster(errors.BzrError):
97
100
        self.hoster = hoster
98
101
 
99
102
 
 
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
 
100
115
class MergeProposal(object):
101
116
    """A merge proposal.
102
117
 
126
141
        """Return the source branch."""
127
142
        raise NotImplementedError(self.get_source_branch_url)
128
143
 
 
144
    def get_source_revision(self):
 
145
        """Return the latest revision for the source branch."""
 
146
        raise NotImplementedError(self.get_source_revision)
 
147
 
129
148
    def get_target_branch_url(self):
130
149
        """Return the target branch."""
131
150
        raise NotImplementedError(self.get_target_branch_url)
172
191
        """
173
192
        raise NotImplementedError(self.get_merged_at)
174
193
 
 
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
 
175
202
 
176
203
class MergeProposalBuilder(object):
177
204
    """Merge proposal creator.
226
253
    # proposals?
227
254
    supports_merge_proposal_labels = None
228
255
 
 
256
    @property
 
257
    def name(self):
 
258
        """Name of this instance."""
 
259
        return "%s at %s" % (type(self).__name__, self.base_url)
 
260
 
229
261
    # Does this hoster support suggesting a commit message in the
230
262
    # merge proposal?
231
263
    supports_merge_proposal_commit_message = None
252
284
        :raise HosterLoginRequired: Action requires a hoster login, but none is
253
285
            known.
254
286
        """
255
 
        raise NotImplementedError(self.publish)
 
287
        raise NotImplementedError(self.publish_derived)
256
288
 
257
289
    def get_derived_branch(self, base_branch, name, project=None, owner=None):
258
290
        """Get a derived branch ('a fork').
309
341
        """Create a Hoster object if this hoster knows about a URL."""
310
342
        raise NotImplementedError(cls.probe_from_url)
311
343
 
312
 
    def iter_my_proposals(self, status='open'):
 
344
    def iter_my_proposals(self, status='open', author=None):
313
345
        """Iterate over the proposals created by the currently logged in user.
314
346
 
315
347
        :param status: Only yield proposals with this status
316
348
            (one of: 'open', 'closed', 'merged', 'all')
 
349
        :param author: Name of author to query (defaults to current user)
317
350
        :return: Iterator over MergeProposal objects
318
351
        :raise HosterLoginRequired: Action requires a hoster login, but none is
319
352
            known.
320
353
        """
321
354
        raise NotImplementedError(self.iter_my_proposals)
322
355
 
323
 
    def iter_my_forks(self):
 
356
    def iter_my_forks(self, owner=None):
324
357
        """Iterate over the currently logged in users' forks.
325
358
 
 
359
        :param owner: Name of owner to query (defaults to current user)
326
360
        :return: Iterator over project_name
327
361
        """
328
362
        raise NotImplementedError(self.iter_my_forks)
340
374
        """
341
375
        raise NotImplementedError(cls.iter_instances)
342
376
 
 
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
 
343
388
 
344
389
def determine_title(description):
345
390
    """Determine the title for a merge proposal based on full description."""
346
 
    return description.splitlines()[0].split('.')[0]
 
391
    firstline = description.splitlines()[0]
 
392
    try:
 
393
        i = firstline.index('. ')
 
394
    except ValueError:
 
395
        return firstline.rstrip('.')
 
396
    else:
 
397
        return firstline[:i]
347
398
 
348
399
 
349
400
def get_hoster(branch, possible_hosters=None):
370
421
    raise UnsupportedHoster(branch)
371
422
 
372
423
 
 
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
 
373
438
def get_proposal_by_url(url):
374
439
    """Get the proposal object associated with a URL.
375
440
 
377
442
    :raise UnsupportedHoster: if there is no hoster that supports the URL
378
443
    :return: A `MergeProposal` object
379
444
    """
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
 
445
    for instance in iter_hoster_instances():
 
446
        try:
 
447
            return instance.get_proposal_by_url(url)
 
448
        except UnsupportedHoster:
 
449
            pass
386
450
    raise UnsupportedHoster(url)
387
451
 
388
452