~bzr-pqm/bzr/bzr.dev

5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2005-2011 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
16
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
17
from cStringIO import StringIO
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
18
import os
6206.1.9 by Vincent Ladeuil
Simpler fix for test_smart_server_connection_reset re-using more of the existing test server infrastructure.
19
import SocketServer
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
20
import sys
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
21
1910.2.64 by Aaron Bentley
Changes from review
22
from bzrlib import (
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
23
    bzrdir,
4241.14.13 by Vincent Ladeuil
Some more cleanup.
24
    diff,
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
25
    errors,
26
    inventory,
4241.14.13 by Vincent Ladeuil
Some more cleanup.
27
    merge,
3638.3.2 by Vincent Ladeuil
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.
28
    osutils,
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
29
    revision as _mod_revision,
4241.14.13 by Vincent Ladeuil
Some more cleanup.
30
    tests,
1910.2.64 by Aaron Bentley
Changes from review
31
    treebuilder,
32
    )
3251.4.11 by Aaron Bentley
Fix wrong local lookups
33
from bzrlib.bundle import read_mergeable_from_url
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
34
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
1793.2.3 by Aaron Bentley
Rename read_bundle.py to bundle_data.py
35
from bzrlib.bundle.bundle_data import BundleTree
3251.4.11 by Aaron Bentley
Fix wrong local lookups
36
from bzrlib.directory_service import directories
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
37
from bzrlib.bundle.serializer import write_bundle, read_bundle, v09, v4
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
38
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
39
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
2520.4.72 by Aaron Bentley
Rename format to 4alpha
40
from bzrlib.bundle.serializer.v4 import BundleSerializerV4
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
41
from bzrlib.repofmt import knitrepo
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
42
from bzrlib.tests import (
6206.1.9 by Vincent Ladeuil
Simpler fix for test_smart_server_connection_reset re-using more of the existing test server infrastructure.
43
    features,
44
    test_commit,
3251.4.11 by Aaron Bentley
Fix wrong local lookups
45
    test_read_bundle,
6206.1.9 by Vincent Ladeuil
Simpler fix for test_smart_server_connection_reset re-using more of the existing test server infrastructure.
46
    test_server,
2949.5.1 by Alexander Belchenko
selftest: use SymlinkFeature instead of TestSkipped where appropriate
47
    )
1185.82.66 by Aaron Bentley
Handle new executable files
48
from bzrlib.transform import TreeTransform
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
49
1185.82.90 by Aaron Bentley
Reorganized test suite
50
4543.2.9 by John Arbash Meinel
Down to 2 failing tests.
51
def get_text(vf, key):
52
    """Get the fulltext for a given revision id that is present in the vf"""
53
    stream = vf.get_record_stream([key], 'unordered', True)
54
    record = stream.next()
55
    return record.get_bytes_as('fulltext')
56
57
58
def get_inventory_text(repo, revision_id):
59
    """Get the fulltext for the inventory at revision id"""
60
    repo.lock_read()
61
    try:
62
        return get_text(repo.inventories, (revision_id,))
63
    finally:
64
        repo.unlock()
65
66
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
67
class MockTree(object):
5837.2.5 by Jelmer Vernooij
Fix two warnings.
68
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
69
    def __init__(self):
1731.1.4 by Aaron Bentley
merge from bzr.dev
70
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
71
        object.__init__(self)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
72
        self.paths = {ROOT_ID: ""}
73
        self.ids = {"": ROOT_ID}
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
74
        self.contents = {}
1731.1.4 by Aaron Bentley
merge from bzr.dev
75
        self.root = InventoryDirectory(ROOT_ID, '', None)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
76
77
    inventory = property(lambda x:x)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
78
5837.2.5 by Jelmer Vernooij
Fix two warnings.
79
    def all_file_ids(self):
80
        return set(self.paths.keys())
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
81
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
82
    def __getitem__(self, file_id):
83
        if file_id == self.root.file_id:
84
            return self.root
85
        else:
86
            return self.make_entry(file_id, self.paths[file_id])
87
88
    def parent_id(self, file_id):
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
89
        parent_dir = os.path.dirname(self.paths[file_id])
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
90
        if parent_dir == "":
91
            return None
92
        return self.ids[parent_dir]
93
94
    def iter_entries(self):
95
        for path, file_id in self.ids.iteritems():
96
            yield path, self[file_id]
97
98
    def get_file_kind(self, file_id):
99
        if file_id in self.contents:
100
            kind = 'file'
101
        else:
102
            kind = 'directory'
103
        return kind
104
105
    def make_entry(self, file_id, path):
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
106
        from bzrlib.inventory import (InventoryEntry, InventoryFile
107
                                    , InventoryDirectory, InventoryLink)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
108
        name = os.path.basename(path)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
109
        kind = self.get_file_kind(file_id)
110
        parent_id = self.parent_id(file_id)
111
        text_sha_1, text_size = self.contents_stats(file_id)
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
112
        if kind == 'directory':
113
            ie = InventoryDirectory(file_id, name, parent_id)
114
        elif kind == 'file':
115
            ie = InventoryFile(file_id, name, parent_id)
5365.2.2 by Andrew Bennetts
Fix test failures for bundles and upgrades.
116
            ie.text_sha1 = text_sha_1
117
            ie.text_size = text_size
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
118
        elif kind == 'symlink':
119
            ie = InventoryLink(file_id, name, parent_id)
120
        else:
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
121
            raise errors.BzrError('unknown kind %r' % kind)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
122
        return ie
123
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
124
    def add_dir(self, file_id, path):
125
        self.paths[file_id] = path
126
        self.ids[path] = file_id
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
127
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
128
    def add_file(self, file_id, path, contents):
129
        self.add_dir(file_id, path)
130
        self.contents[file_id] = contents
131
132
    def path2id(self, path):
133
        return self.ids.get(path)
134
135
    def id2path(self, file_id):
136
        return self.paths.get(file_id)
137
138
    def has_id(self, file_id):
139
        return self.id2path(file_id) is not None
140
141
    def get_file(self, file_id):
142
        result = StringIO()
143
        result.write(self.contents[file_id])
144
        result.seek(0,0)
145
        return result
146
5793.2.6 by Jelmer Vernooij
Add MockTree.get_file_revision.
147
    def get_file_revision(self, file_id):
148
        return self.inventory[file_id].revision
149
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
150
    def contents_stats(self, file_id):
151
        if file_id not in self.contents:
152
            return None, None
4241.14.13 by Vincent Ladeuil
Some more cleanup.
153
        text_sha1 = osutils.sha_file(self.get_file(file_id))
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
154
        return text_sha1, len(self.contents[file_id])
155
156
4241.14.13 by Vincent Ladeuil
Some more cleanup.
157
class BTreeTester(tests.TestCase):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
158
    """A simple unittest tester for the BundleTree class."""
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
159
160
    def make_tree_1(self):
161
        mtree = MockTree()
162
        mtree.add_dir("a", "grandparent")
163
        mtree.add_dir("b", "grandparent/parent")
164
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
165
        mtree.add_dir("d", "grandparent/alt_parent")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
166
        return BundleTree(mtree, ''), mtree
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
167
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
168
    def test_renames(self):
169
        """Ensure that file renames have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
170
        btree = self.make_tree_1()[0]
171
        self.assertEqual(btree.old_path("grandparent"), "grandparent")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
172
        self.assertEqual(btree.old_path("grandparent/parent"),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
173
                         "grandparent/parent")
174
        self.assertEqual(btree.old_path("grandparent/parent/file"),
175
                         "grandparent/parent/file")
176
177
        self.assertEqual(btree.id2path("a"), "grandparent")
178
        self.assertEqual(btree.id2path("b"), "grandparent/parent")
179
        self.assertEqual(btree.id2path("c"), "grandparent/parent/file")
180
181
        self.assertEqual(btree.path2id("grandparent"), "a")
182
        self.assertEqual(btree.path2id("grandparent/parent"), "b")
183
        self.assertEqual(btree.path2id("grandparent/parent/file"), "c")
184
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
185
        self.assertTrue(btree.path2id("grandparent2") is None)
186
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
187
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
188
189
        btree.note_rename("grandparent", "grandparent2")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
190
        self.assertTrue(btree.old_path("grandparent") is None)
191
        self.assertTrue(btree.old_path("grandparent/parent") is None)
192
        self.assertTrue(btree.old_path("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
193
194
        self.assertEqual(btree.id2path("a"), "grandparent2")
195
        self.assertEqual(btree.id2path("b"), "grandparent2/parent")
196
        self.assertEqual(btree.id2path("c"), "grandparent2/parent/file")
197
198
        self.assertEqual(btree.path2id("grandparent2"), "a")
199
        self.assertEqual(btree.path2id("grandparent2/parent"), "b")
200
        self.assertEqual(btree.path2id("grandparent2/parent/file"), "c")
201
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
202
        self.assertTrue(btree.path2id("grandparent") is None)
203
        self.assertTrue(btree.path2id("grandparent/parent") is None)
204
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
205
206
        btree.note_rename("grandparent/parent", "grandparent2/parent2")
207
        self.assertEqual(btree.id2path("a"), "grandparent2")
208
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
209
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file")
210
211
        self.assertEqual(btree.path2id("grandparent2"), "a")
212
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
213
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), "c")
214
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
215
        self.assertTrue(btree.path2id("grandparent2/parent") is None)
216
        self.assertTrue(btree.path2id("grandparent2/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
217
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
218
        btree.note_rename("grandparent/parent/file",
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
219
                          "grandparent2/parent2/file2")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
220
        self.assertEqual(btree.id2path("a"), "grandparent2")
221
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
222
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file2")
223
224
        self.assertEqual(btree.path2id("grandparent2"), "a")
225
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
226
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), "c")
227
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
228
        self.assertTrue(btree.path2id("grandparent2/parent2/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
229
230
    def test_moves(self):
231
        """Ensure that file moves have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
232
        btree = self.make_tree_1()[0]
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
233
        btree.note_rename("grandparent/parent/file",
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
234
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
235
        self.assertEqual(btree.id2path("c"), "grandparent/alt_parent/file")
236
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), "c")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
237
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
238
239
    def unified_diff(self, old, new):
240
        out = StringIO()
4241.14.13 by Vincent Ladeuil
Some more cleanup.
241
        diff.internal_diff("old", old, "new", new, out)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
242
        out.seek(0,0)
243
        return out.read()
