~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bundle.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2013, 2016 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 socket
 
19
import SocketServer
20
20
import sys
21
 
import threading
22
21
 
23
22
from bzrlib import (
24
23
    bzrdir,
28
27
    merge,
29
28
    osutils,
30
29
    revision as _mod_revision,
31
 
    symbol_versioning,
32
30
    tests,
33
31
    treebuilder,
34
32
    )
42
40
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
43
41
from bzrlib.repofmt import knitrepo
44
42
from bzrlib.tests import (
 
43
    features,
 
44
    test_commit,
45
45
    test_read_bundle,
46
 
    test_commit,
 
46
    test_server,
47
47
    )
48
48
from bzrlib.transform import TreeTransform
49
49
 
75
75
        self.root = InventoryDirectory(ROOT_ID, '', None)
76
76
 
77
77
    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
78
82
 
79
83
    def all_file_ids(self):
80
84
        return set(self.paths.keys())
81
85
 
 
86
    def is_executable(self, file_id):
 
87
        # Not all the files are executable.
 
88
        return False
 
89
 
82
90
    def __getitem__(self, file_id):
83
91
        if file_id == self.root.file_id:
84
92
            return self.root
95
103
        for path, file_id in self.ids.iteritems():
96
104
            yield path, self[file_id]
97
105
 
98
 
    def get_file_kind(self, file_id):
 
106
    def kind(self, file_id):
99
107
        if file_id in self.contents:
100
108
            kind = 'file'
101
109
        else:
103
111
        return kind
104
112
 
105
113
    def make_entry(self, file_id, path):
106
 
        from bzrlib.inventory import (InventoryEntry, InventoryFile
107
 
                                    , InventoryDirectory, InventoryLink)
 
114
        from bzrlib.inventory import (InventoryFile , InventoryDirectory,
 
115
            InventoryLink)
108
116
        name = os.path.basename(path)
109
 
        kind = self.get_file_kind(file_id)
 
117
        kind = self.kind(file_id)
110
118
        parent_id = self.parent_id(file_id)
111
119
        text_sha_1, text_size = self.contents_stats(file_id)
112
120
        if kind == 'directory':
147
155
    def get_file_revision(self, file_id):
148
156
        return self.inventory[file_id].revision
149
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
 
150
164
    def contents_stats(self, file_id):
151
165
        if file_id not in self.contents:
152
166
            return None, None
315
329
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
316
330
 
317
331
    def sorted_ids(self, tree):
318
 
        ids = list(tree)
 
332
        ids = list(tree.all_file_ids())
319
333
        ids.sort()
320
334
        return ids
321
335
 
507
521
                new.unlock()
508
522
                old.unlock()
509
523
        if not _mod_revision.is_null(rev_id):
510
 
            rh = self.b1.revision_history()
511
 
            self.applyDeprecated(symbol_versioning.deprecated_in((2, 4, 0)),
512
 
                tree.branch.set_revision_history, rh[:rh.index(rev_id)+1])
 
524
            tree.branch.generate_revision_history(rev_id)
513
525
            tree.update()
514
526
            delta = tree.changes_from(self.b1.repository.revision_tree(rev_id))
515
527
            self.assertFalse(delta.has_changed(),
533
545
        original_parents = to_tree.get_parent_ids()
534
546
        self.assertIs(repository.has_revision(base_rev_id), True)
535
547
        for rev in info.real_revisions:
536
 
            self.assert_(not repository.has_revision(rev.revision_id),
537
 
                'Revision {%s} present before applying bundle'
538
 
                % rev.revision_id)
 
548
            self.assertTrue(not repository.has_revision(rev.revision_id),
 
549
                            'Revision {%s} present before applying bundle'
 
550
                            % rev.revision_id)
539
551
        merge_bundle(info, to_tree, True, merge.Merge3Merger, False, False)
540
552
 
541
553
        for rev in info.real_revisions:
542
 
            self.assert_(repository.has_revision(rev.revision_id),
543
 
                'Missing revision {%s} after applying bundle'
544
 
                % rev.revision_id)
 
554
            self.assertTrue(repository.has_revision(rev.revision_id),
 
555
                            'Missing revision {%s} after applying bundle'
 
556
                            % rev.revision_id)
545
557
 
546
 
        self.assert_(to_tree.branch.repository.has_revision(info.target))
 
558
        self.assertTrue(to_tree.branch.repository.has_revision(info.target))
547
559
        # Do we also want to verify that all the texts have been added?
548
560
 
549
561
        self.assertEqual(original_parents + [info.target],
550
 
            to_tree.get_parent_ids())
 
562
                         to_tree.get_parent_ids())
551
563
 
552
564
        rev = info.real_revisions[-1]
553
565
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
651
663
        bundle = self.get_valid_bundle('null:', 'a@cset-0-4')
652
664
 
653
665
        # Modified files
