~bzr-pqm/bzr/bzr.dev

1551.12.36 by Aaron Bentley
Fix failing tests
1
# Copyright (C) 2007 Canonical Ltd
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
19
from bzrlib import (
20
    errors,
1551.12.16 by Aaron Bentley
Enable signing merge directives
21
    gpg,
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
22
    merge_directive,
23
    tests,
24
    )
25
1551.12.4 by Aaron Bentley
Add failing test
26
1551.12.45 by Aaron Bentley
Change format marker to not experimental
27
OUTPUT1 = """# Bazaar merge directive format 1
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
28
# revision_id: example:
29
# target_branch: http://example.com
30
# testament_sha1: sha
31
# timestamp: 1970-01-01 00:09:33 +0002
32
#\x20
33
booga"""
34
2687.2.2 by Martin Pool
Fix up other references to 0.19
35
OUTPUT1_2 = """# Bazaar merge directive format 2 (Bazaar 0.90)
2520.4.73 by Aaron Bentley
Implement new merge directive format
36
# revision_id: example:
37
# target_branch: http://example.com
38
# testament_sha1: sha
39
# timestamp: 1970-01-01 00:09:33 +0002
2520.4.105 by Aaron Bentley
Implement patch verification
40
# base_revision_id: null:
2520.4.73 by Aaron Bentley
Implement new merge directive format
41
#\x20
42
# Begin bundle
43
booga"""
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
44
1551.12.45 by Aaron Bentley
Change format marker to not experimental
45
OUTPUT2 = """# Bazaar merge directive format 1
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
46
# revision_id: example:
47
# target_branch: http://example.com
48
# testament_sha1: sha
49
# timestamp: 1970-01-01 00:09:33 +0002
50
# source_branch: http://example.org
51
# message: Hi mom!
52
#\x20
53
booga"""
54
2687.2.2 by Martin Pool
Fix up other references to 0.19
55
OUTPUT2_2 = """# Bazaar merge directive format 2 (Bazaar 0.90)
2520.4.73 by Aaron Bentley
Implement new merge directive format
56
# revision_id: example:
57
# target_branch: http://example.com
58
# testament_sha1: sha
59
# timestamp: 1970-01-01 00:09:33 +0002
60
# source_branch: http://example.org
61
# message: Hi mom!
2520.4.105 by Aaron Bentley
Implement patch verification
62
# base_revision_id: null:
2520.4.73 by Aaron Bentley
Implement new merge directive format
63
#\x20
64
# Begin patch
65
booga"""
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
66
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
67
INPUT1 = """
68
I was thinking today about creating a merge directive.
69
70
So I did.
71
72
Here it is.
73
74
(I've pasted it in the body of this message)
75
76
Aaron
77
78
# Bazaar merge directive format 1\r
79
# revision_id: example:
80
# target_branch: http://example.com
81
# testament_sha1: sha
82
# timestamp: 1970-01-01 00:09:33 +0002
83
# source_branch: http://example.org
84
# message: Hi mom!
85
#\x20
86
booga""".splitlines(True)
87
88
2520.4.73 by Aaron Bentley
Implement new merge directive format
89
INPUT1_2 = """
90
I was thinking today about creating a merge directive.
91
92
So I did.
93
94
Here it is.
95
96
(I've pasted it in the body of this message)
97
98
Aaron
99
2687.2.2 by Martin Pool
Fix up other references to 0.19
100
# Bazaar merge directive format 2 (Bazaar 0.90)\r
2520.4.73 by Aaron Bentley
Implement new merge directive format
101
# revision_id: example:
102
# target_branch: http://example.com
103
# testament_sha1: sha
104
# timestamp: 1970-01-01 00:09:33 +0002
105
# source_branch: http://example.org
2520.4.105 by Aaron Bentley
Implement patch verification
106
# base_revision_id: null:
2520.4.73 by Aaron Bentley
Implement new merge directive format
107
# message: Hi mom!
108
#\x20
109
# Begin patch
110
booga""".splitlines(True)
111
112
2694.1.1 by Aaron Bentley
Restore support for Merge directive 2 / 0.19
113
INPUT1_2_OLD = """
114
I was thinking today about creating a merge directive.
115
116
So I did.
117
118
Here it is.
119
120
(I've pasted it in the body of this message)
121
122
Aaron
123
124
# Bazaar merge directive format 2 (Bazaar 0.19)\r
125
# revision_id: example:
126
# target_branch: http://example.com
127
# testament_sha1: sha
128
# timestamp: 1970-01-01 00:09:33 +0002
129
# source_branch: http://example.org
130
# base_revision_id: null:
131
# message: Hi mom!
132
#\x20
133
# Begin patch
134
booga""".splitlines(True)
135
2694.1.2 by Aaron Bentley
Fix whitespace
136
2694.1.1 by Aaron Bentley
Restore support for Merge directive 2 / 0.19
137
OLD_DIRECTIVE_2 = """# Bazaar merge directive format 2 (Bazaar 0.19)
138
# revision_id: abentley@panoramicfeedback.com-20070807234458-\
139
#   nzhkoyza56lan7z5
140
# target_branch: http://panoramicfeedback.com/opensource/bzr/repo\
141
#   /bzr.ab
142
# testament_sha1: d825a5cdb267a90ec2ba86b00895f3d8a9bed6bf
143
# timestamp: 2007-08-10 16:15:02 -0400
144
# source_branch: http://panoramicfeedback.com/opensource/bzr/repo\
145
#   /bzr.ab
146
# base_revision_id: abentley@panoramicfeedback.com-20070731163346-\
147
#   623xwcycwij91xen
148
#
149
""".splitlines(True)
150
151
2520.4.73 by Aaron Bentley
Implement new merge directive format
152
class TestMergeDirective(object):
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
153
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
154
    def test_merge_source(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
155
        time = 500000.0
156
        timezone = 5 * 3600
2520.4.73 by Aaron Bentley
Implement new merge directive format
157
        self.assertRaises(errors.NoMergeSource, self.make_merge_directive,
1551.12.3 by Aaron Bentley
Add timestamps to merge directives
158
            'example:', 'sha', time, timezone, 'http://example.com')
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',
161
            patch_type='diff')
