~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_smart.py

  • Committer: Vincent Ladeuil
  • Date: 2012-02-24 12:50:51 UTC
  • mfrom: (6437.23.15 2.5)
  • mto: This revision was merged to the branch mainline in revision 6475.
  • Revision ID: v.ladeuil+lp@free.fr-20120224125051-i7p1xmjxw56jhmj3
Merge 2.5 branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2011 Canonical Ltd
 
1
# Copyright (C) 2006-2012 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
25
25
"""
26
26
 
27
27
import bz2
 
28
import zlib
28
29
 
29
30
from bzrlib import (
 
31
    bencode,
30
32
    branch as _mod_branch,
31
33
    bzrdir,
32
34
    errors,
 
35
    gpg,
 
36
    inventory_delta,
33
37
    tests,
34
38
    transport,
35
39
    urlutils,
44
48
    server,
45
49
    vfs,
46
50
    )
 
51
from bzrlib.testament import Testament
47
52
from bzrlib.tests import test_server
48
53
from bzrlib.transport import (
49
54
    chroot,
85
90
            backing_transport = tests.TestCaseWithTransport.get_transport(self)
86
91
            self._chroot_server = chroot.ChrootServer(backing_transport)
87
92
            self.start_server(self._chroot_server)
88
 
        t = transport.get_transport(self._chroot_server.get_url())
 
93
        t = transport.get_transport_from_url(self._chroot_server.get_url())
89
94
        if relpath is not None:
90
95
            t = t.clone(relpath)
91
96
        return t
221
226
        self.assertEqual(expected, request.execute('', 'False'))
222
227
 
223
228
 
 
229
class TestSmartServerBzrDirRequestCloningMetaDir(
 
230
    tests.TestCaseWithMemoryTransport):
 
231
    """Tests for BzrDir.checkout_metadir."""
 
232
 
 
233
    def test_checkout_metadir(self):
 
234
        backing = self.get_transport()
 
235
        request = smart_dir.SmartServerBzrDirRequestCheckoutMetaDir(
 
236
            backing)
 
237
        branch = self.make_branch('.', format='2a')
 
238
        response = request.execute('')
 
239
        self.assertEqual(
 
240
            smart_req.SmartServerResponse(
 
241
                ('Bazaar-NG meta directory, format 1\n',
 
242
                 'Bazaar repository format 2a (needs bzr 1.16 or later)\n',
 
243
                 'Bazaar Branch Format 7 (needs bzr 1.6)\n')),
 
244
            response)
 
245
 
 
246
 
 
247
class TestSmartServerBzrDirRequestDestroyBranch(
 
248
    tests.TestCaseWithMemoryTransport):
 
249
    """Tests for BzrDir.destroy_branch."""
 
250
 
 
251
    def test_destroy_branch_default(self):
 
252
        """The default branch can be removed."""
 
253
        backing = self.get_transport()
 
254
        dir = self.make_branch('.').bzrdir
 
255
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
256
        request = request_class(backing)
 
257
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
258
        self.assertEqual(expected, request.execute('', None))
 
259
 
 
260
    def test_destroy_branch_named(self):
 
261
        """A named branch can be removed."""
 
262
        backing = self.get_transport()
 
263
        dir = self.make_repository('.', format="development-colo").bzrdir
 
264
        dir.create_branch(name="branchname")
 
265
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
266
        request = request_class(backing)
 
267
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
268
        self.assertEqual(expected, request.execute('', "branchname"))
 
269
 
 
270
    def test_destroy_branch_missing(self):
 
271
        """An error is raised if the branch didn't exist."""
 
272
        backing = self.get_transport()
 
273
        dir = self.make_bzrdir('.', format="development-colo")
 
274
        request_class = smart_dir.SmartServerBzrDirRequestDestroyBranch
 
275
        request = request_class(backing)
 
276
        expected = smart_req.FailedSmartServerResponse(('nobranch',), None)
 
277
        self.assertEqual(expected, request.execute('', "branchname"))
 
278
 
 
279
 
 
280
class TestSmartServerBzrDirRequestHasWorkingTree(
 
281
    tests.TestCaseWithTransport):
 
282
    """Tests for BzrDir.has_workingtree."""
 
283
 
 
284
    def test_has_workingtree_yes(self):
 
285
        """A working tree is present."""
 
286
        backing = self.get_transport()
 
287
        dir = self.make_branch_and_tree('.').bzrdir
 
288
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
289
        request = request_class(backing)
 
290
        expected = smart_req.SuccessfulSmartServerResponse(('yes',))
 
291
        self.assertEqual(expected, request.execute(''))
 
292
 
 
293
    def test_has_workingtree_no(self):
 
294
        """A working tree is missing."""
 
295
        backing = self.get_transport()
 
296
        dir = self.make_bzrdir('.')
 
297
        request_class = smart_dir.SmartServerBzrDirRequestHasWorkingTree
 
298
        request = request_class(backing)
 
299
        expected = smart_req.SuccessfulSmartServerResponse(('no',))
 
300
        self.assertEqual(expected, request.execute(''))
 
301
 
 
302
 
 
303
class TestSmartServerBzrDirRequestDestroyRepository(
 
304
    tests.TestCaseWithMemoryTransport):
 
305
    """Tests for BzrDir.destroy_repository."""
 
306
 
 
307
    def test_destroy_repository_default(self):
 
308
        """The repository can be removed."""
 
309
        backing = self.get_transport()
 
310
        dir = self.make_repository('.').bzrdir
 
311
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
312
        request = request_class(backing)
 
313
        expected = smart_req.SuccessfulSmartServerResponse(('ok',))
 
314
        self.assertEqual(expected, request.execute(''))
 
315
 
 
316
    def test_destroy_repository_missing(self):
 
317
        """An error is raised if the repository didn't exist."""
 
318
        backing = self.get_transport()
 
319
        dir = self.make_bzrdir('.')
 
320
        request_class = smart_dir.SmartServerBzrDirRequestDestroyRepository
 
321
        request = request_class(backing)
 
