/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6404.6.7 by Vincent Ladeuil
Change set/remove to require a lock for the branch config files.
1
# Copyright (C) 2007 Canonical Ltd
1551.12.36 by Aaron Bentley
Fix failing tests
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
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1551.12.36 by Aaron Bentley
Fix failing tests
16
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
17
import re
1551.12.36 by Aaron Bentley
Fix failing tests
18
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
19
from .. import (
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
20
    errors,
1551.12.16 by Aaron Bentley
Enable signing merge directives
21
    gpg,
4098.5.16 by Aaron Bentley
Move hook to MergeDirective, implement MergeDirective.compose_merge_request.
22
    mail_client,
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
23
    merge_directive,
24
    tests,
4098.5.18 by Aaron Bentley
Gracefully handle mail clients that don't support bodies.
25
    trace,
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
26
    )
27
1551.12.4 by Aaron Bentley
Add failing test
28
1551.12.45 by Aaron Bentley
Change format marker to not experimental
29
OUTPUT1 = """# Bazaar merge directive format 1
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
30
# revision_id: example:
31
# target_branch: http://example.com
32
# testament_sha1: sha
33
# timestamp: 1970-01-01 00:09:33 +0002
34
#\x20
35
booga"""
36
2687.2.2 by Martin Pool
Fix up other references to 0.19
37
OUTPUT1_2 = """# Bazaar merge directive format 2 (Bazaar 0.90)
2520.4.73 by Aaron Bentley
Implement new merge directive format
38
# revision_id: example:
39
# target_branch: http://example.com
40
# testament_sha1: sha
41
# timestamp: 1970-01-01 00:09:33 +0002
2520.4.105 by Aaron Bentley
Implement patch verification
42
# base_revision_id: null:
2520.4.73 by Aaron Bentley
Implement new merge directive format
43
#\x20
44
# Begin bundle
45
booga"""
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
46
1551.12.45 by Aaron Bentley
Change format marker to not experimental
47
OUTPUT2 = """# Bazaar merge directive format 1
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
48
# revision_id: example:
49
# target_branch: http://example.com
50
# testament_sha1: sha
51
# timestamp: 1970-01-01 00:09:33 +0002
52
# source_branch: http://example.org
53
# message: Hi mom!
54
#\x20
55
booga"""
56
2687.2.2 by Martin Pool
Fix up other references to 0.19
57
OUTPUT2_2 = """# Bazaar merge directive format 2 (Bazaar 0.90)
2520.4.73 by Aaron Bentley
Implement new merge directive format
58
# revision_id: example:
59
# target_branch: http://example.com
60
# testament_sha1: sha
61
# timestamp: 1970-01-01 00:09:33 +0002
62
# source_branch: http://example.org
63
# message: Hi mom!
2520.4.105 by Aaron Bentley
Implement patch verification
64
# base_revision_id: null:
2520.4.73 by Aaron Bentley
Implement new merge directive format
65
#\x20
66
# Begin patch
67
booga"""
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
68
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
69
INPUT1 = """
70
I was thinking today about creating a merge directive.
71
72
So I did.
73
74
Here it is.
75
76
(I've pasted it in the body of this message)
77
78
Aaron
79
80
# Bazaar merge directive format 1\r
81
# revision_id: example:
82
# target_branch: http://example.com
83
# testament_sha1: sha
84
# timestamp: 1970-01-01 00:09:33 +0002
85
# source_branch: http://example.org
86
# message: Hi mom!
87
#\x20
88
booga""".splitlines(True)
89
90
2520.4.73 by Aaron Bentley
Implement new merge directive format
91
INPUT1_2 = """
92
I was thinking today about creating a merge directive.
93
94
So I did.
95
96
Here it is.
97
98
(I've pasted it in the body of this message)
99
100
Aaron
101
2687.2.2 by Martin Pool
Fix up other references to 0.19
102
# Bazaar merge directive format 2 (Bazaar 0.90)\r
2520.4.73 by Aaron Bentley
Implement new merge directive format
103
# revision_id: example:
104
# target_branch: http://example.com
105
# testament_sha1: sha
106
# timestamp: 1970-01-01 00:09:33 +0002
107
# source_branch: http://example.org
2520.4.105 by Aaron Bentley
Implement patch verification
108
# base_revision_id: null:
2520.4.73 by Aaron Bentley
Implement new merge directive format
109
# message: Hi mom!
110
#\x20
111
# Begin patch
112
booga""".splitlines(True)
113
114
2694.1.1 by Aaron Bentley
Restore support for Merge directive 2 / 0.19
115
INPUT1_2_OLD = """
116
I was thinking today about creating a merge directive.
117
118
So I did.
119
120
Here it is.
121
122
(I've pasted it in the body of this message)
123
124
Aaron
125
126
# Bazaar merge directive format 2 (Bazaar 0.19)\r
127
# revision_id: example:
128
# target_branch: http://example.com
129
# testament_sha1: sha
130
# timestamp: 1970-01-01 00:09:33 +0002
131
# source_branch: http://example.org
132
# base_revision_id: null:
133
# message: Hi mom!
134
#\x20
135
# Begin patch
136
booga""".splitlines(True)
137
2694.1.2 by Aaron Bentley
Fix whitespace
138
2694.1.1 by Aaron Bentley
Restore support for Merge directive 2 / 0.19
139
OLD_DIRECTIVE_2 = """# Bazaar merge directive format 2 (Bazaar 0.19)
140
# revision_id: abentley@panoramicfeedback.com-20070807234458-\
141
#   nzhkoyza56lan7z5
142
# target_branch: http://panoramicfeedback.com/opensource/bzr/repo\
143
#   /bzr.ab
144
# testament_sha1: d825a5cdb267a90ec2ba86b00895f3d8a9bed6bf
145
# timestamp: 2007-08-10 16:15:02 -0400
146
# source_branch: http://panoramicfeedback.com/opensource/bzr/repo\
147
#   /bzr.ab
148
# base_revision_id: abentley@panoramicfeedback.com-20070731163346-\
149
#   623xwcycwij91xen
150
#
151
""".splitlines(True)
152
153
2520.4.73 by Aaron Bentley
Implement new merge directive format
154
class TestMergeDirective(object):
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
155
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
156
    def test_merge_source(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
157
        time = 500000.0
158
        timezone = 5 * 3600
2520.4.73 by Aaron Bentley
Implement new merge directive format
159
        self.assertRaises(errors.NoMergeSource, self.make_merge_directive,
1551.12.3 by Aaron Bentley
Add timestamps to merge directives
160
            'example:', 'sha', time, timezone, 'http://example.com')
2520.4.73 by Aaron Bentley
Implement new merge directive format
161
        self.assertRaises(errors.NoMergeSource, self.make_merge_directive,
1551.12.3 by Aaron Bentley
Add timestamps to merge directives
162
            'example:', 'sha', time, timezone, 'http://example.com',
163
            patch_type='diff')
2520.4.73 by Aaron Bentley
Implement new merge directive format
164
        self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.13 by Aaron Bentley
Rename fields
165
            'http://example.com', source_branch='http://example.org')
