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