322
        expected = smart_req.FailedSmartServerResponse(
 
323
            ('norepository',), None)
 
324
        self.assertEqual(expected, request.execute(''))
 
325
 
 
326
 
224
327
class TestSmartServerRequestCreateRepository(tests.TestCaseWithMemoryTransport):
225
328
    """Tests for BzrDir.create_repository."""
226
329
 
316
419
        backing = self.get_transport()
317
420
        request = self._request_class(backing)
318
421
        result = self._make_repository_and_result(
319
 
            format='dirstate-with-subtree')
 
422
            format='development-subtree')
320
423
        # check the test will be valid
321
424
        self.assertEqual('yes', result.args[2])
322
425
        self.assertEqual('yes', result.args[3])
327
430
        backing = self.get_transport()
328
431
        request = self._request_class(backing)
329
432
        result = self._make_repository_and_result(
330
 
            format='dirstate-with-subtree')
 
433
            format='development-subtree')
331
434
        # check the test will be valid
332
 
        self.assertEqual('no', result.args[4])
 
435
        self.assertEqual('yes', result.args[4])
333
436
        self.assertEqual(result, request.execute(''))
334
437
 
335
438
 
356
459
        self.assertEqual(expected, request.execute(''))
357
460
 
358
461
 
 
462
class TestSmartServerBzrDirRequestGetBranches(
 
463
    tests.TestCaseWithMemoryTransport):
 
464
    """Tests for BzrDir.get_branches."""
 
465
 
 
466
    def test_simple(self):
 
467
        backing = self.get_transport()
 
468
        branch = self.make_branch('.')
 
469
        request_class = smart_dir.SmartServerBzrDirRequestGetBranches
 
470
        request = request_class(backing)
 
471
        local_result = bencode.bencode(
 
472
            {"": ("branch", branch._format.network_name())})
 
473
        expected = smart_req.SuccessfulSmartServerResponse(
 
474
            ("success", ), local_result)
 
475
        self.assertEqual(expected, request.execute(''))
 
476
 
 
477
    def test_empty(self):
 
478
        backing = self.get_transport()
 
479
        dir = self.make_bzrdir('.')
 
480
        request_class = smart_dir.SmartServerBzrDirRequestGetBranches
 
481
        request = request_class(backing)
 
482
        local_result = bencode.bencode({})
 
483
        expected = smart_req.SuccessfulSmartServerResponse(
 
484
            ('success',), local_result)
 
485
        self.assertEqual(expected, request.execute(''))
 
486
 
 
487
 
359
488
class TestSmartServerRequestInitializeBzrDir(tests.TestCaseWithMemoryTransport):
360
489
 
361
490
    def test_empty_dir(self):
383
512
        backing = self.get_transport()
384
513
        request = smart_dir.SmartServerRequestInitializeBzrDir(backing)
385
514
        self.make_bzrdir('subdir')
386
 
        self.assertRaises(errors.FileExists,
 
515
        self.assertRaises(errors.AlreadyControlDirError,
387
516
            request.execute, 'subdir')
388
517
 
389
518
 
735
864
            request.execute(''))
736
865
 
737
866
 
 
867
class TestSmartServerBranchRequestRevisionIdToRevno(
 
868
    tests.TestCaseWithMemoryTransport):
 
869
 
 
870
    def test_null(self):
 
871
        backing = self.get_transport()
 
872
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
873
            backing)
 
874
        self.make_branch('.')
 
875
        self.assertEqual(smart_req.SmartServerResponse(('ok', '0')),
 
876
            request.execute('', 'null:'))
 
877
 
 
878
    def test_simple(self):
 
879
        backing = self.get_transport()
 
880
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
881
            backing)
 
882
        tree = self.make_branch_and_memory_tree('.')
 
883
        tree.lock_write()
 
884
        tree.add('')
 
885
        r1 = tree.commit('1st commit')
 
886
        tree.unlock()
 
887
        self.assertEqual(
 
888
            smart_req.SmartServerResponse(('ok', '1')),
 
889
            request.execute('', r1))
 
890
 
 
891
    def test_not_found(self):
 
892
        backing = self.get_transport()
 
893
        request = smart_branch.SmartServerBranchRequestRevisionIdToRevno(
 
894
            backing)
 
895
        branch = self.make_branch('.')
 
896
        self.assertEqual(
 
897
            smart_req.FailedSmartServerResponse(
 
898
                ('NoSuchRevision', 'idontexist')),
 
899
            request.execute('', 'idontexist'))
 
900
 
 
901
 
738
902
class TestSmartServerBranchRequestGetConfigFile(
739
903
    tests.TestCaseWithMemoryTransport):
740
904
 
769
933
        return branch_token, repo_token
770
934
 
771
935
 
 
936
class TestSmartServerBranchRequestPutConfigFile(TestLockedBranch):
 
937
 
 
938
    def test_with_content(self):
 
939
        backing = self.get_transport()
 
940
        request = smart_branch.SmartServerBranchPutConfigFile(backing)
 
941
        branch = self.make_branch('.')
 
942
        branch_token, repo_token = self.get_lock_tokens(branch)
 
943
        self.assertIs(None, request.execute('', branch_token, repo_token))
 
944
        self.assertEqual(
 
945
            smart_req.SmartServerResponse(('ok', )),
 
946
            request.do_body('foo bar baz'))
 
947
        self.assertEquals(
 
948
            branch.control_transport.get_bytes('branch.conf'),
 
949
            'foo bar baz')
 
950
        branch.unlock()
 
951
 
 
952
 
772
953
class TestSmartServerBranchRequestSetConfigOption(TestLockedBranch):
773
954
 
774
955
    def test_value_name(self):
1088
1269
        self.assertEqual('child-1', self.tree.branch.last_revision())
1089
1270
 
1090
1271
 
 
1272
class TestSmartServerBranchBreakLock(tests.TestCaseWithMemoryTransport):
 
1273
 
 
1274
    def test_lock_to_break(self):
 
1275
        base_branch = self.make_branch('base')
 