2520.4.73 by Aaron Bentley
Implement new merge directive format
166
        md = self.make_merge_directive('null:', 'sha', time, timezone,
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
167
            'http://example.com', patch='blah', patch_type='bundle')
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
168
        self.assertIs(None, md.source_branch)
2520.4.73 by Aaron Bentley
Implement new merge directive format
169
        md2 = self.make_merge_directive('null:', 'sha', time, timezone,
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
170
            'http://example.com', patch='blah', patch_type='bundle',
171
            source_branch='bar')
172
        self.assertEqual('bar', md2.source_branch)
173
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
174
    def test_serialization(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
175
        time = 453
176
        timezone = 120
2520.4.73 by Aaron Bentley
Implement new merge directive format
177
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
178
            'http://example.com', patch='booga', patch_type='bundle')
2520.4.73 by Aaron Bentley
Implement new merge directive format
179
        self.assertEqualDiff(self.OUTPUT1, ''.join(md.to_lines()))
180
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
181
            'http://example.com', source_branch="http://example.org",
182
            patch='booga', patch_type='diff', message="Hi mom!")
2520.4.73 by Aaron Bentley
Implement new merge directive format
183
        self.assertEqualDiff(self.OUTPUT2, ''.join(md.to_lines()))
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
184
1551.12.49 by Aaron Bentley
Proper error when deserializing junk
185
    def test_deserialize_junk(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
186
        time = 501
1551.12.49 by Aaron Bentley
Proper error when deserializing junk
187
        self.assertRaises(errors.NotAMergeDirective,
188
                          merge_directive.MergeDirective.from_lines, 'lala')
189
1551.12.59 by Aaron Bentley
Correctly handle empty merge directive texts
190
    def test_deserialize_empty(self):
191
        self.assertRaises(errors.NotAMergeDirective,
192
                          merge_directive.MergeDirective.from_lines, [])
193
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
194
    def test_deserialize_leading_junk(self):
2520.4.73 by Aaron Bentley
Implement new merge directive format
195
        md = merge_directive.MergeDirective.from_lines(self.INPUT1)
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
196
        self.assertEqual('example:', md.revision_id)
197
        self.assertEqual('sha', md.testament_sha1)
198
        self.assertEqual('http://example.com', md.target_branch)
199
        self.assertEqual('http://example.org', md.source_branch)
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
200
        self.assertEqual(453, md.time)
201
        self.assertEqual(120, md.timezone)
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
202
        self.assertEqual('booga', md.patch)
203
        self.assertEqual('diff', md.patch_type)
204
        self.assertEqual('Hi mom!', md.message)
1551.12.49 by Aaron Bentley
Proper error when deserializing junk
205
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
206
    def test_roundtrip(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
207
        time = 500000
208
        timezone = 7.5 * 3600
2520.4.73 by Aaron Bentley
Implement new merge directive format
209
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.13 by Aaron Bentley
Rename fields
210
            'http://example.com', source_branch="http://example.org",
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
211
            patch='booga', patch_type='diff')
212
        md2 = merge_directive.MergeDirective.from_lines(md.to_lines())
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
213
        self.assertEqual('example:', md2.revision_id)
1551.12.54 by Aaron Bentley
Decoded revision ids are utf-8
214
        self.assertIsInstance(md2.revision_id, str)
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
215
        self.assertEqual('sha', md2.testament_sha1)
1551.12.13 by Aaron Bentley
Rename fields
216
        self.assertEqual('http://example.com', md2.target_branch)
217
        self.assertEqual('http://example.org', md2.source_branch)
1551.12.3 by Aaron Bentley
Add timestamps to merge directives
218
        self.assertEqual(time, md2.time)
219
        self.assertEqual(timezone, md2.timezone)
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
220
        self.assertEqual('diff', md2.patch_type)
221
        self.assertEqual('booga', md2.patch)
1551.12.26 by Aaron Bentley
Get email working, with optional message
222
        self.assertEqual(None, md2.message)
2520.4.73 by Aaron Bentley
Implement new merge directive format
223
        self.set_bundle(md, "# Bazaar revision bundle v0.9\n#\n")
1551.12.26 by Aaron Bentley
Get email working, with optional message
224
        md.message = "Hi mom!"
2520.4.73 by Aaron Bentley
Implement new merge directive format
225
        lines = md.to_lines()
226
        md3 = merge_directive.MergeDirective.from_lines(lines)
227
        self.assertEqual("# Bazaar revision bundle v0.9\n#\n", md3.bundle)
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
228
        self.assertEqual("bundle", md3.patch_type)
1551.12.12 by Aaron Bentley
Add format header
229
        self.assertContainsRe(md3.to_lines()[0],
230
            '^# Bazaar merge directive format ')
1551.12.26 by Aaron Bentley
Get email working, with optional message
231
        self.assertEqual("Hi mom!", md3.message)
2520.4.73 by Aaron Bentley
Implement new merge directive format
232
        md3.clear_payload()
2520.4.80 by Aaron Bentley
Improve merge directive tests
233
        self.assertIs(None, md3.get_raw_bundle())
1551.12.53 by Aaron Bentley
Fix deserialization of merge directives with no patch
234
        md4 = merge_directive.MergeDirective.from_lines(md3.to_lines())
235
        self.assertIs(None, md4.patch_type)
1551.12.26 by Aaron Bentley
Get email working, with optional message
236
237
2520.4.73 by Aaron Bentley
Implement new merge directive format
238
class TestMergeDirective1(tests.TestCase, TestMergeDirective):
239
    """Test merge directive format 1"""
240
241
    INPUT1 = INPUT1
242
243
    OUTPUT1 = OUTPUT1
244
245
    OUTPUT2 = OUTPUT2
246
247
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
248
                 target_branch, patch=None, patch_type=None,
249
                 source_branch=None, message=None):
