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