~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,
4241.14.13 by Vincent Ladeuil
Some more cleanup.
25
    diff,
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
26
    errors,
27
    inventory,
4241.14.13 by Vincent Ladeuil
Some more cleanup.
28
    merge,
3638.3.2 by Vincent Ladeuil
Fix all calls to tempfile.mkdtemp to osutils.mkdtemp.
29
    osutils,
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,
4241.14.13 by Vincent Ladeuil
Some more cleanup.
32
    tests,
1910.2.64 by Aaron Bentley
Changes from review
33
    treebuilder,
34
    )
3251.4.11 by Aaron Bentley
Fix wrong local lookups
35
from bzrlib.bundle import read_mergeable_from_url
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
36
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
1793.2.3 by Aaron Bentley
Rename read_bundle.py to bundle_data.py
37
from bzrlib.bundle.bundle_data import BundleTree
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
4241.14.13 by Vincent Ladeuil
Some more cleanup.
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
4241.14.13 by Vincent Ladeuil
Some more cleanup.
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()
4241.14.13 by Vincent Ladeuil
Some more cleanup.
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
4241.14.13 by Vincent Ladeuil
Some more cleanup.
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()
4241.14.13 by Vincent Ladeuil
Some more cleanup.
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()
4241.14.13 by Vincent Ladeuil
Some more cleanup.
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)
4241.14.13 by Vincent Ladeuil
Some more cleanup.
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
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
660
    def _test_symlink_bundle(self, link_name, link_target, new_link_target):
661
        link_id = 'link-1'
662
4241.14.13 by Vincent Ladeuil
Some more cleanup.
663
        self.requireFeature(tests.SymlinkFeature)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
664
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.87 by Aaron Bentley
Got symlink adding working
665
        self.b1 = self.tree1.branch
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
666
1185.82.87 by Aaron Bentley
Got symlink adding working
667
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
668
        tt.new_symlink(link_name, tt.root, link_target, link_id)
1185.82.87 by Aaron Bentley
Got symlink adding working
669
        tt.apply()
670
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
671
        bundle = self.get_valid_bundle('null:', 'l@cset-0-1')
672
        if getattr(bundle ,'revision_tree', None) is not None:
673
            # Not all bundle formats supports revision_tree
674
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-1')
675
            self.assertEqual(link_target, bund_tree.get_symlink_target(link_id))
