~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
3251.2.1 by Aaron Bentley
Use nick/revno-based names for merge directives
375
    def test_disk_name(self):
376
        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``
377
        tree_a.branch.nick = 'fancy <name>'
3251.2.1 by Aaron Bentley
Use nick/revno-based names for merge directives
378
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
379
            tree_b.branch.base)
380
        self.assertEqual('fancy-name-2', md.get_disk_name(tree_a.branch))
381
382
    def test_disk_name_old_revno(self):
383
        tree_a, tree_b, branch_c = self.make_trees()
384
        tree_a.branch.nick = 'fancy-name'
385
        md = self.from_objects(tree_a.branch.repository, 'rev1', 500, 120,
386
            tree_b.branch.base)
387
        self.assertEqual('fancy-name-1', md.get_disk_name(tree_a.branch))
388
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
389
    def test_generate_patch(self):
390
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.73 by Aaron Bentley
Implement new merge directive format
391
        md2 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
392
            tree_b.branch.base, patch_type='diff',
393
            public_branch=tree_a.branch.base)
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
394
        self.assertNotContainsRe(md2.patch, 'Bazaar revision bundle')
395
        self.assertContainsRe(md2.patch, '\\+content_c')
396
        self.assertNotContainsRe(md2.patch, '\\+\\+\\+ b/')
397
        self.assertContainsRe(md2.patch, '\\+\\+\\+ file')
398
399
    def test_public_branch(self):
1551.12.26 by Aaron Bentley
Get email working, with optional message
400
        tree_a, tree_b, branch_c = self.make_trees()
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
401
        self.assertRaises(errors.PublicBranchOutOfDate,
2520.4.73 by Aaron Bentley
Implement new merge directive format
402
            self.from_objects, tree_a.branch.repository, 'rev2a', 500, 144,
403
            tree_b.branch.base, public_branch=branch_c.base, patch_type='diff')
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
404
        self.assertRaises(errors.PublicBranchOutOfDate,
405
            self.from_objects, tree_a.branch.repository, 'rev2a', 500, 144,
406
            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
407
        # public branch is not checked if patch format is bundle.
2520.4.73 by Aaron Bentley
Implement new merge directive format
408
        md1 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 144,
409
            tree_b.branch.base, public_branch=branch_c.base)
1551.12.34 by Aaron Bentley
Check public branch only if not using a bundle
410
        # public branch is provided with a bundle, despite possibly being out
411
        # of date, because it's not required if a bundle is present.
412
        self.assertEqual(md1.source_branch, branch_c.base)
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
413
        # Once we update the public branch, we can generate a diff.
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
414
        branch_c.pull(tree_a.branch)
2520.4.73 by Aaron Bentley
Implement new merge directive format
415
        md3 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 144,
416
            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
417
1551.12.50 by Aaron Bentley
Use public location of submit branch if possible
418
    def test_use_public_submit_branch(self):
419
        tree_a, tree_b, branch_c = self.make_trees()
420
        branch_c.pull(tree_a.branch)
2520.4.80 by Aaron Bentley
Improve merge directive tests
421
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 144,
422
            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
423
        self.assertEqual(md.target_branch, tree_b.branch.base)
424
        tree_b.branch.set_public_branch('http://example.com')
2520.4.80 by Aaron Bentley
Improve merge directive tests
425
        md2 = self.from_objects(
1551.12.50 by Aaron Bentley
Use public location of submit branch if possible
426
              tree_a.branch.repository, 'rev2a', 500, 144, tree_b.branch.base,
427
              patch_type=None, public_branch=branch_c.base)
428
        self.assertEqual(md2.target_branch, 'http://example.com')
429
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
430
    def test_message(self):
431
        tree_a, tree_b, branch_c = self.make_trees()
2520.5.4 by Aaron Bentley
Replace 'bundle-revisions' with 'submit' command
432
        md3 = self.from_objects(tree_a.branch.repository, 'rev1', 500, 120,
2520.4.80 by Aaron Bentley
Improve merge directive tests
433
            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
434
            message='Merge message')
1551.12.7 by Aaron Bentley
Fix use of public location/branch
435
        md3.to_lines()
1551.12.5 by Aaron Bentley
Get MergeDirective.from_objects working
436
        self.assertIs(None, md3.patch)
1551.12.27 by Aaron Bentley
support custom message everywhere
437
        self.assertEqual('Merge message', md3.message)
1551.12.16 by Aaron Bentley
Enable signing merge directives
438
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
439
    def test_generate_bundle(self):
1551.12.40 by Aaron Bentley
Do not show prefixes in diffs
440
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.80 by Aaron Bentley
Improve merge directive tests
441
        md1 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