654
 
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
655
 
        open('b1/sub/dir/ pre space', 'ab').write(
 
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(
656
668
             '\r\nAdding some\r\nDOS format lines\r\n')
657
 
        open('b1/sub/dir/nolastnewline.txt', 'ab').write('\n')
 
669
        with open('b1/sub/dir/nolastnewline.txt', 'ab') as f: f.write('\n')
658
670
        self.tree1.rename_one('sub/dir/ pre space',
659
671
                              'sub/ start space')
660
672
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
682
694
    def _test_symlink_bundle(self, link_name, link_target, new_link_target):
683
695
        link_id = 'link-1'
684
696
 
685
 
        self.requireFeature(tests.SymlinkFeature)
 
697
        self.requireFeature(features.SymlinkFeature)
686
698
        self.tree1 = self.make_branch_and_tree('b1')
687
699
        self.b1 = self.tree1.branch
688
700
 
729
741
        self._test_symlink_bundle('link', 'bar/foo', 'mars')
730
742
 
731
743
    def test_unicode_symlink_bundle(self):
732
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
744
        self.requireFeature(features.UnicodeFilenameFeature)
733
745
        self._test_symlink_bundle(u'\N{Euro Sign}link',
734
746
                                  u'bar/\N{Euro Sign}foo',
735
747
                                  u'mars\N{Euro Sign}')
809
821
        self.tree1 = self.make_branch_and_tree('b1')
810
822
        self.b1 = self.tree1.branch
811
823
 
812
 
        open('b1/one', 'wb').write('one\n')
 
824
        with open('b1/one', 'wb') as f: f.write('one\n')
813
825
        self.tree1.add('one')
814
826
        self.tree1.commit('add file', rev_id='a@cset-0-1')
815
 
        open('b1/one', 'wb').write('two\n')
 
827
        with open('b1/one', 'wb') as f: f.write('two\n')
816
828
        self.tree1.commit('modify', rev_id='a@cset-0-2')
817
 
        open('b1/one', 'wb').write('three\n')
 
829
        with open('b1/one', 'wb') as f: f.write('three\n')
818
830
        self.tree1.commit('modify', rev_id='a@cset-0-3')
819
831
        bundle_file = StringIO()
820
832
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
836
848
        return bundle_file.getvalue()
837
849
 
838
850
    def test_unicode_bundle(self):
839
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
851
        self.requireFeature(features.UnicodeFilenameFeature)
840
852
        # Handle international characters
841
853
        os.mkdir('b1')
842
854
        f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
899
911
        bundle = self.get_valid_bundle('null:', 'white-1')
900
912
 
901
913
        # Modified
902
 
        open('b1/trailing space ', 'ab').write('add some text\n')
 
914
        with open('b1/trailing space ', 'ab') as f: f.write('add some text\n')
903
915
        self.tree1.commit('add text', rev_id='white-2')
904
916
 
905
917
        bundle = self.get_valid_bundle('white-1', 'white-2')
947
959
        self.tree1.commit('message', rev_id='revid1')
948
960
        bundle = self.get_valid_bundle('null:', 'revid1')
949
961
        tree = self.get_bundle_tree(bundle, 'revid1')
950
 
        self.assertEqual('revid1', tree.inventory.root.revision)
 
962
        root_revision = tree.get_file_revision(tree.get_root_id())
 
963
        self.assertEqual('revid1', root_revision)
951
964
 
952
965
    def test_install_revisions(self):
953
966
        self.tree1 = self.make_branch_and_tree('b1')
1420
1433
            from bzrlib.testament import Testament
1421
1434
            # monkey patch gpg signing mechanism
1422
1435
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
1423
 
            new_config = test_commit.MustSignConfig(branch)
1424
 
            commit.Commit(config=new_config).commit(message="base",
 
1436
            new_config = test_commit.MustSignConfig()
 
1437
            commit.Commit(config_stack=new_config).commit(message="base",
1425
1438
                                                    allow_pointless=True,
1426
1439
                                                    rev_id='B',
1427
1440
                                                    working_tree=tree_a)
1836
1849
        bundle, then the ConnectionReset error should be propagated.
1837
1850
        """
1838
1851
        # Instantiate a server that will provoke a ConnectionReset
1839
 
        sock_server = _DisconnectingTCPServer()
 
1852
        sock_server = DisconnectingServer()
1840
1853
        self.start_server(sock_server)
1841
1854
        # We don't really care what the url is since the server will close the
1842
1855
        # connection without interpreting it
1844
1857
        self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url)
1845
1858
 
1846
1859
 
1847
 
class _DisconnectingTCPServer(object):
1848
 
    """A TCP server that immediately closes any connection made to it."""
1849
 
 
1850
 
    def start_server(self):
1851
 
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1852
 
        self.sock.bind(('127.0.0.1', 0))
1853
 
        self.sock.listen(1)
1854
 
        self.port = self.sock.getsockname()[1]
1855
 
        self.thread = threading.Thread(
1856
 
            name='%s (port %d)' % (self.__class__.__name__, self.port),
1857
 
            target=self.accept_and_close)
1858
 
        self.thread.start()
1859
 
 
1860
 
    def accept_and_close(self):
1861
 
        conn, addr = self.sock.accept()
1862
 
        conn.shutdown(socket.SHUT_RDWR)
1863
 
        conn.close()
 
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)
1864
1874
 
1865
1875
    def get_url(self):
1866
 
        return 'bzr://127.0.0.1:%d/' % (self.port,)
1867
 
 
1868
 
    def stop_server(self):
1869
 
        try:
1870
 
            # make sure the thread dies by connecting to the listening socket,
1871
 
            # just in case the test failed to do so.
1872
 
            conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1873
 
            conn.connect(self.sock.getsockname())
1874
 
            conn.close()
1875
 
        except socket.error:
1876
 
            pass
1877
 
        self.sock.close()
1878
 
        self.thread.join()
 
1876
        """Return the url of the server"""
 
1877
        return "bzr://%s:%d/" % self.server.server_address