676
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
677
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
678
        trans_id = tt.trans_id_tree_file_id(link_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
679
        tt.adjust_path('link2', tt.root, trans_id)
680
        tt.delete_contents(trans_id)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
681
        tt.create_symlink(new_link_target, trans_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
682
        tt.apply()
683
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
684
        bundle = self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
685
        if getattr(bundle ,'revision_tree', None) is not None:
686
            # Not all bundle formats supports revision_tree
687
            bund_tree = bundle.revision_tree(self.b1.repository, 'l@cset-0-2')
688
            self.assertEqual(new_link_target,
689
                             bund_tree.get_symlink_target(link_id))
690
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
691
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
692
        trans_id = tt.trans_id_tree_file_id(link_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
693
        tt.delete_contents(trans_id)
694
        tt.create_symlink('jupiter', trans_id)
695
        tt.apply()
696
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
697
        bundle = self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
698
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
699
        tt = TreeTransform(self.tree1)
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
700
        trans_id = tt.trans_id_tree_file_id(link_id)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
701
        tt.delete_contents(trans_id)
702
        tt.apply()
703
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
4241.14.12 by Vincent Ladeuil
Far too many modifications for a single commit, need to restart.
704
        bundle = self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
705
706
    def test_symlink_bundle(self):
707
        self._test_symlink_bundle('link', 'bar/foo', 'mars')
708
709
    def test_unicode_symlink_bundle(self):
710
        self.requireFeature(tests.UnicodeFilenameFeature)
711
        self._test_symlink_bundle(u'\N{Euro Sign}link',
712
                                  u'bar/\N{Euro Sign}foo',
713
                                  u'mars\N{Euro Sign}')
1185.82.96 by Aaron Bentley
Got first binary test passing
714
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
715
    def test_binary_bundle(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
716
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.96 by Aaron Bentley
Got first binary test passing
717
        self.b1 = self.tree1.branch
718
        tt = TreeTransform(self.tree1)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
719
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
720
        # Add
721
        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
722
        tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff',
723
            'binary-2')
1185.82.96 by Aaron Bentley
Got first binary test passing
724
        tt.apply()
725
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
726
        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.
727
728
        # Delete
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
729
        tt = TreeTransform(self.tree1)
730
        trans_id = tt.trans_id_tree_file_id('binary-1')
731
        tt.delete_contents(trans_id)
732
        tt.apply()
733
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
734
        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.
735
736
        # Rename & modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
737
        tt = TreeTransform(self.tree1)
738
        trans_id = tt.trans_id_tree_file_id('binary-2')
739
        tt.adjust_path('file3', tt.root, trans_id)
740
        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.
741
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
742
        tt.apply()
743
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
744
        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.
745
746
        # Modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
747
        tt = TreeTransform(self.tree1)
748
        trans_id = tt.trans_id_tree_file_id('binary-2')
749
        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.
750
        tt.create_file('\x00file\rcontents', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
751
        tt.apply()
752
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
753
        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
754
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
755
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
756
        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.
757
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
758
    def test_last_modified(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
759
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
760
        self.b1 = self.tree1.branch
761
        tt = TreeTransform(self.tree1)
762
        tt.new_file('file', tt.root, 'file', 'file')
763
        tt.apply()
764
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
765
766
        tt = TreeTransform(self.tree1)
767
        trans_id = tt.trans_id_tree_file_id('file')
768
        tt.delete_contents(trans_id)
769
        tt.create_file('file2', trans_id)
770
        tt.apply()
771
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
772
773
        other = self.get_checkout('a@lmod-0-1')
774
        tt = TreeTransform(other)
775
        trans_id = tt.trans_id_tree_file_id('file')
776
        tt.delete_contents(trans_id)
777
        tt.create_file('file2', trans_id)
778
        tt.apply()
779
        other.commit('modify text in another tree', rev_id='a@lmod-0-2b')
1551.15.72 by Aaron Bentley
remove builtins._merge_helper
780
        self.tree1.merge_from_branch(other.branch)
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
781
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
782
                          verbose=False)
783
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
784
        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
785
786
    def test_hide_history(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
787
        self.tree1 = self.make_branch_and_tree('b1')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
788
        self.b1 = self.tree1.branch
789
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
790
        open('b1/one', 'wb').write('one\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
791
        self.tree1.add('one')
792
        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.
793
        open('b1/one', 'wb').write('two\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
794
        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.
795
        open('b1/one', 'wb').write('three\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
796
        self.tree1.commit('modify', rev_id='a@cset-0-3')
797
        bundle_file = StringIO()
798
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
799
                               '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
800
        self.assertNotContainsRe(bundle_file.getvalue(), '\btwo\b')
2520.4.32 by Aaron Bentley
Fix test case
801
        self.assertContainsRe(self.get_raw(bundle_file), 'one')
802
        self.assertContainsRe(self.get_raw(bundle_file), 'three')
803
2520.4.75 by Aaron Bentley
Fix traceback on empty bundles.
804
    def test_bundle_same_basis(self):
805
        """Ensure using the basis as the target doesn't cause an error"""
806
        self.tree1 = self.make_branch_and_tree('b1')
807
        self.tree1.commit('add file', rev_id='a@cset-0-1')
808
        bundle_file = StringIO()
809
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-1',
810
                               'a@cset-0-1', bundle_file)
811
2520.4.32 by Aaron Bentley
Fix test case
812
    @staticmethod
813
    def get_raw(bundle_file):
814
        return bundle_file.getvalue()
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
815
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
816
    def test_unicode_bundle(self):
4241.14.13 by Vincent Ladeuil
Some more cleanup.
817
        self.requireFeature(tests.UnicodeFilenameFeature)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
818
        # Handle international characters
819
        os.mkdir('b1')
4241.14.13 by Vincent Ladeuil
Some more cleanup.
820
        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.
821
822
        self.tree1 = self.make_branch_and_tree('b1')
823
        self.b1 = self.tree1.branch
824
825
        f.write((u'A file\n'
826
            u'With international man of mystery\n'
827
            u'William Dod\xe9\n').encode('utf-8'))
828
        f.close()
829
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
830
        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
831
        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.
832
                          rev_id='i18n-1', committer=u'William Dod\xe9')
833
834
        # Add
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
835
        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.
836
837
        # Modified
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
838
        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.
839
        f.write(u'Modified \xb5\n'.encode('utf8'))
840
        f.close()
841
        self.tree1.commit(u'modified', rev_id='i18n-2')
842
843
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
844
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
845
        # Renamed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
846
        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.
847
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
848
                          committer=u'Erik B\xe5gfors')
849
850
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
851
852
        # Removed
3638.3.18 by Vincent Ladeuil
Fixed as per jam's review.
853
        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.
854
        self.tree1.commit(u'removed', rev_id='i18n-4')
855
856
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
857
858
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
859
        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.
860
861
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
862
    def test_whitespace_bundle(self):
863
        if sys.platform in ('win32', 'cygwin'):
4241.14.13 by Vincent Ladeuil
Some more cleanup.
864
            raise tests.TestSkipped('Windows doesn\'t support filenames'
865
                                    ' with tabs or trailing spaces')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
866
        self.tree1 = self.make_branch_and_tree('b1')
867
        self.b1 = self.tree1.branch
868
869
        self.build_tree(['b1/trailing space '])
870
        self.tree1.add(['trailing space '])
871
        # TODO: jam 20060701 Check for handling files with '\t' characters
872
        #       once we actually support them
873
874
        # Added
875
        self.tree1.commit('funky whitespace', rev_id='white-1')
876
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
877
        bundle = self.get_valid_bundle('null:', 'white-1')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
878
879
        # Modified
880
        open('b1/trailing space ', 'ab').write('add some text\n')
881
        self.tree1.commit('add text', rev_id='white-2')
882
883
        bundle = self.get_valid_bundle('white-1', 'white-2')
884
885
        # Renamed
886
        self.tree1.rename_one('trailing space ', ' start and end space ')
887
        self.tree1.commit('rename', rev_id='white-3')
888
889
        bundle = self.get_valid_bundle('white-2', 'white-3')
890
891
        # Removed
892
        self.tree1.remove([' start and end space '])
893
        self.tree1.commit('removed', rev_id='white-4')
894
895
        bundle = self.get_valid_bundle('white-3', 'white-4')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
896
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
897
        # Now test a complet roll-up
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
898
        bundle = self.get_valid_bundle('null:', 'white-4')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
899
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
900
    def test_alt_timezone_bundle(self):
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
901
        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
902
        self.b1 = self.tree1.branch
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
903
        builder = treebuilder.TreeBuilder()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
904
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
905
        self.tree1.lock_write()
906
        builder.start_tree(self.tree1)
907
        builder.build(['newfile'])
908
        builder.finish_tree()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
909
910
        # Asia/Colombo offset = 5 hours 30 minutes
911
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
912
                          timezone=19800, timestamp=1152544886.0)
913
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
914
        bundle = self.get_valid_bundle('null:', 'tz-1')
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
915
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
916
        rev = bundle.revisions[0]
917
        self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
918
        self.assertEqual(19800, rev.timezone)
919
        self.assertEqual(1152544886.0, rev.timestamp)
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
920
        self.tree1.unlock()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
921
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
922
    def test_bundle_root_id(self):
923
        self.tree1 = self.make_branch_and_tree('b1')
924
        self.b1 = self.tree1.branch
925
        self.tree1.commit('message', rev_id='revid1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
926
        bundle = self.get_valid_bundle('null:', 'revid1')
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
927
        tree = self.get_bundle_tree(bundle, 'revid1')
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
928
        self.assertEqual('revid1', tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
929
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
930
    def test_install_revisions(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
931
        self.tree1 = self.make_branch_and_tree('b1')
932
        self.b1 = self.tree1.branch
933
        self.tree1.commit('message', rev_id='rev2a')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
934
        bundle = self.get_valid_bundle('null:', 'rev2a')
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
935
        branch2 = self.make_branch('b2')
936
        self.assertFalse(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
937
        target_revision = bundle.install_revisions(branch2.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
938
        self.assertTrue(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
939
        self.assertEqual('rev2a', target_revision)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
940
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
941
    def test_bundle_empty_property(self):
942
        """Test serializing revision properties with an empty value."""
943
        tree = self.make_branch_and_memory_tree('tree')
944
        tree.lock_write()
945
        self.addCleanup(tree.unlock)
946
        tree.add([''], ['TREE_ROOT'])
947
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
948
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
949
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
950
        bundle = read_bundle(bundle_sio)
951
        revision_info = bundle.revisions[0]
952
        self.assertEqual('rev1', revision_info.revision_id)
953
        rev = revision_info.as_revision()
954
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
955
                         rev.properties)
956
957
    def test_bundle_sorted_properties(self):
958
        """For stability the writer should write properties in sorted order."""
959
        tree = self.make_branch_and_memory_tree('tree')
960
        tree.lock_write()
961
        self.addCleanup(tree.unlock)
962
963
        tree.add([''], ['TREE_ROOT'])
964
        tree.commit('One', rev_id='rev1',
965
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
966
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
967
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
968
        bundle = read_bundle(bundle_sio)
969
        revision_info = bundle.revisions[0]
970
        self.assertEqual('rev1', revision_info.revision_id)
971
        rev = revision_info.as_revision()
972
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
973
                          'd':'1'}, rev.properties)
974
975
    def test_bundle_unicode_properties(self):
976
        """We should be able to round trip a non-ascii property."""
977
        tree = self.make_branch_and_memory_tree('tree')
978
        tree.lock_write()
979
        self.addCleanup(tree.unlock)
980
981
        tree.add([''], ['TREE_ROOT'])
982
        # Revisions themselves do not require anything about revision property
983
        # keys, other than that they are a basestring, and do not contain
984
        # whitespace.
985
        # However, Testaments assert than they are str(), and thus should not
986
        # be Unicode.
987
        tree.commit('One', rev_id='rev1',
988
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
989
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
990
        bundle_sio, revision_ids = self.create_bundle_text('null:', 'rev1')
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
991
        bundle = read_bundle(bundle_sio)
992
        revision_info = bundle.revisions[0]
993
        self.assertEqual('rev1', revision_info.revision_id)
994
        rev = revision_info.as_revision()
995
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
996
                          'alpha':u'\u03b1'}, rev.properties)
997
2520.4.43 by Aaron Bentley
Fix test suite
998
    def test_bundle_with_ghosts(self):
999
        tree = self.make_branch_and_tree('tree')
1000
        self.b1 = tree.branch
1001
        self.build_tree_contents([('tree/file', 'content1')])
1002
        tree.add(['file'])
1003
        tree.commit('rev1')
1004
        self.build_tree_contents([('tree/file', 'content2')])
1005
        tree.add_parent_tree_id('ghost')
1006
        tree.commit('rev2', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1007
        bundle = self.get_valid_bundle('null:', 'rev2')
2520.4.43 by Aaron Bentley
Fix test suite
1008
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1009
    def make_simple_tree(self, format=None):
1010
        tree = self.make_branch_and_tree('b1', format=format)
1011
        self.b1 = tree.branch
1012
        self.build_tree(['b1/file'])
1013
        tree.add('file')
1014
        return tree
1015
1016
    def test_across_serializers(self):
1017
        tree = self.make_simple_tree('knit')
1018
        tree.commit('hello', rev_id='rev1')
2520.4.98 by Aaron Bentley
Support inventory conversion with parents
1019
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1020
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1021
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1022
        bundle.install_revisions(repo)
2520.4.98 by Aaron Bentley
Support inventory conversion with parents
1023
        inv_text = repo.get_inventory_xml('rev2')
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1024
        self.assertNotContainsRe(inv_text, 'format="5"')
2520.4.99 by Aaron Bentley
Test conversion across models
1025
        self.assertContainsRe(inv_text, 'format="7"')
1026
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1027
    def make_repo_with_installed_revisions(self):
1028
        tree = self.make_simple_tree('knit')
1029
        tree.commit('hello', rev_id='rev1')
1030
        tree.commit('hello', rev_id='rev2')
1031
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
1032
        repo = self.make_repository('repo', format='dirstate-with-subtree')
1033
        bundle.install_revisions(repo)
1034
        return repo
1035
2520.4.99 by Aaron Bentley
Test conversion across models
1036
    def test_across_models(self):
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1037
        repo = self.make_repo_with_installed_revisions()
3380.1.12 by Aaron Bentley
fix test
1038
        inv = repo.get_inventory('rev2')
2520.4.99 by Aaron Bentley
Test conversion across models
1039
        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.
1040
        root_id = inv.root.file_id
1041
        repo.lock_read()
1042
        self.addCleanup(repo.unlock)
1043
        self.assertEqual({(root_id, 'rev1'):(),
1044
            (root_id, 'rev2'):((root_id, 'rev1'),)},
1045
            repo.texts.get_parent_map([(root_id, 'rev1'), (root_id, 'rev2')]))
2520.4.99 by Aaron Bentley
Test conversion across models
1046
3380.1.8 by Aaron Bentley
Test that the stored inventory hash is correct when bundles are used
1047
    def test_inv_hash_across_serializers(self):
1048
        repo = self.make_repo_with_installed_revisions()
1049
        recorded_inv_sha1 = repo.get_inventory_sha1('rev2')
1050
        xml = repo.get_inventory_xml('rev2')
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1051
        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
1052
2520.4.99 by Aaron Bentley
Test conversion across models
1053
    def test_across_models_incompatible(self):
1054
        tree = self.make_simple_tree('dirstate-with-subtree')
1055
        tree.commit('hello', rev_id='rev1')
1056
        tree.commit('hello', rev_id='rev2')
1057
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1058
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1059
        except errors.IncompatibleBundleFormat:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1060
            raise tests.TestSkipped("Format 0.8 doesn't work with knit3")
2520.4.99 by Aaron Bentley
Test conversion across models
1061
        repo = self.make_repository('repo', format='knit')
1062
        bundle.install_revisions(repo)
1063
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1064
        bundle = read_bundle(self.create_bundle_text('null:', 'rev2')[0])
2520.4.99 by Aaron Bentley
Test conversion across models
1065
        self.assertRaises(errors.IncompatibleRevision,
1066
                          bundle.install_revisions, repo)
2520.4.97 by Aaron Bentley
Hack in support for inventory conversion
1067
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1068
    def test_get_merge_request(self):
1069
        tree = self.make_simple_tree()
1070
        tree.commit('hello', rev_id='rev1')
1071
        tree.commit('hello', rev_id='rev2')
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1072
        bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.4.109 by Aaron Bentley
start work on directive cherry-picking
1073
        result = bundle.get_merge_request(tree.branch.repository)
1074
        self.assertEqual((None, 'rev1', 'inapplicable'), result)
1075
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1076
    def test_with_subtree(self):
1077
        tree = self.make_branch_and_tree('tree',
1078
                                         format='dirstate-with-subtree')
1079
        self.b1 = tree.branch
1080
        subtree = self.make_branch_and_tree('tree/subtree',
1081
                                            format='dirstate-with-subtree')
1082
        tree.add('subtree')
1083
        tree.commit('hello', rev_id='rev1')
1084
        try:
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1085
            bundle = read_bundle(self.create_bundle_text('null:', 'rev1')[0])
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1086
        except errors.IncompatibleBundleFormat:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1087
            raise tests.TestSkipped("Format 0.8 doesn't work with knit3")
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1088
        if isinstance(bundle, v09.BundleInfo09):
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1089
            raise tests.TestSkipped("Format 0.9 doesn't work with subtrees")
2520.5.1 by Aaron Bentley
Test installing revisions with subtrees
1090
        repo = self.make_repository('repo', format='knit')
1091
        self.assertRaises(errors.IncompatibleRevision,
1092
                          bundle.install_revisions, repo)
1093
        repo2 = self.make_repository('repo2', format='dirstate-with-subtree')
1094
        bundle.install_revisions(repo2)
1095
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1096
    def test_revision_id_with_slash(self):
1097
        self.tree1 = self.make_branch_and_tree('tree')
1098
        self.b1 = self.tree1.branch
1099
        try:
1100
            self.tree1.commit('Revision/id/with/slashes', rev_id='rev/id')
1101
        except ValueError:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1102
            raise tests.TestSkipped(
1103
                "Repository doesn't support revision ids with slashes")
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1104
        bundle = self.get_valid_bundle('null:', 'rev/id')
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1105
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1106
    def test_skip_file(self):
1107
        """Make sure we don't accidentally write to the wrong versionedfile"""
1108
        self.tree1 = self.make_branch_and_tree('tree')
1109
        self.b1 = self.tree1.branch
1110
        # rev1 is not present in bundle, done by fetch
1111
        self.build_tree_contents([('tree/file2', 'contents1')])
1112
        self.tree1.add('file2', 'file2-id')
1113
        self.tree1.commit('rev1', rev_id='reva')
1114
        self.build_tree_contents([('tree/file3', 'contents2')])
1115
        # rev2 is present in bundle, and done by fetch
1116
        # having file1 in the bunle causes file1's versionedfile to be opened.
1117
        self.tree1.add('file3', 'file3-id')
1118
        self.tree1.commit('rev2')
1119
        # Updating file2 should not cause an attempt to add to file1's vf
1120
        target = self.tree1.bzrdir.sprout('target').open_workingtree()
1121
        self.build_tree_contents([('tree/file2', 'contents3')])
1122
        self.tree1.commit('rev3', rev_id='rev3')
1123
        bundle = self.get_valid_bundle('reva', 'rev3')
2520.6.5 by Aaron Bentley
Skip for bundle formats that don't provide get_bundle_reader
1124
        if getattr(bundle, 'get_bundle_reader', None) is None:
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1125
            raise tests.TestSkipped('Bundle format cannot provide reader')
2520.6.2 by Aaron Bentley
Fix bundle installation wrong-versionedfile bug
1126
        # be sure that file1 comes before file2
1127
        for b, m, k, r, f in bundle.get_bundle_reader().iter_records():
1128
            if f == 'file3-id':
1129
                break
1130
            self.assertNotEqual(f, 'file2-id')
1131
        bundle.install_revisions(target.branch.repository)
1132
2520.4.43 by Aaron Bentley
Fix test suite
1133
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1134
class V08BundleTester(BundleTester, tests.TestCaseWithTransport):
2520.4.33 by Aaron Bentley
remove test dependencies on serialization minutia
1135
1136
    format = '0.8'
1137
1138
    def test_bundle_empty_property(self):
1139
        """Test serializing revision properties with an empty value."""
1140
        tree = self.make_branch_and_memory_tree('tree')
1141
        tree.lock_write()
1142
        self.addCleanup(tree.unlock)
1143
        tree.add([''], ['TREE_ROOT'])
1144
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1145
        self.b1 = tree.branch
2520.4.132 by Aaron Bentley
Merge from bzr.dev
1146
        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'.
1147
        self.assertContainsRe(bundle_sio.getvalue(),
1148
                              '# properties:\n'
1149
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1150
                              '#   empty: \n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1151
                              '#   one: two\n'
1152
                             )
1153
        bundle = read_bundle(bundle_sio)
1154
        revision_info = bundle.revisions[0]
1155
        self.assertEqual('rev1', revision_info.revision_id)
1156
        rev = revision_info.as_revision()
1157
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1158
                         rev.properties)
1159
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1160
    def get_bundle_tree(self, bundle, revision_id):
1161
        repository = self.make_repository('repo')
1162
        return bundle.revision_tree(repository, 'revid1')
1163
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1164
    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.
1165
        """Test serializing revision properties with an empty value.
1166
1167
        Older readers had a bug when reading an empty property.
1168
        They assumed that all keys ended in ': \n'. However they would write an
1169
        empty value as ':\n'. This tests make sure that all newer bzr versions
1170
        can handle th second form.
1171
        """
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1172
        tree = self.make_branch_and_memory_tree('tree')
1173
        tree.lock_write()
1174
        self.addCleanup(tree.unlock)
1175
        tree.add([''], ['TREE_ROOT'])
1176
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
1177
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1178
        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'.
1179
        txt = bundle_sio.getvalue()
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1180
        loc = txt.find('#   empty: ') + len('#   empty:')
1181
        # Create a new bundle, which strips the trailing space after empty
1182
        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'.
1183
1184
        self.assertContainsRe(bundle_sio.getvalue(),
1185
                              '# properties:\n'
1186
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
1187
                              '#   empty:\n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
1188
                              '#   one: two\n'
1189
                             )
1190
        bundle = read_bundle(bundle_sio)
1191
        revision_info = bundle.revisions[0]
1192
        self.assertEqual('rev1', revision_info.revision_id)
1193
        rev = revision_info.as_revision()
1194
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
1195
                         rev.properties)
1196
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1197
    def test_bundle_sorted_properties(self):
1198
        """For stability the writer should write properties in sorted order."""
1199
        tree = self.make_branch_and_memory_tree('tree')
1200
        tree.lock_write()
1201
        self.addCleanup(tree.unlock)
1202
1203
        tree.add([''], ['TREE_ROOT'])
1204
        tree.commit('One', rev_id='rev1',
1205
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
1206
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1207
        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.
1208
        self.assertContainsRe(bundle_sio.getvalue(),
1209
                              '# properties:\n'
1210
                              '#   a: 4\n'
1211
                              '#   b: 3\n'
1212
                              '#   branch-nick: tree\n'
1213
                              '#   c: 2\n'
1214
                              '#   d: 1\n'
1215
                             )
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
1216
        bundle = read_bundle(bundle_sio)
1217
        revision_info = bundle.revisions[0]
1218
        self.assertEqual('rev1', revision_info.revision_id)
1219
        rev = revision_info.as_revision()
1220
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
1221
                          'd':'1'}, rev.properties)
1222
1223
    def test_bundle_unicode_properties(self):
1224
        """We should be able to round trip a non-ascii property."""
1225
        tree = self.make_branch_and_memory_tree('tree')
1226
        tree.lock_write()
1227
        self.addCleanup(tree.unlock)
1228
1229
        tree.add([''], ['TREE_ROOT'])
1230
        # Revisions themselves do not require anything about revision property
1231
        # keys, other than that they are a basestring, and do not contain
1232
        # whitespace.
1233
        # However, Testaments assert than they are str(), and thus should not
1234
        # be Unicode.
1235
        tree.commit('One', rev_id='rev1',
1236
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1237
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1238
        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.
1239
        self.assertContainsRe(bundle_sio.getvalue(),
1240
                              '# properties:\n'
1241
                              '#   alpha: \xce\xb1\n'
1242
                              '#   branch-nick: tree\n'
1243
                              '#   omega: \xce\xa9\n'
1244
                             )
1245
        bundle = read_bundle(bundle_sio)
1246
        revision_info = bundle.revisions[0]
1247
        self.assertEqual('rev1', revision_info.revision_id)
1248
        rev = revision_info.as_revision()
1249
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
1250
                          'alpha':u'\u03b1'}, rev.properties)
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1251
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1252
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1253
class V09BundleKnit2Tester(V08BundleTester):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1254
1255
    format = '0.9'
1256
1257
    def bzrdir_format(self):
1258
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
1259
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1260
        return format
1261
1262
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1263
class V09BundleKnit1Tester(V08BundleTester):
1264
1265
    format = '0.9'
1266
1267
    def bzrdir_format(self):
1268
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1269
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1270
        return format
1271
1272
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1273
class V4BundleTester(BundleTester, tests.TestCaseWithTransport):
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1274
2520.4.136 by Aaron Bentley
Fix format strings
1275
    format = '4'
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1276
1277
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
1278
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1279
        Make sure that the text generated is valid, and that it
1280
        can be applied against the base, and generate the same information.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1281
1282
        :return: The in-memory bundle
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1283
        """
1284
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1285
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1286
        # This should also validate the generated bundle
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1287
        bundle = read_bundle(bundle_txt)
1288
        repository = self.b1.repository
1289
        for bundle_rev in bundle.real_revisions:
1290
            # These really should have already been checked when we read the
1291
            # bundle, since it computes the sha1 hash for the revision, which
1292
            # only will match if everything is okay, but lets be explicit about
1293
            # it
1294
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1295
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1296
                      'timestamp', 'timezone', 'message', 'committer',
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1297
                      'parent_ids', 'properties'):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1298
                self.assertEqual(getattr(branch_rev, a),
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1299
                                 getattr(bundle_rev, a))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1300
            self.assertEqual(len(branch_rev.parent_ids),
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1301
                             len(bundle_rev.parent_ids))
2520.4.29 by Aaron Bentley
Reactivate some testing, fix topo_iter
1302
        self.assertEqual(set(rev_ids),
1303
                         set([r.revision_id for r in bundle.real_revisions]))
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1304
        self.valid_apply_bundle(base_rev_id, bundle,
1305
                                   checkout_dir=checkout_dir)
1306
1307
        return bundle
1308
2520.4.34 by Aaron Bentley
Add signature support
1309
    def get_invalid_bundle(self, base_rev_id, rev_id):
1310
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1311
        Munge the text so that it's invalid.
1312
1313
        :return: The in-memory bundle
1314
        """
1315
        from bzrlib.bundle import serializer
1316
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1317
        new_text = self.get_raw(StringIO(''.join(bundle_txt)))
1318
        new_text = new_text.replace('<file file_id="exe-1"',
1319
                                    '<file executable="y" file_id="exe-1"')
2520.4.143 by Aaron Bentley
Fix invalid bundle test
1320
        new_text = new_text.replace('B222', 'B237')
2520.4.34 by Aaron Bentley
Add signature support
1321
        bundle_txt = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1322
        bundle_txt.write(serializer._get_bundle_header('4'))
2520.4.34 by Aaron Bentley
Add signature support
1323
        bundle_txt.write('\n')
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1324
        bundle_txt.write(new_text.encode('bz2'))
2520.4.34 by Aaron Bentley
Add signature support
1325
        bundle_txt.seek(0)
1326
        bundle = read_bundle(bundle_txt)
1327
        self.valid_apply_bundle(base_rev_id, bundle)
1328
        return bundle
1329
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1330
    def create_bundle_text(self, base_rev_id, rev_id):
1331
        bundle_txt = StringIO()
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1332
        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
1333
                               bundle_txt, format=self.format)
1334
        bundle_txt.seek(0)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1335
        self.assertEqual(bundle_txt.readline(),
2520.4.14 by Aaron Bentley
Get most tests passing, use format header
1336
                         '# Bazaar revision bundle v%s\n' % self.format)
1337
        self.assertEqual(bundle_txt.readline(), '#\n')
1338
        rev = self.b1.repository.get_revision(rev_id)
1339
        bundle_txt.seek(0)
1340
        return bundle_txt, rev_ids
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1341
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1342
    def get_bundle_tree(self, bundle, revision_id):
1343
        repository = self.make_repository('repo')
1344
        bundle.install_revisions(repository)
1345
        return repository.revision_tree(revision_id)
1346
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1347
    def test_creation(self):
1348
        tree = self.make_branch_and_tree('tree')
2520.4.8 by Aaron Bentley
Serialize inventory
1349
        self.build_tree_contents([('tree/file', 'contents1\nstatic\n')])
2520.4.6 by Aaron Bentley
Get installation started
1350
        tree.add('file', 'fileid-2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1351
        tree.commit('added file', rev_id='rev1')
2520.4.8 by Aaron Bentley
Serialize inventory
1352
        self.build_tree_contents([('tree/file', 'contents2\nstatic\n')])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1353
        tree.commit('changed file', rev_id='rev2')
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1354
        s = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1355
        serializer = BundleSerializerV4('1.0')
2520.4.8 by Aaron Bentley
Serialize inventory
1356
        serializer.write(tree.branch.repository, ['rev1', 'rev2'], {}, s)
2520.4.5 by Aaron Bentley
Start work on reading mpbundles
1357
        s.seek(0)
2520.4.6 by Aaron Bentley
Get installation started
1358
        tree2 = self.make_branch_and_tree('target')
1359
        target_repo = tree2.branch.repository
1360
        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.
1361
        target_repo.lock_read()
1362
        self.addCleanup(target_repo.unlock)
4202.1.1 by John Arbash Meinel
Update Repository.iter_files_bytes() to return an iterable of bytestrings.
1363
        # Turn the 'iterators_of_bytes' back into simple strings for comparison
1364
        repo_texts = dict((i, ''.join(content)) for i, content
1365
                          in target_repo.iter_files_bytes(
1366
                                [('fileid-2', 'rev1', '1'),
1367
                                 ('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.
1368
        self.assertEqual({'1':'contents1\nstatic\n',
4202.1.1 by John Arbash Meinel
Update Repository.iter_files_bytes() to return an iterable of bytestrings.
1369
                          '2':'contents2\nstatic\n'},
1370
                         repo_texts)
2520.4.8 by Aaron Bentley
Serialize inventory
1371
        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.
1372
        inventory_vf = target_repo.inventories
1373
        # If the inventory store has a graph, it must match the revision graph.
1374
        self.assertSubset(
1375
            [inventory_vf.get_parent_map([('rev2',)])[('rev2',)]],
1376
            [None, (('rev1',),)])
2520.4.10 by Aaron Bentley
Enable installation of revisions
1377
        self.assertEqual('changed file',
1378
                         target_repo.get_revision('rev2').message)
2520.4.6 by Aaron Bentley
Get installation started
1379
2520.4.32 by Aaron Bentley
Fix test case
1380
    @staticmethod
1381
    def get_raw(bundle_file):
1382
        bundle_file.seek(0)
2520.4.70 by Aaron Bentley
Yank patch-handling functionality
1383
        line = bundle_file.readline()
1384
        line = bundle_file.readline()
2520.4.32 by Aaron Bentley
Fix test case
1385
        lines = bundle_file.readlines()
2520.4.76 by Aaron Bentley
Move base64-encoding into merge directives
1386
        return ''.join(lines).decode('bz2')
2520.4.32 by Aaron Bentley
Fix test case
1387
2520.4.34 by Aaron Bentley
Add signature support
1388
    def test_copy_signatures(self):
1389
        tree_a = self.make_branch_and_tree('tree_a')
1390
        import bzrlib.gpg
1391
        import bzrlib.commit as commit
1392
        oldstrategy = bzrlib.gpg.GPGStrategy
1393
        branch = tree_a.branch
1394
        repo_a = branch.repository
1395
        tree_a.commit("base", allow_pointless=True, rev_id='A')
1396
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
1397
        try:
1398
            from bzrlib.testament import Testament
1399
            # monkey patch gpg signing mechanism
1400
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
1401
            new_config = test_commit.MustSignConfig(branch)
1402
            commit.Commit(config=new_config).commit(message="base",
1403
                                                    allow_pointless=True,
1404
                                                    rev_id='B',
1405
                                                    working_tree=tree_a)
1406
            def sign(text):
1407
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
1408
            self.assertTrue(repo_a.has_signature_for_revision_id('B'))
1409
        finally:
1410
            bzrlib.gpg.GPGStrategy = oldstrategy
1411
        tree_b = self.make_branch_and_tree('tree_b')
1412
        repo_b = tree_b.branch.repository
1413
        s = StringIO()
2520.4.136 by Aaron Bentley
Fix format strings
1414
        serializer = BundleSerializerV4('4')
2520.4.34 by Aaron Bentley
Add signature support
1415
        serializer.write(tree_a.branch.repository, ['A', 'B'], {}, s)
1416
        s.seek(0)
1417
        install_bundle(repo_b, serializer.read(s))
1418
        self.assertTrue(repo_b.has_signature_for_revision_id('B'))
1419
        self.assertEqual(repo_b.get_signature_text('B'),
1420
                         repo_a.get_signature_text('B'))
2520.4.100 by Aaron Bentley
Fix repeat signature installs
1421
        s.seek(0)
1422
        # ensure repeat installs are harmless
1423
        install_bundle(repo_b, serializer.read(s))
2520.4.34 by Aaron Bentley
Add signature support
1424
2520.4.4 by Aaron Bentley
Get basis support for a new bundle format in place
1425
2520.4.90 by Aaron Bentley
Handle \r terminated lines in Weaves properly
1426
class V4WeaveBundleTester(V4BundleTester):
1427
1428
    def bzrdir_format(self):
2520.4.91 by Aaron Bentley
Okay, so I meant metaweave. I think.
1429
        return 'metaweave'
2520.4.90 by Aaron Bentley
Handle \r terminated lines in Weaves properly
1430
1431
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1432
class MungedBundleTester(object):
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1433
1434
    def build_test_bundle(self):
1435
        wt = self.make_branch_and_tree('b1')
1436
1437
        self.build_tree(['b1/one'])
1438
        wt.add('one')
1439
        wt.commit('add one', rev_id='a@cset-0-1')
1440
        self.build_tree(['b1/two'])
1441
        wt.add('two')
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1442
        wt.commit('add two', rev_id='a@cset-0-2',
1443
                  revprops={'branch-nick':'test'})
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1444
1445
        bundle_txt = StringIO()
1446
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1447
                               'a@cset-0-1', bundle_txt, self.format)
1448
        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
1449
        bundle_txt.seek(0, 0)
1450
        return bundle_txt
1451
1452
    def check_valid(self, bundle):
1453
        """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
1454
        self.assertEqual(['a@cset-0-2'],
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1455
            [r.revision_id for r in bundle.real_revisions])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1456
1457
    def test_extra_whitespace(self):
1458
        bundle_txt = self.build_test_bundle()
1459
1460
        # Seek to the end of the file
1461
        # Adding one extra newline used to give us
1462
        # TypeError: float() argument must be a string or a number
1463
        bundle_txt.seek(0, 2)
1464
        bundle_txt.write('\n')
1465
        bundle_txt.seek(0)
1466
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1467
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1468
        self.check_valid(bundle)
1469
1470
    def test_extra_whitespace_2(self):
1471
        bundle_txt = self.build_test_bundle()
1472
1473
        # Seek to the end of the file
1474
        # Adding two extra newlines used to give us
1475
        # MalformedPatches: The first line of all patches should be ...
1476
        bundle_txt.seek(0, 2)
1477
        bundle_txt.write('\n\n')
1478
        bundle_txt.seek(0)
1479
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1480
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1481
        self.check_valid(bundle)
1482
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1483
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1484
class MungedBundleTesterV09(tests.TestCaseWithTransport, MungedBundleTester):
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1485
1486
    format = '0.9'
1487
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1488
    def test_missing_trailing_whitespace(self):
1489
        bundle_txt = self.build_test_bundle()
1490
1491
        # Remove a trailing newline, it shouldn't kill the parser
1492
        raw = bundle_txt.getvalue()
1493
        # The contents of the bundle don't have to be this, but this
1494
        # test is concerned with the exact case where the serializer
1495
        # creates a blank line at the end, and fails if that
1496
        # line is stripped
1497
        self.assertEqual('\n\n', raw[-2:])
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1498
        bundle_txt = StringIO(raw[:-1])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1499
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1500
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1501
        self.check_valid(bundle)
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1502
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
1503
    def test_opening_text(self):
1504
        bundle_txt = self.build_test_bundle()
1505
1506
        bundle_txt = StringIO("Some random\nemail comments\n"
1507
                              + bundle_txt.getvalue())
1508
1509
        bundle = read_bundle(bundle_txt)
1510
        self.check_valid(bundle)
1511
1512
    def test_trailing_text(self):
1513
        bundle_txt = self.build_test_bundle()
1514
1515
        bundle_txt = StringIO(bundle_txt.getvalue() +
1516
                              "Some trailing\nrandom\ntext\n")
1517
1518
        bundle = read_bundle(bundle_txt)
1519
        self.check_valid(bundle)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1520
1521
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1522
class MungedBundleTesterV4(tests.TestCaseWithTransport, MungedBundleTester):
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1523
2520.4.136 by Aaron Bentley
Fix format strings
1524
    format = '4'
2520.4.79 by Aaron Bentley
Fixed up not-really-relevant munging tests
1525
1526
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1527
class TestBundleWriterReader(tests.TestCase):
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1528
1529
    def test_roundtrip_record(self):
1530
        fileobj = StringIO()
2520.4.72 by Aaron Bentley
Rename format to 4alpha
1531
        writer = v4.BundleWriter(fileobj)
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1532
        writer.begin()
2520.4.95 by Aaron Bentley
Add support for header/info records
1533
        writer.add_info_record(foo='bar')
1534
        writer._add_record("Record body", {'parents': ['1', '3'],
1535
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
2520.4.56 by Aaron Bentley
Begin adding support for arbitrary metadata
1536
        writer.end()
1537
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1538
        reader = v4.BundleReader(fileobj, stream_input=True)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1539
        record_iter = reader.iter_records()
1540
        record = record_iter.next()
1541
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1542
            'info', None, None), record)
1543
        record = record_iter.next()
1544
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1545
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1546
                          record)
1547
1548
    def test_roundtrip_record_memory_hungry(self):
1549
        fileobj = StringIO()
1550
        writer = v4.BundleWriter(fileobj)
1551
        writer.begin()
1552
        writer.add_info_record(foo='bar')
1553
        writer._add_record("Record body", {'parents': ['1', '3'],
1554
            'storage_kind':'fulltext'}, 'file', 'revid', 'fileid')
1555
        writer.end()
1556
        fileobj.seek(0)
2520.4.148 by Aaron Bentley
Updates from review
1557
        reader = v4.BundleReader(fileobj, stream_input=False)
2520.4.145 by Aaron Bentley
Add memory_friendly toggle, be memory-unfriendly for merge directives
1558
        record_iter = reader.iter_records()
2520.4.95 by Aaron Bentley
Add support for header/info records
1559
        record = record_iter.next()
1560
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1561
            'info', None, None), record)
1562
        record = record_iter.next()
1563
        self.assertEqual(("Record body", {'storage_kind': 'fulltext',
1564
                          'parents': ['1', '3']}, 'file', 'revid', 'fileid'),
1565
                          record)
1566
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1567
    def test_encode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1568
        self.assertEqual('revision/rev1',
1569
            v4.BundleWriter.encode_name('revision', 'rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1570
        self.assertEqual('file/rev//1/file-id-1',
1571
            v4.BundleWriter.encode_name('file', 'rev/1', 'file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1572
        self.assertEqual('info',
1573
            v4.BundleWriter.encode_name('info', None, None))
1574
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1575
    def test_decode_name(self):
2520.4.95 by Aaron Bentley
Add support for header/info records
1576
        self.assertEqual(('revision', 'rev1', None),
1577
            v4.BundleReader.decode_name('revision/rev1'))
2520.4.127 by Aaron Bentley
Fix up name encoding to handle revision-ids with slashes
1578
        self.assertEqual(('file', 'rev/1', 'file-id-1'),
1579
            v4.BundleReader.decode_name('file/rev//1/file-id-1'))
2520.4.95 by Aaron Bentley
Add support for header/info records
1580
        self.assertEqual(('info', None, None),
1581
                         v4.BundleReader.decode_name('info'))
2520.4.131 by Aaron Bentley
Raise BadBundle for records with wrong number of names
1582
1583
    def test_too_many_names(self):
1584
        fileobj = StringIO()
1585
        writer = v4.BundleWriter(fileobj)
1586
        writer.begin()
1587
        writer.add_info_record(foo='bar')
1588
        writer._container.add_bytes_record('blah', ['two', 'names'])
1589
        writer.end()
1590
        fileobj.seek(0)
1591
        record_iter = v4.BundleReader(fileobj).iter_records()
1592
        record = record_iter.next()
1593
        self.assertEqual((None, {'foo': 'bar', 'storage_kind': 'header'},
1594
            'info', None, None), record)
3638.3.16 by Vincent Ladeuil
Remove XFAIL from test_unicode_bundle.
1595
        self.assertRaises(errors.BadBundle, record_iter.next)
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1596
1597
4241.14.13 by Vincent Ladeuil
Some more cleanup.
1598
class TestReadMergeableFromUrl(tests.TestCaseWithTransport):
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1599
1600
    def test_read_mergeable_skips_local(self):
1601
        """A local bundle named like the URL should not be read.
1602
        """
1603
        out, wt = test_read_bundle.create_bundle_file(self)
1604
        class FooService(object):
1605
            """A directory service that always returns source"""
1606
1607
            def look_up(self, name, url):
1608
                return 'source'
3251.4.12 by Aaron Bentley
Updates from review
1609
        directories.register('foo:', FooService, 'Testing directory service')
3251.4.11 by Aaron Bentley
Fix wrong local lookups
1610
        self.addCleanup(lambda: directories.remove('foo:'))
1611
        self.build_tree_contents([('./foo:bar', out.getvalue())])
1612
        self.assertRaises(errors.NotABundle, read_mergeable_from_url,
1613
                          'foo:bar')
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
1614
1615
    def test_smart_server_connection_reset(self):
1616
        """If a smart server connection fails during the attempt to read a
1617
        bundle, then the ConnectionReset error should be propagated.
1618
        """
1619
        # Instantiate a server that will provoke a ConnectionReset
1620
        sock_server = _DisconnectingTCPServer()
1621
        sock_server.setUp()
1622
        self.addCleanup(sock_server.tearDown)
3750.1.3 by Vincent Ladeuil
Cleanups.
1623
        # We don't really care what the url is since the server will close the
1624
        # connection without interpreting it
3703.2.1 by Andrew Bennetts
Allow ConnectionReset to propagate from read_mergeable_from_url.
1625
        url = sock_server.get_url()
1626
        self.assertRaises(errors.ConnectionReset, read_mergeable_from_url, url)
1627
1628
1629
class _DisconnectingTCPServer(object):
1630
    """A TCP server that immediately closes any connection made to it."""
1631
1632
    def setUp(self):
1633
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1634
        self.sock.bind(('127.0.0.1', 0))
1635
        self.sock.listen(1)
1636
        self.port = self.sock.getsockname()[1]
1637
        self.thread = threading.Thread(
1638
            name='%s (port %d)' % (self.__class__.__name__, self.port),
1639
            target=self.accept_and_close)
1640
        self.thread.start()
1641
1642
    def accept_and_close(self):
1643
        conn, addr = self.sock.accept()
1644
        conn.shutdown(socket.SHUT_RDWR)
1645
        conn.close()
1646
1647
    def get_url(self):
1648
        return 'bzr://127.0.0.1:%d/' % (self.port,)
1649
1650
    def tearDown(self):
1651
        try:
1652
            # make sure the thread dies by connecting to the listening socket,
1653
            # just in case the test failed to do so.
1654
            conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1655
            conn.connect(self.sock.getsockname())
1656
            conn.close()
1657
        except socket.error:
1658
            pass
1659
        self.sock.close()
1660
        self.thread.join()
1661