1276
        request = smart_branch.SmartServerBranchBreakLock(
 
1277
            self.get_transport())
 
1278
        base_branch.lock_write()
 
1279
        self.assertEqual(
 
1280
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1281
            request.execute('base'))
 
1282
 
 
1283
    def test_nothing_to_break(self):
 
1284
        base_branch = self.make_branch('base')
 
1285
        request = smart_branch.SmartServerBranchBreakLock(
 
1286
            self.get_transport())
 
1287
        self.assertEqual(
 
1288
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1289
            request.execute('base'))
 
1290
 
 
1291
 
1091
1292
class TestSmartServerBranchRequestGetParent(tests.TestCaseWithMemoryTransport):
1092
1293
 
1093
1294
    def test_get_parent_none(self):
1122
1323
        finally:
1123
1324
            branch.unlock()
1124
1325
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
 
1326
        # Refresh branch as SetParentLocation modified it
 
1327
        branch = branch.bzrdir.open_branch()
1125
1328
        self.assertEqual(None, branch.get_parent())
1126
1329
 
1127
1330
    def test_set_parent_something(self):
1131
1334
        branch_token, repo_token = self.get_lock_tokens(branch)
1132
1335
        try:
1133
1336
            response = request.execute('base', branch_token, repo_token,
1134
 
            'http://bar/')
 
1337
                                       'http://bar/')
1135
1338
        finally:
1136
1339
            branch.unlock()
1137
1340
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(()), response)
1138
 
        self.assertEqual('http://bar/', branch.get_parent())
 
1341
        refreshed = _mod_branch.Branch.open(branch.base)
 
1342
        self.assertEqual('http://bar/', refreshed.get_parent())
1139
1343
 
1140
1344
 
1141
1345
class TestSmartServerBranchRequestGetTagsBytes(
1275
1479
        self.assertEqual('LockFailed', error_name)
1276
1480
 
1277
1481
 
 
1482
class TestSmartServerBranchRequestGetPhysicalLockStatus(TestLockedBranch):
 
1483
 
 
1484
    def setUp(self):
 
1485
        tests.TestCaseWithMemoryTransport.setUp(self)
 
1486
 
 
1487
    def test_true(self):
 
1488
        backing = self.get_transport()
 
1489
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1490
            backing)
 
1491
        branch = self.make_branch('.')
 
1492
        branch_token, repo_token = self.get_lock_tokens(branch)
 
1493
        self.assertEquals(True, branch.get_physical_lock_status())
 
1494
        response = request.execute('')
 
1495
        self.assertEqual(
 
1496
            smart_req.SmartServerResponse(('yes',)), response)
 
1497
        branch.unlock()
 
1498
 
 
1499
    def test_false(self):
 
1500
        backing = self.get_transport()
 
1501
        request = smart_branch.SmartServerBranchRequestGetPhysicalLockStatus(
 
1502
            backing)
 
1503
        branch = self.make_branch('.')
 
1504
        self.assertEquals(False, branch.get_physical_lock_status())
 
1505
        response = request.execute('')
 
1506
        self.assertEqual(
 
1507
            smart_req.SmartServerResponse(('no',)), response)
 
1508
 
 
1509
 
1278
1510
class TestSmartServerBranchRequestUnlock(TestLockedBranch):
1279
1511
 
1280
1512
    def setUp(self):
1345
1577
            request.execute, 'subdir')
1346
1578
 
1347
1579
 
 
1580
class TestSmartServerRepositoryAddSignatureText(tests.TestCaseWithMemoryTransport):
 
1581
 
 
1582
    def test_add_text(self):
 
1583
        backing = self.get_transport()
 
1584
        request = smart_repo.SmartServerRepositoryAddSignatureText(backing)
 
1585
        tree = self.make_branch_and_memory_tree('.')
 
1586
        write_token = tree.lock_write()
 
1587
        self.addCleanup(tree.unlock)
 
1588
        tree.add('')
 
1589
        tree.commit("Message", rev_id='rev1')
 
1590
        tree.branch.repository.start_write_group()
 
1591
        write_group_tokens = tree.branch.repository.suspend_write_group()
 
1592
        self.assertEqual(None, request.execute('', write_token,
 
1593
            'rev1', *write_group_tokens))
 
1594
        response = request.do_body('somesignature')
 
1595
        self.assertTrue(response.is_successful())
 
1596
        self.assertEqual(response.args[0], 'ok')
 
1597
        write_group_tokens = response.args[1:]
 
1598
        tree.branch.repository.resume_write_group(write_group_tokens)
 
1599
        tree.branch.repository.commit_write_group()
 
1600
        tree.unlock()
 
1601
        self.assertEqual("somesignature",
 
1602
            tree.branch.repository.get_signature_text("rev1"))
 
1603
 
 
1604
 
 
1605
class TestSmartServerRepositoryAllRevisionIds(
 
1606
    tests.TestCaseWithMemoryTransport):
 
1607
 
 
1608
    def test_empty(self):
 
1609
        """An empty body should be returned for an empty repository."""
 
1610
        backing = self.get_transport()
 
1611
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1612
        self.make_repository('.')
 
1613
        self.assertEquals(
 
1614
            smart_req.SuccessfulSmartServerResponse(("ok", ), ""),
 
1615
            request.execute(''))
 
1616
 
 
1617
    def test_some_revisions(self):
 
1618
        """An empty body should be returned for an empty repository."""
 
1619
        backing = self.get_transport()
 
1620
        request = smart_repo.SmartServerRepositoryAllRevisionIds(backing)
 
1621
        tree = self.make_branch_and_memory_tree('.')
 
1622
        tree.lock_write()
 
1623
        tree.add('')
 
1624
        tree.commit(rev_id='origineel', message="message")
 
1625
        tree.commit(rev_id='nog-een-revisie', message="message")
 
1626
        tree.unlock()
 
1627
        self.assertEquals(
 
1628
            smart_req.SuccessfulSmartServerResponse(("ok", ),
 
1629
                "origineel\nnog-een-revisie"),
 
1630
            request.execute(''))
 
