/breezy/unstable

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy/unstable

« back to all changes in this revision

Viewing changes to breezy/tests/test_bundle.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-24 01:39:33 UTC
  • mfrom: (3815.3776.6)
  • Revision ID: jelmer@jelmer.uk-20170524013933-ir4y4tqtrsiz2ka2
New upstream snapshot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from cStringIO import StringIO
18
17
import os
19
 
import SocketServer
 
18
try:
 
19
    import socketserver
 
20
except ImportError:
 
21
    import SocketServer as socketserver
20
22
import sys
21
23
 
22
 
from bzrlib import (
 
24
from .. import (
23
25
    bzrdir,
24
26
    diff,
25
27
    errors,
30
32
    tests,
31
33
    treebuilder,
32
34
    )
33
 
from bzrlib.bundle import read_mergeable_from_url
34
 
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
35
 
from bzrlib.bundle.bundle_data import BundleTree
36
 
from bzrlib.directory_service import directories
37
 
from bzrlib.bundle.serializer import write_bundle, read_bundle, v09, v4
38
 
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
39
 
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
40
 
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
41
 
from bzrlib.repofmt import knitrepo
42
 
from bzrlib.tests import (
 
35
from ..bundle import read_mergeable_from_url
 
36
from ..bundle.apply_bundle import install_bundle, merge_bundle
 
37
from ..bundle.bundle_data import BundleTree
 
38
from ..directory_service import directories
 
39
from ..bundle.serializer import write_bundle, read_bundle, v09, v4
 
40
from ..bundle.serializer.v08 import BundleSerializerV08
 
41
from ..bundle.serializer.v09 import BundleSerializerV09
 
42
from ..bundle.serializer.v4 import BundleSerializerV4
 
43
from ..repofmt import knitrepo
 
44
from ..sixish import (
 
45
    BytesIO,
 
46
    )
 
47
from . import (
43
48
    features,
44
49
    test_commit,
45
50
    test_read_bundle,
46
51
    test_server,
47
52
    )
48
 
from bzrlib.transform import TreeTransform
 
53
from ..transform import TreeTransform
49
54
 
50
55
 
51
56
def get_text(vf, key):
67
72
class MockTree(object):
68
73
 
69
74
    def __init__(self):
70
 
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
 
75
        from ..inventory import InventoryDirectory, ROOT_ID
71
76
        object.__init__(self)
72
77
        self.paths = {ROOT_ID: ""}
73
78
        self.ids = {"": ROOT_ID}
111
116
        return kind
112
117
 
113
118
    def make_entry(self, file_id, path):
114
 
        from bzrlib.inventory import (InventoryFile , InventoryDirectory,
 
119
        from ..inventory import (InventoryFile , InventoryDirectory,
115
120
            InventoryLink)
116
121
        name = os.path.basename(path)
117
122
        kind = self.kind(file_id)
147
152
        return self.id2path(file_id) is not None
148
153
 
149
154
    def get_file(self, file_id):
150
 
        result = StringIO()
 
155
        result = BytesIO()
151
156
        result.write(self.contents[file_id])
152
157
        result.seek(0,0)
153
158
        return result
251
256
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
252
257
 
253
258
    def unified_diff(self, old, new):
254
 
        out = StringIO()
 
259
        out = BytesIO()
255
260
        diff.internal_diff("old", old, "new", new, out)
256
261
        out.seek(0,0)
257
262
        return out.read()
329
334
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
330
335
 
331
336
    def sorted_ids(self, tree):
332
 
        ids = list(tree.all_file_ids())
333
 
        ids.sort()
 
337
        ids = sorted(tree.all_file_ids())
334
338
        return ids
335
339
 
336
340
    def test_iteration(self):
354
358
        serializer = BundleSerializerV08('0.8')
355
359
        b = self.make_branch('.', format=format)
356
360
        self.assertRaises(errors.IncompatibleBundleFormat, serializer.write,
357
 
                          b.repository, [], {}, StringIO())
 
361
                          b.repository, [], {}, BytesIO())
358
362
 
359
363
    def test_matched_bundle(self):
360
364
        """Don't raise IncompatibleBundleFormat for knit2 and bundle0.9"""
362
366
        format.repository_format = knitrepo.RepositoryFormatKnit3()
363
367
        serializer = BundleSerializerV09('0.9')
364
368
        b = self.make_branch('.', format=format)
365
 
        serializer.write(b.repository, [], {}, StringIO())
 
369
        serializer.write(b.repository, [], {}, BytesIO())
366
370
 
367
371
    def test_mismatched_model(self):
368
372
        """Try copying a bundle from knit2 to knit1"""
371
375
        source = self.make_branch_and_tree('source', format=format)
372
376
        source.commit('one', rev_id='one-id')
373
377
        source.commit('two', rev_id='two-id')
374
 
        text = StringIO()
 
378
        text = BytesIO()
375
379
        write_bundle(source.branch.repository, 'two-id', 'null:', text,
376
380
                     format='0.9')
377
381
        text.seek(0)
402
406
        return tests.TestCaseWithTransport.make_branch(self, path, format)
403
407
 
404
408
    def create_bundle_text(self, base_rev_id, rev_id):
405
 
        bundle_txt = StringIO()
 
409
        bundle_txt = BytesIO()
406
410
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id,
407
411
                               bundle_txt, format=self.format)
408
412
        bundle_txt.seek(0)
457
461
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
458
462
        new_text = bundle_txt.getvalue().replace('executable:no',
459
463
                                               'executable:yes')
460
 
        bundle_txt = StringIO(new_text)
 
464
        bundle_txt = BytesIO(new_text)
461
465
        bundle = read_bundle(bundle_txt)
462
466
        self.valid_apply_bundle(base_rev_id, bundle)
463
467
        return bundle
464
468
 
465
469
    def test_non_bundle(self):
466
470
        self.assertRaises(errors.NotABundle,
467
 
                          read_bundle, StringIO('#!/bin/sh\n'))
 
471
                          read_bundle, BytesIO(b'#!/bin/sh\n'))
