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