~bzr-pqm/bzr/bzr.dev

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