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