442
            tree_b.branch.base, public_branch=branch_c.base)
443
444
        self.assertContainsRe(md1.get_raw_bundle(), 'Bazaar revision bundle')
1551.12.41 by Aaron Bentley
Clean up tests, add serialization text test
445
        self.assertContainsRe(md1.patch, '\\+content_c')
446
        self.assertNotContainsRe(md1.patch, '\\+content_a')
447
        self.assertContainsRe(md1.patch, '\\+content_c')
448
        self.assertNotContainsRe(md1.patch, '\\+content_a')
1551.12.40 by Aaron Bentley
Do not show prefixes in diffs
449
1551.15.29 by Aaron Bentley
Make merge directives robust against broken bundles
450
    def test_broken_bundle(self):
451
        tree_a, tree_b, branch_c = self.make_trees()
2520.4.73 by Aaron Bentley
Implement new merge directive format
452
        md1 = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 120,
453
            tree_b.branch.base, public_branch=branch_c.base)
1551.15.29 by Aaron Bentley
Make merge directives robust against broken bundles
454
        lines = md1.to_lines()
455
        lines = [l.replace('\n', '\r\n') for l in lines]
456
        md2 = merge_directive.MergeDirective.from_lines(lines)
457
        self.assertEqual('rev2a', md2.revision_id)
458
1551.12.16 by Aaron Bentley
Enable signing merge directives
459
    def test_signing(self):
2425.6.1 by Martin Pool
Fix formatting of timezones in bundles and merge directives.
460
        time = 453
461
        timezone = 7200
1551.12.16 by Aaron Bentley
Enable signing merge directives
462
        class FakeBranch(object):
463
            def get_config(self):
464
                return self
465
            def gpg_signing_command(self):
466
                return 'loopback'
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()
2520.4.80 by Aaron Bentley
Improve merge directive tests
482
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 476, 60,
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()
2520.4.80 by Aaron Bentley
Improve merge directive tests
493
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
494
            tree_b.branch.base, patch_type=None,
495
            public_branch=tree_a.branch.base)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
496
        self.assertFalse(tree_b.branch.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
497
        revision = md.install_revisions(tree_b.branch.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
498
        self.assertEqual('rev2a', revision)
499
        self.assertTrue(tree_b.branch.repository.has_revision('rev2a'))
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()
503
        md = self.from_objects(tree_a.branch.repository, '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)
506
        self.assertFalse(tree_b.branch.repository.has_revision('rev2a'))
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:
514
            self.assertEqual('rev1', base)
515
            self.assertEqual('verified', verified)
516
        self.assertEqual('rev2a', revision)
517
        self.assertTrue(tree_b.branch.repository.has_revision('rev2a'))
518
        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
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:
527
            self.assertEqual('rev1', base)
528
            self.assertEqual('inapplicable', verified)
529
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
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:
538
            self.assertEqual('rev1', base)
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:
547
            self.assertEqual('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()
2520.4.80 by Aaron Bentley
Improve merge directive tests
552
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 36,
553
            tree_b.branch.base, patch_type='bundle',
554
            public_branch=tree_a.branch.base)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
555
        self.assertFalse(tree_b.branch.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
556
        revision = md.install_revisions(tree_b.branch.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
557
        self.assertEqual('rev2a', revision)
558
        self.assertTrue(tree_b.branch.repository.has_revision('rev2a'))
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)
2520.4.80 by Aaron Bentley
Improve merge directive tests
563
        md = self.from_objects( tree_a.branch.repository, 'rev2a', 500, 36,
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)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
568
        self.assertEqual('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)
573
        self.build_tree_contents([('tree_a/file', 'content_q\ncontent_r\n')])
574
        tree_a.commit('rev3a', rev_id='rev3a')
575
        md = self.from_objects(tree_a.branch.repository, 'rev3a', 500, 36,
576
            branch_c.base, base_revision_id='rev2a')
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)
582
        self.build_tree_contents([('tree_a/file', 'content_q\ncontent_r\n')])
583
        tree_a.commit('rev3a', rev_id='rev3a')
584
        md = self.from_objects(tree_a.branch.repository, 'rev3a', 500, 36,
585
            branch_c.base, base_revision_id='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()
654
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 60,
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)
2520.4.105 by Aaron Bentley
Implement patch verification
657
        self.assertEqual('rev1', md.base_revision_id)
2520.4.112 by Aaron Bentley
Make cherry-pick merge directives possible
658
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 60,
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()
668
        md = self.from_objects(tree_a.branch.repository, 'rev2a', 500, 60,
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)