250
        return merge_directive.MergeDirective(revision_id, testament_sha1,
251
                 time, timezone, target_branch, patch, patch_type,
252
                 source_branch, message)
253
254
    @staticmethod
255
    def set_bundle(md, value):
256
        md.patch = value
257
258
    def test_require_patch(self):
259
        time = 500.0
260
        timezone = 120
261
        self.assertRaises(errors.PatchMissing, merge_directive.MergeDirective,
262
            'example:', 'sha', time, timezone, 'http://example.com',
263
            patch_type='bundle')
264
        md = merge_directive.MergeDirective('example:', 'sha1', time, timezone,
265
            'http://example.com', source_branch="http://example.org",
266
            patch='', patch_type='diff')
267
        self.assertEqual(md.patch, '')
268
269
270
class TestMergeDirective2(tests.TestCase, TestMergeDirective):
271
    """Test merge directive format 2"""
272
273
    INPUT1 = INPUT1_2
274
275
    OUTPUT1 = OUTPUT1_2
276
277
    OUTPUT2 = OUTPUT2_2
278
279
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
280
                 target_branch, patch=None, patch_type=None,
2520.4.105 by Aaron Bentley
Implement patch verification
281
                 source_branch=None, message=None, base_revision_id='null:'):
2520.4.73 by Aaron Bentley
Implement new merge directive format
282
        if patch_type == 'bundle':
283
            bundle = patch
284
            patch = None
285
        else:
286
            bundle = None
287
        return merge_directive.MergeDirective2(revision_id, testament_sha1,
288
            time, timezone, target_branch, patch, source_branch, message,
2520.4.105 by Aaron Bentley
Implement patch verification
289
            bundle, base_revision_id)
2520.4.73 by Aaron Bentley
Implement new merge directive format
290
291
    @staticmethod
292
    def set_bundle(md, value):
293
        md.bundle = value
294
295
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
296
EMAIL1 = """From: "J. Random Hacker" <jrandom@example.com>
1551.12.26 by Aaron Bentley
Get email working, with optional message
297
Subject: Commit of rev2a
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
298
To: pqm@example.com
6798.1.1 by Jelmer Vernooij
Properly escape backslashes.
299
User-Agent: Bazaar \\(.*\\)
1551.12.26 by Aaron Bentley
Get email working, with optional message
300
1551.12.45 by Aaron Bentley
Change format marker to not experimental
301
# Bazaar merge directive format 1
1551.12.26 by Aaron Bentley
Get email working, with optional message
302
# revision_id: rev2a
303
# target_branch: (.|\n)*
304
# testament_sha1: .*
1551.12.30 by Aaron Bentley
Use patch-style dates for timestamps in merge directives
305
# timestamp: 1970-01-01 00:08:56 \\+0001
1551.12.26 by Aaron Bentley
Get email working, with optional message
306
# source_branch: (.|\n)*
307
"""
308
309
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
310
EMAIL1_2 = """From: "J. Random Hacker" <jrandom@example.com>
2520.4.80 by Aaron Bentley
Improve merge directive tests
311
Subject: Commit of rev2a
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
312
To: pqm@example.com
6798.1.1 by Jelmer Vernooij
Properly escape backslashes.
313
User-Agent: Bazaar \\(.*\\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
314
2687.2.2 by Martin Pool
Fix up other references to 0.19
315
# Bazaar merge directive format 2 \\(Bazaar 0.90\\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
316
# revision_id: rev2a
317
# target_branch: (.|\n)*
318
# testament_sha1: .*
319
# timestamp: 1970-01-01 00:08:56 \\+0001
320
# source_branch: (.|\n)*
321
"""
322
323
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
324
EMAIL2 = """From: "J. Random Hacker" <jrandom@example.com>
1551.12.26 by Aaron Bentley
Get email working, with optional message
325
Subject: Commit of rev2a with special message
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
326
To: pqm@example.com
6798.1.1 by Jelmer Vernooij
Properly escape backslashes.
327
User-Agent: Bazaar \\(.*\\)
1551.12.26 by Aaron Bentley
Get email working, with optional message
328
1551.12.45 by Aaron Bentley
Change format marker to not experimental
329
# Bazaar merge directive format 1
1551.12.26 by Aaron Bentley
Get email working, with optional message
330
# revision_id: rev2a
331
# target_branch: (.|\n)*
332
# testament_sha1: .*
1551.12.30 by Aaron Bentley
Use patch-style dates for timestamps in merge directives
333
# timestamp: 1970-01-01 00:08:56 \\+0001
1551.12.26 by Aaron Bentley
Get email working, with optional message
334
# source_branch: (.|\n)*
335
# message: Commit of rev2a with special message
336
"""
1551.12.4 by Aaron Bentley
Add failing test
337
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
338
EMAIL2_2 = """From: "J. Random Hacker" <jrandom@example.com>
2520.4.80 by Aaron Bentley
Improve merge directive tests
339
Subject: Commit of rev2a with special message
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
340
To: pqm@example.com
6798.1.1 by Jelmer Vernooij
Properly escape backslashes.
341
User-Agent: Bazaar \\(.*\\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
342
2687.2.2 by Martin Pool
Fix up other references to 0.19
343
# Bazaar merge directive format 2 \\(Bazaar 0.90\\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
344
# revision_id: rev2a
345
# target_branch: (.|\n)*
346
# testament_sha1: .*
347
# timestamp: 1970-01-01 00:08:56 \\+0001
348
# source_branch: (.|\n)*
349
# message: Commit of rev2a with special message
350
"""
1551.12.4 by Aaron Bentley
Add failing test
351
2520.4.73 by Aaron Bentley
Implement new merge directive format
352
class TestMergeDirectiveBranch(object):
1551.12.4 by Aaron Bentley
Add failing test
353
1551.12.26 by Aaron Bentley
Get email working, with optional message
354
    def make_trees(self):