1631
 
 
1632
 
 
1633
class TestSmartServerRepositoryBreakLock(tests.TestCaseWithMemoryTransport):
 
1634
 
 
1635
    def test_lock_to_break(self):
 
1636
        backing = self.get_transport()
 
1637
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1638
        tree = self.make_branch_and_memory_tree('.')
 
1639
        tree.branch.repository.lock_write()
 
1640
        self.assertEqual(
 
1641
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1642
            request.execute(''))
 
1643
 
 
1644
    def test_nothing_to_break(self):
 
1645
        backing = self.get_transport()
 
1646
        request = smart_repo.SmartServerRepositoryBreakLock(backing)
 
1647
        tree = self.make_branch_and_memory_tree('.')
 
1648
        self.assertEqual(
 
1649
            smart_req.SuccessfulSmartServerResponse(('ok', ), None),
 
1650
            request.execute(''))
 
1651
 
 
1652
 
1348
1653
class TestSmartServerRepositoryGetParentMap(tests.TestCaseWithMemoryTransport):
1349
1654
 
1350
1655
    def test_trivial_bzipped(self):
1470
1775
            request.execute('stacked', 1, (3, r3)))
1471
1776
 
1472
1777
 
 
1778
class TestSmartServerRepositoryIterRevisions(
 
1779
    tests.TestCaseWithMemoryTransport):
 
1780
 
 
1781
    def test_basic(self):
 
1782
        backing = self.get_transport()
 
1783
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1784
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1785
        tree.lock_write()
 
1786
        tree.add('')
 
1787
        tree.commit('1st commit', rev_id="rev1")
 
1788
        tree.commit('2nd commit', rev_id="rev2")
 
1789
        tree.unlock()
 
1790
 
 
1791
        self.assertIs(None, request.execute(''))
 
1792
        response = request.do_body("rev1\nrev2")
 
1793
        self.assertTrue(response.is_successful())
 
1794
        # Format 2a uses serializer format 10
 
1795
        self.assertEquals(response.args, ("ok", "10"))
 
1796
 
 
1797
        self.addCleanup(tree.branch.lock_read().unlock)
 
1798
        entries = [zlib.compress(record.get_bytes_as("fulltext")) for record in
 
1799
            tree.branch.repository.revisions.get_record_stream(
 
1800
            [("rev1", ), ("rev2", )], "unordered", True)]
 
1801
 
 
1802
        contents = "".join(response.body_stream)
 
1803
        self.assertTrue(contents in (
 
1804
            "".join([entries[0], entries[1]]),
 
1805
            "".join([entries[1], entries[0]])))
 
1806
 
 
1807
    def test_missing(self):
 
1808
        backing = self.get_transport()
 
1809
        request = smart_repo.SmartServerRepositoryIterRevisions(backing)
 
1810
        tree = self.make_branch_and_memory_tree('.', format='2a')
 
1811
 
 
1812
        self.assertIs(None, request.execute(''))
 
1813
        response = request.do_body("rev1\nrev2")
 
1814
        self.assertTrue(response.is_successful())
 
1815
        # Format 2a uses serializer format 10
 
1816
        self.assertEquals(response.args, ("ok", "10"))
 
1817
 
 
1818
        contents = "".join(response.body_stream)
 
1819
        self.assertEquals(contents, "")
 
1820
 
 
1821
 
1473
1822
class GetStreamTestBase(tests.TestCaseWithMemoryTransport):
1474
1823
 
1475
1824
    def make_two_commit_repo(self):
1549
1898
            request.execute('', rev_id_utf8))
1550
1899
 
1551
1900
 
 
1901
class TestSmartServerRepositoryIterFilesBytes(tests.TestCaseWithTransport):
 
1902
 
 
1903
    def test_single(self):
 
1904
        backing = self.get_transport()
 
1905
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1906
        t = self.make_branch_and_tree('.')
 
1907
        self.addCleanup(t.lock_write().unlock)
 
1908
        self.build_tree_contents([("file", "somecontents")])
 
1909
        t.add(["file"], ["thefileid"])
 
1910
        t.commit(rev_id='somerev', message="add file")
 
1911
        self.assertIs(None, request.execute(''))
 
1912
        response = request.do_body("thefileid\0somerev\n")
 
1913
        self.assertTrue(response.is_successful())
 
1914
        self.assertEquals(response.args, ("ok", ))
 
1915
        self.assertEquals("".join(response.body_stream),
 
1916
            "ok\x000\n" + zlib.compress("somecontents"))
 
1917
 
 
1918
    def test_missing(self):
 
1919
        backing = self.get_transport()
 
1920
        request = smart_repo.SmartServerRepositoryIterFilesBytes(backing)
 
1921
        t = self.make_branch_and_tree('.')
 
1922
        self.addCleanup(t.lock_write().unlock)
 
1923
        self.assertIs(None, request.execute(''))
 
1924
        response = request.do_body("thefileid\0revision\n")
 
1925
        self.assertTrue(response.is_successful())
 
1926
        self.assertEquals(response.args, ("ok", ))
 
1927
        self.assertEquals("".join(response.body_stream),
 
1928
            "absent\x00thefileid\x00revision\x000\n")
 
1929
 
 
1930
 
 
1931
class TestSmartServerRequestHasSignatureForRevisionId(
 
1932
        tests.TestCaseWithMemoryTransport):
 
1933
 
 
1934
    def test_missing_revision(self):
 
1935
        """For a missing revision, NoSuchRevision is returned."""
 
1936
        backing = self.get_transport()
 
1937
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1938
            backing)
 
1939
        self.make_repository('.')
 
1940
        self.assertEqual(
 
1941
            smart_req.FailedSmartServerResponse(
 
1942
                ('nosuchrevision', 'revid'), None),
 
1943
            request.execute('', 'revid'))
 
1944
 
 
1945
    def test_missing_signature(self):
 
1946
        """For a missing signature, ('no', ) is returned."""
 
1947
        backing = self.get_transport()
 
1948
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1949
            backing)
 
1950
        tree = self.make_branch_and_memory_tree('.')
 