2520.4.73 by Aaron Bentley
Implement new merge directive format
162
        self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.13 by Aaron Bentley
Rename fields
163
            'http://example.com', source_branch='http://example.org')
2520.4.73 by Aaron Bentley
Implement new merge directive format
164
        md = self.make_merge_directive('null:', 'sha', time, timezone,
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
165
            'http://example.com', patch='blah', patch_type='bundle')
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
166
        self.assertIs(None, md.source_branch)
2520.4.73 by Aaron Bentley
Implement new merge directive format
167
        md2 = self.make_merge_directive('null:', 'sha', time, timezone,
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
168
            'http://example.com', patch='blah', patch_type='bundle',
169
            source_branch='bar')
170
        self.assertEqual('bar', md2.source_branch)
171
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
172
    def test_serialization(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
173
        time = 453
174
        timezone = 120
2520.4.73 by Aaron Bentley
Implement new merge directive format
175
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
176
            'http://example.com', patch='booga', patch_type='bundle')
2520.4.73 by Aaron Bentley
Implement new merge directive format
177
        self.assertEqualDiff(self.OUTPUT1, ''.join(md.to_lines()))
178
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
179
            'http://example.com', source_branch="http://example.org",
180
            patch='booga', patch_type='diff', message="Hi mom!")
2520.4.73 by Aaron Bentley
Implement new merge directive format
181
        self.assertEqualDiff(self.OUTPUT2, ''.join(md.to_lines()))
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
182
1551.12.49 by Aaron Bentley
Proper error when deserializing junk
183
    def test_deserialize_junk(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
184
        time = 501
1551.12.49 by Aaron Bentley
Proper error when deserializing junk
185
        self.assertRaises(errors.NotAMergeDirective,
186
                          merge_directive.MergeDirective.from_lines, 'lala')
187
1551.12.59 by Aaron Bentley
Correctly handle empty merge directive texts
188
    def test_deserialize_empty(self):
189
        self.assertRaises(errors.NotAMergeDirective,
190
                          merge_directive.MergeDirective.from_lines, [])
191
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
192
    def test_deserialize_leading_junk(self):
2520.4.73 by Aaron Bentley
Implement new merge directive format
193
        md = merge_directive.MergeDirective.from_lines(self.INPUT1)
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
194
        self.assertEqual('example:', md.revision_id)
195
        self.assertEqual('sha', md.testament_sha1)
196
        self.assertEqual('http://example.com', md.target_branch)
197
        self.assertEqual('http://example.org', md.source_branch)
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
198
        self.assertEqual(453, md.time)
199
        self.assertEqual(120, md.timezone)
1551.12.51 by Aaron Bentley
Allow leading junk before merge directive header
200
        self.assertEqual('booga', md.patch)
201
        self.assertEqual('diff', md.patch_type)
202
        self.assertEqual('Hi mom!', md.message)
1551.12.49 by Aaron Bentley
Proper error when deserializing junk
203
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
204
    def test_roundtrip(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
205
        time = 500000
206
        timezone = 7.5 * 3600
2520.4.73 by Aaron Bentley
Implement new merge directive format
207
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.13 by Aaron Bentley
Rename fields
208
            'http://example.com', source_branch="http://example.org",
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
209
            patch='booga', patch_type='diff')
210
        md2 = merge_directive.MergeDirective.from_lines(md.to_lines())
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
211
        self.assertEqual('example:', md2.revision_id)
1551.12.54 by Aaron Bentley
Decoded revision ids are utf-8
212
        self.assertIsInstance(md2.revision_id, str)
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
213
        self.assertEqual('sha', md2.testament_sha1)
1551.12.13 by Aaron Bentley
Rename fields
214
        self.assertEqual('http://example.com', md2.target_branch)
215
        self.assertEqual('http://example.org', md2.source_branch)
1551.12.3 by Aaron Bentley
Add timestamps to merge directives
216
        self.assertEqual(time, md2.time)
217
        self.assertEqual(timezone, md2.timezone)
1551.12.2 by Aaron Bentley
Got directives round-tripping, with bundles and everything
218
        self.assertEqual('diff', md2.patch_type)
219
        self.assertEqual('booga', md2.patch)
1551.12.26 by Aaron Bentley
Get email working, with optional message
220
        self.assertEqual(None, md2.message)
2520.4.73 by Aaron Bentley
Implement new merge directive format
221
        self.set_bundle(md, "# Bazaar revision bundle v0.9\n#\n")
1551.12.26 by Aaron Bentley
Get email working, with optional message
222
        md.message = "Hi mom!"
2520.4.73 by Aaron Bentley
Implement new merge directive format
223
        lines = md.to_lines()
224
        md3 = merge_directive.MergeDirective.from_lines(lines)
225
        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
226
        self.assertEqual("bundle", md3.patch_type)
1551.12.12 by Aaron Bentley
Add format header
227
        self.assertContainsRe(md3.to_lines()[0],
228
            '^# Bazaar merge directive format ')
1551.12.26 by Aaron Bentley
Get email working, with optional message
229
        self.assertEqual("Hi mom!", md3.message)
2520.4.73 by Aaron Bentley
Implement new merge directive format
230
        md3.clear_payload()
2520.4.80 by Aaron Bentley
Improve merge directive tests
231
        self.assertIs(None, md3.get_raw_bundle())
1551.12.53 by Aaron Bentley
Fix deserialization of merge directives with no patch
232
        md4 = merge_directive.MergeDirective.from_lines(md3.to_lines())
233
        self.assertIs(None, md4.patch_type)
1551.12.26 by Aaron Bentley
Get email working, with optional message
234
235
2520.4.73 by Aaron Bentley
Implement new merge directive format
236
class TestMergeDirective1(tests.TestCase, TestMergeDirective):
237
    """Test merge directive format 1"""
238
239
    INPUT1 = INPUT1
240
241
    OUTPUT1 = OUTPUT1
242
243
    OUTPUT2 = OUTPUT2
244
245
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
246
                 target_branch, patch=None, patch_type=None,
247
                 source_branch=None, message=None):
