Merge lp:~jelmer/bzr/merge-dir-prober into lp:bzr

Proposed by Jelmer Vernooij
Status: Rejected
Rejected by: Jelmer Vernooij
Proposed branch: lp:~jelmer/bzr/merge-dir-prober
Merge into: lp:bzr
Diff against target: 509 lines (+107/-58)
12 files modified
NEWS (+12/-0)
bzrlib/builtins.py (+1/-1)
bzrlib/bundle/commands.py (+1/-1)
bzrlib/hooks.py (+1/-1)
bzrlib/merge_directive.py (+64/-28)
bzrlib/send.py (+2/-2)
bzrlib/tests/blackbox/test_bundle_info.py (+1/-1)
bzrlib/tests/blackbox/test_merge.py (+1/-1)
bzrlib/tests/blackbox/test_send.py (+4/-4)
bzrlib/tests/per_repository/test_merge_directive.py (+2/-2)
bzrlib/tests/test_merge_core.py (+2/-2)
bzrlib/tests/test_merge_directive.py (+16/-15)
To merge this branch: bzr merge lp:~jelmer/bzr/merge-dir-prober
Reviewer Review Type Date Requested Status
Aaron Bentley mid-implementation Pending
bzr-core mid-implementation Pending
Review via email: mp+31795@code.launchpad.net

Description of the change

This branch makes it possible to register custom "Prober" classes that can detect merge directives in files. This is necessary so that we can start registering custom merge directives, such as Mercurial bundles, Git-am-style bundles, etc.

There is a single Prober implementation that reads the existing bzr bundle formats.

I've also renamed a few classes to make the distinction between the base class and the bzr implementations a bit clearer:

 BaseMergeDirective -> MergeDirective
 MergeDirective -> BzrMergeDirective1
 MergeDirective2 -> BzrMergeDirective2

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