1951
        tree.lock_write()
 
1952
        tree.add('')
 
1953
        r1 = tree.commit('a commit', rev_id='A')
 
1954
        tree.unlock()
 
1955
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1956
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
1957
            request.execute('', 'A'))
 
1958
 
 
1959
    def test_present_signature(self):
 
1960
        """For a present signature, ('yes', ) is returned."""
 
1961
        backing = self.get_transport()
 
1962
        request = smart_repo.SmartServerRequestHasSignatureForRevisionId(
 
1963
            backing)
 
1964
        strategy = gpg.LoopbackGPGStrategy(None)
 
1965
        tree = self.make_branch_and_memory_tree('.')
 
1966
        tree.lock_write()
 
1967
        tree.add('')
 
1968
        r1 = tree.commit('a commit', rev_id='A')
 
1969
        tree.branch.repository.start_write_group()
 
1970
        tree.branch.repository.sign_revision('A', strategy)
 
1971
        tree.branch.repository.commit_write_group()
 
1972
        tree.unlock()
 
1973
        self.assertTrue(tree.branch.repository.has_revision('A'))
 
1974
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
1975
            request.execute('', 'A'))
 
1976
 
 
1977
 
1552
1978
class TestSmartServerRepositoryGatherStats(tests.TestCaseWithMemoryTransport):
1553
1979
 
1554
1980
    def test_empty_revid(self):
1607
2033
                         request.execute('',
1608
2034
                                         rev_id_utf8, 'yes'))
1609
2035
 
 
2036
    def test_unknown_revid(self):
 
2037
        """An unknown revision id causes a 'nosuchrevision' error."""
 
2038
        backing = self.get_transport()
 
2039
        request = smart_repo.SmartServerRepositoryGatherStats(backing)
 
2040
        repository = self.make_repository('.')
 
2041
        expected_body = 'revisions: 0\n'
 
2042
        self.assertEqual(
 
2043
            smart_req.FailedSmartServerResponse(
 
2044
                ('nosuchrevision', 'mia'), None),
 
2045
            request.execute('', 'mia', 'yes'))
 
2046
 
1610
2047
 
1611
2048
class TestSmartServerRepositoryIsShared(tests.TestCaseWithMemoryTransport):
1612
2049
 
1627
2064
            request.execute('', ))
1628
2065
 
1629
2066
 
 
2067
class TestSmartServerRepositoryGetRevisionSignatureText(
 
2068
        tests.TestCaseWithMemoryTransport):
 
2069
 
 
2070
    def test_get_signature(self):
 
2071
        backing = self.get_transport()
 
2072
        request = smart_repo.SmartServerRepositoryGetRevisionSignatureText(
 
2073
            backing)
 
2074
        bb = self.make_branch_builder('.')
 
2075
        bb.build_commit(rev_id='A')
 
2076
        repo = bb.get_branch().repository
 
2077
        strategy = gpg.LoopbackGPGStrategy(None)
 
2078
        self.addCleanup(repo.lock_write().unlock)
 
2079
        repo.start_write_group()
 
2080
        repo.sign_revision('A', strategy)
 
2081
        repo.commit_write_group()
 
2082
        expected_body = (
 
2083
            '-----BEGIN PSEUDO-SIGNED CONTENT-----\n' +
 
2084
            Testament.from_revision(repo, 'A').as_short_text() +
 
2085
            '-----END PSEUDO-SIGNED CONTENT-----\n')
 
2086
        self.assertEqual(
 
2087
            smart_req.SmartServerResponse(('ok', ), expected_body),
 
2088
            request.execute('', 'A'))
 
2089
 
 
2090
 
 
2091
class TestSmartServerRepositoryMakeWorkingTrees(
 
2092
        tests.TestCaseWithMemoryTransport):
 
2093
 
 
2094
    def test_make_working_trees(self):
 
2095
        """For a repository with working trees, ('yes', ) is returned."""
 
2096
        backing = self.get_transport()
 
2097
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2098
        r = self.make_repository('.')
 
2099
        r.set_make_working_trees(True)
 
2100
        self.assertEqual(smart_req.SmartServerResponse(('yes', )),
 
2101
            request.execute('', ))
 
2102
 
 
2103
    def test_is_not_shared(self):
 
2104
        """For a repository with working trees, ('no', ) is returned."""
 
2105
        backing = self.get_transport()
 
2106
        request = smart_repo.SmartServerRepositoryMakeWorkingTrees(backing)
 
2107
        r = self.make_repository('.')
 
2108
        r.set_make_working_trees(False)
 
2109
        self.assertEqual(smart_req.SmartServerResponse(('no', )),
 
2110
            request.execute('', ))
 
2111
 
 
2112
 
1630
2113
class TestSmartServerRepositoryLockWrite(tests.TestCaseWithMemoryTransport):
1631
2114
 
1632
2115
    def test_lock_write_on_unlocked_repo(self):
1746
2229
            smart_req.SmartServerResponse(('TokenMismatch',)), response)
1747
2230
 
1748
2231
 
 
2232
class TestSmartServerRepositoryGetPhysicalLockStatus(
 
2233
    tests.TestCaseWithTransport):
 
2234
 
 
2235
    def test_with_write_lock(self):
 
2236
        backing = self.get_transport()
 
2237
        repo = self.make_repository('.')
 
2238
        self.addCleanup(repo.lock_write().unlock)
 
2239
        # lock_write() doesn't necessarily actually take a physical
 
2240
        # lock out.
 
2241
        if repo.get_physical_lock_status():
 
2242
            expected = 'yes'
 
2243
        else:
 
2244
            expected = 'no'
 
2245
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2246
        request = request_class(backing)
 
2247
        self.assertEqual(smart_req.SuccessfulSmartServerResponse((expected,)),
 
2248
            request.execute('', ))
 
2249
 
 
2250
    def test_without_write_lock(self):
 
2251
        backing = self.get_transport()
 
2252
        repo = self.make_repository('.')
 
2253
        self.assertEquals(False, repo.get_physical_lock_status())
 