248
        return merge_directive.MergeDirective(revision_id, testament_sha1,
249
                 time, timezone, target_branch, patch, patch_type,
250
                 source_branch, message)
251
252
    @staticmethod
253
    def set_bundle(md, value):
254
        md.patch = value
255
256
    def test_require_patch(self):
257
        time = 500.0
258
        timezone = 120
259
        self.assertRaises(errors.PatchMissing, merge_directive.MergeDirective,
260
            'example:', 'sha', time, timezone, 'http://example.com',
261
            patch_type='bundle')
262
        md = merge_directive.MergeDirective('example:', 'sha1', time, timezone,
263
            'http://example.com', source_branch="http://example.org",
264
            patch='', patch_type='diff')
265
        self.assertEqual(md.patch, '')
266
267
268
class TestMergeDirective2(tests.TestCase, TestMergeDirective):
269
    """Test merge directive format 2"""
270
271
    INPUT1 = INPUT1_2
272
273
    OUTPUT1 = OUTPUT1_2
274
275
    OUTPUT2 = OUTPUT2_2
276
277
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
278
                 target_branch, patch=None, patch_type=None,
2520.4.105 by Aaron Bentley
Implement patch verification
279
                 source_branch=None, message=None, base_revision_id='null:'):
2520.4.73 by Aaron Bentley
Implement new merge directive format
280
        if patch_type == 'bundle':
281
            bundle = patch
282
            patch = None
283
        else:
284
            bundle = None
285
        return merge_directive.MergeDirective2(revision_id, testament_sha1,
286
            time, timezone, target_branch, patch, source_branch, message,
2520.4.105 by Aaron Bentley
Implement patch verification
287
            bundle, base_revision_id)
2520.4.73 by Aaron Bentley
Implement new merge directive format
288
289
    @staticmethod
290
    def set_bundle(md, value):
291
        md.bundle = value
