~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bundle.py

  • Committer: Ian Clatworthy
  • Date: 2009-09-09 15:30:59 UTC
  • mto: (4634.37.2 prepare-2.0)
  • mto: This revision was merged to the branch mainline in revision 4689.
  • Revision ID: ian.clatworthy@canonical.com-20090909153059-sb038agvd38ci2q8
more link fixes in the User Guide

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2013, 2016 Canonical Ltd
 
1
# Copyright (C) 2004, 2005, 2006, 2007 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
16
16
 
17
17
from cStringIO import StringIO
18
18
import os
19
 
import SocketServer
 
19
import socket
20
20
import sys
 
21
import threading
21
22
 
22
23
from bzrlib import (
23
24
    bzrdir,
26
27
    inventory,
27
28
    merge,
28
29
    osutils,
 
30
    repository,
29
31
    revision as _mod_revision,
30
32
    tests,
31
33
    treebuilder,
33
35
from bzrlib.bundle import read_mergeable_from_url
34
36
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
35
37
from bzrlib.bundle.bundle_data import BundleTree
 
38
from bzrlib.bzrdir import BzrDir
36
39
from bzrlib.directory_service import directories
37
40
from bzrlib.bundle.serializer import write_bundle, read_bundle, v09, v4
38
41
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
39
42
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
40
43
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
 
44
from bzrlib.branch import Branch
41
45
from bzrlib.repofmt import knitrepo
42
46
from bzrlib.tests import (
43
 
    features,
 
47
    test_read_bundle,
44
48
    test_commit,
45
 
    test_read_bundle,
46
 
    test_server,
47
49
    )
48
50
from bzrlib.transform import TreeTransform
49
51
 
65
67
 
66
68
 
67
69
class MockTree(object):
68
 
 
69
70
    def __init__(self):
70
71
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
71
72
        object.__init__(self)
75
76
        self.root = InventoryDirectory(ROOT_ID, '', None)
76
77
 
77
78
    inventory = property(lambda x:x)
78
 
    root_inventory = property(lambda x:x)
79
 
 
80
 
    def get_root_id(self):
81
 
        return self.root.file_id
82
 
 
83
 
    def all_file_ids(self):
84
 
        return set(self.paths.keys())
85
 
 
86
 
    def is_executable(self, file_id):
87
 
        # Not all the files are executable.
88
 
        return False
 
79
 
 
80
    def __iter__(self):
 
81
        return self.paths.iterkeys()
89
82
 
90
83
    def __getitem__(self, file_id):
91
84
        if file_id == self.root.file_id:
103
96
        for path, file_id in self.ids.iteritems():
104
97
            yield path, self[file_id]
105
98
 
106
 
    def kind(self, file_id):
 
99
    def get_file_kind(self, file_id):
107
100
        if file_id in self.contents:
108
101
            kind = 'file'
109
102
        else:
111
104
        return kind
112
105
 
113
106
    def make_entry(self, file_id, path):
114
 
        from bzrlib.inventory import (InventoryFile , InventoryDirectory,
115
 
            InventoryLink)
 
107
        from bzrlib.inventory import (InventoryEntry, InventoryFile
 
108
                                    , InventoryDirectory, InventoryLink)
116
109
        name = os.path.basename(path)
117
 
        kind = self.kind(file_id)
 
110
        kind = self.get_file_kind(file_id)
118
111
        parent_id = self.parent_id(file_id)
119
112
        text_sha_1, text_size = self.contents_stats(file_id)
120
113
        if kind == 'directory':
121
114
            ie = InventoryDirectory(file_id, name, parent_id)
122
115
        elif kind == 'file':
123
116
            ie = InventoryFile(file_id, name, parent_id)
124
 
            ie.text_sha1 = text_sha_1
125
 
            ie.text_size = text_size
126
117
        elif kind == 'symlink':
127
118
            ie = InventoryLink(file_id, name, parent_id)
128
119
        else:
129
120
            raise errors.BzrError('unknown kind %r' % kind)
 
121
        ie.text_sha1 = text_sha_1
 
122
        ie.text_size = text_size
130
123
        return ie
131
124
 
132
125
    def add_dir(self, file_id, path):
152
145
        result.seek(0,0)
153
146
        return result
154
147
 
155
 
    def get_file_revision(self, file_id):
156
 
        return self.inventory[file_id].revision
157
 
 
158
 
    def get_file_size(self, file_id):
159
 
        return self.inventory[file_id].text_size
160
 
 
161
 
    def get_file_sha1(self, file_id):
162
 
        return self.inventory[file_id].text_sha1
163
 
 
164
148
    def contents_stats(self, file_id):
165
149
        if file_id not in self.contents:
166
150
            return None, None
329
313
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
330
314
 
331
315
    def sorted_ids(self, tree):
332
 
        ids = list(tree.all_file_ids())
 
316
        ids = list(tree)
333
317
        ids.sort()
334
318
        return ids
335
319
 
508
492
                                 % (ancestor,))