2254
        request_class = smart_repo.SmartServerRepositoryGetPhysicalLockStatus
 
2255
        request = request_class(backing)
 
2256
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('no',)),
 
2257
            request.execute('', ))
 
2258
 
 
2259
 
 
2260
class TestSmartServerRepositoryReconcile(tests.TestCaseWithTransport):
 
2261
 
 
2262
    def test_reconcile(self):
 
2263
        backing = self.get_transport()
 
2264
        repo = self.make_repository('.')
 
2265
        token = repo.lock_write().repository_token
 
2266
        self.addCleanup(repo.unlock)
 
2267
        request_class = smart_repo.SmartServerRepositoryReconcile
 
2268
        request = request_class(backing)
 
2269
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(
 
2270
            ('ok', ),
 
2271
             'garbage_inventories: 0\n'
 
2272
             'inconsistent_parents: 0\n'),
 
2273
            request.execute('', token))
 
2274
 
 
2275
 
1749
2276
class TestSmartServerIsReadonly(tests.TestCaseWithMemoryTransport):
1750
2277
 
1751
2278
    def test_is_readonly_no(self):
1789
2316
        self.assertTrue(repo.make_working_trees())
1790
2317
 
1791
2318
 
 
2319
class TestSmartServerRepositoryGetSerializerFormat(
 
2320
    tests.TestCaseWithMemoryTransport):
 
2321
 
 
2322
    def test_get_serializer_format(self):
 
2323
        backing = self.get_transport()
 
2324
        repo = self.make_repository('.', format='2a')
 
2325
        request_class = smart_repo.SmartServerRepositoryGetSerializerFormat
 
2326
        request = request_class(backing)
 
2327
        self.assertEqual(
 
2328
            smart_req.SuccessfulSmartServerResponse(('ok', '10')),
 
2329
            request.execute(''))
 
2330
 
 
2331
 
 
2332
class TestSmartServerRepositoryWriteGroup(
 
2333
    tests.TestCaseWithMemoryTransport):
 
2334
 
 
2335
    def test_start_write_group(self):
 
2336
        backing = self.get_transport()
 
2337
        repo = self.make_repository('.')
 
2338
        lock_token = repo.lock_write().repository_token
 
2339
        self.addCleanup(repo.unlock)
 
2340
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2341
        request = request_class(backing)
 
2342
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok', [])),
 
2343
            request.execute('', lock_token))
 
2344
 
 
2345
    def test_start_write_group_unsuspendable(self):
 
2346
        backing = self.get_transport()
 
2347
        repo = self.make_repository('.', format='knit')
 
2348
        lock_token = repo.lock_write().repository_token
 
2349
        self.addCleanup(repo.unlock)
 
2350
        request_class = smart_repo.SmartServerRepositoryStartWriteGroup
 
2351
        request = request_class(backing)
 
2352
        self.assertEqual(
 
2353
            smart_req.FailedSmartServerResponse(('UnsuspendableWriteGroup',)),
 
2354
            request.execute('', lock_token))
 
2355
 
 
2356
    def test_commit_write_group(self):
 
2357
        backing = self.get_transport()
 
2358
        repo = self.make_repository('.')
 
2359
        lock_token = repo.lock_write().repository_token
 
2360
        self.addCleanup(repo.unlock)
 
2361
        repo.start_write_group()
 
2362
        tokens = repo.suspend_write_group()
 
2363
        request_class = smart_repo.SmartServerRepositoryCommitWriteGroup
 
2364
        request = request_class(backing)
 
2365
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2366
            request.execute('', lock_token, tokens))
 
2367
 
 
2368
    def test_abort_write_group(self):
 
2369
        backing = self.get_transport()
 
2370
        repo = self.make_repository('.')
 
2371
        lock_token = repo.lock_write().repository_token
 
2372
        repo.start_write_group()
 
2373
        tokens = repo.suspend_write_group()
 
2374
        self.addCleanup(repo.unlock)
 
2375
        request_class = smart_repo.SmartServerRepositoryAbortWriteGroup
 
2376
        request = request_class(backing)
 
2377
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2378
            request.execute('', lock_token, tokens))
 
2379
 
 
2380
    def test_check_write_group(self):
 
2381
        backing = self.get_transport()
 
2382
        repo = self.make_repository('.')
 
2383
        lock_token = repo.lock_write().repository_token
 
2384
        repo.start_write_group()
 
2385
        tokens = repo.suspend_write_group()
 
2386
        self.addCleanup(repo.unlock)
 
2387
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2388
        request = request_class(backing)
 
2389
        self.assertEqual(smart_req.SuccessfulSmartServerResponse(('ok',)),
 
2390
            request.execute('', lock_token, tokens))
 
2391
 
 
2392
    def test_check_write_group_invalid(self):
 
2393
        backing = self.get_transport()
 
2394
        repo = self.make_repository('.')
 
2395
        lock_token = repo.lock_write().repository_token
 
2396
        self.addCleanup(repo.unlock)
 
2397
        request_class = smart_repo.SmartServerRepositoryCheckWriteGroup
 
2398
        request = request_class(backing)
 
2399
        self.assertEqual(smart_req.FailedSmartServerResponse(
 
2400
            ('UnresumableWriteGroup', ['random'],
 
2401
                'Malformed write group token')),
 
2402
            request.execute('', lock_token, ["random"]))
 
2403
 
 
2404
 
1792
2405
class TestSmartServerPackRepositoryAutopack(tests.TestCaseWithTransport):
1793
2406
 
1794
2407
    def make_repo_needing_autopacking(self, path='.'):
1860
2473
        """All registered request_handlers can be found."""
1861
2474
        # If there's a typo in a register_lazy call, this loop will fail with
1862
2475
        # an AttributeError.
1863
 
        for key, item in smart_req.request_handlers.iteritems():
1864
 
            pass
 
2476
        for key in smart_req.request_handlers.keys():
 
2477
            try:
 
2478
                item = smart_req.request_handlers.get(key)
 
2479
            except AttributeError, e:
 