292
293
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
294
EMAIL1 = """From: "J. Random Hacker" <jrandom@example.com>
1551.12.26 by Aaron Bentley
Get email working, with optional message
295
Subject: Commit of rev2a
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
296
To: pqm@example.com
297
User-Agent: Bazaar \(.*\)
1551.12.26 by Aaron Bentley
Get email working, with optional message
298
1551.12.45 by Aaron Bentley
Change format marker to not experimental
299
# Bazaar merge directive format 1
1551.12.26 by Aaron Bentley
Get email working, with optional message
300
# revision_id: rev2a
301
# target_branch: (.|\n)*
302
# testament_sha1: .*
1551.12.30 by Aaron Bentley
Use patch-style dates for timestamps in merge directives
303
# timestamp: 1970-01-01 00:08:56 \\+0001
1551.12.26 by Aaron Bentley
Get email working, with optional message
304
# source_branch: (.|\n)*
305
"""
306
307
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
308
EMAIL1_2 = """From: "J. Random Hacker" <jrandom@example.com>
2520.4.80 by Aaron Bentley
Improve merge directive tests
309
Subject: Commit of rev2a
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
310
To: pqm@example.com
311
User-Agent: Bazaar \(.*\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
312
2687.2.2 by Martin Pool
Fix up other references to 0.19
313
# Bazaar merge directive format 2 \\(Bazaar 0.90\\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
314
# revision_id: rev2a
315
# target_branch: (.|\n)*
316
# testament_sha1: .*
317
# timestamp: 1970-01-01 00:08:56 \\+0001
318
# source_branch: (.|\n)*
319
"""
320
321
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
322
EMAIL2 = """From: "J. Random Hacker" <jrandom@example.com>
1551.12.26 by Aaron Bentley
Get email working, with optional message
323
Subject: Commit of rev2a with special message
2625.6.1 by Adeodato Simó
New EmailMessage class, façade around email.Message and MIMEMultipart.
324
To: pqm@example.com
325
User-Agent: Bazaar \(.*\)
1551.12.26 by Aaron Bentley
Get email working, with optional message
326
1551.12.45 by Aaron Bentley
Change format marker to not experimental
327
# Bazaar merge directive format 1
1551.12.26 by Aaron Bentley
Get email working, with optional message
328
# revision_id: rev2a
329
# target_branch: (.|\n)*
330
# testament_sha1: .*
1551.12.30 by Aaron Bentley
Use patch-style dates for timestamps in merge directives
331
# timestamp: 1970-01-01 00:08:56 \\+0001
1551.12.26 by Aaron Bentley
Get email working, with optional message
332
# source_branch: (.|\n)*
333
# message: Commit of rev2a with special message
334
"""
1551.12.4 by Aaron Bentley
Add failing test
335
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
336
EMAIL2_2 = """From: "J. Random Hacker" <jrandom@example.com>
2520.4.80 by Aaron Bentley
Improve merge directive tests
337
Subject: Commit of rev2a with special message
2625.6.2 by Adeodato Simó
Merge bzr.dev, resolving conflicts and updating test_merge_directive.py.
338
To: pqm@example.com
339
User-Agent: Bazaar \(.*\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
340
2687.2.2 by Martin Pool
Fix up other references to 0.19
341
# Bazaar merge directive format 2 \\(Bazaar 0.90\\)
2520.4.80 by Aaron Bentley
Improve merge directive tests
342
# revision_id: rev2a
343
# target_branch: (.|\n)*
344
# testament_sha1: .*
345
# timestamp: 1970-01-01 00:08:56 \\+0001
346
# source_branch: (.|\n)*
347
# message: Commit of rev2a with special message
348
"""
1551.12.4 by Aaron Bentley
Add failing test
349
2520.4.73 by Aaron Bentley
Implement new merge directive format
350
class TestMergeDirectiveBranch(object):
1551.12.4 by Aaron Bentley
Add failing test
351
1551.12.26 by Aaron Bentley
Get email working, with optional message
352
    def make_trees(self):
1551.12.4 by Aaron Bentley
Add failing test
353
        tree_a = self.make_branch_and_tree('tree_a')
1551.12.26 by Aaron Bentley
Get email working, with optional message
354
        tree_a.branch.get_config().set_user_option('email',
355
            'J. Random Hacker <jrandom@example.com>')
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
356
        self.build_tree_contents([('tree_a/file', 'content_a\ncontent_b\n'),
357
                                  ('tree_a/file_2', 'content_x\rcontent_y\r')])
358
        tree_a.add(['file', 'file_2'])
1551.12.4 by Aaron Bentley
Add failing test
359
        tree_a.commit('message', rev_id='rev1')
360
        tree_b = tree_a.bzrdir.sprout('tree_b').open_workingtree()
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
361
        branch_c = tree_a.bzrdir.sprout('branch_c').open_branch()
