/brz/remove-bazaar

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