468
472
 
469
473
    def test_malformed(self):
470
474
        self.assertRaises(errors.BadBundle, read_bundle,
471
 
                          StringIO('# Bazaar revision bundle v'))
 
475
                          BytesIO(b'# Bazaar revision bundle v'))
472
476
 
473
477
    def test_crlf_bundle(self):
474
478
        try:
475
 
            read_bundle(StringIO('# Bazaar revision bundle v0.8\r\n'))
 
479
            read_bundle(BytesIO(b'# Bazaar revision bundle v0.8\r\n'))
476
480
        except errors.BadBundle:
477
481
            # It is currently permitted for bundles with crlf line endings to
478
482
            # make read_bundle raise a BadBundle, but this should be fixed.
489
493
            if not os.path.exists(checkout_dir):
490
494
                os.mkdir(checkout_dir)
491
495
        tree = self.make_branch_and_tree(checkout_dir)
492
 
        s = StringIO()
 
496
        s = BytesIO()
493
497
        ancestors = write_bundle(self.b1.repository, rev_id, 'null:', s,
494
498
                                 format=self.format)
495
499
        s.seek(0)
828
832
        self.tree1.commit('modify', rev_id='a@cset-0-2')
829
833
        with open('b1/one', 'wb') as f: f.write('three\n')
830
834
        self.tree1.commit('modify', rev_id='a@cset-0-3')
831
 
        bundle_file = StringIO()
 
835
        bundle_file = BytesIO()
832
836
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
833
837
                               'a@cset-0-1', bundle_file, format=self.format)
834
838
        self.assertNotContainsRe(bundle_file.getvalue(), '\btwo\b')
839
843
        """Ensure using the basis as the target doesn't cause an error"""
840
844
        self.tree1 = self.make_branch_and_tree('b1')
841
845
        self.tree1.commit('add file', rev_id='a@cset-0-1')
842
 
        bundle_file = StringIO()
 
846
        bundle_file = BytesIO()
843
847
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-1',
844
848
                               'a@cset-0-1', bundle_file)
845
849
 
1214
1218
        txt = bundle_sio.getvalue()
1215
1219
        loc = txt.find('#   empty: ') + len('#   empty:')
1216
1220
        # Create a new bundle, which strips the trailing space after empty
1217
 
        bundle_sio = StringIO(txt[:loc] + txt[loc+1:])
 
1221
        bundle_sio = BytesIO(txt[:loc] + txt[loc+1:])
1218
1222
 
1219
1223
        self.assertContainsRe(bundle_sio.getvalue(),
1220
1224
                              '# properties:\n'
1335
1339
            self.assertEqual(len(branch_rev.parent_ids),
1336
1340
                             len(bundle_rev.parent_ids))
1337
1341
        self.assertEqual(set(rev_ids),
1338
 
                         set([r.revision_id for r in bundle.real_revisions]))
 
1342
                         {r.revision_id for r in bundle.real_revisions})
1339
1343
        self.valid_apply_bundle(base_rev_id, bundle,
1340
1344
                                   checkout_dir=checkout_dir)
1341
1345
 
1347
1351
 
1348
1352
        :return: The in-memory bundle