1551.12.4 by Aaron Bentley
Add failing test
362
        tree_b.commit('message', rev_id='rev2b')
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
363
        self.build_tree_contents([('tree_a/file', 'content_a\ncontent_c \n'),
364
                                  ('tree_a/file_2', 'content_x\rcontent_z\r')])
1551.12.26 by Aaron Bentley
Get email working, with optional message
365
        tree_a.commit('Commit of rev2a', rev_id='rev2a')
366
        return tree_a, tree_b, branch_c
367
2490.2.28 by Aaron Bentley
Fix handling of null revision
368
    def test_empty_target(self):
369
        tree_a, tree_b, branch_c = self.make_trees()
370
        tree_d = self.make_branch_and_tree('tree_d')
2520.4.73 by Aaron Bentley
Implement new merge directive format
371
        md2 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
372
            tree_d.branch.base, patch_type='diff',
373
            public_branch=tree_a.branch.base)
2490.2.28 by Aaron Bentley
Fix handling of null revision
374
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
375
    def test_generate_patch(self):
376
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.73 by Aaron Bentley
Implement new merge directive format
377
        md2 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
378
            tree_b.branch.base, patch_type='diff',
379
            public_branch=tree_a.branch.base)
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
380
        self.assertNotContainsRe(md2.patch, 'Bazaar revision bundle')
381
        self.assertContainsRe(md2.patch, '\\+content_c')
382
        self.assertNotContainsRe(md2.patch, '\\+\\+\\+ b/')
383
        self.assertContainsRe(md2.patch, '\\+\\+\\+ file')
384
385
    def test_public_branch(self):
1551.12.26 by Aaron Bentley
Get email working, with optional message
386
        tree_a, tree_b, branch_c = self.make_trees()
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
387
        self.assertRaises(errors.PublicBranchOutOfDate,
2520.4.73 by Aaron Bentley
Implement new merge directive format
388
            self.from_objects, tree_a.branch.repository, 'rev2a', 500, 144,
389
            tree_b.branch.base, public_branch=branch_c.base, patch_type='diff')
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
390
        self.assertRaises(errors.PublicBranchOutOfDate,
391
            self.from_objects, tree_a.branch.repository, 'rev2a', 500, 144,
392
            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
393
        # public branch is not checked if patch format is bundle.
2520.4.73 by Aaron Bentley
Implement new merge directive format
394
        md1 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 144,
395
            tree_b.branch.base, public_branch=branch_c.base)
1551.12.34 by Aaron Bentley
Check public branch only if not using a bundle
396
        # public branch is provided with a bundle, despite possibly being out
397
        # of date, because it's not required if a bundle is present.
398
        self.assertEqual(md1.source_branch, branch_c.base)
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
399
        # Once we update the public branch, we can generate a diff.
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
400
        branch_c.pull(tree_a.branch)
2520.4.73 by Aaron Bentley
Implement new merge directive format
401
        md3 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 144,
402
            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
403
1551.12.50 by Aaron Bentley
Use public location of submit branch if possible
404
    def test_use_public_submit_branch(self):
405
        tree_a, tree_b, branch_c = self.make_trees()
406
        branch_c.pull(tree_a.branch)
2520.4.80 by Aaron Bentley
Improve merge directive tests
407
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 144,
408
            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
409
        self.assertEqual(md.target_branch, tree_b.branch.base)
410
        tree_b.branch.set_public_branch('http://example.com')
2520.4.80 by Aaron Bentley
Improve merge directive tests
411
        md2 = self.from_objects(
1551.12.50 by Aaron Bentley
Use public location of submit branch if possible
412
              tree_a.branch.repository, 'rev2a', 500, 144, tree_b.branch.base,
413
              patch_type=None, public_branch=branch_c.base)
414
        self.assertEqual(md2.target_branch, 'http://example.com')
415
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
416
    def test_message(self):
417
        tree_a, tree_b, branch_c = self.make_trees()
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
418
        md3 = self.from_objects(tree_a.branch.repository, 'rev1', 500, 120,
2520.4.80 by Aaron Bentley
Improve merge directive tests
419
            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
420
            message='Merge message')
1551.12.7 by Aaron Bentley
Fix use of public location/branch
421
        md3.to_lines()
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
422
        self.assertIs(None, md3.patch)
1551.12.27 by Aaron Bentley
support custom message everywhere
423
        self.assertEqual('Merge message', md3.message)
1551.12.16 by Aaron Bentley
Enable signing merge directives
424
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
425
    def test_generate_bundle(self):
1551.12.40 by Aaron Bentley
Do not show prefixes in diffs
426
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.80 by Aaron Bentley
Improve merge directive tests
427
        md1 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
428
            tree_b.branch.base, public_branch=branch_c.base)