1551.12.4 by Aaron Bentley
Add failing test
355
        tree_a = self.make_branch_and_tree('tree_a')
6421.3.1 by Vincent Ladeuil
Migrate more branch options to config stacks.
356
        tree_a.branch.get_config_stack().set(
357
            'email', 'J. Random Hacker <jrandom@example.com>')
6855.3.1 by Jelmer Vernooij
Several more fixes.
358
        self.build_tree_contents([('tree_a/file', b'content_a\ncontent_b\n'),
359
                                  ('tree_a/file_2', b'content_x\rcontent_y\r')])
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
360
        tree_a.add(['file', 'file_2'])
6855.3.1 by Jelmer Vernooij
Several more fixes.
361
        tree_a.commit('message', rev_id=b'rev1')
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
362
        tree_b = tree_a.controldir.sprout('tree_b').open_workingtree()
363
        branch_c = tree_a.controldir.sprout('branch_c').open_branch()
6855.3.1 by Jelmer Vernooij
Several more fixes.
364
        tree_b.commit('message', rev_id=b'rev2b')
365
        self.build_tree_contents([('tree_a/file', b'content_a\ncontent_c \n'),
366
                                  ('tree_a/file_2', b'content_x\rcontent_z\r')])
367
        tree_a.commit('Commit of rev2a', rev_id=b'rev2a')
1551.12.26 by Aaron Bentley
Get email working, with optional message
368
        return tree_a, tree_b, branch_c
369
2490.2.28 by Aaron Bentley
Fix handling of null revision
370
    def test_empty_target(self):
371
        tree_a, tree_b, branch_c = self.make_trees()
372
        tree_d = self.make_branch_and_tree('tree_d')
6855.3.1 by Jelmer Vernooij
Several more fixes.
373
        md2 = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 120,
2520.4.73 by Aaron Bentley
Implement new merge directive format
374
            tree_d.branch.base, patch_type='diff',
375
            public_branch=tree_a.branch.base)
2490.2.28 by Aaron Bentley
Fix handling of null revision
376
3251.2.1 by Aaron Bentley
Use nick/revno-based names for merge directives
377
    def test_disk_name(self):
378
        tree_a, tree_b, branch_c = self.make_trees()
3449.4.1 by Lukáš Lalinský
Sanitize branch nick before using it as an attachment filename in ``bzr send``
379
        tree_a.branch.nick = 'fancy <name>'
6855.3.1 by Jelmer Vernooij
Several more fixes.
380
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 120,
3251.2.1 by Aaron Bentley
Use nick/revno-based names for merge directives
381
            tree_b.branch.base)
382
        self.assertEqual('fancy-name-2', md.get_disk_name(tree_a.branch))
383
384
    def test_disk_name_old_revno(self):
385
        tree_a, tree_b, branch_c = self.make_trees()
386
        tree_a.branch.nick = 'fancy-name'
6855.3.1 by Jelmer Vernooij
Several more fixes.
387
        md = self.from_objects(tree_a.branch.repository, b'rev1', 500, 120,
3251.2.1 by Aaron Bentley
Use nick/revno-based names for merge directives
388
            tree_b.branch.base)
389
        self.assertEqual('fancy-name-1', md.get_disk_name(tree_a.branch))
390
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
391
    def test_generate_patch(self):
392
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
393
        md2 = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 120,
2520.4.73 by Aaron Bentley
Implement new merge directive format
394
            tree_b.branch.base, patch_type='diff',
395
            public_branch=tree_a.branch.base)
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
396
        self.assertNotContainsRe(md2.patch, 'Bazaar revision bundle')
397
        self.assertContainsRe(md2.patch, '\\+content_c')
398
        self.assertNotContainsRe(md2.patch, '\\+\\+\\+ b/')
399
        self.assertContainsRe(md2.patch, '\\+\\+\\+ file')
400
401
    def test_public_branch(self):
1551.12.26 by Aaron Bentley
Get email working, with optional message
402
        tree_a, tree_b, branch_c = self.make_trees()
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
403
        self.assertRaises(errors.PublicBranchOutOfDate,
6855.3.1 by Jelmer Vernooij
Several more fixes.
404
            self.from_objects, tree_a.branch.repository, b'rev2a', 500, 144,
2520.4.73 by Aaron Bentley
Implement new merge directive format
405
            tree_b.branch.base, public_branch=branch_c.base, patch_type='diff')
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
406
        self.assertRaises(errors.PublicBranchOutOfDate,
6855.3.1 by Jelmer Vernooij
Several more fixes.
407
            self.from_objects, tree_a.branch.repository, b'rev2a', 500, 144,
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
408
            tree_b.branch.base, public_branch=branch_c.base, patch_type=None)
1551.12.34 by Aaron Bentley
Check public branch only if not using a bundle
409
        # public branch is not checked if patch format is bundle.
6855.3.1 by Jelmer Vernooij
Several more fixes.
410
        md1 = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 144,
2520.4.73 by Aaron Bentley
Implement new merge directive format
411
            tree_b.branch.base, public_branch=branch_c.base)
1551.12.34 by Aaron Bentley
Check public branch only if not using a bundle
412
        # public branch is provided with a bundle, despite possibly being out
413
        # of date, because it's not required if a bundle is present.