2480
                raise AttributeError('failed to get %s: %s' % (key, e))
1865
2481
 
1866
2482
    def assertHandlerEqual(self, verb, handler):
1867
2483
        self.assertEqual(smart_req.request_handlers.get(verb), handler)
1868
2484
 
1869
2485
    def test_registered_methods(self):
1870
2486
        """Test that known methods are registered to the correct object."""
 
2487
        self.assertHandlerEqual('Branch.break_lock',
 
2488
            smart_branch.SmartServerBranchBreakLock)
1871
2489
        self.assertHandlerEqual('Branch.get_config_file',
1872
2490
            smart_branch.SmartServerBranchGetConfigFile)
 
2491
        self.assertHandlerEqual('Branch.put_config_file',
 
2492
            smart_branch.SmartServerBranchPutConfigFile)
1873
2493
        self.assertHandlerEqual('Branch.get_parent',
1874
2494
            smart_branch.SmartServerBranchGetParent)
 
2495
        self.assertHandlerEqual('Branch.get_physical_lock_status',
 
2496
            smart_branch.SmartServerBranchRequestGetPhysicalLockStatus)
1875
2497
        self.assertHandlerEqual('Branch.get_tags_bytes',
1876
2498
            smart_branch.SmartServerBranchGetTagsBytes)
1877
2499
        self.assertHandlerEqual('Branch.lock_write',
1880
2502
            smart_branch.SmartServerBranchRequestLastRevisionInfo)
1881
2503
        self.assertHandlerEqual('Branch.revision_history',
1882
2504
            smart_branch.SmartServerRequestRevisionHistory)
 
2505
        self.assertHandlerEqual('Branch.revision_id_to_revno',
 
2506
            smart_branch.SmartServerBranchRequestRevisionIdToRevno)
1883
2507
        self.assertHandlerEqual('Branch.set_config_option',
1884
2508
            smart_branch.SmartServerBranchRequestSetConfigOption)
1885
2509
        self.assertHandlerEqual('Branch.set_last_revision',
1892
2516
            smart_branch.SmartServerBranchRequestSetParentLocation)
1893
2517
        self.assertHandlerEqual('Branch.unlock',
1894
2518
            smart_branch.SmartServerBranchRequestUnlock)
 
2519
        self.assertHandlerEqual('BzrDir.destroy_branch',
 
2520
            smart_dir.SmartServerBzrDirRequestDestroyBranch)
1895
2521
        self.assertHandlerEqual('BzrDir.find_repository',
1896
2522
            smart_dir.SmartServerRequestFindRepositoryV1)
1897
2523
        self.assertHandlerEqual('BzrDir.find_repositoryV2',
1900
2526
            smart_dir.SmartServerRequestInitializeBzrDir)
1901
2527
        self.assertHandlerEqual('BzrDirFormat.initialize_ex_1.16',
1902
2528
            smart_dir.SmartServerRequestBzrDirInitializeEx)
 
2529
        self.assertHandlerEqual('BzrDir.checkout_metadir',
 
2530
            smart_dir.SmartServerBzrDirRequestCheckoutMetaDir)
1903
2531
        self.assertHandlerEqual('BzrDir.cloning_metadir',
1904
2532
            smart_dir.SmartServerBzrDirRequestCloningMetaDir)
 
2533
        self.assertHandlerEqual('BzrDir.get_branches',
 
2534
            smart_dir.SmartServerBzrDirRequestGetBranches)
1905
2535
        self.assertHandlerEqual('BzrDir.get_config_file',
1906
2536
            smart_dir.SmartServerBzrDirRequestConfigFile)
1907
2537
        self.assertHandlerEqual('BzrDir.open_branch',
1912
2542
            smart_dir.SmartServerRequestOpenBranchV3)
1913
2543
        self.assertHandlerEqual('PackRepository.autopack',
1914
2544
            smart_packrepo.SmartServerPackRepositoryAutopack)
 
2545
        self.assertHandlerEqual('Repository.add_signature_text',
 
2546
            smart_repo.SmartServerRepositoryAddSignatureText)
 
2547
        self.assertHandlerEqual('Repository.all_revision_ids',
 
2548
            smart_repo.SmartServerRepositoryAllRevisionIds)
 
2549
        self.assertHandlerEqual('Repository.break_lock',
 
2550
            smart_repo.SmartServerRepositoryBreakLock)
1915
2551
        self.assertHandlerEqual('Repository.gather_stats',
1916
2552
            smart_repo.SmartServerRepositoryGatherStats)
1917
2553
        self.assertHandlerEqual('Repository.get_parent_map',
1918
2554
            smart_repo.SmartServerRepositoryGetParentMap)
 
2555
        self.assertHandlerEqual('Repository.get_physical_lock_status',
 
2556
            smart_repo.SmartServerRepositoryGetPhysicalLockStatus)
1919
2557
        self.assertHandlerEqual('Repository.get_rev_id_for_revno',
1920
2558
            smart_repo.SmartServerRepositoryGetRevIdForRevno)
1921
2559
        self.assertHandlerEqual('Repository.get_revision_graph',
1922
2560
            smart_repo.SmartServerRepositoryGetRevisionGraph)
 
2561
        self.assertHandlerEqual('Repository.get_revision_signature_text',
 
2562
            smart_repo.SmartServerRepositoryGetRevisionSignatureText)
1923
2563
        self.assertHandlerEqual('Repository.get_stream',
1924
2564
            smart_repo.SmartServerRepositoryGetStream)
1925
2565
        self.assertHandlerEqual('Repository.get_stream_1.19',
1926
2566
            smart_repo.SmartServerRepositoryGetStream_1_19)
 
2567
        self.assertHandlerEqual('Repository.iter_revisions',
 
2568
            smart_repo.SmartServerRepositoryIterRevisions)
1927
2569
        self.assertHandlerEqual('Repository.has_revision',
1928
2570
            smart_repo.SmartServerRequestHasRevision)
1929
2571
        self.assertHandlerEqual('Repository.insert_stream',
1932
2574
            smart_repo.SmartServerRepositoryInsertStreamLocked)