429
430
        self.assertContainsRe(md1.get_raw_bundle(), 'Bazaar revision bundle')
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
431
        self.assertContainsRe(md1.patch, '\\+content_c')
432
        self.assertNotContainsRe(md1.patch, '\\+content_a')
433
        self.assertContainsRe(md1.patch, '\\+content_c')
434
        self.assertNotContainsRe(md1.patch, '\\+content_a')
1551.12.40 by Aaron Bentley
Do not show prefixes in diffs
435
1551.15.29 by Aaron Bentley
Make merge directives robust against broken bundles
436
    def test_broken_bundle(self):
437
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.73 by Aaron Bentley
Implement new merge directive format
438
        md1 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
439
            tree_b.branch.base, public_branch=branch_c.base)
1551.15.29 by Aaron Bentley
Make merge directives robust against broken bundles
440
        lines = md1.to_lines()
441
        lines = [l.replace('\n', '\r\n') for l in lines]
442
        md2 = merge_directive.MergeDirective.from_lines(lines)
443
        self.assertEqual('rev2a', md2.revision_id)
444
1551.12.16 by Aaron Bentley
Enable signing merge directives
445
    def test_signing(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
446
        time = 453
447
        timezone = 7200
1551.12.16 by Aaron Bentley
Enable signing merge directives
448
        class FakeBranch(object):
449
            def get_config(self):
450
                return self
451
            def gpg_signing_command(self):
452
                return 'loopback'
2520.4.80 by Aaron Bentley
Improve merge directive tests
453
        md = self.make_merge_directive('example:', 'sha', time, timezone,
1551.12.16 by Aaron Bentley
Enable signing merge directives
454
            'http://example.com', source_branch="http://example.org",
455
            patch='booga', patch_type='diff')
456
        old_strategy = gpg.GPGStrategy
457
        gpg.GPGStrategy = gpg.LoopbackGPGStrategy
458
        try:
459
            signed = md.to_signed(FakeBranch())
460
        finally:
461
            gpg.GPGStrategy = old_strategy
462
        self.assertContainsRe(signed, '^-----BEGIN PSEUDO-SIGNED CONTENT')
463
        self.assertContainsRe(signed, 'example.org')
464
        self.assertContainsRe(signed, 'booga')
1551.12.26 by Aaron Bentley
Get email working, with optional message
465
466
    def test_email(self):
467
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.80 by Aaron Bentley
Improve merge directive tests
468
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 476, 60,
469
            tree_b.branch.base, patch_type=None,
470
            public_branch=tree_a.branch.base)
1551.12.26 by Aaron Bentley
Get email working, with optional message
471
        message = md.to_email('pqm@example.com', tree_a.branch)
2520.4.80 by Aaron Bentley
Improve merge directive tests
472
        self.assertContainsRe(message.as_string(), self.EMAIL1)
1551.12.26 by Aaron Bentley
Get email working, with optional message
473
        md.message = 'Commit of rev2a with special message'
474
        message = md.to_email('pqm@example.com', tree_a.branch)
2520.4.80 by Aaron Bentley
Improve merge directive tests
475
        self.assertContainsRe(message.as_string(), self.EMAIL2)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
476
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
477
    def test_install_revisions_branch(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
478
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.80 by Aaron Bentley
Improve merge directive tests
479
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
480
            tree_b.branch.base, patch_type=None,
481
            public_branch=tree_a.branch.base)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
482
        self.assertFalse(tree_b.branch.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
483
        revision = md.install_revisions(tree_b.branch.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
484
        self.assertEqual('rev2a', revision)
485
        self.assertTrue(tree_b.branch.repository.has_revision('rev2a'))
486
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
487
    def test_get_merge_request(self):
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
488
        tree_a, tree_b, branch_c = self.make_trees()
489
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
490
            tree_b.branch.base, patch_type='bundle',
491
            public_branch=tree_a.branch.base)
492
        self.assertFalse(tree_b.branch.repository.has_revision('rev2a'))
493
        md.install_revisions(tree_b.branch.repository)
494
        base, revision, verified = md.get_merge_request(
495
            tree_b.branch.repository)
496
        if isinstance(md, merge_directive.MergeDirective):
497
            self.assertIs(None, base)
498
            self.assertEqual('inapplicable', verified)
499
        else:
500
            self.assertEqual('rev1', base)
501
            self.assertEqual('verified', verified)
502
        self.assertEqual('rev2a', revision)
503
        self.assertTrue(tree_b.branch.repository.has_revision('rev2a'))
504
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
505
            tree_b.branch.base, patch_type=None,
506
            public_branch=tree_a.branch.base)
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
507
        base, revision, verified = md.get_merge_request(
508
            tree_b.branch.repository)
509
        if isinstance(md, merge_directive.MergeDirective):
510
            self.assertIs(None, base)