414
        self.assertEqual(md1.source_branch, branch_c.base)
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
415
        # Once we update the public branch, we can generate a diff.
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
416
        branch_c.pull(tree_a.branch)
6855.3.1 by Jelmer Vernooij
Several more fixes.
417
        md3 = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 144,
2520.4.73 by Aaron Bentley
Implement new merge directive format
418
            tree_b.branch.base, patch_type=None, public_branch=branch_c.base)
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
419
1551.12.50 by Aaron Bentley
Use public location of submit branch if possible
420
    def test_use_public_submit_branch(self):
421
        tree_a, tree_b, branch_c = self.make_trees()
422
        branch_c.pull(tree_a.branch)
6855.3.1 by Jelmer Vernooij
Several more fixes.
423
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 144,
2520.4.80 by Aaron Bentley
Improve merge directive tests
424
            tree_b.branch.base, patch_type=None, public_branch=branch_c.base)
1551.12.50 by Aaron Bentley
Use public location of submit branch if possible
425
        self.assertEqual(md.target_branch, tree_b.branch.base)
6404.6.7 by Vincent Ladeuil
Change set/remove to require a lock for the branch config files.
426
        tree_b.branch.set_public_branch('http://example.com')
2520.4.80 by Aaron Bentley
Improve merge directive tests
427
        md2 = self.from_objects(
6855.3.1 by Jelmer Vernooij
Several more fixes.
428
              tree_a.branch.repository, b'rev2a', 500, 144, tree_b.branch.base,
1551.12.50 by Aaron Bentley
Use public location of submit branch if possible
429
              patch_type=None, public_branch=branch_c.base)
430
        self.assertEqual(md2.target_branch, 'http://example.com')
431
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
432
    def test_message(self):
433
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
434
        md3 = self.from_objects(tree_a.branch.repository, b'rev1', 500, 120,
2520.4.80 by Aaron Bentley
Improve merge directive tests
435
            tree_b.branch.base, patch_type=None, public_branch=branch_c.base,
1551.12.33 by Aaron Bentley
Take public_branch as a string, not object
436
            message='Merge message')
1551.12.7 by Aaron Bentley
Fix use of public location/branch
437
        md3.to_lines()
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
438
        self.assertIs(None, md3.patch)
1551.12.27 by Aaron Bentley
support custom message everywhere
439
        self.assertEqual('Merge message', md3.message)
1551.12.16 by Aaron Bentley
Enable signing merge directives
440
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
441
    def test_generate_bundle(self):
1551.12.40 by Aaron Bentley
Do not show prefixes in diffs
442
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
443
        md1 = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 120,
2520.4.80 by Aaron Bentley
Improve merge directive tests
444
            tree_b.branch.base, public_branch=branch_c.base)
445
446
        self.assertContainsRe(md1.get_raw_bundle(), 'Bazaar revision bundle')
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
447
        self.assertContainsRe(md1.patch, '\\+content_c')
448
        self.assertNotContainsRe(md1.patch, '\\+content_a')
449
        self.assertContainsRe(md1.patch, '\\+content_c')
450
        self.assertNotContainsRe(md1.patch, '\\+content_a')
1551.12.40 by Aaron Bentley
Do not show prefixes in diffs
451
1551.15.29 by Aaron Bentley
Make merge directives robust against broken bundles
452
    def test_broken_bundle(self):
453
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
454
        md1 = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 120,
2520.4.73 by Aaron Bentley
Implement new merge directive format
455
            tree_b.branch.base, public_branch=branch_c.base)
1551.15.29 by Aaron Bentley
Make merge directives robust against broken bundles
456
        lines = md1.to_lines()
457
        lines = [l.replace('\n', '\r\n') for l in lines]
458
        md2 = merge_directive.MergeDirective.from_lines(lines)
6855.3.1 by Jelmer Vernooij
Several more fixes.
459
        self.assertEqual(b'rev2a', md2.revision_id)
1551.15.29 by Aaron Bentley
Make merge directives robust against broken bundles
460
1551.12.16 by Aaron Bentley
Enable signing merge directives
461
    def test_signing(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
462
        time = 453
463
        timezone = 7200
1551.12.16 by Aaron Bentley
Enable signing merge directives
464
        class FakeBranch(object):
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
465
            def get_config_stack(self):
1551.12.16 by Aaron Bentley
Enable signing merge directives
466
                return self
2520.4.80 by Aaron Bentley
Improve merge directive tests
467
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.16 by Aaron Bentley
Enable signing merge directives
468
            'http://example.com', source_branch="http://example.org",
469
            patch='booga', patch_type='diff')
470
        old_strategy = gpg.GPGStrategy
471
        gpg.GPGStrategy = gpg.LoopbackGPGStrategy
472
        try:
473
            signed = md.to_signed(FakeBranch())
474
        finally:
475
            gpg.GPGStrategy = old_strategy
476
        self.assertContainsRe(signed, '^-----BEGIN PSEUDO-SIGNED CONTENT')
477
        self.assertContainsRe(signed, 'example.org')
478
        self.assertContainsRe(signed, 'booga')
1551.12.26 by Aaron Bentley
Get email working, with optional message
479
480
    def test_email(self):
481
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
482
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 476, 60,
2520.4.80 by Aaron Bentley
Improve merge directive tests
483
            tree_b.branch.base, patch_type=None,
484
            public_branch=tree_a.branch.base)
1551.12.26 by Aaron Bentley
Get email working, with optional message
485
        message = md.to_email('pqm@example.com', tree_a.branch)
2520.4.80 by Aaron Bentley
Improve merge directive tests
486
        self.assertContainsRe(message.as_string(), self.EMAIL1)
1551.12.26 by Aaron Bentley
Get email working, with optional message
487
        md.message = 'Commit of rev2a with special message'
488
        message = md.to_email('pqm@example.com', tree_a.branch)
2520.4.80 by Aaron Bentley
Improve merge directive tests
489
        self.assertContainsRe(message.as_string(), self.EMAIL2)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