(I'm not looking for an in-depth review but would be interested to hear whether this is the right overall approach).

Revision history for this message
Aaron Bentley (abentley) wrote :

This seems fine in general, but I believe you're changing the signature of from_lines somewhat. Previously, it accepted an iterable, which could be a collection (i.e. list) or an iterator. Now, it seems a collection is mandatory because the iteration is repeated for every prober, but an iterator would be exhausted by the first prober.

Mandating lists may increase memory use, though of course, a given line could be twelve gigabytes if we were really unlucky. At the very least, you should change the docstring if you change the signature.

Because each prober is handled in sequence, you'll also be consuming the whole list of lines for every probe type, even if there's a header at the top of the file, indicating its kind.

Perhaps it would be better to us a coroutine approach instead. For example:

def get_merge_directive_type(lines):
    for line in lines:
        for prober in probers:
            prober.consume(line)
            if prober.merge_directive_type is not None:
                return prober.merge_directive_type

Revision history for this message
Martin Packman (gz) wrote :

> This seems fine in general, but I believe you're changing the signature of
> from_lines somewhat. Previously, it accepted an iterable, which could be a
> collection (i.e. list) or an iterator. Now, it seems a collection is
> mandatory because the iteration is repeated for every prober, but an iterator
> would be exhausted by the first prober.

Just to note, until I rewrote it in r4792.7.3 from_lines did in fact require a list despite the docstring claiming it took an iterable, so changing the contract to actually require a list is unlikely to cause any kind of regression.

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

On Fri, 2010-08-06 at 19:58 +0000, Martin [gz] wrote:
> > This seems fine in general, but I believe you're changing the signature of
> > from_lines somewhat. Previously, it accepted an iterable, which could be a
> > collection (i.e. list) or an iterator. Now, it seems a collection is
> > mandatory because the iteration is repeated for every prober, but an iterator
> > would be exhausted by the first prober.
>
> Just to note, until I rewrote it in r4792.7.3 from_lines did in fact
> require a list despite the docstring claiming it took an iterable, so
> changing the contract to actually require a list is unlikely to cause
> any kind of regression.
Ahh, thanks for letting me know. I thought that was the case so was
surprised to find it was using an iterator now.

Cheers,

Jelmer

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

Hi Aaron,

On Thu, 2010-08-05 at 02:42 +0000, Aaron Bentley wrote:
> This seems fine in general, but I believe you're changing the signature
> of from_lines somewhat. Previously, it accepted an iterable, which
> could be a collection (i.e. list) or an iterator. Now, it seems a
> collection is mandatory because the iteration is repeated for every
> prober, but an iterator would be exhausted by the first prober.
>
> Mandating lists may increase memory use, though of course, a given line
> could be twelve gigabytes if we were really unlucky. At the very
> least, you should change the docstring if you change the signature.
>
> Because each prober is handled in sequence, you'll also be consuming
> the whole list of lines for every probe type, even if there's a header
> at the top of the file, indicating its kind.
>
> Perhaps it would be better to us a coroutine approach instead. For example:
That's a good point, for some reason I thought that it scaled with the
size of the file anyway. Using coroutines does indeed seem like a good
approach here.

Thanks for the review.

Cheers,

Jelmer

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2010-07-29 11:17:57 +0000
3+++ NEWS 2010-08-04 22:41:44 +0000
4@@ -14,6 +14,14 @@
5 Compatibility Breaks
6 ********************
7
8+* `BaseMergeDirective` has been renamed to `MergeDirective`.
9+ `MergeDirective` has been renamed to `BzrMergeDirective1`,
10+ `MergeDirective2` has been renamed to `BzrMergeDirective2`.
11+
12+ `MergeDirective.from_lines` should still be used for opening
13+ merge directives from lines.
14+ (Jelmer Vernooij)
15+
16 * BzrError subclasses no longer support the name "message" to be used
17 as an argument for __init__ or in _fmt format specification as this
18 breaks in some Python versions. errors.LockError.__init__ argument
19@@ -33,6 +41,7 @@
20 macrobenchmark suite.
21 (Martin Pool)
22
23+
24 New Features
25 ************
26
27@@ -84,6 +93,9 @@
28 Internals
29 *********
30
31+* `MergeDirective.register_prober` can now be used to register custom
32+ probers for non-bzr merge directives. (Jelmer Vernooij)
33+
34 Testing
35 *******
36
37
38=== modified file 'bzrlib/builtins.py'
39--- bzrlib/builtins.py 2010-07-29 11:17:57 +0000
40+++ bzrlib/builtins.py 2010-08-04 22:41:44 +0000
41@@ -5061,7 +5061,7 @@
42 revision_id = ensure_null(revision_id)
43 if revision_id == NULL_REVISION:
44 raise errors.BzrCommandError('No revisions to bundle.')
45- directive = merge_directive.MergeDirective2.from_objects(
46+ directive = merge_directive.BzrMergeDirective2.from_objects(
47 branch.repository, revision_id, time.time(),
48 osutils.local_time_offset(), submit_branch,
49 public_branch=public_branch, include_patch=include_patch,
50
51=== modified file 'bzrlib/bundle/commands.py'
52--- bzrlib/bundle/commands.py 2010-04-02 19:12:58 +0000
53+++ bzrlib/bundle/commands.py 2010-08-04 22:41:44 +0000
54@@ -54,7 +54,7 @@
55 from bzrlib import osutils
56 term_encoding = osutils.get_terminal_encoding()
57 bundle_info = read_mergeable_from_url(location)
58- if isinstance(bundle_info, merge_directive.BaseMergeDirective):
59+ if isinstance(bundle_info, merge_directive.MergeDirective):
60 bundle_file = StringIO(bundle_info.get_raw_bundle())
61 bundle_info = read_bundle(bundle_file)
62 else:
63
64=== modified file 'bzrlib/hooks.py'
65--- bzrlib/hooks.py 2010-05-26 04:26:59 +0000
66+++ bzrlib/hooks.py 2010-08-04 22:41:44 +0000
67@@ -58,7 +58,7 @@
68 ('bzrlib.version_info_formats.format_rio', 'RioVersionInfoBuilder.hooks'),
69 'bzrlib.version_info_formats.format_rio', 'RioVersionInfoBuilderHooks')
70 known_hooks.register_lazy(
71- ('bzrlib.merge_directive', 'BaseMergeDirective.hooks'),
72+ ('bzrlib.merge_directive', 'MergeDirective.hooks'),
73 'bzrlib.merge_directive', 'MergeDirectiveHooks')
74
75
76
77=== modified file 'bzrlib/merge_directive.py'
78--- bzrlib/merge_directive.py 2010-03-13 02:49:14 +0000
79+++ bzrlib/merge_directive.py 2010-08-04 22:41:44 +0000
80@@ -64,7 +64,7 @@
81 " provided to the next.", (1, 15, 0), False))
82
83
84-class BaseMergeDirective(object):
85+class MergeDirective(object):
86 """A request to perform a merge into a branch.
87
88 This is the base class that all merge directive implementations
89@@ -78,6 +78,8 @@
90
91 multiple_output_files = False
92
93+ _probers = []
94+
95 def __init__(self, revision_id, testament_sha1, time, timezone,
96 target_branch, patch=None, source_branch=None, message=None,
97 bundle=None):
98@@ -102,6 +104,28 @@
99 self.source_branch = source_branch
100 self.message = message
101
102+ @classmethod
103+ def register_prober(klass, prober):
104+ """Register a merge directive prober.
105+
106+ """
107+ klass._probers.append(prober)
108+
109+ @classmethod
110+ def from_lines(klass, lines):
111+ """Deserialize a MergeRequest from an iterable of lines
112+
113+ :param lines: An iterable of lines
114+ :return: a MergeRequest
115+ """
116+ for prober_kls in klass._probers:
117+ prober = prober_kls()
118+ try:
119+ return prober.probe_lines(lines)
120+ except errors.NotAMergeDirective, e:
121+ pass
122+ raise e
123+
124 def to_lines(self):
125 """Serialize as a list of lines
126
127@@ -341,8 +365,7 @@
128 basename, body)
129
130
131-class MergeDirective(BaseMergeDirective):
132-
133+class BzrMergeDirective1(MergeDirective):
134 """A request to perform a merge into a branch.
135
136 Designed to be serialized and mailed. It provides all the information
137@@ -376,7 +399,7 @@
138 :param source_branch: A public location to merge the revision from
139 :param message: The message to use when committing this merge
140 """
141- BaseMergeDirective.__init__(self, revision_id, testament_sha1, time,
142+ MergeDirective.__init__(self, revision_id, testament_sha1, time,
143 timezone, target_branch, patch, source_branch, message)
144 if patch_type not in (None, 'diff', 'bundle'):
145 raise ValueError(patch_type)
146@@ -402,22 +425,6 @@
147 bundle = property(_bundle)
148
149 @classmethod
150- def from_lines(klass, lines):
151- """Deserialize a MergeRequest from an iterable of lines
152-
153- :param lines: An iterable of lines
154- :return: a MergeRequest
155- """
156- line_iter = iter(lines)
157- firstline = ""
158- for line in line_iter:
159- if line.startswith('# Bazaar merge directive format '):
160- return _format_registry.get(line[2:].rstrip())._from_lines(
161- line_iter)
162- firstline = firstline or line.strip()
163- raise errors.NotAMergeDirective(firstline)
164-
165- @classmethod
166 def _from_lines(klass, line_iter):
167 stanza = rio.read_patch_stanza(line_iter)
168 patch_lines = list(line_iter)
169@@ -442,7 +449,7 @@
170 except KeyError:
171 pass
172 kwargs['revision_id'] = kwargs['revision_id'].encode('utf-8')
173- return MergeDirective(time=time, timezone=timezone,
174+ return BzrMergeDirective1(time=time, timezone=timezone,
175 patch_type=patch_type, patch=patch, **kwargs)
176
177 def to_lines(self):
178@@ -466,7 +473,7 @@
179 return None, self.revision_id, 'inapplicable'
180
181
182-class MergeDirective2(BaseMergeDirective):
183+class BzrMergeDirective2(MergeDirective):
184
185 _format_string = 'Bazaar merge directive format 2 (Bazaar 0.90)'
186
187@@ -475,7 +482,7 @@
188 bundle=None, base_revision_id=None):
189 if source_branch is None and bundle is None:
190 raise errors.NoMergeSource()
191- BaseMergeDirective.__init__(self, revision_id, testament_sha1, time,
192+ MergeDirective.__init__(self, revision_id, testament_sha1, time,
193 timezone, target_branch, patch, source_branch, message)
194 self.bundle = bundle
195 self.base_revision_id = base_revision_id
196@@ -655,7 +662,19 @@
197 return 'inapplicable'
198
199
200-class MergeDirectiveFormatRegistry(registry.Registry):
201+class MergeDirectiveProber(object):
202+
203+ def probe_lines(self, lines):
204+ """Find a merge directive using the contents of a file (as lines).
205+
206+ :param lines: An iterable over lines
207+ :raise NotAMergeDirective: Raised when no merge directive could be opened.
208+ :return: A MergeDirective instance
209+ """
210+ raise NotImplementedError(self.probe_lines)
211+
212+
213+class BzrMergeDirectiveFormatRegistry(registry.Registry):
214
215 def register(self, directive, format_string=None):
216 if format_string is None:
217@@ -663,11 +682,28 @@
218 registry.Registry.register(self, format_string, directive)
219
220
221-_format_registry = MergeDirectiveFormatRegistry()
222-_format_registry.register(MergeDirective)
223-_format_registry.register(MergeDirective2)
224+class BzrMergeDirectiveProber(MergeDirectiveProber):
225+
226+ formats = BzrMergeDirectiveFormatRegistry()
227+
228+ def probe_lines(self, lines):
229+ line_iter = iter(lines)
230+ firstline = ""
231+ for line in line_iter:
232+ if line.startswith('# Bazaar merge directive format '):
233+ return self.formats.get(line[2:].rstrip())._from_lines(
234+ line_iter)
235+ firstline = firstline or line.strip()
236+ raise errors.NotAMergeDirective(firstline)
237+
238+
239+BzrMergeDirectiveProber.formats.register(BzrMergeDirective1)
240+BzrMergeDirectiveProber.formats.register(BzrMergeDirective2)
241 # 0.19 never existed. It got renamed to 0.90. But by that point, there were
242 # already merge directives in the wild that used 0.19. Registering with the old
243 # format string to retain compatibility with those merge directives.
244-_format_registry.register(MergeDirective2,
245+BzrMergeDirectiveProber.formats.register(BzrMergeDirective2,
246 'Bazaar merge directive format 2 (Bazaar 0.19)')
247+
248+
249+MergeDirective.register_prober(BzrMergeDirectiveProber)
250
251=== modified file 'bzrlib/send.py'
252--- bzrlib/send.py 2010-04-22 14:18:17 +0000
253+++ bzrlib/send.py 2010-08-04 22:41:44 +0000
254@@ -156,7 +156,7 @@
255 def _send_4(branch, revision_id, submit_branch, public_branch,
256 no_patch, no_bundle, message, base_revision_id):
257 from bzrlib import merge_directive
258- return merge_directive.MergeDirective2.from_objects(
259+ return merge_directive.BzrMergeDirective2.from_objects(
260 branch.repository, revision_id, time.time(),
261 osutils.local_time_offset(), submit_branch,
262 public_branch=public_branch, include_patch=not no_patch,
263@@ -178,7 +178,7 @@
264 else:
265 patch_type = None
266 from bzrlib import merge_directive
267- return merge_directive.MergeDirective.from_objects(
268+ return merge_directive.BzrMergeDirective1.from_objects(
269 branch.repository, revision_id, time.time(),
270 osutils.local_time_offset(), submit_branch,
271 public_branch=public_branch, patch_type=patch_type,
272
273=== modified file 'bzrlib/tests/blackbox/test_bundle_info.py'
274--- bzrlib/tests/blackbox/test_bundle_info.py 2009-08-06 05:20:04 +0000
275+++ bzrlib/tests/blackbox/test_bundle_info.py 2010-08-04 22:41:44 +0000
276@@ -43,7 +43,7 @@
277 self.run_bzr_error(['--verbose requires a merge directive'],
278 'bundle-info -v bundle')
279 target = self.make_branch('target')
280- md = merge_directive.MergeDirective2.from_objects(
281+ md = merge_directive.BzrMergeDirective2.from_objects(
282 source.branch.repository, 'rev1', 0, 0, 'target',
283 base_revision_id='null:')
284 directive = open('directive', 'wb')
285
286=== modified file 'bzrlib/tests/blackbox/test_merge.py'
287--- bzrlib/tests/blackbox/test_merge.py 2010-05-20 18:23:17 +0000
288+++ bzrlib/tests/blackbox/test_merge.py 2010-08-04 22:41:44 +0000
289@@ -414,7 +414,7 @@
290
291 def write_directive(self, filename, source, target, revision_id,
292 base_revision_id=None, mangle_patch=False):
293- md = merge_directive.MergeDirective2.from_objects(
294+ md = merge_directive.BzrMergeDirective2.from_objects(
295 source.repository, revision_id, 0, 0, target,
296 base_revision_id=base_revision_id)
297 if mangle_patch:
298
299=== modified file 'bzrlib/tests/blackbox/test_send.py'
300--- bzrlib/tests/blackbox/test_send.py 2010-04-28 10:30:48 +0000
301+++ bzrlib/tests/blackbox/test_send.py 2010-08-04 22:41:44 +0000
302@@ -234,7 +234,7 @@
303
304 def test_format(self):
305 md = self.get_MD(['--format=4'])
306- self.assertIs(merge_directive.MergeDirective2, md.__class__)
307+ self.assertIs(merge_directive.BzrMergeDirective2, md.__class__)
308 self.assertFormatIs('# Bazaar revision bundle v4', md)
309
310 md = self.get_MD(['--format=0.9'])
311@@ -242,7 +242,7 @@
312
313 md = self.get_MD(['--format=0.9'], cmd=['bundle'])
314 self.assertFormatIs('# Bazaar revision bundle v0.9', md)
315- self.assertIs(merge_directive.MergeDirective, md.__class__)
316+ self.assertIs(merge_directive.BzrMergeDirective1, md.__class__)
317
318 self.run_bzr_error(['Bad value .* for option .format.'],
319 'send -f branch -o- --format=0.999')[0]
320@@ -251,7 +251,7 @@
321 parent_config = branch.Branch.open('parent').get_config()
322 parent_config.set_user_option('child_submit_format', '4')
323 md = self.get_MD([])
324- self.assertIs(merge_directive.MergeDirective2, md.__class__)
325+ self.assertIs(merge_directive.BzrMergeDirective2, md.__class__)
326
327 parent_config.set_user_option('child_submit_format', '0.9')
328 md = self.get_MD([])
329@@ -259,7 +259,7 @@
330
331 md = self.get_MD([], cmd=['bundle'])
332 self.assertFormatIs('# Bazaar revision bundle v0.9', md)
333- self.assertIs(merge_directive.MergeDirective, md.__class__)
334+ self.assertIs(merge_directive.BzrMergeDirective1, md.__class__)
335
336 parent_config.set_user_option('child_submit_format', '0.999')
337 self.run_bzr_error(["No such send format '0.999'"],
338
339=== modified file 'bzrlib/tests/per_repository/test_merge_directive.py'
340--- bzrlib/tests/per_repository/test_merge_directive.py 2009-07-22 17:22:06 +0000
341+++ bzrlib/tests/per_repository/test_merge_directive.py 2010-08-04 22:41:44 +0000
342@@ -48,7 +48,7 @@
343 return b1, b2
344
345 def create_merge_directive(self, source_branch, submit_url):
346- return merge_directive.MergeDirective2.from_objects(
347+ return merge_directive.BzrMergeDirective2.from_objects(
348 source_branch.repository,
349 source_branch.last_revision(),
350 time=1247775710, timezone=0,
351@@ -58,7 +58,7 @@
352 source_branch, target_branch = self.make_two_branches()
353 directive = self.create_merge_directive(source_branch,
354 target_branch.base)
355- self.assertIsInstance(directive, merge_directive.MergeDirective2)
356+ self.assertIsInstance(directive, merge_directive.BzrMergeDirective2)
357
358
359 def test_create_and_install_directive(self):
360
361=== modified file 'bzrlib/tests/test_merge_core.py'
362--- bzrlib/tests/test_merge_core.py 2010-02-23 07:43:11 +0000
363+++ bzrlib/tests/test_merge_core.py 2010-08-04 22:41:44 +0000
364@@ -795,7 +795,7 @@
365
366 def test_from_mergeable(self):
367 this, other = self.prepare_for_merging()
368- md = merge_directive.MergeDirective2.from_objects(
369+ md = merge_directive.BzrMergeDirective2.from_objects(
370 other.branch.repository, 'rev3', 0, 0, 'this')
371 other.lock_read()
372 self.addCleanup(other.unlock)
373@@ -816,7 +816,7 @@
374 this, other = self.prepare_for_merging()
375 other.lock_write()
376 self.addCleanup(other.unlock)
377- md = merge_directive.MergeDirective.from_objects(
378+ md = merge_directive.BzrMergeDirective1.from_objects(
379 other.branch.repository, 'rev3', 0, 0, 'this')
380 merger, verified = Merger.from_mergeable(this, md,
381 None)
382
383=== modified file 'bzrlib/tests/test_merge_directive.py'
384--- bzrlib/tests/test_merge_directive.py 2009-05-11 19:11:14 +0000
385+++ bzrlib/tests/test_merge_directive.py 2010-08-04 22:41:44 +0000
386@@ -247,7 +247,7 @@
387 def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
388 target_branch, patch=None, patch_type=None,
389 source_branch=None, message=None):
390- return merge_directive.MergeDirective(revision_id, testament_sha1,
391+ return merge_directive.BzrMergeDirective1(revision_id, testament_sha1,
392 time, timezone, target_branch, patch, patch_type,
393 source_branch, message)
394
395@@ -258,11 +258,12 @@
396 def test_require_patch(self):
397 time = 500.0
398 timezone = 120
399- self.assertRaises(errors.PatchMissing, merge_directive.MergeDirective,
400+ self.assertRaises(errors.PatchMissing,
401+ merge_directive.BzrMergeDirective1,
402 'example:', 'sha', time, timezone, 'http://example.com',
403 patch_type='bundle')
404- md = merge_directive.MergeDirective('example:', 'sha1', time, timezone,
405- 'http://example.com', source_branch="http://example.org",
406+ md = merge_directive.BzrMergeDirective1('example:', 'sha1', time,
407+ timezone, 'http://example.com', source_branch="http://example.org",
408 patch='', patch_type='diff')
409 self.assertEqual(md.patch, '')
410
411@@ -284,7 +285,7 @@
412 patch = None
413 else:
414 bundle = None
415- return merge_directive.MergeDirective2(revision_id, testament_sha1,
416+ return merge_directive.BzrMergeDirective2(revision_id, testament_sha1,
417 time, timezone, target_branch, patch, source_branch, message,
418 bundle, base_revision_id)
419
420@@ -509,7 +510,7 @@
421 md.install_revisions(tree_b.branch.repository)
422 base, revision, verified = md.get_merge_request(
423 tree_b.branch.repository)
424- if isinstance(md, merge_directive.MergeDirective):
425+ if isinstance(md, merge_directive.BzrMergeDirective1):
426 self.assertIs(None, base)
427 self.assertEqual('inapplicable', verified)
428 else:
429@@ -522,7 +523,7 @@
430 public_branch=tree_a.branch.base)
431 base, revision, verified = md.get_merge_request(
432 tree_b.branch.repository)
433- if isinstance(md, merge_directive.MergeDirective):
434+ if isinstance(md, merge_directive.BzrMergeDirective1):
435 self.assertIs(None, base)
436 self.assertEqual('inapplicable', verified)
437 else:
438@@ -533,7 +534,7 @@
439 public_branch=tree_a.branch.base)
440 base, revision, verified = md.get_merge_request(
441 tree_b.branch.repository)
442- if isinstance(md, merge_directive.MergeDirective):
443+ if isinstance(md, merge_directive.BzrMergeDirective1):
444 self.assertIs(None, base)
445 self.assertEqual('inapplicable', verified)
446 else:
447@@ -542,7 +543,7 @@
448 md.patch='asdf'
449 base, revision, verified = md.get_merge_request(
450 tree_b.branch.repository)
451- if isinstance(md, merge_directive.MergeDirective):
452+ if isinstance(md, merge_directive.BzrMergeDirective1):
453 self.assertIs(None, base)
454 self.assertEqual('inapplicable', verified)
455 else:
456@@ -606,7 +607,7 @@
457 ' explicit bases.')
458 repository.lock_write()
459 try:
460- return merge_directive.MergeDirective.from_objects( repository,
461+ return merge_directive.BzrMergeDirective1.from_objects(repository,
462 revision_id, time, timezone, target_branch, patch_type,
463 local_target_branch, public_branch, message)
464 finally:
465@@ -615,7 +616,7 @@
466 def make_merge_directive(self, revision_id, testament_sha1, time, timezone,
467 target_branch, patch=None, patch_type=None,
468 source_branch=None, message=None):
469- return merge_directive.MergeDirective(revision_id, testament_sha1,
470+ return merge_directive.BzrMergeDirective1(revision_id, testament_sha1,
471 time, timezone, target_branch, patch, patch_type,
472 source_branch, message)
473
474@@ -634,7 +635,7 @@
475 include_patch = (patch_type in ('bundle', 'diff'))
476 include_bundle = (patch_type == 'bundle')
477 self.assertTrue(patch_type in ('bundle', 'diff', None))
478- return merge_directive.MergeDirective2.from_objects(
479+ return merge_directive.BzrMergeDirective2.from_objects(
480 repository, revision_id, time, timezone, target_branch,
481 include_patch, include_bundle, local_target_branch, public_branch,
482 message, base_revision_id)
483@@ -647,7 +648,7 @@
484 patch = None
485 else:
486 bundle = None
487- return merge_directive.MergeDirective2(revision_id, testament_sha1,
488+ return merge_directive.BzrMergeDirective2(revision_id, testament_sha1,
489 time, timezone, target_branch, patch, source_branch, message,
490 bundle, base_revision_id)
491
492@@ -662,7 +663,7 @@
493 public_branch=tree_a.branch.base, base_revision_id='null:')
494 self.assertEqual('null:', md.base_revision_id)
495 lines = md.to_lines()
496- md2 = merge_directive.MergeDirective.from_lines(lines)
497+ md2 = merge_directive.BzrMergeDirective1.from_lines(lines)
498 self.assertEqual(md2.base_revision_id, md.base_revision_id)
499
500 def test_patch_verification(self):
501@@ -735,7 +736,7 @@
502 'merge_request_body', test_hook, 'test')
503 tree = self.make_branch_and_tree('foo')
504 tree.commit('foo')
505- directive = merge_directive.MergeDirective2(
506+ directive = merge_directive.BzrMergeDirective2(
507 tree.branch.last_revision(), 'sha', 0, 0, 'sha',
508 source_branch=tree.branch.base,
509 base_revision_id=tree.branch.last_revision(),