511
            self.assertEqual('inapplicable', verified)
512
        else:
513
            self.assertEqual('rev1', base)
514
            self.assertEqual('inapplicable', verified)
515
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
516
            tree_b.branch.base, patch_type='diff',
517
            public_branch=tree_a.branch.base)
518
        base, revision, verified = md.get_merge_request(
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
519
            tree_b.branch.repository)
520
        if isinstance(md, merge_directive.MergeDirective):
521
            self.assertIs(None, base)
522
            self.assertEqual('inapplicable', verified)
523
        else:
524
            self.assertEqual('rev1', base)
525
            self.assertEqual('verified', verified)
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
526
        md.patch='asdf'
527
        base, revision, verified = md.get_merge_request(
528
            tree_b.branch.repository)
529
        if isinstance(md, merge_directive.MergeDirective):
530
            self.assertIs(None, base)
531
            self.assertEqual('inapplicable', verified)
532
        else:
533
            self.assertEqual('rev1', base)
2520.7.1 by Aaron Bentley
Reactivate patch verification
534
            self.assertEqual('failed', verified)
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
535
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
536
    def test_install_revisions_bundle(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
537
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.80 by Aaron Bentley
Improve merge directive tests
538
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
539
            tree_b.branch.base, patch_type='bundle',
540
            public_branch=tree_a.branch.base)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
541
        self.assertFalse(tree_b.branch.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
542
        revision = md.install_revisions(tree_b.branch.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
543
        self.assertEqual('rev2a', revision)
544
        self.assertTrue(tree_b.branch.repository.has_revision('rev2a'))
545
546
    def test_get_target_revision_nofetch(self):
547
        tree_a, tree_b, branch_c = self.make_trees()
548
        tree_b.branch.fetch(tree_a.branch)
2520.4.80 by Aaron Bentley
Improve merge directive tests
549
        md = self.from_objects( tree_a.branch.repository, 'rev2a', 500, 36,
550
            tree_b.branch.base, patch_type=None,
551
            public_branch=tree_a.branch.base)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
552
        md.source_branch = '/dev/null'
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
553
        revision = md.install_revisions(tree_b.branch.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
554
        self.assertEqual('rev2a', revision)
2520.4.73 by Aaron Bentley
Implement new merge directive format
555
1551.19.19 by Aaron Bentley
Merge directives can now fetch prerequisites from the target branch
556
    def test_use_submit_for_missing_dependency(self):
557
        tree_a, tree_b, branch_c = self.make_trees()
558
        branch_c.pull(tree_a.branch)
559
        self.build_tree_contents([('tree_a/file', 'content_q\ncontent_r\n')])
560
        tree_a.commit('rev3a', rev_id='rev3a')
561
        md = self.from_objects(tree_a.branch.repository, 'rev3a', 500, 36,
562
            branch_c.base, base_revision_id='rev2a')
563
        revision = md.install_revisions(tree_b.branch.repository)
564
2520.4.73 by Aaron Bentley
Implement new merge directive format
565
566
class TestMergeDirective1Branch(tests.TestCaseWithTransport,
567
    TestMergeDirectiveBranch):
568
    """Test merge directive format 1 with a branch"""
2520.4.80 by Aaron Bentley
Improve merge directive tests
569
570
    EMAIL1 = EMAIL1
571
572
    EMAIL2 = EMAIL2
573
2520.4.73 by Aaron Bentley
Implement new merge directive format
574
    def from_objects(self, repository, revision_id, time, timezone,
575
        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
576
        public_branch=None, message=None, base_revision_id=None):
577
        if base_revision_id is not None:
578
            raise tests.TestNotApplicable('This format does not support'
579
                                          ' explicit bases.')
3010.1.9 by Robert Collins
test_merge_directive locking correctness.
580
        repository.lock_write()
581
        try:
582
            return merge_directive.MergeDirective.from_objects( repository,
583
                revision_id, time, timezone, target_branch, patch_type,
584
                local_target_branch, public_branch, message)
585
        finally:
586
            repository.unlock()
2520.4.73 by Aaron Bentley
Implement new merge directive format
587
2520.4.80 by Aaron Bentley
Improve merge directive tests
588
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
589
                 target_branch, patch=None, patch_type=None,
590
                 source_branch=None, message=None):
591
        return merge_directive.MergeDirective(revision_id, testament_sha1,
592
                 time, timezone, target_branch, patch, patch_type,
593
                 source_branch, message)
594
2520.4.73 by Aaron Bentley
Implement new merge directive format
595
596
class TestMergeDirective2Branch(tests.TestCaseWithTransport,
597
    TestMergeDirectiveBranch):
598
    """Test merge directive format 2 with a branch"""
599
2520.4.80 by Aaron Bentley
Improve merge directive tests
600
    EMAIL1 = EMAIL1_2
601
602
    EMAIL2 = EMAIL2_2
603
2520.4.73 by Aaron Bentley
Implement new merge directive format
604
    def from_objects(self, repository, revision_id, time, timezone,
605
        target_branch, patch_type='bundle', local_target_branch=None,
2520.4.112 by Aaron Bentley
Make cherry-pick merge directives possible
606
        public_branch=None, message=None, base_revision_id=None):
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
607
        include_patch = (patch_type in ('bundle', 'diff'))
608
        include_bundle = (patch_type == 'bundle')
609
        assert patch_type in ('bundle', 'diff', None)
2520.4.73 by Aaron Bentley
Implement new merge directive format
610
        return merge_directive.MergeDirective2.from_objects(
611
            repository, revision_id, time, timezone, target_branch,
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
612
            include_patch, include_bundle, local_target_branch, public_branch,
613
            message, base_revision_id)
2520.4.80 by Aaron Bentley
Improve merge directive tests
614
615
    def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
616
                 target_branch, patch=None, patch_type=None,
2520.4.105 by Aaron Bentley
Implement patch verification
617
                 source_branch=None, message=None, base_revision_id='null:'):
2520.4.80 by Aaron Bentley
Improve merge directive tests
618
        if patch_type == 'bundle':
619
            bundle = patch
620
            patch = None
621
        else:
622
            bundle = None
623
        return merge_directive.MergeDirective2(revision_id, testament_sha1,
624
            time, timezone, target_branch, patch, source_branch, message,
2520.4.105 by Aaron Bentley
Implement patch verification
625
            bundle, base_revision_id)
626
627
    def test_base_revision(self):
628
        tree_a, tree_b, branch_c = self.make_trees()
629
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 60,
630
            tree_b.branch.base, patch_type='bundle',
2520.4.112 by Aaron Bentley
Make cherry-pick merge directives possible
631
            public_branch=tree_a.branch.base, base_revision_id=None)