509
493
 
510
494
                # Now check that the file contents are all correct
511
 
                for inventory_id in old.all_file_ids():
 
495
                for inventory_id in old:
512
496
                    try:
513
497
                        old_file = old.get_file(inventory_id)
514
498
                    except errors.NoSuchFile:
521
505
                new.unlock()
522
506
                old.unlock()
523
507
        if not _mod_revision.is_null(rev_id):
524
 
            tree.branch.generate_revision_history(rev_id)
 
508
            rh = self.b1.revision_history()
 
509
            tree.branch.set_revision_history(rh[:rh.index(rev_id)+1])
525
510
            tree.update()
526
511
            delta = tree.changes_from(self.b1.repository.revision_tree(rev_id))
527
512
            self.assertFalse(delta.has_changed(),
545
530
        original_parents = to_tree.get_parent_ids()
546
531
        self.assertIs(repository.has_revision(base_rev_id), True)
547
532
        for rev in info.real_revisions:
548
 
            self.assertTrue(not repository.has_revision(rev.revision_id),
549
 
                            'Revision {%s} present before applying bundle'
550
 
                            % rev.revision_id)
 
533
            self.assert_(not repository.has_revision(rev.revision_id),
 
534
                'Revision {%s} present before applying bundle'
 
535
                % rev.revision_id)
551
536
        merge_bundle(info, to_tree, True, merge.Merge3Merger, False, False)
552
537
 
553
538
        for rev in info.real_revisions:
554
 
            self.assertTrue(repository.has_revision(rev.revision_id),
555
 
                            'Missing revision {%s} after applying bundle'
556
 
                            % rev.revision_id)
 
539
            self.assert_(repository.has_revision(rev.revision_id),
 
540
                'Missing revision {%s} after applying bundle'
 
541
                % rev.revision_id)
557
542
 
558
 
        self.assertTrue(to_tree.branch.repository.has_revision(info.target))
 
543
        self.assert_(to_tree.branch.repository.has_revision(info.target))
559
544
        # Do we also want to verify that all the texts have been added?
560
545
 
561
546
        self.assertEqual(original_parents + [info.target],
562
 
                         to_tree.get_parent_ids())
 
547
            to_tree.get_parent_ids())
563
548
 
564
549
        rev = info.real_revisions[-1]
565
550
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
663
648
        bundle = self.get_valid_bundle('null:', 'a@cset-0-4')
664
649
 
665
650
        # Modified files
666
 
        with open('b1/sub/dir/WithCaps.txt', 'ab') as f: f.write('\nAdding some text\n')