490
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
491
    def test_install_revisions_branch(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
492
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
493
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 36,
2520.4.80 by Aaron Bentley
Improve merge directive tests
494
            tree_b.branch.base, patch_type=None,
495
            public_branch=tree_a.branch.base)
6855.3.1 by Jelmer Vernooij
Several more fixes.
496
        self.assertFalse(tree_b.branch.repository.has_revision(b'rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
497
        revision = md.install_revisions(tree_b.branch.repository)
6855.3.1 by Jelmer Vernooij
Several more fixes.
498
        self.assertEqual(b'rev2a', revision)
499
        self.assertTrue(tree_b.branch.repository.has_revision(b'rev2a'))
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
500
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
501
    def test_get_merge_request(self):
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
502
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
503
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 36,
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
504
            tree_b.branch.base, patch_type='bundle',
505
            public_branch=tree_a.branch.base)
6855.3.1 by Jelmer Vernooij
Several more fixes.
506
        self.assertFalse(tree_b.branch.repository.has_revision(b'rev2a'))
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
507
        md.install_revisions(tree_b.branch.repository)
508
        base, revision, verified = md.get_merge_request(
509
            tree_b.branch.repository)
510
        if isinstance(md, merge_directive.MergeDirective):
511
            self.assertIs(None, base)
512
            self.assertEqual('inapplicable', verified)
513
        else:
6855.3.1 by Jelmer Vernooij
Several more fixes.
514
            self.assertEqual(b'rev1', base)
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
515
            self.assertEqual('verified', verified)
6855.3.1 by Jelmer Vernooij
Several more fixes.
516
        self.assertEqual(b'rev2a', revision)
517
        self.assertTrue(tree_b.branch.repository.has_revision(b'rev2a'))
518
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 36,
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
519
            tree_b.branch.base, patch_type=None,
520
            public_branch=tree_a.branch.base)
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
521
        base, revision, verified = md.get_merge_request(
522
            tree_b.branch.repository)
523
        if isinstance(md, merge_directive.MergeDirective):
524
            self.assertIs(None, base)
525
            self.assertEqual('inapplicable', verified)
526
        else:
6855.3.1 by Jelmer Vernooij
Several more fixes.
527
            self.assertEqual(b'rev1', base)
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
528
            self.assertEqual('inapplicable', verified)
6855.3.1 by Jelmer Vernooij
Several more fixes.
529
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 36,
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
530
            tree_b.branch.base, patch_type='diff',
531
            public_branch=tree_a.branch.base)
532
        base, revision, verified = md.get_merge_request(
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
533
            tree_b.branch.repository)
534
        if isinstance(md, merge_directive.MergeDirective):
535
            self.assertIs(None, base)
536
            self.assertEqual('inapplicable', verified)
537
        else:
6855.3.1 by Jelmer Vernooij
Several more fixes.
538
            self.assertEqual(b'rev1', base)
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
539
            self.assertEqual('verified', verified)
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
540
        md.patch='asdf'
541
        base, revision, verified = md.get_merge_request(
542
            tree_b.branch.repository)
543
        if isinstance(md, merge_directive.MergeDirective):
544
            self.assertIs(None, base)
545
            self.assertEqual('inapplicable', verified)
546
        else:
6855.3.1 by Jelmer Vernooij
Several more fixes.
547
            self.assertEqual(b'rev1', base)
2520.7.1 by Aaron Bentley
Reactivate patch verification
548
            self.assertEqual('failed', verified)
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
549
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
550
    def test_install_revisions_bundle(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
551
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
552
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 36,
2520.4.80 by Aaron Bentley
Improve merge directive tests
553
            tree_b.branch.base, patch_type='bundle',
554
            public_branch=tree_a.branch.base)