1349
1353
        """
1350
 
        from bzrlib.bundle import serializer
 
1354
        from ..bundle import serializer
1351
1355
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1352
 
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
 
1356
        new_text = self.get_raw(BytesIO(b''.join(bundle_txt)))
1353
1357
        new_text = new_text.replace('<file file_id="exe-1"',
1354
1358
                                    '<file executable="y" file_id="exe-1"')
1355
1359
        new_text = new_text.replace('B260', 'B275')
1356
 
        bundle_txt = StringIO()
 
1360
        bundle_txt = BytesIO()
1357
1361
        bundle_txt.write(serializer._get_bundle_header('4'))
1358
1362
        bundle_txt.write('\n')
1359
1363
        bundle_txt.write(new_text.encode('bz2'))
1363
1367
        return bundle
1364
1368
 
1365
1369
    def create_bundle_text(self, base_rev_id, rev_id):
1366
 
        bundle_txt = StringIO()
 
1370
        bundle_txt = BytesIO()
1367
1371
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id,
1368
1372
                               bundle_txt, format=self.format)
1369
1373
        bundle_txt.seek(0)
1386
1390
        tree.commit('added file', rev_id='rev1')
1387
1391
        self.build_tree_contents([('tree/file', 'contents2\nstatic\n')])
1388
1392
        tree.commit('changed file', rev_id='rev2')
1389
 
        s = StringIO()
 
1393
        s = BytesIO()
1390
1394
        serializer = BundleSerializerV4('1.0')
1391
1395
        serializer.write(tree.branch.repository, ['rev1', 'rev2'], {}, s)
1392
1396
        s.seek(0)
1422
1426
 
1423
1427
    def test_copy_signatures(self):
1424
1428
        tree_a = self.make_branch_and_tree('tree_a')
1425
 
        import bzrlib.gpg
1426
 
        import bzrlib.commit as commit
1427
 
        oldstrategy = bzrlib.gpg.GPGStrategy
 
1429
        import breezy.gpg
 
1430
        import breezy.commit as commit
 
1431
        oldstrategy = breezy.gpg.GPGStrategy
1428
1432
        branch = tree_a.branch
1429
1433
        repo_a = branch.repository
1430
1434
        tree_a.commit("base", allow_pointless=True, rev_id='A')
1431
1435
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
1432
1436
        try:
1433
 
            from bzrlib.testament import Testament
 
1437
            from ..testament import Testament
1434
1438
            # monkey patch gpg signing mechanism
1435
 
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
 
1439
            breezy.gpg.GPGStrategy = breezy.gpg.LoopbackGPGStrategy
1436
1440
            new_config = test_commit.MustSignConfig()
1437
1441
            commit.Commit(config_stack=new_config).commit(message="base",
1438
1442
                                                    allow_pointless=True,
1439
1443
                                                    rev_id='B',
1440
1444
                                                    working_tree=tree_a)
1441
1445
            def sign(text):
1442
 
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
 
1446
                return breezy.gpg.LoopbackGPGStrategy(None).sign(text)
1443
1447
            self.assertTrue(repo_a.has_signature_for_revision_id('B'))
1444
1448
        finally:
1445
 
            bzrlib.gpg.GPGStrategy = oldstrategy
 
1449
            breezy.gpg.GPGStrategy = oldstrategy
1446
1450
        tree_b = self.make_branch_and_tree('tree_b')
1447
1451
        repo_b = tree_b.branch.repository
1448
 
        s = StringIO()
 
1452
        s = BytesIO()
1449
1453
        serializer = BundleSerializerV4('4')
1450
1454
        serializer.write(tree_a.branch.repository, ['A', 'B'], {}, s)
1451
1455
        s.seek(0)
1469
1473
 
1470
1474
        :return: The in-memory bundle
1471
1475
        """
1472
 
        from bzrlib.bundle import serializer
 
1476
        from ..bundle import serializer
1473
1477
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1474
 
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
 
1478
        new_text = self.get_raw(BytesIO(b''.join(bundle_txt)))
1475
1479
        # We are going to be replacing some text to set the executable bit on a
1476
1480
        # file. Make sure the text replacement actually works correctly.
1477
1481
        self.assertContainsRe(new_text, '(?m)B244\n\ni 1\n<inventory')
1478
1482
        new_text = new_text.replace('<file file_id="exe-1"',
1479
1483
                                    '<file executable="y" file_id="exe-1"')
1480
1484
        new_text = new_text.replace('B244', 'B259')
1481
 
        bundle_txt = StringIO()
 
1485
        bundle_txt = BytesIO()
1482
1486
        bundle_txt.write(serializer._get_bundle_header('4'))
1483
1487
        bundle_txt.write('\n')