1933
2575
        self.assertHandlerEqual('Repository.is_shared',
1934
2576
            smart_repo.SmartServerRepositoryIsShared)
 
2577
        self.assertHandlerEqual('Repository.iter_files_bytes',
 
2578
            smart_repo.SmartServerRepositoryIterFilesBytes)
1935
2579
        self.assertHandlerEqual('Repository.lock_write',
1936
2580
            smart_repo.SmartServerRepositoryLockWrite)
 
2581
        self.assertHandlerEqual('Repository.make_working_trees',
 
2582
            smart_repo.SmartServerRepositoryMakeWorkingTrees)
 
2583
        self.assertHandlerEqual('Repository.pack',
 
2584
            smart_repo.SmartServerRepositoryPack)
 
2585
        self.assertHandlerEqual('Repository.reconcile',
 
2586
            smart_repo.SmartServerRepositoryReconcile)
1937
2587
        self.assertHandlerEqual('Repository.tarball',
1938
2588
            smart_repo.SmartServerRepositoryTarball)
1939
2589
        self.assertHandlerEqual('Repository.unlock',
1940
2590
            smart_repo.SmartServerRepositoryUnlock)
 
2591
        self.assertHandlerEqual('Repository.start_write_group',
 
2592
            smart_repo.SmartServerRepositoryStartWriteGroup)
 
2593
        self.assertHandlerEqual('Repository.check_write_group',
 
2594
            smart_repo.SmartServerRepositoryCheckWriteGroup)
 
2595
        self.assertHandlerEqual('Repository.commit_write_group',
 
2596
            smart_repo.SmartServerRepositoryCommitWriteGroup)
 
2597
        self.assertHandlerEqual('Repository.abort_write_group',
 
2598
            smart_repo.SmartServerRepositoryAbortWriteGroup)
 
2599
        self.assertHandlerEqual('VersionedFileRepository.get_serializer_format',
 
2600
            smart_repo.SmartServerRepositoryGetSerializerFormat)
 
2601
        self.assertHandlerEqual('VersionedFileRepository.get_inventories',
 
2602
            smart_repo.SmartServerRepositoryGetInventories)
1941
2603
        self.assertHandlerEqual('Transport.is_readonly',
1942
2604
            smart_req.SmartServerIsReadonly)
1943
2605
 
1987
2649
        self.server.run_server_stopped_hooks()
1988
2650
        self.assertEquals(stopped_calls,
1989
2651
            [([self.get_transport().base], 'bzr://example.com:42/')])
 
2652
 
 
2653
 
 
2654
class TestSmartServerRepositoryPack(tests.TestCaseWithMemoryTransport):
 
2655
 
 
2656
    def test_pack(self):
 
2657
        backing = self.get_transport()
 
2658
        request = smart_repo.SmartServerRepositoryPack(backing)
 
2659
        tree = self.make_branch_and_memory_tree('.')
 
2660
        repo_token = tree.branch.repository.lock_write().repository_token
 
2661
 
 
2662
        self.assertIs(None, request.execute('', repo_token, False))
 
2663
 
 
2664
        self.assertEqual(
 
2665
            smart_req.SuccessfulSmartServerResponse(('ok', ), ),
 
2666
            request.do_body(''))
 
2667
 
 
2668
 
 
2669
class TestSmartServerRepositoryGetInventories(tests.TestCaseWithTransport):
 
2670
 
 
2671
    def _get_serialized_inventory_delta(self, repository, base_revid, revid):
 
2672
        base_inv = repository.revision_tree(base_revid).root_inventory
 
2673
        inv = repository.revision_tree(revid).root_inventory
 
2674
        inv_delta = inv._make_delta(base_inv)
 
2675
        serializer = inventory_delta.InventoryDeltaSerializer(True, False)
 
2676
        return "".join(serializer.delta_to_lines(base_revid, revid, inv_delta))
 
2677
 
 
2678
    def test_single(self):
 
2679
        backing = self.get_transport()
 
2680
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2681
        t = self.make_branch_and_tree('.', format='2a')
 
2682
        self.addCleanup(t.lock_write().unlock)
 
2683
        self.build_tree_contents([("file", "somecontents")])
 
2684
        t.add(["file"], ["thefileid"])
 
2685
        t.commit(rev_id='somerev', message="add file")
 
2686
        self.assertIs(None, request.execute('', 'unordered'))
 
2687
        response = request.do_body("somerev\n")
 
2688
        self.assertTrue(response.is_successful())
 
2689
        self.assertEquals(response.args, ("ok", ))
 
2690
        stream = [('inventory-deltas', [
 
2691
            versionedfile.FulltextContentFactory('somerev', None, None,
 
2692
                self._get_serialized_inventory_delta(
 
2693
                    t.branch.repository, 'null:', 'somerev'))])]
 
2694
        fmt = bzrdir.format_registry.get('2a')().repository_format
 
2695
        self.assertEquals(
 
2696
            "".join(response.body_stream),
 
2697
            "".join(smart_repo._stream_to_byte_stream(stream, fmt)))
 
2698
 
 
2699
    def test_empty(self):
 
2700
        backing = self.get_transport()
 
2701
        request = smart_repo.SmartServerRepositoryGetInventories(backing)
 
2702
        t = self.make_branch_and_tree('.', format='2a')
 
2703
        self.addCleanup(t.lock_write().unlock)
 
2704
        self.build_tree_contents([("file", "somecontents")])
 
2705
        t.add(["file"], ["thefileid"])
 
2706
        t.commit(rev_id='somerev', message="add file")
 
2707
        self.assertIs(None, request.execute('', 'unordered'))
 
2708
        response = request.do_body("")
 
2709
        self.assertTrue(response.is_successful())
 
2710
        self.assertEquals(response.args, ("ok", ))
 
2711
        self.assertEquals("".join(response.body_stream),
 
2712
            "Bazaar pack format 1 (introduced in 0.18)\nB54\n\nBazaar repository format 2a (needs bzr 1.16 or later)\nE")