244
245
    def make_tree_2(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
246
        btree = self.make_tree_1()[0]
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
247
        btree.note_rename("grandparent/parent/file",
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
248
                          "grandparent/alt_parent/file")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
249
        self.assertTrue(btree.id2path("e") is None)
250
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
251
        btree.note_id("e", "grandparent/parent/file")
252
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
253
254
    def test_adds(self):
255
        """File/inventory adds"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
256
        btree = self.make_tree_2()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
257
        add_patch = self.unified_diff([], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
258
        btree.note_patch("grandparent/parent/file", add_patch)
259
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
260
        btree.note_target('grandparent/parent/symlink', 'venus')
261
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
262
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
263
    def adds_test(self, btree):
264
        self.assertEqual(btree.id2path("e"), "grandparent/parent/file")
265
        self.assertEqual(btree.path2id("grandparent/parent/file"), "e")
266
        self.assertEqual(btree.get_file("e").read(), "Extra cheese\n")
267
        self.assertEqual(btree.get_symlink_target('f'), 'venus')
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
268
269
    def test_adds2(self):
270
        """File/inventory adds, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
271
        btree = self.make_tree_2()
272
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
273
        add_patch = self.unified_diff(["Hello\n"], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
274
        btree.note_patch("grandparent/parent/file", add_patch)
275
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
276
        btree.note_target('grandparent/parent/symlink', 'venus')
277
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
278
279
    def make_tree_3(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
280
        btree, mtree = self.make_tree_1()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
281
        mtree.add_file("e", "grandparent/parent/topping", "Anchovies\n")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
282
        btree.note_rename("grandparent/parent/file",
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
283
                          "grandparent/alt_parent/file")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
284
        btree.note_rename("grandparent/parent/topping",
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
285
                          "grandparent/alt_parent/stopping")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
286
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
287
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
288
    def get_file_test(self, btree):
289
        self.assertEqual(btree.get_file("e").read(), "Lemon\n")
290
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
291
292
    def test_get_file(self):
293
        """Get file contents"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
294
        btree = self.make_tree_3()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
295
        mod_patch = self.unified_diff(["Anchovies\n"], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
296
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
297
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
298
299
    def test_get_file2(self):
300
        """Get file contents, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
301
        btree = self.make_tree_3()
302
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
303
        mod_patch = self.unified_diff([], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
304
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
305
        mod_patch = self.unified_diff([], ["Hello\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
306
        btree.note_patch("grandparent/alt_parent/file", mod_patch)
307
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
308
309
    def test_delete(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
310
        "Deletion by bundle"
311
        btree = self.make_tree_1()[0]
312
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
313
        btree.note_deletion("grandparent/parent/file")
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
314
        self.assertTrue(btree.id2path("c") is None)
315
        self.assertTrue(btree.path2id("grandparent/parent/file") is None)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
316
317
    def sorted_ids(self, tree):
318
        ids = list(tree)
319
        ids.sort()
320
        return ids
321
322
    def test_iteration(self):
323
        """Ensure that iteration through ids works properly"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
324
        btree = self.make_tree_1()[0]
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
325
        self.assertEqual(self.sorted_ids(btree),
326
            [inventory.ROOT_ID, 'a', 'b', 'c', 'd'])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
327
        btree.note_deletion("grandparent/parent/file")
328
        btree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
329
        btree.note_last_changed("grandparent/alt_parent/fool",
1185.82.95 by Aaron Bentley
Restore path-orientation of ChangesetTree
330
                                "revisionidiguess")
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
331
        self.assertEqual(self.sorted_ids(btree),
332
            [inventory.ROOT_ID, 'a', 'b', 'd', 'e'])
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
333
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
334
4241.14.13 by Vincent Ladeuil
Some more cleanup.
335
class BundleTester1(tests.TestCaseWithTransport):
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
336
337
    def test_mismatched_bundle(self):
338
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
339
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
340
        serializer = BundleSerializerV08('0.8')
341
        b = self.make_branch('.', format=format)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
342
        self.assertRaises(errors.IncompatibleBundleFormat, serializer.write,
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
343
                          b.repository, [], {}, StringIO())
344
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
345
    def test_matched_bundle(self):
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
346
        """Don't raise IncompatibleBundleFormat for knit2 and bundle0.9"""
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
347
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
348
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
349
        serializer = BundleSerializerV09('0.9')
350
        b = self.make_branch('.', format=format)
351
        serializer.write(b.repository, [], {}, StringIO())
352
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
353
    def test_mismatched_model(self):
354
        """Try copying a bundle from knit2 to knit1"""
355
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
356
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
357
        source = self.make_branch_and_tree('source', format=format)
358
        source.commit('one', rev_id='one-id')
359
        source.commit('two', rev_id='two-id')
360
        text = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
361
        write_bundle(source.branch.repository, 'two-id', 'null:', text,
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
362
                     format='0.9')
363
        text.seek(0)
364
365
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
366
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
367
        target = self.make_branch('target', format=format)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
368
        self.assertRaises(errors.IncompatibleRevision, install_bundle,
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
369
                          target.repository, read_bundle(text))
370
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
371
2520.4.43 by Aaron Bentley
Fix test suite
372
class BundleTester(object):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
373
374
    def bzrdir_format(self):
375
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
376
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
377
        return format
378
379
    def make_branch_and_tree(self, path, format=None):
380
        if format is None:
381
            format = self.bzrdir_format()
4241.14.13 by Vincent Ladeuil
Some more cleanup.
382
        return tests.TestCaseWithTransport.make_branch_and_tree(
383
            self, path, format)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
384
385
    def make_branch(self, path, format=None):
386
        if format is None:
387
            format = self.bzrdir_format()
4241.14.13 by Vincent Ladeuil
Some more cleanup.
388
        return tests.TestCaseWithTransport.make_branch(self, path, format)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
389
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
390
    def create_bundle_text(self, base_rev_id, rev_id):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
391
        bundle_txt = StringIO()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
392
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id,
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
393
                               bundle_txt, format=self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
394
        bundle_txt.seek(0)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
395
        self.assertEqual(bundle_txt.readline(),
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
396
                         '# Bazaar revision bundle v%s\n' % self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
397
        self.assertEqual(bundle_txt.readline(), '#\n')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
398
1185.82.14 by Aaron Bentley
API updates
399
        rev = self.b1.repository.get_revision(rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
400
        self.assertEqual(bundle_txt.readline().decode('utf-8'),
401
                         u'# message:\n')
402
        bundle_txt.seek(0)
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
403
        return bundle_txt, rev_ids
404
405
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
406
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
407
        Make sure that the text generated is valid, and that it
408
        can be applied against the base, and generate the same information.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
409
410
        :return: The in-memory bundle
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
411
        """
412
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
413
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
414
        # This should also validate the generated bundle
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
415
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
416
        repository = self.b1.repository
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
417
        for bundle_rev in bundle.real_revisions:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
418
            # These really should have already been checked when we read the
419
            # bundle, since it computes the sha1 hash for the revision, which
420
            # only will match if everything is okay, but lets be explicit about
421
            # it
422
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1185.82.33 by Aaron Bentley
Strengthen tests
423
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
424
                      'timestamp', 'timezone', 'message', 'committer',
1185.82.33 by Aaron Bentley
Strengthen tests
425
                      'parent_ids', 'properties'):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
426
                self.assertEqual(getattr(branch_rev, a),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
427
                                 getattr(bundle_rev, a))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
428
            self.assertEqual(len(branch_rev.parent_ids),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
429
                             len(bundle_rev.parent_ids))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
430
        self.assertEqual(rev_ids,
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
431
                         [r.revision_id for r in bundle.real_revisions])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
432
        self.valid_apply_bundle(base_rev_id, bundle,
1185.82.89 by Aaron Bentley
Remove auto_commit stuff
433
                                   checkout_dir=checkout_dir)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
434
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
435
        return bundle
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
436
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
437
    def get_invalid_bundle(self, base_rev_id, rev_id):
438
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
439
        Munge the text so that it's invalid.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
440
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
441
        :return: The in-memory bundle
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
442
        """
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
443
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
444
        new_text = bundle_txt.getvalue().replace('executable:no',
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
445
                                               'executable:yes')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
446
        bundle_txt = StringIO(new_text)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
447
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
448
        self.valid_apply_bundle(base_rev_id, bundle)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
449
        return bundle
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
450
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
451
    def test_non_bundle(self):
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
452
        self.assertRaises(errors.NotABundle,
453
                          read_bundle, StringIO('#!/bin/sh\n'))
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
454
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
455
    def test_malformed(self):
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
456
        self.assertRaises(errors.BadBundle, read_bundle,
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
457
                          StringIO('# Bazaar revision bundle v'))
458
459
    def test_crlf_bundle(self):
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
460
        try:
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
461
            read_bundle(StringIO('# Bazaar revision bundle v0.8\r\n'))
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
462
        except errors.BadBundle:
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
463
            # It is currently permitted for bundles with crlf line endings to
464
            # make read_bundle raise a BadBundle, but this should be fixed.
1793.2.10 by Aaron Bentley
Whitespace/comment fix
465
            # Anything else, especially NotABundle, is an error.
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
466
            pass
467
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
468
    def get_checkout(self, rev_id, checkout_dir=None):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
469
        """Get a new tree, with the specified revision in it.
470
        """
471
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
472
        if checkout_dir is None:
3638.3.2 by Vincent Ladeuil
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.
473
            checkout_dir = osutils.mkdtemp(prefix='test-branch-', dir='.')
0.5.89 by John Arbash Meinel
Updating for explicitly defined directories.
474
        else:
475
            if not os.path.exists(checkout_dir):
476
                os.mkdir(checkout_dir)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
477
        tree = self.make_branch_and_tree(checkout_dir)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
478
        s = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
479
        ancestors = write_bundle(self.b1.repository, rev_id, 'null:', s,
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
480
                                 format=self.format)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
481
        s.seek(0)
3376.2.4 by Martin Pool
Remove every assert statement from bzrlib!
482
        self.assertIsInstance(s.getvalue(), str)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
483
        install_bundle(tree.branch.repository, read_bundle(s))
1185.82.41 by Aaron Bentley
More work on installing changesets
484
        for ancestor in ancestors:
485
            old = self.b1.repository.revision_tree(ancestor)
486
            new = tree.branch.repository.revision_tree(ancestor)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
487
            old.lock_read()
488
            new.lock_read()
489
            try:
490
                # Check that there aren't any inventory level changes
491
                delta = new.changes_from(old)
492
                self.assertFalse(delta.has_changed(),
493
                                 'Revision %s not copied correctly.'
494
                                 % (ancestor,))
495
496
                # Now check that the file contents are all correct
5837.2.2 by Jelmer Vernooij
Fix more uses of Tree.__iter__
497
                for inventory_id in old.all_file_ids():
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
498
                    try:
499
                        old_file = old.get_file(inventory_id)
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
500
                    except errors.NoSuchFile:
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
501
                        continue
502
                    if old_file is None:
503
                        continue
504
                    self.assertEqual(old_file.read(),
505
                                     new.get_file(inventory_id).read())
506
            finally:
507
                new.unlock()
508
                old.unlock()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
509
        if not _mod_revision.is_null(rev_id):
6165.4.19 by Jelmer Vernooij
Avoid all iter_reverse_revision_history calls.
510
            tree.branch.generate_revision_history(rev_id)
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
511
            tree.update()
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
512
            delta = tree.changes_from(self.b1.repository.revision_tree(rev_id))
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
513
            self.assertFalse(delta.has_changed(),
2255.10.5 by John Arbash Meinel
Fix a small bug when we have a symlink that does not need to be re-read.
514
                             'Working tree has modifications: %s' % delta)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
515
        return tree
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
516
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
517
    def valid_apply_bundle(self, base_rev_id, info, checkout_dir=None):
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
518
        """Get the base revision, apply the changes, and make
519
        sure everything matches the builtin branch.
520
        """
1185.82.17 by Aaron Bentley
More API updates
521
        to_tree = self.get_checkout(base_rev_id, checkout_dir=checkout_dir)
3146.4.11 by Aaron Bentley
Fix lock errors in bundle tests
522
        to_tree.lock_write()
523
        try:
524
            self._valid_apply_bundle(base_rev_id, info, to_tree)
525
        finally:
526
            to_tree.unlock()
527
528
    def _valid_apply_bundle(self, base_rev_id, info, to_tree):
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
529
        original_parents = to_tree.get_parent_ids()
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
530
        repository = to_tree.branch.repository
1927.2.1 by Robert Collins
Alter set_pending_merges to shove the left most merge into the trees last-revision if that is not set. Related bugfixes include basis_tree handling ghosts, de-duping the merges with the last-revision and update changing where and how it adds its pending merge.
531
        original_parents = to_tree.get_parent_ids()
1185.82.41 by Aaron Bentley
More work on installing changesets
532
        self.assertIs(repository.has_revision(base_rev_id), True)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
533
        for rev in info.real_revisions:
534
            self.assert_(not repository.has_revision(rev.revision_id),
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
535
                'Revision {%s} present before applying bundle'
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
536
                % rev.revision_id)
4241.14.13 by Vincent Ladeuil
Some more cleanup.
537
        merge_bundle(info, to_tree, True, merge.Merge3Merger, False, False)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
538
539
        for rev in info.real_revisions:
1185.82.17 by Aaron Bentley
More API updates
540
            self.assert_(repository.has_revision(rev.revision_id),
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
541
                'Missing revision {%s} after applying bundle'
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
542
                % rev.revision_id)
543
1185.82.17 by Aaron Bentley
More API updates
544
        self.assert_(to_tree.branch.repository.has_revision(info.target))
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
545
        # Do we also want to verify that all the texts have been added?
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
546
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
547
        self.assertEqual(original_parents + [info.target],
548
            to_tree.get_parent_ids())
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
549
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
550
        rev = info.real_revisions[-1]
1185.82.17 by Aaron Bentley
More API updates
551
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
552
        to_tree = to_tree.branch.repository.revision_tree(rev.revision_id)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
553
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
554
        # TODO: make sure the target tree is identical to base tree
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
555
        #       we might also check the working tree.
556
557
        base_files = list(base_tree.list_files())
558
        to_files = list(to_tree.list_files())
559
        self.assertEqual(len(base_files), len(to_files))
1185.82.66 by Aaron Bentley
Handle new executable files
560
        for base_file, to_file in zip(base_files, to_files):
561
            self.assertEqual(base_file, to_file)
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
562
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
563
        for path, status, kind, fileid, entry in base_files:
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
564
            # Check that the meta information is the same
565
            self.assertEqual(base_tree.get_file_size(fileid),
566
                    to_tree.get_file_size(fileid))
567
            self.assertEqual(base_tree.get_file_sha1(fileid),
568
                    to_tree.get_file_sha1(fileid))
569
            # Check that the contents are the same
570
            # This is pretty expensive
571
            # self.assertEqual(base_tree.get_file(fileid).read(),
572
            #         to_tree.get_file(fileid).read())
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
573
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
574
    def test_bundle(self):
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
575
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.14 by Aaron Bentley
API updates
576
        self.b1 = self.tree1.branch
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
577
4543.2.11 by John Arbash Meinel
Use a fixed file-id for the root to make the tests more stable.
578
        self.build_tree_contents([('b1/one', 'one\n')])
579
        self.tree1.add('one', 'one-id')
580
        self.tree1.set_root_id('root-id')
1185.82.14 by Aaron Bentley
API updates
581
        self.tree1.commit('add one', rev_id='a@cset-0-1')
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
582
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
583
        bundle = self.get_valid_bundle('null:', 'a@cset-0-1')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
584
585
        # Make sure we can handle files with spaces, tabs, other
586
        # bogus characters
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
587
        self.build_tree([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
588
                'b1/with space.txt'
589
                , 'b1/dir/'
590
                , 'b1/dir/filein subdir.c'
591
                , 'b1/dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
592
                , 'b1/dir/ pre space'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
593
                , 'b1/sub/'
594
                , 'b1/sub/sub/'
595
                , 'b1/sub/sub/nonempty.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
596
                ])
4543.2.11 by John Arbash Meinel
Use a fixed file-id for the root to make the tests more stable.
597
        self.build_tree_contents([('b1/sub/sub/emptyfile.txt', ''),
598
                                  ('b1/dir/nolastnewline.txt', 'bloop')])
1185.82.66 by Aaron Bentley
Handle new executable files
599
        tt = TreeTransform(self.tree1)
600
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
601
        tt.apply()
2520.4.84 by Aaron Bentley
Fix heisenbug record-rewriting test
602
        # have to fix length of file-id so that we can predictably rewrite
603
        # a (length-prefixed) record containing it later.
604
        self.tree1.add('with space.txt', 'withspace-id')
1185.82.14 by Aaron Bentley
API updates
605
        self.tree1.add([
2520.4.84 by Aaron Bentley
Fix heisenbug record-rewriting test
606
                  'dir'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
607
                , 'dir/filein subdir.c'
608
                , 'dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
609
                , 'dir/ pre space'
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
610
                , 'dir/nolastnewline.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
611
                , 'sub'
612
                , 'sub/sub'
613
                , 'sub/sub/nonempty.txt'
614
                , 'sub/sub/emptyfile.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
615
                ])
1185.82.14 by Aaron Bentley
API updates
616
        self.tree1.commit('add whitespace', rev_id='a@cset-0-2')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
617
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
618
        bundle = self.get_valid_bundle('a@cset-0-1', 'a@cset-0-2')
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
619
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
620
        # Check a rollup bundle
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
621
        bundle = self.get_valid_bundle('null:', 'a@cset-0-2')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
622
623
        # Now delete entries
1185.82.21 by Aaron Bentley
Stop using deprecated function
624
        self.tree1.remove(
0.5.118 by John Arbash Meinel
Got most of test_changeset to work. Still needs work for Aaron's test code.
625
                ['sub/sub/nonempty.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
626
                , 'sub/sub/emptyfile.txt'
0.5.118 by John Arbash Meinel
Got most of test_changeset to work. Still needs work for Aaron's test code.
627
                , 'sub/sub'
628
                ])
1185.82.68 by Aaron Bentley
Handle execute bit on modified files
629
        tt = TreeTransform(self.tree1)
630
        trans_id = tt.trans_id_tree_file_id('exe-1')
631
        tt.set_executability(False, trans_id)
632
        tt.apply()
1185.82.19 by Aaron Bentley
More API updates
633
        self.tree1.commit('removed', rev_id='a@cset-0-3')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
634
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
635
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
636
        self.assertRaises((errors.TestamentMismatch,
4543.2.8 by John Arbash Meinel
Add a custom get_invalid_bundle and allow BadBundle to be
637
            errors.VersionedFileInvalidChecksum,
638
            errors.BadBundle), self.get_invalid_bundle,
2520.4.71 by Aaron Bentley
Update test to accept VersionedFileInvalidChecksum instead of TestamentMismatch
639
            'a@cset-0-2', 'a@cset-0-3')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
640
        # Check a rollup bundle
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
641
        bundle = self.get_valid_bundle('null:', 'a@cset-0-3')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
642
643
        # Now move the directory
1185.82.19 by Aaron Bentley
More API updates
644
        self.tree1.rename_one('dir', 'sub/dir')
645
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
646
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
647
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
648
        # Check a rollup bundle
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
649
        bundle = self.get_valid_bundle('null:', 'a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
650
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
651
        # Modified files
652
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
2520.4.83 by Aaron Bentley
Clean up tests
653
        open('b1/sub/dir/ pre space', 'ab').write(
654
             '\r\nAdding some\r\nDOS format lines\r\n')
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
655
        open('b1/sub/dir/nolastnewline.txt', 'ab').write('\n')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
656
        self.tree1.rename_one('sub/dir/ pre space',
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
657
                              'sub/ start space')
1185.82.19 by Aaron Bentley
More API updates
658
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
659
        bundle = self.get_valid_bundle('a@cset-0-4', 'a@cset-0-5')
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
660
1185.82.70 by Aaron Bentley
Handle renamed files better
661
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
662
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
663
        self.tree1.rename_one('temp', 'with space.txt')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
664
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
665
                          verbose=False)
666
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
667
        other = self.get_checkout('a@cset-0-5')
4543.2.9 by John Arbash Meinel
Down to 2 failing tests.
668
        tree1_inv = get_inventory_text(self.tree1.branch.repository,
669
                                       'a@cset-0-5')
670
        tree2_inv = get_inventory_text(other.branch.repository,
671
                                       'a@cset-0-5')
1910.2.54 by Aaron Bentley
Implement testament format 3 strict
672
        self.assertEqualDiff(tree1_inv, tree2_inv)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
673
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
674
        other.commit('rename file', rev_id='a@cset-0-6b')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
675
        self.tree1.merge_from_branch(other.branch)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
676
        self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
1185.82.70 by Aaron Bentley
Handle renamed files better
677
                          verbose=False)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
678
        bundle = self.get_valid_bundle('a@cset-0-6', 'a@cset-0-7')
1185.82.72 by Aaron Bentley
Always use leftmost base for changesets
679
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
680
    def _test_symlink_bundle(self, link_name, link_target, new_link_target):
681
        link_id = 'link-1'
682
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
683
        self.requireFeature(features.SymlinkFeature)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
684
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.87 by Aaron Bentley
Got symlink adding working
685
        self.b1 = self.tree1.branch
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
686
1185.82.87 by Aaron Bentley
Got symlink adding working
687
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
688
        tt.new_symlink(link_name, tt.root, link_target, link_id)
1185.82.87 by Aaron Bentley
Got symlink adding working
689
        tt.apply()
690
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
691
        bundle = self.get_valid_bundle('null:', 'l@cset-0-1')
692
        if getattr(bundle ,'revision_tree', None) is not None:
693
            # Not all bundle formats supports revision_tree
694
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-1')
695
            self.assertEqual(link_target, bund_tree.get_symlink_target(link_id))
696
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
697
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
698
        trans_id = tt.trans_id_tree_file_id(link_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
699
        tt.adjust_path('link2', tt.root, trans_id)
700
        tt.delete_contents(trans_id)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
701
        tt.create_symlink(new_link_target, trans_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
702
        tt.apply()
703
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
704
        bundle = self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
705
        if getattr(bundle ,'revision_tree', None) is not None:
706
            # Not all bundle formats supports revision_tree
707
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-2')
708
            self.assertEqual(new_link_target,
709
                             bund_tree.get_symlink_target(link_id))
710
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
711
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
712
        trans_id = tt.trans_id_tree_file_id(link_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
713
        tt.delete_contents(trans_id)
714
        tt.create_symlink('jupiter', trans_id)
715
        tt.apply()
716
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
717
        bundle = self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
718
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
719
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
720
        trans_id = tt.trans_id_tree_file_id(link_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
721
        tt.delete_contents(trans_id)
722
        tt.apply()
723
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
724
        bundle = self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
725
726
    def test_symlink_bundle(self):
727
        self._test_symlink_bundle('link', 'bar/foo', 'mars')
728
729
    def test_unicode_symlink_bundle(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
730
        self.requireFeature(features.UnicodeFilenameFeature)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
731
        self._test_symlink_bundle(u'\N{Euro Sign}link',
732
                                  u'bar/\N{Euro Sign}foo',
733
                                  u'mars\N{Euro Sign}')
1185.82.96 by Aaron Bentley
Got first binary test passing
734
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
735
    def test_binary_bundle(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
736
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.96 by Aaron Bentley
Got first binary test passing
737
        self.b1 = self.tree1.branch
738
        tt = TreeTransform(self.tree1)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
739
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
740
        # Add
741
        tt.new_file('file', tt.root, '\x00\n\x00\r\x01\n\x02\r\xff', 'binary-1')
2520.4.83 by Aaron Bentley
Clean up tests
742
        tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff',
743
            'binary-2')
1185.82.96 by Aaron Bentley
Got first binary test passing
744
        tt.apply()
745
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
746
        self.get_valid_bundle('null:', 'b@cset-0-1')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
747
748
        # Delete
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
749
        tt = TreeTransform(self.tree1)
750
        trans_id = tt.trans_id_tree_file_id('binary-1')
751
        tt.delete_contents(trans_id)
752
        tt.apply()
753
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
754
        self.get_valid_bundle('b@cset-0-1', 'b@cset-0-2')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
755
756
        # Rename & modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
757
        tt = TreeTransform(self.tree1)
758
        trans_id = tt.trans_id_tree_file_id('binary-2')
759
        tt.adjust_path('file3', tt.root, trans_id)
760
        tt.delete_contents(trans_id)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
761
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
762
        tt.apply()
763
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
764
        self.get_valid_bundle('b@cset-0-2', 'b@cset-0-3')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
765
766
        # Modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
767
        tt = TreeTransform(self.tree1)
768
        trans_id = tt.trans_id_tree_file_id('binary-2')
769
        tt.delete_contents(trans_id)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
770
        tt.create_file('\x00file\rcontents', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
771
        tt.apply()
772
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
773
        self.get_valid_bundle('b@cset-0-3', 'b@cset-0-4')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
774
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
775
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
776
        self.get_valid_bundle('null:', 'b@cset-0-4')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
777
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
778
    def test_last_modified(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
779
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
780
        self.b1 = self.tree1.branch
781
        tt = TreeTransform(self.tree1)
782
        tt.new_file('file', tt.root, 'file', 'file')
783
        tt.apply()
784
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
785
786
        tt = TreeTransform(self.tree1)
787
        trans_id = tt.trans_id_tree_file_id('file')
788
        tt.delete_contents(trans_id)
789
        tt.create_file('file2', trans_id)
790
        tt.apply()
791
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
792
793
        other = self.get_checkout('a@lmod-0-1')
794
        tt = TreeTransform(other)
795
        trans_id = tt.trans_id_tree_file_id('file')
796
        tt.delete_contents(trans_id)
797
        tt.create_file('file2', trans_id)
798
        tt.apply()
799
        other.commit('modify text in another tree', rev_id='a@lmod-0-2b')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
800
        self.tree1.merge_from_branch(other.branch)
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
801
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
802
                          verbose=False)
803
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
804
        bundle = self.get_valid_bundle('a@lmod-0-2a', 'a@lmod-0-4')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
805
806
    def test_hide_history(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
807
        self.tree1 = self.make_branch_and_tree('b1')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
808
        self.b1 = self.tree1.branch
809
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
810
        open('b1/one', 'wb').write('one\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
811
        self.tree1.add('one')
812
        self.tree1.commit('add file', rev_id='a@cset-0-1')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
813
        open('b1/one', 'wb').write('two\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
814
        self.tree1.commit('modify', rev_id='a@cset-0-2')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
815
        open('b1/one', 'wb').write('three\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
816
        self.tree1.commit('modify', rev_id='a@cset-0-3')
817
        bundle_file = StringIO()
818
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
819
                               'a@cset-0-1', bundle_file, format=self.format)
2382.1.1 by Ian Clatworthy
Fixes #98510 - bundle selftest fails if email has 'two' embedded
820
        self.assertNotContainsRe(bundle_file.getvalue(), '\btwo\b')
2520.4.32 by Aaron Bentley
Fix test case
821
        self.assertContainsRe(self.get_raw(bundle_file), 'one')
822
        self.assertContainsRe(self.get_raw(bundle_file), 'three')
823
2520.4.75 by Aaron Bentley
Fix traceback on empty bundles.
824
    def test_bundle_same_basis(self):
825
        """Ensure using the basis as the target doesn't cause an error"""
826
        self.tree1 = self.make_branch_and_tree('b1')
827
        self.tree1.commit('add file', rev_id='a@cset-0-1')
828
        bundle_file = StringIO()
829
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-1',
830
                               'a@cset-0-1', bundle_file)
831
2520.4.32 by Aaron Bentley
Fix test case
832
    @staticmethod
833
    def get_raw(bundle_file):
834
        return bundle_file.getvalue()
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
835
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
836
    def test_unicode_bundle(self):
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
837
        self.requireFeature(features.UnicodeFilenameFeature)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
838
        # Handle international characters
839
        os.mkdir('b1')
4241.14.13 by Vincent Ladeuil
Some more cleanup.
840
        f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
841
842
        self.tree1 = self.make_branch_and_tree('b1')
843
        self.b1 = self.tree1.branch
844
845
        f.write((u'A file\n'
846
            u'With international man of mystery\n'
847
            u'William Dod\xe9\n').encode('utf-8'))
848
        f.close()
849
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
850
        self.tree1.add([u'with Dod\N{Euro Sign}'], ['withdod-id'])
2386.1.1 by John Arbash Meinel
Update test_unicode_bundle, since we know how it fails on Mac OSX
851
        self.tree1.commit(u'i18n commit from William Dod\xe9',
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
852
                          rev_id='i18n-1', committer=u'William Dod\xe9')
853
854
        # Add
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
855
        bundle = self.get_valid_bundle('null:', 'i18n-1')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
856
857
        # Modified
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
858
        f = open(u'b1/with Dod\N{Euro Sign}', 'wb')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
859
        f.write(u'Modified \xb5\n'.encode('utf8'))
860
        f.close()
861
        self.tree1.commit(u'modified', rev_id='i18n-2')
862
863
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
864
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
865
        # Renamed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
866
        self.tree1.rename_one(u'with Dod\N{Euro Sign}', u'B\N{Euro Sign}gfors')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
867
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
868
                          committer=u'Erik B\xe5gfors')
869
870
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
871
872
        # Removed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
873
        self.tree1.remove([u'B\N{Euro Sign}gfors'])
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
874
        self.tree1.commit(u'removed', rev_id='i18n-4')
875
876
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
877
878
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
879
        bundle = self.get_valid_bundle('null:', 'i18n-4')
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
880
881
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
882
    def test_whitespace_bundle(self):
883
        if sys.platform in ('win32', 'cygwin'):
4241.14.13 by Vincent Ladeuil
Some more cleanup.
884
            raise tests.TestSkipped('Windows doesn\'t support filenames'
885
                                    ' with tabs or trailing spaces')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
886
        self.tree1 = self.make_branch_and_tree('b1')
887
        self.b1 = self.tree1.branch
888
889
        self.build_tree(['b1/trailing space '])
890
        self.tree1.add(['trailing space '])
891
        # TODO: jam 20060701 Check for handling files with '\t' characters
892
        #       once we actually support them
893
894
        # Added
895
        self.tree1.commit('funky whitespace', rev_id='white-1')
896
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
897
        bundle = self.get_valid_bundle('null:', 'white-1')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
898
899
        # Modified
900
        open('b1/trailing space ', 'ab').write('add some text\n')
901
        self.tree1.commit('add text', rev_id='white-2')
902
903
        bundle = self.get_valid_bundle('white-1', 'white-2')
904
905
        # Renamed
906
        self.tree1.rename_one('trailing space ', ' start and end space ')
907
        self.tree1.commit('rename', rev_id='white-3')
908
909
        bundle = self.get_valid_bundle('white-2', 'white-3')
910
911
        # Removed
912
        self.tree1.remove([' start and end space '])
913
        self.tree1.commit('removed', rev_id='white-4')
914
915
        bundle = self.get_valid_bundle('white-3', 'white-4')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
916
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
917
        # Now test a complet roll-up
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
918
        bundle = self.get_valid_bundle('null:', 'white-4')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
919
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
920
    def test_alt_timezone_bundle(self):
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
921
        self.tree1 = self.make_branch_and_memory_tree('b1')
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
922
        self.b1 = self.tree1.branch
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
923
        builder = treebuilder.TreeBuilder()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
924
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
925
        self.tree1.lock_write()
926
        builder.start_tree(self.tree1)
927
        builder.build(['newfile'])
928
        builder.finish_tree()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
929
930
        # Asia/Colombo offset = 5 hours 30 minutes
931
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
932
                          timezone=19800, timestamp=1152544886.0)
933
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
934
        bundle = self.get_valid_bundle('null:', 'tz-1')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
935
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
936
        rev = bundle.revisions[0]
937
        self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
938
        self.assertEqual(19800, rev.timezone)
939
        self.assertEqual(1152544886.0, rev.timestamp)
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
940
        self.tree1.unlock()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
941
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
942
    def test_bundle_root_id(self):
943
        self.tree1 = self.make_branch_and_tree('b1')
944
        self.b1 = self.tree1.branch
945
        self.tree1.commit('message', rev_id='revid1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
946
        bundle = self.get_valid_bundle('null:', 'revid1')
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
947
        tree = self.get_bundle_tree(bundle, 'revid1')
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
948
        self.assertEqual('revid1', tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
949
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
950
    def test_install_revisions(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
951
        self.tree1 = self.make_branch_and_tree('b1')
952
        self.b1 = self.tree1.branch
953
        self.tree1.commit('message', rev_id='rev2a')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
954
        bundle = self.get_valid_bundle('null:', 'rev2a')
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
955
        branch2 = self.make_branch('b2')
956
        self.assertFalse(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
957
        target_revision = bundle.install_revisions(branch2.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
958
        self.assertTrue(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
959
        self.assertEqual('rev2a', target_revision)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
960
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
961
    def test_bundle_empty_property(self):
962
        """Test serializing revision properties with an empty value."""
963
        tree = self.make_branch_and_memory_tree('tree')
964
        tree.lock_write()
965
        self.addCleanup(tree.unlock)
966
        tree.add([''], ['TREE_ROOT'])
967
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
968
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
969
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
970
        bundle = read_bundle(bundle_sio)
971
        revision_info = bundle.revisions[0]
972
        self.assertEqual('rev1', revision_info.revision_id)
973
        rev = revision_info.as_revision()
974
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
975
                         rev.properties)
976
977
    def test_bundle_sorted_properties(self):
978
        """For stability the writer should write properties in sorted order."""
979
        tree = self.make_branch_and_memory_tree('tree')
980
        tree.lock_write()
981
        self.addCleanup(tree.unlock)
982
983
        tree.add([''], ['TREE_ROOT'])
984
        tree.commit('One', rev_id='rev1',
985
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
986
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
987
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
988
        bundle = read_bundle(bundle_sio)
989
        revision_info = bundle.revisions[0]
990
        self.assertEqual('rev1', revision_info.revision_id)
991
        rev = revision_info.as_revision()
992
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
993
                          'd':'1'}, rev.properties)
994
995
    def test_bundle_unicode_properties(self):
996
        """We should be able to round trip a non-ascii property."""
997
        tree = self.make_branch_and_memory_tree('tree')
998
        tree.lock_write()
999
        self.addCleanup(tree.unlock)
1000
1001
        tree.add([''], ['TREE_ROOT'])
1002
        # Revisions themselves do not require anything about revision property
1003
        # keys, other than that they are a basestring, and do not contain
1004
        # whitespace.
1005
        # However, Testaments assert than they are str(), and thus should not
1006
        # be Unicode.
1007
        tree.commit('One', rev_id='rev1',
1008
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1009
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1010
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
1011
        bundle = read_bundle(bundle_sio)
1012
        revision_info = bundle.revisions[0]
1013
        self.assertEqual('rev1', revision_info.revision_id)
1014
        rev = revision_info.as_revision()
1015
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
1016
                          'alpha':u'\u03b1'}, rev.properties)
1017
2520.4.43 by Aaron Bentley
Fix test suite
1018
    def test_bundle_with_ghosts(self):
1019
        tree = self.make_branch_and_tree('tree')
1020
        self.b1 = tree.branch
1021
        self.build_tree_contents([('tree/file', 'content1')])
1022
        tree.add(['file'])
1023
        tree.commit('rev1')
1024
        self.build_tree_contents([('tree/file', 'content2')])
1025
        tree.add_parent_tree_id('ghost')
1026
        tree.commit('rev2', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1027
        bundle = self.get_valid_bundle('null:', 'rev2')
2520.4.43 by Aaron Bentley
Fix test suite
1028
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1029
    def make_simple_tree(self, format=None):
1030
        tree = self.make_branch_and_tree('b1', format=format)
1031
        self.b1 = tree.branch
1032
        self.build_tree(['b1/file'])
1033
        tree.add('file')
1034
        return tree
1035
1036
    def test_across_serializers(self):
1037
        tree = self.make_simple_tree('knit')
1038
        tree.commit('hello', rev_id='rev1')
2520.4.98 by Aaron Bentley
Support inventory conversion with parents
1039
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1040
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1041
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1042
        bundle.install_revisions(repo)
4988.5.1 by Jelmer Vernooij
Rename Repository.get_inventory_xml -> Repository._get_inventory_xml.
1043
        inv_text = repo._get_inventory_xml('rev2')
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1044
        self.assertNotContainsRe(inv_text, 'format="5"')
2520.4.99 by Aaron Bentley
Test conversion across models
1045
        self.assertContainsRe(inv_text, 'format="7"')
1046
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1047
    def make_repo_with_installed_revisions(self):
1048
        tree = self.make_simple_tree('knit')
1049
        tree.commit('hello', rev_id='rev1')
1050
        tree.commit('hello', rev_id='rev2')
1051
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1052
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1053
        bundle.install_revisions(repo)
1054
        return repo
1055
2520.4.99 by Aaron Bentley
Test conversion across models
1056
    def test_across_models(self):
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1057
        repo = self.make_repo_with_installed_revisions()
3380.1.12 by Aaron Bentley
fix test
1058
        inv = repo.get_inventory('rev2')
2520.4.99 by Aaron Bentley
Test conversion across models
1059
        self.assertEqual('rev2', inv.root.revision)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1060
        root_id = inv.root.file_id
1061
        repo.lock_read()
1062
        self.addCleanup(repo.unlock)
1063
        self.assertEqual({(root_id, 'rev1'):(),
1064
            (root_id, 'rev2'):((root_id, 'rev1'),)},
1065
            repo.texts.get_parent_map([(root_id, 'rev1'), (root_id, 'rev2')]))
2520.4.99 by Aaron Bentley
Test conversion across models
1066
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1067
    def test_inv_hash_across_serializers(self):
1068
        repo = self.make_repo_with_installed_revisions()
4988.3.1 by Jelmer Vernooij
Remove Repository.get_inventory_sha1().
1069
        recorded_inv_sha1 = repo.get_revision('rev2').inventory_sha1
4988.5.1 by Jelmer Vernooij
Rename Repository.get_inventory_xml -> Repository._get_inventory_xml.
1070
        xml = repo._get_inventory_xml('rev2')
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1071
        self.assertEqual(osutils.sha_string(xml), recorded_inv_sha1)
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1072
2520.4.99 by Aaron Bentley
Test conversion across models
1073
    def test_across_models_incompatible(self):
1074
        tree = self.make_simple_tree('dirstate-with-subtree')
1075
        tree.commit('hello', rev_id='rev1')
1076
        tree.commit('hello', rev_id='rev2')
1077
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1078
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1079
        except errors.IncompatibleBundleFormat:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1080
            raise tests.TestSkipped("Format 0.8 doesn't work with knit3")
2520.4.99 by Aaron Bentley
Test conversion across models
1081
        repo = self.make_repository('repo', format='knit')
1082
        bundle.install_revisions(repo)
1083
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1084
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1085
        self.assertRaises(errors.IncompatibleRevision,
1086
                          bundle.install_revisions, repo)
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1087
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1088
    def test_get_merge_request(self):
1089
        tree = self.make_simple_tree()
1090
        tree.commit('hello', rev_id='rev1')
1091
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1092
        bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1093
        result = bundle.get_merge_request(tree.branch.repository)
1094
        self.assertEqual((None, 'rev1', 'inapplicable'), result)
1095
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1096
    def test_with_subtree(self):
1097
        tree = self.make_branch_and_tree('tree',
1098
                                         format='dirstate-with-subtree')
1099
        self.b1 = tree.branch
1100
        subtree = self.make_branch_and_tree('tree/subtree',
1101
                                            format='dirstate-with-subtree')
1102
        tree.add('subtree')
1103
        tree.commit('hello', rev_id='rev1')
1104
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1105
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1106
        except errors.IncompatibleBundleFormat:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1107
            raise tests.TestSkipped("Format 0.8 doesn't work with knit3")
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1108
        if isinstance(bundle, v09.BundleInfo09):
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1109
            raise tests.TestSkipped("Format 0.9 doesn't work with subtrees")
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1110
        repo = self.make_repository('repo', format='knit')
1111
        self.assertRaises(errors.IncompatibleRevision,
1112
                          bundle.install_revisions, repo)
1113
        repo2 = self.make_repository('repo2', format='dirstate-with-subtree')
1114
        bundle.install_revisions(repo2)
1115
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1116
    def test_revision_id_with_slash(self):
1117
        self.tree1 = self.make_branch_and_tree('tree')
1118
        self.b1 = self.tree1.branch
1119
        try:
1120
            self.tree1.commit('Revision/id/with/slashes', rev_id='rev/id')
1121
        except ValueError:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1122
            raise tests.TestSkipped(
1123
                "Repository doesn't support revision ids with slashes")
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1124
        bundle = self.get_valid_bundle('null:', 'rev/id')
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1125
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1126
    def test_skip_file(self):
1127
        """Make sure we don't accidentally write to the wrong versionedfile"""
1128
        self.tree1 = self.make_branch_and_tree('tree')
1129
        self.b1 = self.tree1.branch
1130
        # rev1 is not present in bundle, done by fetch
1131
        self.build_tree_contents([('tree/file2', 'contents1')])
1132
        self.tree1.add('file2', 'file2-id')
1133
        self.tree1.commit('rev1', rev_id='reva')
1134
        self.build_tree_contents([('tree/file3', 'contents2')])
1135
        # rev2 is present in bundle, and done by fetch
1136
        # having file1 in the bunle causes file1's versionedfile to be opened.
1137
        self.tree1.add('file3', 'file3-id')
1138
        self.tree1.commit('rev2')
1139
        # Updating file2 should not cause an attempt to add to file1's vf
1140
        target = self.tree1.bzrdir.sprout('target').open_workingtree()
1141
        self.build_tree_contents([('tree/file2', 'contents3')])
1142
        self.tree1.commit('rev3', rev_id='rev3')
1143
        bundle = self.get_valid_bundle('reva', 'rev3')
2520.6.5 by Aaron Bentley
Skip for bundle formats that don't provide get_bundle_reader
1144
        if getattr(bundle, 'get_bundle_reader', None) is None:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1145
            raise tests.TestSkipped('Bundle format cannot provide reader')
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1146
        # be sure that file1 comes before file2
1147
        for b, m, k, r, f in bundle.get_bundle_reader().iter_records():
1148
            if f == 'file3-id':
1149
                break
1150
            self.assertNotEqual(f, 'file2-id')
1151
        bundle.install_revisions(target.branch.repository)
1152
2520.4.43 by Aaron Bentley
Fix test suite
1153
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1154
class V08BundleTester(BundleTester, tests.TestCaseWithTransport):
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
1155
1156
    format = '0.8'
1157
1158
    def test_bundle_empty_property(self):
1159
        """Test serializing revision properties with an empty value."""
1160
        tree = self.make_branch_and_memory_tree('tree')
1161
        tree.lock_write()
1162
        self.addCleanup(tree.unlock)
1163
        tree.add([''], ['TREE_ROOT'])
1164
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1165
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1166
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1167
        self.assertContainsRe(bundle_sio.getvalue(),
1168
                              '# properties:\n'
1169
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1170
                              '#   empty: \n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1171
                              '#   one: two\n'
1172
                             )
1173
        bundle = read_bundle(bundle_sio)
1174
        revision_info = bundle.revisions[0]
1175
        self.assertEqual('rev1', revision_info.revision_id)
1176
        rev = revision_info.as_revision()
1177
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1178
                         rev.properties)
1179
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1180
    def get_bundle_tree(self, bundle, revision_id):
1181
        repository = self.make_repository('repo')
1182
        return bundle.revision_tree(repository, 'revid1')
1183
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1184
    def test_bundle_empty_property_alt(self):
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1185
        """Test serializing revision properties with an empty value.
1186
1187
        Older readers had a bug when reading an empty property.
1188
        They assumed that all keys ended in ': \n'. However they would write an
1189
        empty value as ':\n'. This tests make sure that all newer bzr versions
1190
        can handle th second form.
1191
        """
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1192
        tree = self.make_branch_and_memory_tree('tree')
1193
        tree.lock_write()
1194
        self.addCleanup(tree.unlock)
1195
        tree.add([''], ['TREE_ROOT'])
1196
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1197
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1198
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1199
        txt = bundle_sio.getvalue()
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1200
        loc = txt.find('#   empty: ') + len('#   empty:')
1201
        # Create a new bundle, which strips the trailing space after empty
1202
        bundle_sio = StringIO(txt[:loc] + txt[loc+1:])
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1203
1204
        self.assertContainsRe(bundle_sio.getvalue(),
1205
                              '# properties:\n'
1206
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1207
                              '#   empty:\n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1208
                              '#   one: two\n'
1209
                             )
1210
        bundle = read_bundle(bundle_sio)
1211
        revision_info = bundle.revisions[0]
1212
        self.assertEqual('rev1', revision_info.revision_id)
1213
        rev = revision_info.as_revision()
1214
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1215
                         rev.properties)
1216
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1217
    def test_bundle_sorted_properties(self):
1218
        """For stability the writer should write properties in sorted order."""
1219
        tree = self.make_branch_and_memory_tree('tree')
1220
        tree.lock_write()
1221
        self.addCleanup(tree.unlock)
1222
1223
        tree.add([''], ['TREE_ROOT'])
1224
        tree.commit('One', rev_id='rev1',
1225
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
1226
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1227
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1228
        self.assertContainsRe(bundle_sio.getvalue(),
1229
                              '# properties:\n'
1230
                              '#   a: 4\n'
1231
                              '#   b: 3\n'
1232
                              '#   branch-nick: tree\n'
1233
                              '#   c: 2\n'
1234
                              '#   d: 1\n'
1235
                             )
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
1236
        bundle = read_bundle(bundle_sio)
1237
        revision_info = bundle.revisions[0]
1238
        self.assertEqual('rev1', revision_info.revision_id)
1239
        rev = revision_info.as_revision()
1240
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
1241
                          'd':'1'}, rev.properties)
1242
1243
    def test_bundle_unicode_properties(self):
1244
        """We should be able to round trip a non-ascii property."""
1245
        tree = self.make_branch_and_memory_tree('tree')
1246
        tree.lock_write()
1247
        self.addCleanup(tree.unlock)
1248
1249
        tree.add([''], ['TREE_ROOT'])
1250
        # Revisions themselves do not require anything about revision property
1251
        # keys, other than that they are a basestring, and do not contain
1252
        # whitespace.
1253
        # However, Testaments assert than they are str(), and thus should not
1254
        # be Unicode.
1255
        tree.commit('One', rev_id='rev1',
1256
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1257
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1258
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
1259
        self.assertContainsRe(bundle_sio.getvalue(),
1260
                              '# properties:\n'
1261
                              '#   alpha: \xce\xb1\n'
1262
                              '#   branch-nick: tree\n'
1263
                              '#   omega: \xce\xa9\n'
1264
                             )
1265
        bundle = read_bundle(bundle_sio)
1266
        revision_info = bundle.revisions[0]
1267
        self.assertEqual('rev1', revision_info.revision_id)
1268
        rev = revision_info.as_revision()
1269
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
1270
                          'alpha':u'\u03b1'}, rev.properties)
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1271
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1272
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1273
class V09BundleKnit2Tester(V08BundleTester):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1274
1275
    format = '0.9'
1276
1277
    def bzrdir_format(self):
1278
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
1279
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1280
        return format
1281
1282
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1283
class V09BundleKnit1Tester(V08BundleTester):
1284
1285
    format = '0.9'
1286
1287
    def bzrdir_format(self):
1288
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1289
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1290
        return format
1291
1292
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1293
class V4BundleTester(BundleTester, tests.TestCaseWithTransport):
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1294
2520.4.136 by Aaron Bentley
Fix format strings
1295
    format = '4'
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1296
1297
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
1298
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1299
        Make sure that the text generated is valid, and that it
1300
        can be applied against the base, and generate the same information.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1301
1302
        :return: The in-memory bundle
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1303
        """
1304
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1305
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1306
        # This should also validate the generated bundle
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1307
        bundle = read_bundle(bundle_txt)
1308
        repository = self.b1.repository
1309
        for bundle_rev in bundle.real_revisions:
1310
            # These really should have already been checked when we read the
1311
            # bundle, since it computes the sha1 hash for the revision, which
1312
            # only will match if everything is okay, but lets be explicit about
1313
            # it
1314
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1315
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1316
                      'timestamp', 'timezone', 'message', 'committer',
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1317
                      'parent_ids', 'properties'):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1318
                self.assertEqual(getattr(branch_rev, a),
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1319
                                 getattr(bundle_rev, a))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1320
            self.assertEqual(len(branch_rev.parent_ids),
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1321
                             len(bundle_rev.parent_ids))
2520.4.29 by Aaron Bentley
Reactivate some testing, fix topo_iter
1322
        self.assertEqual(set(rev_ids),
1323
                         set([r.revision_id for r in bundle.real_revisions]))
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1324
        self.valid_apply_bundle(base_rev_id, bundle,
1325
                                   checkout_dir=checkout_dir)
1326
1327
        return bundle
1328
2520.4.34 by Aaron Bentley
Add signature support
1329
    def get_invalid_bundle(self, base_rev_id, rev_id):
1330
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1331
        Munge the text so that it's invalid.
1332
1333
        :return: The in-memory bundle
1334
        """
1335
        from bzrlib.bundle import serializer
1336
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1337
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1338
        new_text = new_text.replace('<file file_id="exe-1"',
1339
                                    '<file executable="y" file_id="exe-1"')
4543.2.11 by John Arbash Meinel
Use a fixed file-id for the root to make the tests more stable.
1340
        new_text = new_text.replace('B260', 'B275')
2520.4.34 by Aaron Bentley
Add signature support
1341
        bundle_txt = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1342
        bundle_txt.write(serializer._get_bundle_header('4'))
2520.4.34 by Aaron Bentley
Add signature support
1343
        bundle_txt.write('\n')
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1344
        bundle_txt.write(new_text.encode('bz2'))
2520.4.34 by Aaron Bentley
Add signature support
1345
        bundle_txt.seek(0)
1346
        bundle = read_bundle(bundle_txt)
1347
        self.valid_apply_bundle(base_rev_id, bundle)
1348
        return bundle
1349
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1350
    def create_bundle_text(self, base_rev_id, rev_id):
1351
        bundle_txt = StringIO()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1352
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id,
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1353
                               bundle_txt, format=self.format)
1354
        bundle_txt.seek(0)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1355
        self.assertEqual(bundle_txt.readline(),
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1356
                         '# Bazaar revision bundle v%s\n' % self.format)
1357
        self.assertEqual(bundle_txt.readline(), '#\n')
1358
        rev = self.b1.repository.get_revision(rev_id)
1359
        bundle_txt.seek(0)
1360
        return bundle_txt, rev_ids
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1361
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1362
    def get_bundle_tree(self, bundle, revision_id):
1363
        repository = self.make_repository('repo')
1364
        bundle.install_revisions(repository)
1365
        return repository.revision_tree(revision_id)
1366
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1367
    def test_creation(self):
1368
        tree = self.make_branch_and_tree('tree')
2520.4.8 by Aaron Bentley
Serialize inventory
1369
        self.build_tree_contents([('tree/file', 'contents1\nstatic\n')])
2520.4.6 by Aaron Bentley
Get installation started
1370
        tree.add('file', 'fileid-2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1371
        tree.commit('added file', rev_id='rev1')
2520.4.8 by Aaron Bentley
Serialize inventory
1372
        self.build_tree_contents([('tree/file', 'contents2\nstatic\n')])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1373
        tree.commit('changed file', rev_id='rev2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1374
        s = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1375
        serializer = BundleSerializerV4('1.0')
2520.4.8 by Aaron Bentley
Serialize inventory
1376
        serializer.write(tree.branch.repository, ['rev1', 'rev2'], {}, s)
2520.4.5 by Aaron Bentley
Start work on reading mpbundles
1377
        s.seek(0)
2520.4.6 by Aaron Bentley
Get installation started
1378
        tree2 = self.make_branch_and_tree('target')
1379
        target_repo = tree2.branch.repository
1380
        install_bundle(target_repo, serializer.read(s))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1381
        target_repo.lock_read()
1382
        self.addCleanup(target_repo.unlock)
4202.1.1 by John Arbash Meinel
Update Repository.iter_files_bytes() to return an iterable of bytestrings.
1383
        # Turn the 'iterators_of_bytes' back into simple strings for comparison
1384
        repo_texts = dict((i, ''.join(content)) for i, content
1385
                          in target_repo.iter_files_bytes(
1386
                                [('fileid-2', 'rev1', '1'),
1387
                                 ('fileid-2', 'rev2', '2')]))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1388
        self.assertEqual({'1':'contents1\nstatic\n',
4202.1.1 by John Arbash Meinel
Update Repository.iter_files_bytes() to return an iterable of bytestrings.
1389
                          '2':'contents2\nstatic\n'},
1390
                         repo_texts)
2520.4.8 by Aaron Bentley
Serialize inventory
1391
        rtree = target_repo.revision_tree('rev2')
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1392
        inventory_vf = target_repo.inventories
1393
        # If the inventory store has a graph, it must match the revision graph.
1394
        self.assertSubset(
1395
            [inventory_vf.get_parent_map([('rev2',)])[('rev2',)]],
1396
            [None, (('rev1',),)])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1397
        self.assertEqual('changed file',
1398
                         target_repo.get_revision('rev2').message)
2520.4.6 by Aaron Bentley
Get installation started
1399
2520.4.32 by Aaron Bentley
Fix test case
1400
    @staticmethod
1401
    def get_raw(bundle_file):
1402
        bundle_file.seek(0)
2520.4.70 by Aaron Bentley
Yank patch-handling functionality
1403
        line = bundle_file.readline()
1404
        line = bundle_file.readline()
2520.4.32 by Aaron Bentley
Fix test case
1405
        lines = bundle_file.readlines()
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1406
        return ''.join(lines).decode('bz2')
2520.4.32 by Aaron Bentley
Fix test case
1407
2520.4.34 by Aaron Bentley
Add signature support
1408
    def test_copy_signatures(self):
1409
        tree_a = self.make_branch_and_tree('tree_a')
1410
        import bzrlib.gpg
1411
        import bzrlib.commit as commit
1412
        oldstrategy = bzrlib.gpg.GPGStrategy
1413
        branch = tree_a.branch
1414
        repo_a = branch.repository
1415
        tree_a.commit("base", allow_pointless=True, rev_id='A')
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1416
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
2520.4.34 by Aaron Bentley
Add signature support
1417
        try:
1418
            from bzrlib.testament import Testament
1419
            # monkey patch gpg signing mechanism
1420
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
1421
            new_config = test_commit.MustSignConfig()
6351.3.3 by Jelmer Vernooij
Convert more stuff to use config stacks.
1422
            commit.Commit(config_stack=new_config).commit(message="base",
2520.4.34 by Aaron Bentley
Add signature support
1423
                                                    allow_pointless=True,
1424
                                                    rev_id='B',
1425
                                                    working_tree=tree_a)
1426
            def sign(text):
1427
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
1428
            self.assertTrue(repo_a.has_signature_for_revision_id('B'))
1429
        finally:
1430
            bzrlib.gpg.GPGStrategy = oldstrategy
1431
        tree_b = self.make_branch_and_tree('tree_b')
1432
        repo_b = tree_b.branch.repository
1433
        s = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1434
        serializer = BundleSerializerV4('4')
2520.4.34 by Aaron Bentley
Add signature support
1435
        serializer.write(tree_a.branch.repository, ['A', 'B'], {}, s)
1436
        s.seek(0)
1437
        install_bundle(repo_b, serializer.read(s))
1438
        self.assertTrue(repo_b.has_signature_for_revision_id('B'))
1439
        self.assertEqual(repo_b.get_signature_text('B'),
1440
                         repo_a.get_signature_text('B'))
2520.4.100 by Aaron Bentley
Fix repeat signature installs
1441
        s.seek(0)
1442
        # ensure repeat installs are harmless
1443
        install_bundle(repo_b, serializer.read(s))
2520.4.34 by Aaron Bentley
Add signature support
1444
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1445
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1446
class V4_2aBundleTester(V4BundleTester):
1447
1448
    def bzrdir_format(self):
1449
        return '2a'
1450
4543.2.8 by John Arbash Meinel
Add a custom get_invalid_bundle and allow BadBundle to be
1451
    def get_invalid_bundle(self, base_rev_id, rev_id):
1452
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1453
        Munge the text so that it's invalid.
1454
1455
        :return: The in-memory bundle
1456
        """
1457
        from bzrlib.bundle import serializer
1458
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1459
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
4543.2.9 by John Arbash Meinel
Down to 2 failing tests.
1460
        # We are going to be replacing some text to set the executable bit on a
1461
        # file. Make sure the text replacement actually works correctly.
4543.2.11 by John Arbash Meinel
Use a fixed file-id for the root to make the tests more stable.
1462
        self.assertContainsRe(new_text, '(?m)B244\n\ni 1\n<inventory')
4543.2.8 by John Arbash Meinel
Add a custom get_invalid_bundle and allow BadBundle to be
1463
        new_text = new_text.replace('<file file_id="exe-1"',
1464
                                    '<file executable="y" file_id="exe-1"')
4543.2.11 by John Arbash Meinel
Use a fixed file-id for the root to make the tests more stable.
1465
        new_text = new_text.replace('B244', 'B259')
4543.2.8 by John Arbash Meinel
Add a custom get_invalid_bundle and allow BadBundle to be
1466
        bundle_txt = StringIO()
1467
        bundle_txt.write(serializer._get_bundle_header('4'))
1468
        bundle_txt.write('\n')
1469
        bundle_txt.write(new_text.encode('bz2'))
1470
        bundle_txt.seek(0)
1471
        bundle = read_bundle(bundle_txt)
1472
        self.valid_apply_bundle(base_rev_id, bundle)
1473
        return bundle
1474
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1475
    def make_merged_branch(self):
4543.2.6 by John Arbash Meinel
redefinning self.bzrdir_format() automatically sets the default format.
1476
        builder = self.make_branch_builder('source')
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1477
        builder.start_series()
1478
        builder.build_snapshot('a@cset-0-1', None, [
1479
            ('add', ('', 'root-id', 'directory', None)),
1480
            ('add', ('file', 'file-id', 'file', 'original content\n')),
1481
            ])
1482
        builder.build_snapshot('a@cset-0-2a', ['a@cset-0-1'], [
1483
            ('modify', ('file-id', 'new-content\n')),
1484
            ])
1485
        builder.build_snapshot('a@cset-0-2b', ['a@cset-0-1'], [
1486
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
1487
            ])
1488
        builder.build_snapshot('a@cset-0-3', ['a@cset-0-2a', 'a@cset-0-2b'], [
1489
            ('add', ('other-file', 'file2-id', 'file', 'file2-content\n')),
1490
            ])
1491
        builder.finish_series()
1492
        self.b1 = builder.get_branch()
1493
        self.b1.lock_read()
1494
        self.addCleanup(self.b1.unlock)
1495
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1496
    def make_bundle_just_inventories(self, base_revision_id,
1497
                                     target_revision_id,
1498
                                     revision_ids):
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1499
        sio = StringIO()
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1500
        writer = v4.BundleWriteOperation(base_revision_id, target_revision_id,
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1501
                                         self.b1.repository, sio)
1502
        writer.bundle.begin()
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1503
        writer._add_inventory_mpdiffs_from_serializer(revision_ids)
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1504
        writer.bundle.end()
1505
        sio.seek(0)
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1506
        return sio
1507
1508
    def test_single_inventory_multiple_parents_as_xml(self):
1509
        self.make_merged_branch()
1510
        sio = self.make_bundle_just_inventories('a@cset-0-1', 'a@cset-0-3',
1511
                                                ['a@cset-0-3'])
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1512
        reader = v4.BundleReader(sio, stream_input=False)
1513
        records = list(reader.iter_records())
1514
        self.assertEqual(1, len(records))
1515
        (bytes, metadata, repo_kind, revision_id,
1516
         file_id) = records[0]
1517
        self.assertIs(None, file_id)
1518
        self.assertEqual('a@cset-0-3', revision_id)
1519
        self.assertEqual('inventory', repo_kind)
1520
        self.assertEqual({'parents': ['a@cset-0-2a', 'a@cset-0-2b'],
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1521
                          'sha1': '09c53b0c4de0895e11a2aacc34fef60a6e70865c',
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1522
                          'storage_kind': 'mpdiff',
1523
                         }, metadata)
1524
        # We should have an mpdiff that takes some lines from both parents.
1525
        self.assertEqualDiff(
1526
            'i 1\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1527
            '<inventory format="10" revision_id="a@cset-0-3">\n'
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1528
            '\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1529
            'c 0 1 1 2\n'
1530
            'c 1 3 3 2\n', bytes)
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1531
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1532
    def test_single_inv_no_parents_as_xml(self):
1533
        self.make_merged_branch()
1534
        sio = self.make_bundle_just_inventories('null:', 'a@cset-0-1',
1535
                                                ['a@cset-0-1'])
1536
        reader = v4.BundleReader(sio, stream_input=False)
1537
        records = list(reader.iter_records())
1538
        self.assertEqual(1, len(records))
1539
        (bytes, metadata, repo_kind, revision_id,
1540
         file_id) = records[0]
1541
        self.assertIs(None, file_id)
1542
        self.assertEqual('a@cset-0-1', revision_id)
1543
        self.assertEqual('inventory', repo_kind)
1544
        self.assertEqual({'parents': [],
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1545
                          'sha1': 'a13f42b142d544aac9b085c42595d304150e31a2',
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1546
                          'storage_kind': 'mpdiff',
1547
                         }, metadata)
1548
        # We should have an mpdiff that takes some lines from both parents.
1549
        self.assertEqualDiff(
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1550
            'i 4\n'
1551
            '<inventory format="10" revision_id="a@cset-0-1">\n'
1552
            '<directory file_id="root-id" name=""'
1553
                ' revision="a@cset-0-1" />\n'
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1554
            '<file file_id="file-id" name="file" parent_id="root-id"'
1555
                ' revision="a@cset-0-1"'
1556
                ' text_sha1="09c2f8647e14e49e922b955c194102070597c2d1"'
1557
                ' text_size="17" />\n'
1558
            '</inventory>\n'
1559
            '\n', bytes)
1560
1561
    def test_multiple_inventories_as_xml(self):
1562
        self.make_merged_branch()
1563
        sio = self.make_bundle_just_inventories('a@cset-0-1', 'a@cset-0-3',
1564
            ['a@cset-0-2a', 'a@cset-0-2b', 'a@cset-0-3'])
1565
        reader = v4.BundleReader(sio, stream_input=False)
1566
        records = list(reader.iter_records())
1567
        self.assertEqual(3, len(records))
1568
        revision_ids = [rev_id for b, m, k, rev_id, f in records]
1569
        self.assertEqual(['a@cset-0-2a', 'a@cset-0-2b', 'a@cset-0-3'],
1570
                         revision_ids)
1571
        metadata_2a = records[0][1]
1572
        self.assertEqual({'parents': ['a@cset-0-1'],
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1573
                          'sha1': '1e105886d62d510763e22885eec733b66f5f09bf',
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1574
                          'storage_kind': 'mpdiff',
1575
                         }, metadata_2a)
1576
        metadata_2b = records[1][1]
1577
        self.assertEqual({'parents': ['a@cset-0-1'],
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1578
                          'sha1': 'f03f12574bdb5ed2204c28636c98a8547544ccd8',
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1579
                          'storage_kind': 'mpdiff',
1580
                         }, metadata_2b)
1581
        metadata_3 = records[2][1]
1582
        self.assertEqual({'parents': ['a@cset-0-2a', 'a@cset-0-2b'],
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1583
                          'sha1': '09c53b0c4de0895e11a2aacc34fef60a6e70865c',
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1584
                          'storage_kind': 'mpdiff',
1585
                         }, metadata_3)
1586
        bytes_2a = records[0][0]
1587
        self.assertEqualDiff(
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1588
            'i 1\n'
1589
            '<inventory format="10" revision_id="a@cset-0-2a">\n'
1590
            '\n'
1591
            'c 0 1 1 1\n'
1592
            'i 1\n'
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1593
            '<file file_id="file-id" name="file" parent_id="root-id"'
1594
                ' revision="a@cset-0-2a"'
1595
                ' text_sha1="50f545ff40e57b6924b1f3174b267ffc4576e9a9"'
1596
                ' text_size="12" />\n'
1597
            '\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1598
            'c 0 3 3 1\n', bytes_2a)
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1599
        bytes_2b = records[1][0]
1600
        self.assertEqualDiff(
1601
            'i 1\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1602
            '<inventory format="10" revision_id="a@cset-0-2b">\n'
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1603
            '\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1604
            'c 0 1 1 2\n'
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1605
            'i 1\n'
1606
            '<file file_id="file2-id" name="other-file" parent_id="root-id"'
1607
                ' revision="a@cset-0-2b"'
1608
                ' text_sha1="b46c0c8ea1e5ef8e46fc8894bfd4752a88ec939e"'
1609
                ' text_size="14" />\n'
1610
            '\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1611
            'c 0 3 4 1\n', bytes_2b)
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1612
        bytes_3 = records[2][0]
1613
        self.assertEqualDiff(
1614
            'i 1\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1615
            '<inventory format="10" revision_id="a@cset-0-3">\n'
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1616
            '\n'
4543.2.7 by John Arbash Meinel
It turns out CHKSerializer was inheriting from xml5
1617
            'c 0 1 1 2\n'
1618
            'c 1 3 3 2\n', bytes_3)
1619
1620
    def test_creating_bundle_preserves_chk_pages(self):
1621
        self.make_merged_branch()
1622
        target = self.b1.bzrdir.sprout('target',
1623
                                       revision_id='a@cset-0-2a').open_branch()
1624
        bundle_txt, rev_ids = self.create_bundle_text('a@cset-0-2a',
1625
                                                      'a@cset-0-3')
1626
        self.assertEqual(['a@cset-0-2b', 'a@cset-0-3'], rev_ids)
1627
        bundle = read_bundle(bundle_txt)
1628
        target.lock_write()
1629
        self.addCleanup(target.unlock)
1630
        install_bundle(target.repository, bundle)
1631
        inv1 = self.b1.repository.inventories.get_record_stream([
1632
            ('a@cset-0-3',)], 'unordered',
1633
            True).next().get_bytes_as('fulltext')
1634
        inv2 = target.repository.inventories.get_record_stream([
1635
            ('a@cset-0-3',)], 'unordered',
1636
            True).next().get_bytes_as('fulltext')
1637
        self.assertEqualDiff(inv1, inv2)
4543.2.5 by John Arbash Meinel
Fix issues with keys/ids and ghost handling.
1638
4543.2.4 by John Arbash Meinel
Start working on code that will use Repository._serializer.write_inventory_to_strig.
1639
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1640
class MungedBundleTester(object):
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1641
1642
    def build_test_bundle(self):
1643
        wt = self.make_branch_and_tree('b1')
1644
1645
        self.build_tree(['b1/one'])
1646
        wt.add('one')
1647
        wt.commit('add one', rev_id='a@cset-0-1')
1648
        self.build_tree(['b1/two'])
1649
        wt.add('two')
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1650
        wt.commit('add two', rev_id='a@cset-0-2',
1651
                  revprops={'branch-nick':'test'})
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1652
1653
        bundle_txt = StringIO()
1654
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1655
                               'a@cset-0-1', bundle_txt, self.format)
1656
        self.assertEqual(set(['a@cset-0-2']), set(rev_ids))
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1657
        bundle_txt.seek(0, 0)
1658
        return bundle_txt
1659
1660
    def check_valid(self, bundle):
1661
        """Check that after whatever munging, the final object is valid."""
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1662
        self.assertEqual(['a@cset-0-2'],
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1663
            [r.revision_id for r in bundle.real_revisions])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1664
1665
    def test_extra_whitespace(self):
1666
        bundle_txt = self.build_test_bundle()
1667
1668
        # Seek to the end of the file
1669
        # Adding one extra newline used to give us
1670
        # TypeError: float() argument must be a string or a number
1671
        bundle_txt.seek(0, 2)
1672
        bundle_txt.write('\n')
1673
        bundle_txt.seek(0)
1674
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1675
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1676
        self.check_valid(bundle)
1677
1678
    def test_extra_whitespace_2(self):
1679
        bundle_txt = self.build_test_bundle()
1680
1681
        # Seek to the end of the file
1682
        # Adding two extra newlines used to give us
1683
        # MalformedPatches: The first line of all patches should be ...
1684
        bundle_txt.seek(0, 2)
1685
        bundle_txt.write('\n\n')
1686
        bundle_txt.seek(0)
1687
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1688
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1689
        self.check_valid(bundle)
1690
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1691
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1692
class MungedBundleTesterV09(tests.TestCaseWithTransport, MungedBundleTester):
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1693
1694
    format = '0.9'
1695
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1696
    def test_missing_trailing_whitespace(self):
1697
        bundle_txt = self.build_test_bundle()
1698
1699
        # Remove a trailing newline, it shouldn't kill the parser
1700
        raw = bundle_txt.getvalue()
1701
        # The contents of the bundle don't have to be this, but this
1702
        # test is concerned with the exact case where the serializer
1703
        # creates a blank line at the end, and fails if that
1704
        # line is stripped
1705
        self.assertEqual('\n\n', raw[-2:])
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1706
        bundle_txt = StringIO(raw[:-1])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1707
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1708
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1709
        self.check_valid(bundle)
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1710
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
1711
    def test_opening_text(self):
1712
        bundle_txt = self.build_test_bundle()
1713
1714
        bundle_txt = StringIO("Some random\nemail comments\n"
1715
                              + bundle_txt.getvalue())
1716
1717
        bundle = read_bundle(bundle_txt)
1718
        self.check_valid(bundle)
1719
1720
    def test_trailing_text(self):
1721
        bundle_txt = self.build_test_bundle()
1722
1723
        bundle_txt = StringIO(bundle_txt.getvalue() +
1724
                              "Some trailing\nrandom\ntext\n")
1725
1726
        bundle = read_bundle(bundle_txt)
1727
        self.check_valid(bundle)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1728
1729
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1730
class MungedBundleTesterV4(tests.TestCaseWithTransport, MungedBundleTester):
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1731
2520.4.136 by Aaron Bentley
Fix format strings
1732
    format = '4'
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1733
1734
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1735
class TestBundleWriterReader(tests.TestCase):
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1736
1737
    def test_roundtrip_record(self):
1738
        fileobj = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1739
        writer = v4.BundleWriter(fileobj)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1740
        writer.begin()
2520.4.95 by Aaron Bentley
Add support for header/info records
1741
        writer.add_info_record(foo='bar')
1742
        writer._add_record("Record body", {'parents': ['1', '3'],
1743
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1744
        writer.end()
1745
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1746
        reader = v4.BundleReader(fileobj, stream_input=True)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1747
        record_iter = reader.iter_records()
1748
        record = record_iter.next()
1749
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1750
            'info', None, None), record)
1751
        record = record_iter.next()
1752
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1753
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1754
                          record)
1755
1756
    def test_roundtrip_record_memory_hungry(self):
1757
        fileobj = StringIO()
1758
        writer = v4.BundleWriter(fileobj)
1759
        writer.begin()
1760
        writer.add_info_record(foo='bar')
1761
        writer._add_record("Record body", {'parents': ['1', '3'],
1762
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
1763
        writer.end()
1764
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1765
        reader = v4.BundleReader(fileobj, stream_input=False)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1766
        record_iter = reader.iter_records()
2520.4.95 by Aaron Bentley
Add support for header/info records
1767
        record = record_iter.next()
1768
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1769
            'info', None, None), record)
1770
        record = record_iter.next()
1771
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1772
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1773
                          record)
1774
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1775
    def test_encode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1776
        self.assertEqual('revision/rev1',
1777
            v4.BundleWriter.encode_name('revision', 'rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1778
        self.assertEqual('file/rev//1/file-id-1',
1779
            v4.BundleWriter.encode_name('file', 'rev/1', 'file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1780
        self.assertEqual('info',
1781
            v4.BundleWriter.encode_name('info', None, None))
1782
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1783
    def test_decode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1784
        self.assertEqual(('revision', 'rev1', None),
1785
            v4.BundleReader.decode_name('revision/rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1786
        self.assertEqual(('file', 'rev/1', 'file-id-1'),
1787
            v4.BundleReader.decode_name('file/rev//1/file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1788
        self.assertEqual(('info', None, None),
1789
                         v4.BundleReader.decode_name('info'))
2520.4.131 by Aaron Bentley
Raise BadBundle for records with wrong number of names
1790
1791
    def test_too_many_names(self):
1792
        fileobj = StringIO()
1793
        writer = v4.BundleWriter(fileobj)
1794
        writer.begin()
1795
        writer.add_info_record(foo='bar')
1796
        writer._container.add_bytes_record('blah', ['two', 'names'])
1797
        writer.end()
1798
        fileobj.seek(0)
1799
        record_iter = v4.BundleReader(fileobj).iter_records()
1800
        record = record_iter.next()
1801
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1802
            'info', None, None), record)
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
1803
        self.assertRaises(errors.BadBundle, record_iter.next)
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1804
1805
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1806
class TestReadMergeableFromUrl(tests.TestCaseWithTransport):
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1807
1808
    def test_read_mergeable_skips_local(self):
1809
        """A local bundle named like the URL should not be read.
1810
        """
1811
        out, wt = test_read_bundle.create_bundle_file(self)
1812
        class FooService(object):
1813
            """A directory service that always returns source"""
1814
1815
            def look_up(self, name, url):
1816
                return 'source'
3251.4.12 by Aaron Bentley
Updates from review
1817
        directories.register('foo:', FooService, 'Testing directory service')
4985.2.1 by Vincent Ladeuil
Deploy addAttrCleanup on the whole test suite.
1818
        self.addCleanup(directories.remove, 'foo:')
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1819
        self.build_tree_contents([('./foo:bar', out.getvalue())])
1820
        self.assertRaises(errors.NotABundle, read_mergeable_from_url,
1821
                          'foo:bar')
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
1822
4547.2.2 by Andrew Bennetts
Add test for read_mergeable_from_transport raising NotABundle when TooManyRedirections happens.
1823
    def test_infinite_redirects_are_not_a_bundle(self):
1824
        """If a URL causes TooManyRedirections then NotABundle is raised.
1825
        """
1826
        from bzrlib.tests.blackbox.test_push import RedirectingMemoryServer
1827
        server = RedirectingMemoryServer()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
1828
        self.start_server(server)
4547.2.2 by Andrew Bennetts
Add test for read_mergeable_from_transport raising NotABundle when TooManyRedirections happens.
1829
        url = server.get_url() + 'infinite-loop'
1830
        self.assertRaises(errors.NotABundle, read_mergeable_from_url, url)
1831
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
1832
    def test_smart_server_connection_reset(self):
1833
        """If a smart server connection fails during the attempt to read a
1834
        bundle, then the ConnectionReset error should be propagated.
1835
        """
1836
        # Instantiate a server that will provoke a ConnectionReset
6206.1.9 by Vincent Ladeuil
Simpler fix for test_smart_server_connection_reset re-using more of the existing test server infrastructure.
1837
        sock_server = DisconnectingServer()
4659.1.2 by Robert Collins
Refactor creation and shutdown of test servers to use a common helper,
1838
        self.start_server(sock_server)
3750.1.3 by Vincent Ladeuil
Cleanups.
1839
        # We don't really care what the url is since the server will close the
1840
        # connection without interpreting it
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
1841
        url = sock_server.get_url()
1842
        self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url)
6206.1.9 by Vincent Ladeuil
Simpler fix for test_smart_server_connection_reset re-using more of the existing test server infrastructure.
1843
1844
1845
class DisconnectingHandler(SocketServer.BaseRequestHandler):
1846
    """A request handler that immediately closes any connection made to it."""
1847
1848
    def handle(self):
1849
        self.request.close()
1850
1851
1852
class DisconnectingServer(test_server.TestingTCPServerInAThread):
1853
1854
    def __init__(self):
1855
        super(DisconnectingServer, self).__init__(
1856
            ('127.0.0.1', 0),
1857
            test_server.TestingTCPServer,
1858
            DisconnectingHandler)
1859
1860
    def get_url(self):
1861
        """Return the url of the server"""
1862
        return "bzr://%s:%d/" % self.server.server_address