2520.4.105 by Aaron Bentley
Implement patch verification
632
        self.assertEqual('rev1', md.base_revision_id)
2520.4.112 by Aaron Bentley
Make cherry-pick merge directives possible
633
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 60,
634
            tree_b.branch.base, patch_type='bundle',
635
            public_branch=tree_a.branch.base, base_revision_id='null:')
636
        self.assertEqual('null:', md.base_revision_id)
2520.4.105 by Aaron Bentley
Implement patch verification
637
        lines = md.to_lines()
638
        md2 = merge_directive.MergeDirective.from_lines(lines)
639
        self.assertEqual(md2.base_revision_id, md.base_revision_id)
640
641
    def test_patch_verification(self):
642
        tree_a, tree_b, branch_c = self.make_trees()
643
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 60,
644
            tree_b.branch.base, patch_type='bundle',
645
            public_branch=tree_a.branch.base)
646
        lines = md.to_lines()
647
        md2 = merge_directive.MergeDirective.from_lines(lines)
648
        md2._verify_patch(tree_a.branch.repository)
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
649
        # Strip trailing whitespace
2520.4.105 by Aaron Bentley
Implement patch verification
650
        md2.patch = md2.patch.replace(' \n', '\n')
651
        md2._verify_patch(tree_a.branch.repository)
652
        # Convert to Mac line-endings
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
653
        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
654
        self.assertTrue(md2._verify_patch(tree_a.branch.repository))
2520.4.105 by Aaron Bentley
Implement patch verification
655
        # Convert to DOS line-endings
2520.7.2 by Aaron Bentley
Restore patch verification for CR, CRLF files
656
        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
657
        self.assertTrue(md2._verify_patch(tree_a.branch.repository))
2520.4.105 by Aaron Bentley
Implement patch verification
658
        md2.patch = md2.patch.replace('content_c', 'content_d')
2520.4.108 by Aaron Bentley
Start work on using merge base from directives
659
        self.assertFalse(md2._verify_patch(tree_a.branch.repository))
2694.1.1 by Aaron Bentley
Restore support for Merge directive 2 / 0.19
660
661
662
class TestParseOldMergeDirective2(tests.TestCase):
663
664
    def test_parse_old_merge_directive(self):
665
        md = merge_directive.MergeDirective.from_lines(INPUT1_2_OLD)
666
        self.assertEqual('example:', md.revision_id)
667
        self.assertEqual('sha', md.testament_sha1)
668
        self.assertEqual('http://example.com', md.target_branch)
669
        self.assertEqual('http://example.org', md.source_branch)
670
        self.assertEqual(453, md.time)
671
        self.assertEqual(120, md.timezone)
672
        self.assertEqual('booga', md.patch)
673
        self.assertEqual('diff', md.patch_type)
674
        self.assertEqual('Hi mom!', md.message)