6855.3.1 by Jelmer Vernooij
Several more fixes.
555
        self.assertFalse(tree_b.branch.repository.has_revision(b'rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
556
        revision = md.install_revisions(tree_b.branch.repository)
6855.3.1 by Jelmer Vernooij
Several more fixes.
557
        self.assertEqual(b'rev2a', revision)
558
        self.assertTrue(tree_b.branch.repository.has_revision(b'rev2a'))
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
559
560
    def test_get_target_revision_nofetch(self):
561
        tree_a, tree_b, branch_c = self.make_trees()
562
        tree_b.branch.fetch(tree_a.branch)
6855.3.1 by Jelmer Vernooij
Several more fixes.
563
        md = self.from_objects( tree_a.branch.repository, b'rev2a', 500, 36,
2520.4.80 by Aaron Bentley
Improve merge directive tests
564
            tree_b.branch.base, patch_type=None,
565
            public_branch=tree_a.branch.base)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
566
        md.source_branch = '/dev/null'
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
567
        revision = md.install_revisions(tree_b.branch.repository)
6855.3.1 by Jelmer Vernooij
Several more fixes.
568
        self.assertEqual(b'rev2a', revision)
2520.4.73 by Aaron Bentley
Implement new merge directive format
569
1551.19.19 by Aaron Bentley
Merge directives can now fetch prerequisites from the target branch
570
    def test_use_submit_for_missing_dependency(self):
571
        tree_a, tree_b, branch_c = self.make_trees()
572
        branch_c.pull(tree_a.branch)
6855.4.1 by Jelmer Vernooij
Yet more bees.
573
        self.build_tree_contents([('tree_a/file', b'content_q\ncontent_r\n')])
6855.3.1 by Jelmer Vernooij
Several more fixes.
574
        tree_a.commit('rev3a', rev_id=b'rev3a')
575
        md = self.from_objects(tree_a.branch.repository, b'rev3a', 500, 36,
576
            branch_c.base, base_revision_id=b'rev2a')
1551.19.19 by Aaron Bentley
Merge directives can now fetch prerequisites from the target branch
577
        revision = md.install_revisions(tree_b.branch.repository)
578
3535.8.1 by James Westby
Handle something that isn't a branch being specified in target_branch.
579
    def test_handle_target_not_a_branch(self):
580
        tree_a, tree_b, branch_c = self.make_trees()
581
        branch_c.pull(tree_a.branch)
6855.4.1 by Jelmer Vernooij
Yet more bees.
582
        self.build_tree_contents([('tree_a/file', b'content_q\ncontent_r\n')])
6855.3.1 by Jelmer Vernooij
Several more fixes.
583
        tree_a.commit('rev3a', rev_id=b'rev3a')
584
        md = self.from_objects(tree_a.branch.repository, b'rev3a', 500, 36,
585
            branch_c.base, base_revision_id=b'rev2a')
3535.8.2 by James Westby
Incorporate spiv's feedback.
586
        md.target_branch = self.get_url('not-a-branch')
3535.8.1 by James Westby
Handle something that isn't a branch being specified in target_branch.
587
        self.assertRaises(errors.TargetNotBranch, md.install_revisions,
588
                tree_b.branch.repository)
589
2520.4.73 by Aaron Bentley
Implement new merge directive format
590
591
class TestMergeDirective1Branch(tests.TestCaseWithTransport,
592
    TestMergeDirectiveBranch):
593
    """Test merge directive format 1 with a branch"""
2520.4.80 by Aaron Bentley
Improve merge directive tests
594
595
    EMAIL1 = EMAIL1
596
597
    EMAIL2 = EMAIL2
598
2520.4.73 by Aaron Bentley
Implement new merge directive format
599
    def from_objects(self, repository, revision_id, time, timezone,
600
        target_branch, patch_type='bundle', local_target_branch=None,
1551.19.19 by Aaron Bentley
Merge directives can now fetch prerequisites from the target branch
601
        public_branch=None, message=None, base_revision_id=None):
602
        if base_revision_id is not None:
603
            raise tests.TestNotApplicable('This format does not support'
604
                                          ' explicit bases.')
3010.1.9 by Robert Collins
test_merge_directive locking correctness.
605
        repository.lock_write()
606
        try:
607
            return merge_directive.MergeDirective.from_objects( repository,
608
                revision_id, time, timezone, target_branch, patch_type,
609
                local_target_branch, public_branch, message)
610
        finally:
611
            repository.unlock()
2520.4.73 by Aaron Bentley
Implement new merge directive format
612
2520.4.80 by Aaron Bentley
Improve merge directive tests
613
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
614
                 target_branch, patch=None, patch_type=None,
615
                 source_branch=None, message=None):
616
        return merge_directive.MergeDirective(revision_id, testament_sha1,
617
                 time, timezone, target_branch, patch, patch_type,
618
                 source_branch, message)
619
2520.4.73 by Aaron Bentley
Implement new merge directive format
620
621
class TestMergeDirective2Branch(tests.TestCaseWithTransport,
622
    TestMergeDirectiveBranch):
623
    """Test merge directive format 2 with a branch"""
624
2520.4.80 by Aaron Bentley
Improve merge directive tests
625
    EMAIL1 = EMAIL1_2
626
627
    EMAIL2 = EMAIL2_2
628
2520.4.73 by Aaron Bentley
Implement new merge directive format
629
    def from_objects(self, repository, revision_id, time, timezone,
630
        target_branch, patch_type='bundle', local_target_branch=None,
2520.4.112 by Aaron Bentley
Make cherry-pick merge directives possible
631
        public_branch=None, message=None, base_revision_id=None):
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
632
        include_patch = (patch_type in ('bundle', 'diff'))
633
        include_bundle = (patch_type == 'bundle')
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
634
        self.assertTrue(patch_type in ('bundle', 'diff', None))
2520.4.73 by Aaron Bentley
Implement new merge directive format
635
        return merge_directive.MergeDirective2.from_objects(
636
            repository, revision_id, time, timezone, target_branch,
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
637
            include_patch, include_bundle, local_target_branch, public_branch,
638
            message, base_revision_id)
2520.4.80 by Aaron Bentley
Improve merge directive tests
639
640
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
641
                 target_branch, patch=None, patch_type=None,
2520.4.105 by Aaron Bentley
Implement patch verification
642
                 source_branch=None, message=None, base_revision_id='null:'):
2520.4.80 by Aaron Bentley
Improve merge directive tests
643
        if patch_type == 'bundle':
644
            bundle = patch
645
            patch = None
646
        else:
647
            bundle = None
648
        return merge_directive.MergeDirective2(revision_id, testament_sha1,
649
            time, timezone, target_branch, patch, source_branch, message,
2520.4.105 by Aaron Bentley
Implement patch verification
650
            bundle, base_revision_id)
651
652
    def test_base_revision(self):
653
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
654
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 60,
2520.4.105 by Aaron Bentley
Implement patch verification
655
            tree_b.branch.base, patch_type='bundle',
2520.4.112 by Aaron Bentley
Make cherry-pick merge directives possible
656
            public_branch=tree_a.branch.base, base_revision_id=None)
6855.3.1 by Jelmer Vernooij
Several more fixes.
657
        self.assertEqual(b'rev1', md.base_revision_id)
658
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 60,
2520.4.112 by Aaron Bentley
Make cherry-pick merge directives possible
659
            tree_b.branch.base, patch_type='bundle',
660
            public_branch=tree_a.branch.base, base_revision_id='null:')
661
        self.assertEqual('null:', md.base_revision_id)
2520.4.105 by Aaron Bentley
Implement patch verification
662
        lines = md.to_lines()
663
        md2 = merge_directive.MergeDirective.from_lines(lines)
664
        self.assertEqual(md2.base_revision_id, md.base_revision_id)
665
666
    def test_patch_verification(self):
667
        tree_a, tree_b, branch_c = self.make_trees()
6855.3.1 by Jelmer Vernooij
Several more fixes.
668
        md = self.from_objects(tree_a.branch.repository, b'rev2a', 500, 60,
2520.4.105 by Aaron Bentley
Implement patch verification
669
            tree_b.branch.base, patch_type='bundle',
670
            public_branch=tree_a.branch.base)
671
        lines = md.to_lines()