1484
1488
        bundle_txt.write(new_text.encode('bz2'))
1511
1515
    def make_bundle_just_inventories(self, base_revision_id,
1512
1516
                                     target_revision_id,
1513
1517
                                     revision_ids):
1514
 
        sio = StringIO()
 
1518
        sio = BytesIO()
1515
1519
        writer = v4.BundleWriteOperation(base_revision_id, target_revision_id,
1516
1520
                                         self.b1.repository, sio)
1517
1521
        writer.bundle.begin()
1665
1669
        wt.commit('add two', rev_id='a@cset-0-2',
1666
1670
                  revprops={'branch-nick':'test'})
1667
1671
 
1668
 
        bundle_txt = StringIO()
 
1672
        bundle_txt = BytesIO()
1669
1673
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
1670
1674
                               'a@cset-0-1', bundle_txt, self.format)
1671
 
        self.assertEqual(set(['a@cset-0-2']), set(rev_ids))
 
1675
        self.assertEqual({'a@cset-0-2'}, set(rev_ids))
1672
1676
        bundle_txt.seek(0, 0)
1673
1677
        return bundle_txt
1674
1678
 
1718
1722
        # creates a blank line at the end, and fails if that
1719
1723
        # line is stripped
1720
1724
        self.assertEqual('\n\n', raw[-2:])
1721
 
        bundle_txt = StringIO(raw[:-1])
 
1725
        bundle_txt = BytesIO(raw[:-1])
1722
1726
 
1723
1727
        bundle = read_bundle(bundle_txt)
1724
1728
        self.check_valid(bundle)
1726
1730
    def test_opening_text(self):
1727
1731
        bundle_txt = self.build_test_bundle()
1728
1732
 
1729
 
        bundle_txt = StringIO("Some random\nemail comments\n"
1730
 
                              + bundle_txt.getvalue())
 
1733
        bundle_txt = BytesIO(
 
1734
            b"Some random\nemail comments\n" + bundle_txt.getvalue())
1731
1735
 
1732
1736
        bundle = read_bundle(bundle_txt)
1733
1737
        self.check_valid(bundle)
1735
1739
    def test_trailing_text(self):
1736
1740
        bundle_txt = self.build_test_bundle()
1737
1741
 
1738
 
        bundle_txt = StringIO(bundle_txt.getvalue() +
1739
 
                              "Some trailing\nrandom\ntext\n")
 
1742
        bundle_txt = BytesIO(
 
1743
            bundle_txt.getvalue() + b"Some trailing\nrandom\ntext\n")
1740
1744
 
1741
1745
        bundle = read_bundle(bundle_txt)
1742
1746
        self.check_valid(bundle)
1750
1754
class TestBundleWriterReader(tests.TestCase):
1751
1755
 
1752
1756
    def test_roundtrip_record(self):
1753
 
        fileobj = StringIO()
 
1757
        fileobj = BytesIO()
1754
1758
        writer = v4.BundleWriter(fileobj)
1755
1759
        writer.begin()
1756
1760
        writer.add_info_record(foo='bar')
1769
1773
                          record)
1770
1774
 
1771
1775
    def test_roundtrip_record_memory_hungry(self):
1772
 
        fileobj = StringIO()
 
1776
        fileobj = BytesIO()
1773
1777
        writer = v4.BundleWriter(fileobj)
1774
1778
        writer.begin()
1775
1779
        writer.add_info_record(foo='bar')
1804
1808
                         v4.BundleReader.decode_name('info'))
1805
1809
 
1806
1810
    def test_too_many_names(self):
1807
 
        fileobj = StringIO()
 
1811
        fileobj = BytesIO()
1808
1812
        writer = v4.BundleWriter(fileobj)
1809
1813
        writer.begin()
1810
1814
        writer.add_info_record(foo='bar')
1838
1842
    def test_infinite_redirects_are_not_a_bundle(self):
1839
1843
        """If a URL causes TooManyRedirections then NotABundle is raised.
1840
1844
        """
1841
 
        from bzrlib.tests.blackbox.test_push import RedirectingMemoryServer
 
1845
        from .blackbox.test_push import RedirectingMemoryServer
1842
1846
        server = RedirectingMemoryServer()
1843
1847
        self.start_server(server)
1844
1848
        url = server.get_url() + 'infinite-loop'
1857
1861
        self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url)
1858
1862
 
1859
1863
 
1860
 
class DisconnectingHandler(SocketServer.BaseRequestHandler):
 
1864
class DisconnectingHandler(socketserver.BaseRequestHandler):
1861
1865
    """A request handler that immediately closes any connection made to it."""
1862
1866
 
1863
1867
    def handle(self):