/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 bzrlib/merge_directive.py

  • Committer: Robert Collins
  • Date: 2010-05-06 11:08:10 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100506110810-h3j07fh5gmw54s25
Cleaner matcher matching revised unlocking protocol.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2011 Canonical Ltd
 
1
# Copyright (C) 2007-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from __future__ import absolute_import
18
17
 
 
18
from StringIO import StringIO
19
19
import re
20
20
 
21
 
from . import lazy_import
22
 
lazy_import.lazy_import(globals(), """
23
 
from breezy import (
 
21
from bzrlib import (
24
22
    branch as _mod_branch,
25
23
    diff,
26
 
    email_message,
27
24
    errors,
28
25
    gpg,
29
26
    hooks,
34
31
    timestamp,
35
32
    trace,
36
33
    )
37
 
from breezy.bundle import (
 
34
from bzrlib.bundle import (
38
35
    serializer as bundle_serializer,
39
36
    )
40
 
""")
41
 
from .sixish import (
42
 
    BytesIO,
43
 
    )
 
37
from bzrlib.email_message import EmailMessage
44
38
 
45
39
 
46
40
class MergeRequestBodyParams(object):
62
56
    """Hooks for MergeDirective classes."""
63
57
 
64
58
    def __init__(self):
65
 
        hooks.Hooks.__init__(self, "breezy.merge_directive", "BaseMergeDirective.hooks")
66
 
        self.add_hook('merge_request_body',
 
59
        hooks.Hooks.__init__(self)
 
60
        self.create_hook(hooks.HookPoint('merge_request_body',
67
61
            "Called with a MergeRequestBodyParams when a body is needed for"
68
62
            " a merge request.  Callbacks must return a body.  If more"
69
63
            " than one callback is registered, the output of one callback is"
70
 
            " provided to the next.", (1, 15, 0))
 
64
            " provided to the next.", (1, 15, 0), False))
71
65
 
72
66
 
73
67
class BaseMergeDirective(object):
85
79
    multiple_output_files = False
86
80
 
87
81
    def __init__(self, revision_id, testament_sha1, time, timezone,
88
 
                 target_branch, patch=None, source_branch=None,
89
 
                 message=None, bundle=None):
 
82
                 target_branch, patch=None, source_branch=None, message=None,
 
83
                 bundle=None):
90
84
        """Constructor.
91
85
 
92
86
        :param revision_id: The revision to merge
94
88
            merge.
95
89
        :param time: The current POSIX timestamp time
96
90
        :param timezone: The timezone offset
97
 
        :param target_branch: Location of branch to apply the merge to
 
91
        :param target_branch: The branch to apply the merge to
98
92
        :param patch: The text of a diff or bundle
99
93
        :param source_branch: A public location to merge the revision from
100
94
        :param message: The message to use when committing this merge
168
162
        :param target_branch: The url of the branch to merge into
169
163
        :param patch_type: 'bundle', 'diff' or None, depending on the type of
170
164
            patch desired.
171
 
        :param local_target_branch: the submit branch, either itself or a local copy
172
 
        :param public_branch: location of a public branch containing
173
 
            the target revision.
 
165
        :param local_target_branch: a local copy of the target branch
 
166
        :param public_branch: location of a public branch containing the target
 
167
            revision.
174
168
        :param message: Message to use when committing the merge
175
169
        :return: The merge directive
176
170
 
184
178
        if revision_id == _mod_revision.NULL_REVISION:
185
179
            t_revision_id = None
186
180
        t = testament.StrictTestament3.from_revision(repository, t_revision_id)
187
 
        if local_target_branch is None:
188
 
            submit_branch = _mod_branch.Branch.open(target_branch)
189
 
        else:
190
 
            submit_branch = local_target_branch
 
181
        submit_branch = _mod_branch.Branch.open(target_branch)
191
182
        if submit_branch.get_public_branch() is not None:
192
183
            target_branch = submit_branch.get_public_branch()
193
184
        if patch_type is None:
224
215
        if self.revision_id == revision_id:
225
216
            revno = [revno]
226
217
        else:
227
 
            try:
228
 
                revno = branch.revision_id_to_dotted_revno(self.revision_id)
229
 
            except errors.NoSuchRevision:
230
 
                revno = ['merge']
231
 
        nick = re.sub('(\\W+)', '-', branch.nick).strip('-')
 
218
            revno = branch.get_revision_id_to_revno_map().get(self.revision_id,
 
219
                ['merge'])
 
220
        nick = re.sub('(\W+)', '-', branch.nick).strip('-')
232
221
        return '%s-%s' % (nick, '.'.join(str(n) for n in revno))
233
222
 
234
223
    @staticmethod
235
224
    def _generate_diff(repository, revision_id, ancestor_id):
236
225
        tree_1 = repository.revision_tree(ancestor_id)
237
226
        tree_2 = repository.revision_tree(revision_id)
238
 
        s = BytesIO()
 
227
        s = StringIO()
239
228
        diff.show_diff_trees(tree_1, tree_2, s, old_label='', new_label='')
240
229
        return s.getvalue()
241
230
 
242
231
    @staticmethod
243
232
    def _generate_bundle(repository, revision_id, ancestor_id):
244
 
        s = BytesIO()
 
233
        s = StringIO()
245
234
        bundle_serializer.write_bundle(repository, revision_id,
246
235
                                       ancestor_id, s)
247
236
        return s.getvalue()
252
241
        :param branch: The source branch, to get the signing strategy
253
242
        :return: a string
254
243
        """