672
        md2 = merge_directive.MergeDirective.from_lines(lines)
673
        md2._verify_patch(tree_a.branch.repository)
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
674
        # Strip trailing whitespace
2520.4.105 by Aaron Bentley
Implement patch verification
675
        md2.patch = md2.patch.replace(' \n', '\n')
676
        md2._verify_patch(tree_a.branch.repository)
677
        # Convert to Mac line-endings
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
678
        md2.patch = re.sub('(\r\n|\r|\n)', '\r', md2.patch)
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
679
        self.assertTrue(md2._verify_patch(tree_a.branch.repository))
2520.4.105 by Aaron Bentley
Implement patch verification
680
        # Convert to DOS line-endings
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
681
        md2.patch = re.sub('(\r\n|\r|\n)', '\r\n', md2.patch)
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
682
        self.assertTrue(md2._verify_patch(tree_a.branch.repository))
2520.4.105 by Aaron Bentley
Implement patch verification
683
        md2.patch = md2.patch.replace('content_c', 'content_d')
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
684
        self.assertFalse(md2._verify_patch(tree_a.branch.repository))
2694.1.1 by Aaron Bentley
Restore support for Merge directive 2 / 0.19
685
686
687
class TestParseOldMergeDirective2(tests.TestCase):
688
689
    def test_parse_old_merge_directive(self):
690
        md = merge_directive.MergeDirective.from_lines(INPUT1_2_OLD)
691
        self.assertEqual('example:', md.revision_id)
692
        self.assertEqual('sha', md.testament_sha1)
693
        self.assertEqual('http://example.com', md.target_branch)
694
        self.assertEqual('http://example.org', md.source_branch)
695
        self.assertEqual(453, md.time)
696
        self.assertEqual(120, md.timezone)
697
        self.assertEqual('booga', md.patch)
698
        self.assertEqual('diff', md.patch_type)
699
        self.assertEqual('Hi mom!', md.message)
4098.5.16 by Aaron Bentley
Move hook to MergeDirective, implement MergeDirective.compose_merge_request.
700
701
702
class TestHook(object):
703
    """Hook callback for test purposes."""
704
705
    def __init__(self, result=None):
706
        self.calls = []
707
        self.result = result
708
709
    def __call__(self, params):
710
        self.calls.append(params)
711
        return self.result
712
713
714
class HookMailClient(mail_client.MailClient):
715
    """Mail client for testing hooks."""
716
717
    def __init__(self, config):
718
        self.body = None
719
        self.config = config
720
721
    def compose(self, prompt, to, subject, attachment, mime_subtype,
722
                extension, basename=None, body=None):
723
        self.body = body
724
725
726
class TestBodyHook(tests.TestCaseWithTransport):
727
4098.5.18 by Aaron Bentley
Gracefully handle mail clients that don't support bodies.
728
    def compose_with_hooks(self, test_hooks, supports_body=True):
4098.5.16 by Aaron Bentley
Move hook to MergeDirective, implement MergeDirective.compose_merge_request.
729
        client = HookMailClient({})
4098.5.18 by Aaron Bentley
Gracefully handle mail clients that don't support bodies.
730
        client.supports_body = supports_body
4098.5.16 by Aaron Bentley
Move hook to MergeDirective, implement MergeDirective.compose_merge_request.
731
        for test_hook in test_hooks:
732
            merge_directive.MergeDirective.hooks.install_named_hook(
733
                'merge_request_body', test_hook, 'test')
734
        tree = self.make_branch_and_tree('foo')
735
        tree.commit('foo')
736
        directive = merge_directive.MergeDirective2(
737
            tree.branch.last_revision(), 'sha', 0, 0, 'sha',
738
            source_branch=tree.branch.base,
739
            base_revision_id=tree.branch.last_revision(),
740
            message='This code rox')
741
        directive.compose_merge_request(client, 'jrandom@example.com',
742
            None, tree.branch)
743
        return client, directive
744
4098.5.18 by Aaron Bentley
Gracefully handle mail clients that don't support bodies.
745
    def test_no_supports_body(self):
746
        test_hook = TestHook('foo')
747
        old_warn = trace.warning
748
        warnings = []
749
        def warn(*args):
750
            warnings.append(args)
751
        trace.warning = warn
752
        try:
753
            client, directive = self.compose_with_hooks([test_hook],
754
                supports_body=False)
755
        finally:
756
            trace.warning = old_warn
757
        self.assertEqual(0, len(test_hook.calls))
758
        self.assertEqual(('Cannot run merge_request_body hooks because mail'
759
                          ' client %s does not support message bodies.',
760
                          'HookMailClient'), warnings[0])
761
4098.5.16 by Aaron Bentley
Move hook to MergeDirective, implement MergeDirective.compose_merge_request.
762
    def test_body_hook(self):
763
        test_hook = TestHook('foo')
764
        client, directive = self.compose_with_hooks([test_hook])
765
        self.assertEqual(1, len(test_hook.calls))
766
        self.assertEqual('foo', client.body)
767
        params = test_hook.calls[0]
768
        self.assertIsInstance(params,
769
                              merge_directive.MergeRequestBodyParams)
770
        self.assertIs(None, params.body)
771
        self.assertIs(None, params.orig_body)
772
        self.assertEqual('jrandom@example.com', params.to)
773
        self.assertEqual('[MERGE] This code rox', params.subject)
774
        self.assertEqual(directive, params.directive)
775
        self.assertEqual('foo-1', params.basename)
776
777
    def test_body_hook_chaining(self):
778
        test_hook1 = TestHook('foo')
779
        test_hook2 = TestHook('bar')
780
        client = self.compose_with_hooks([test_hook1, test_hook2])[0]
781
        self.assertEqual(None, test_hook1.calls[0].body)
782
        self.assertEqual(None, test_hook1.calls[0].orig_body)
783
        self.assertEqual('foo', test_hook2.calls[0].body)
784
        self.assertEqual(None, test_hook2.calls[0].orig_body)
785
        self.assertEqual('bar', client.body)