667
 
        with open('b1/sub/dir/ pre space', 'ab') as f: f.write(
 
651
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
 
652
        open('b1/sub/dir/ pre space', 'ab').write(
668
653
             '\r\nAdding some\r\nDOS format lines\r\n')
669
 
        with open('b1/sub/dir/nolastnewline.txt', 'ab') as f: f.write('\n')
 
654
        open('b1/sub/dir/nolastnewline.txt', 'ab').write('\n')
670
655
        self.tree1.rename_one('sub/dir/ pre space',
671
656
                              'sub/ start space')
672
657
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
694
679
    def _test_symlink_bundle(self, link_name, link_target, new_link_target):
695
680
        link_id = 'link-1'
696
681
 
697
 
        self.requireFeature(features.SymlinkFeature)
 
682
        self.requireFeature(tests.SymlinkFeature)
698
683
        self.tree1 = self.make_branch_and_tree('b1')
699
684
        self.b1 = self.tree1.branch
700
685
 
741
726
        self._test_symlink_bundle('link', 'bar/foo', 'mars')
742
727
 
743
728
    def test_unicode_symlink_bundle(self):
744
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
729
        self.requireFeature(tests.UnicodeFilenameFeature)
745
730
        self._test_symlink_bundle(u'\N{Euro Sign}link',
746
731
                                  u'bar/\N{Euro Sign}foo',
747
732
                                  u'mars\N{Euro Sign}')
821
806
        self.tree1 = self.make_branch_and_tree('b1')
822
807
        self.b1 = self.tree1.branch
823
808
 
824
 
        with open('b1/one', 'wb') as f: f.write('one\n')
 
809
        open('b1/one', 'wb').write('one\n')
825
810
        self.tree1.add('one')
826
811
        self.tree1.commit('add file', rev_id='a@cset-0-1')
827
 
        with open('b1/one', 'wb') as f: f.write('two\n')
 
812
        open('b1/one', 'wb').write('two\n')
828
813
        self.tree1.commit('modify', rev_id='a@cset-0-2')
829
 
        with open('b1/one', 'wb') as f: f.write('three\n')
 
814
        open('b1/one', 'wb').write('three\n')
830
815
        self.tree1.commit('modify', rev_id='a@cset-0-3')
831
816
        bundle_file = StringIO()
832
817
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
848
833
        return bundle_file.getvalue()
849
834
 
850
835
    def test_unicode_bundle(self):
851
 
        self.requireFeature(features.UnicodeFilenameFeature)
 
836
        self.requireFeature(tests.UnicodeFilenameFeature)
852
837
        # Handle international characters
853
838
        os.mkdir('b1')
854
839
        f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
911
896
        bundle = self.get_valid_bundle('null:', 'white-1')
912
897
 
913
898
        # Modified
914
 
        with open('b1/trailing space ', 'ab') as f: f.write('add some text\n')
 
899
        open('b1/trailing space ', 'ab').write('add some text\n')
915
900
        self.tree1.commit('add text', rev_id='white-2')
916
901
 
917
902
        bundle = self.get_valid_bundle('white-1', 'white-2')
959
944
        self.tree1.commit('message', rev_id='revid1')
960
945
        bundle = self.get_valid_bundle('null:', 'revid1')
961
946
        tree = self.get_bundle_tree(bundle, 'revid1')
962
 
        root_revision = tree.get_file_revision(tree.get_root_id())
963
 
        self.assertEqual('revid1', root_revision)
 
947
        self.assertEqual('revid1', tree.inventory.root.revision)
964
948
 
965
949
    def test_install_revisions(self):
966
950
        self.tree1 = self.make_branch_and_tree('b1')
1055
1039
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1056
1040
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1057
1041
        bundle.install_revisions(repo)
1058
 
        inv_text = repo._get_inventory_xml('rev2')
 
1042
        inv_text = repo.get_inventory_xml('rev2')
1059
1043
        self.assertNotContainsRe(inv_text, 'format="5"')
1060
1044
        self.assertContainsRe(inv_text, 'format="7"')
1061
1045
 
1081
1065
 
1082
1066
    def test_inv_hash_across_serializers(self):
1083
1067
        repo = self.make_repo_with_installed_revisions()
1084
 
        recorded_inv_sha1 = repo.get_revision('rev2').inventory_sha1
1085
 
        xml = repo._get_inventory_xml('rev2')
 
1068
        recorded_inv_sha1 = repo.get_inventory_sha1('rev2')
 
1069
        xml = repo.get_inventory_xml('rev2')
1086
1070
        self.assertEqual(osutils.sha_string(xml), recorded_inv_sha1)
1087
1071
 
1088
1072
    def test_across_models_incompatible(self):
1428
1412
        branch = tree_a.branch
1429
1413
        repo_a = branch.repository
1430
1414
        tree_a.commit("base", allow_pointless=True, rev_id='A')
1431
 
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
 
1415
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
1432
1416
        try:
1433
1417
            from bzrlib.testament import Testament
1434
1418
            # monkey patch gpg signing mechanism
1435
1419
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
1436
 
            new_config = test_commit.MustSignConfig()
1437
 
            commit.Commit(config_stack=new_config).commit(message="base",
 
1420
            new_config = test_commit.MustSignConfig(branch)
 
1421
            commit.Commit(config=new_config).commit(message="base",
1438
1422
                                                    allow_pointless=True,
1439
1423
                                                    rev_id='B',
1440
1424
                                                    working_tree=tree_a)
1458
1442
        install_bundle(repo_b, serializer.read(s))
1459
1443
 
1460
1444
 
 
1445
class V4WeaveBundleTester(V4BundleTester):
 
1446
 
 
1447
    def bzrdir_format(self):
 
1448
        return 'metaweave'
 
1449
 
 
1450
 
1461
1451
class V4_2aBundleTester(V4BundleTester):
1462
1452
 
1463
1453
    def bzrdir_format(self):
1830
1820
            def look_up(self, name, url):
1831
1821
                return 'source'
1832
1822
        directories.register('foo:', FooService, 'Testing directory service')
1833
 
        self.addCleanup(directories.remove, 'foo:')
 
1823
        self.addCleanup(lambda: directories.remove('foo:'))
1834
1824
        self.build_tree_contents([('./foo:bar', out.getvalue())])
1835
1825
        self.assertRaises(errors.NotABundle, read_mergeable_from_url,
1836
1826
                          'foo:bar')
1840
1830
        """
1841
1831
        from bzrlib.tests.blackbox.test_push import RedirectingMemoryServer
1842
1832
        server = RedirectingMemoryServer()
1843
 
        self.start_server(server)
 
1833
        server.setUp()
1844
1834
        url = server.get_url() + 'infinite-loop'
 
1835
        self.addCleanup(server.tearDown)
1845
1836
        self.assertRaises(errors.NotABundle, read_mergeable_from_url, url)
1846
1837
 
1847
1838
    def test_smart_server_connection_reset(self):
1849
1840
        bundle, then the ConnectionReset error should be propagated.
1850
1841
        """
1851
1842
        # Instantiate a server that will provoke a ConnectionReset
1852
 
        sock_server = DisconnectingServer()
1853
 
        self.start_server(sock_server)
 
1843
        sock_server = _DisconnectingTCPServer()
 
1844
        sock_server.setUp()
 
1845
        self.addCleanup(sock_server.tearDown)
1854
1846
        # We don't really care what the url is since the server will close the
1855
1847
        # connection without interpreting it
1856
1848
        url = sock_server.get_url()
1857
1849
        self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url)
1858
1850
 
1859
1851
 
1860
 
class DisconnectingHandler(SocketServer.BaseRequestHandler):
1861
 
    """A request handler that immediately closes any connection made to it."""
1862
 
 
1863
 
    def handle(self):
1864
 
        self.request.close()
1865
 
 
1866
 
 
1867
 
class DisconnectingServer(test_server.TestingTCPServerInAThread):
1868
 
 
1869
 
    def __init__(self):
1870
 
        super(DisconnectingServer, self).__init__(
1871
 
            ('127.0.0.1', 0),
1872
 
            test_server.TestingTCPServer,
1873
 
            DisconnectingHandler)
 
1852
class _DisconnectingTCPServer(object):
 
1853
    """A TCP server that immediately closes any connection made to it."""
 
1854
 
 
1855
    def setUp(self):
 
1856
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
1857
        self.sock.bind(('127.0.0.1', 0))
 
1858
        self.sock.listen(1)
 
1859
        self.port = self.sock.getsockname()[1]
 
1860
        self.thread = threading.Thread(
 
1861
            name='%s (port %d)' % (self.__class__.__name__, self.port),
 
1862
            target=self.accept_and_close)
 
1863
        self.thread.start()
 
1864
 
 
1865
    def accept_and_close(self):
 
1866
        conn, addr = self.sock.accept()
 
1867
        conn.shutdown(socket.SHUT_RDWR)
 
1868
        conn.close()
1874
1869
 
1875
1870
    def get_url(self):
1876
 
        """Return the url of the server"""
1877
 
        return "bzr://%s:%d/" % self.server.server_address
 
1871
        return 'bzr://127.0.0.1:%d/' % (self.port,)
 
1872
 
 
1873
    def tearDown(self):
 
1874
        try:
 
1875
            # make sure the thread dies by connecting to the listening socket,
 
1876
            # just in case the test failed to do so.
 
1877
            conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
1878
            conn.connect(self.sock.getsockname())
 
1879
            conn.close()
 
1880
        except socket.error:
 
1881
            pass
 
1882
        self.sock.close()
 
1883
        self.thread.join()
 
1884