/brz/remove-bazaar

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