255
 
        my_gpg = gpg.GPGStrategy(branch.get_config_stack())
256
 
        return my_gpg.sign(b''.join(self.to_lines()), gpg.MODE_CLEAR)
 
244
        my_gpg = gpg.GPGStrategy(branch.get_config())
 
245
        return my_gpg.sign(''.join(self.to_lines()))
257
246
 
258
247
    def to_email(self, mail_to, branch, sign=False):
259
248
        """Serialize as an email message.
264
253
        :param sign: If True, gpg-sign the email
265
254
        :return: an email message
266
255
        """
267
 
        mail_from = branch.get_config_stack().get('email')
 
256
        mail_from = branch.get_config().username()
268
257
        if self.message is not None:
269
258
            subject = self.message
270
259
        else:
273
262
        if sign:
274
263
            body = self.to_signed(branch)
275
264
        else:
276
 
            body = b''.join(self.to_lines())
277
 
        message = email_message.EmailMessage(mail_from, mail_to, subject,
278
 
            body)
 
265
            body = ''.join(self.to_lines())
 
266
        message = EmailMessage(mail_from, mail_to, subject, body)
279
267
        return message
280
268
 
281
269
    def install_revisions(self, target_repo):
283
271
        if not target_repo.has_revision(self.revision_id):
284
272
            if self.patch_type == 'bundle':
285
273
                info = bundle_serializer.read_bundle(
286
 
                    BytesIO(self.get_raw_bundle()))
 
274
                    StringIO(self.get_raw_bundle()))
287
275
                # We don't use the bundle's target revision, because
288
276
                # MergeDirective.revision_id is authoritative.
289
277
                try:
349
337
                          ' client %s does not support message bodies.',
350
338
                        mail_client.__class__.__name__)
351
339
        mail_client.compose_merge_request(to, subject,
352
 
                                          b''.join(self.to_lines()),
 
340
                                          ''.join(self.to_lines()),
353
341
                                          basename, body)
354
342
 
355
343
 
381
369
            merge.
382
370
        :param time: The current POSIX timestamp time
383
371
        :param timezone: The timezone offset
384
 
        :param target_branch: Location of the branch to apply the merge to
 
372
        :param target_branch: The branch to apply the merge to
385
373
        :param patch: The text of a diff or bundle
386
374
        :param patch_type: None, "diff" or "bundle", depending on the contents
387
375
            of patch
437
425
            patch = None
438
426
            patch_type = None
439
427
        else:
440
 
            patch = b''.join(patch_lines)
 
428
            patch = ''.join(patch_lines)
441
429
            try:
442
 
                bundle_serializer.read_bundle(BytesIO(patch))
 
430
                bundle_serializer.read_bundle(StringIO(patch))
443
431
            except (errors.NotABundle, errors.BundleNotSupported,
444
432
                    errors.BadBundle):
445
433
                patch_type = 'diff'
465
453
 
466
454
    @staticmethod
467
455
    def _generate_bundle(repository, revision_id, ancestor_id):
468
 
        s = BytesIO()
 
456
        s = StringIO()
469
457
        bundle_serializer.write_bundle(repository, revision_id,
470
458
                                       ancestor_id, s, '0.9')
471
459
        return s.getvalue()
518
506
        patch = None
519
507
        bundle = None
520
508
        try:
521
 
            start = next(line_iter)
 
509
            start = line_iter.next()
522
510
        except StopIteration:
523
511
            pass
524
512
        else:
525
 
            if start.startswith(b'# Begin patch'):
 
513
            if start.startswith('# Begin patch'):
526
514
                patch_lines = []
527
515
                for line in line_iter:
528
 
                    if line.startswith(b'# Begin bundle'):
 
516
                    if line.startswith('# Begin bundle'):
529
517
                        start = line
530
518
                        break
531
519
                    patch_lines.append(line)
532
520
                else:
533
521
                    start = None
534
 
                patch = b''.join(patch_lines)
 
522
                patch = ''.join(patch_lines)
535
523
            if start is not None:
536
 
                if start.startswith(b'# Begin bundle'):
537
 
                    bundle = b''.join(line_iter)
 
524
                if start.startswith('# Begin bundle'):
 
525
                    bundle = ''.join(line_iter)
538
526
                else:
539
527
                    raise errors.IllegalMergeDirectivePayload(start)
540
528
        time, timezone = timestamp.parse_patch_date(stanza.get('timestamp'))
575
563
        :param target_branch: The url of the branch to merge into
576
564
        :param include_patch: If true, include a preview patch
577
565
        :param include_bundle: If true, include a bundle
578
 
        :param local_target_branch: the target branch, either itself or a local copy
579
 
        :param public_branch: location of a public branch containing
580
 
            the target revision.
 
566
        :param local_target_branch: a local copy of the target branch
 
567
        :param public_branch: location of a public branch containing the target
 
568
            revision.
581
569
        :param message: Message to use when committing the merge
582
570
        :return: The merge directive
583
571
 
596
584
                t_revision_id = None
597
585
            t = testament.StrictTestament3.from_revision(repository,
598
586
                t_revision_id)
599
 
            if local_target_branch is None:
600
 
                submit_branch = _mod_branch.Branch.open(target_branch)
601
 
            else:
602
 
                submit_branch = local_target_branch
 
587
            submit_branch = _mod_branch.Branch.open(target_branch)
603
588
            submit_branch.lock_read()
604
589
            locked.append(submit_branch)
605
590
            if submit_branch.get_public_branch() is not None: