/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
16
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
17
from cStringIO import StringIO
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
18
import os
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
19
import sys
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
20
import tempfile
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
21
1910.2.64 by Aaron Bentley
Changes from review
22
from bzrlib import (
1996.3.20 by John Arbash Meinel
[merge] bzr.dev 2063
23
    bzrdir,
24
    errors,
25
    inventory,
26
    repository,
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
27
    revision as _mod_revision,
1910.2.64 by Aaron Bentley
Changes from review
28
    treebuilder,
29
    )
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
30
from bzrlib.builtins import _merge_helper
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
31
from bzrlib.bzrdir import BzrDir
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
32
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
1793.2.3 by Aaron Bentley
Rename read_bundle.py to bundle_data.py
33
from bzrlib.bundle.bundle_data import BundleTree
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
34
from bzrlib.bundle.serializer import write_bundle, read_bundle
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
35
from bzrlib.bundle.serializer.v08 import BundleSerializerV08
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
36
from bzrlib.bundle.serializer.v09 import BundleSerializerV09
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,
45
                          TestCase, TestSkipped)
1185.82.66 by Aaron Bentley
Handle new executable files
46
from bzrlib.transform import TreeTransform
1185.82.17 by Aaron Bentley
More API updates
47
from bzrlib.workingtree import WorkingTree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
48
1185.82.90 by Aaron Bentley
Reorganized test suite
49
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
50
class MockTree(object):
51
    def __init__(self):
1731.1.4 by Aaron Bentley
merge from bzr.dev
52
        from bzrlib.inventory import InventoryDirectory, ROOT_ID
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
53
        object.__init__(self)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
54
        self.paths = {ROOT_ID: ""}
55
        self.ids = {"": ROOT_ID}
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
56
        self.contents = {}
1731.1.4 by Aaron Bentley
merge from bzr.dev
57
        self.root = InventoryDirectory(ROOT_ID, '', None)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
58
59
    inventory = property(lambda x:x)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
60
61
    def __iter__(self):
62
        return self.paths.iterkeys()
63
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
64
    def __getitem__(self, file_id):
65
        if file_id == self.root.file_id:
66
            return self.root
67
        else:
68
            return self.make_entry(file_id, self.paths[file_id])
69
70
    def parent_id(self, file_id):
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
71
        parent_dir = os.path.dirname(self.paths[file_id])
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
72
        if parent_dir == "":
73
            return None
74
        return self.ids[parent_dir]
75
76
    def iter_entries(self):
77
        for path, file_id in self.ids.iteritems():
78
            yield path, self[file_id]
79
80
    def get_file_kind(self, file_id):
81
        if file_id in self.contents:
82
            kind = 'file'
83
        else:
84
            kind = 'directory'
85
        return kind
86
87
    def make_entry(self, file_id, path):
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
88
        from bzrlib.inventory import (InventoryEntry, InventoryFile
89
                                    , InventoryDirectory, InventoryLink)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
90
        name = os.path.basename(path)
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
91
        kind = self.get_file_kind(file_id)
92
        parent_id = self.parent_id(file_id)
93
        text_sha_1, text_size = self.contents_stats(file_id)
0.5.119 by John Arbash Meinel
Recreated the factory. We really need InventoryEntry.create()
94
        if kind == 'directory':
95
            ie = InventoryDirectory(file_id, name, parent_id)
96
        elif kind == 'file':
97
            ie = InventoryFile(file_id, name, parent_id)
98
        elif kind == 'symlink':
99
            ie = InventoryLink(file_id, name, parent_id)
100
        else:
101
            raise BzrError('unknown kind %r' % kind)
0.5.91 by Aaron Bentley
Updated to match API change
102
        ie.text_sha1 = text_sha_1
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
103
        ie.text_size = text_size
104
        return ie
105
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
106
    def add_dir(self, file_id, path):
107
        self.paths[file_id] = path
108
        self.ids[path] = file_id
109
    
110
    def add_file(self, file_id, path, contents):
111
        self.add_dir(file_id, path)
112
        self.contents[file_id] = contents
113
114
    def path2id(self, path):
115
        return self.ids.get(path)
116
117
    def id2path(self, file_id):
118
        return self.paths.get(file_id)
119
120
    def has_id(self, file_id):
121
        return self.id2path(file_id) is not None
122
123
    def get_file(self, file_id):
124
        result = StringIO()
125
        result.write(self.contents[file_id])
126
        result.seek(0,0)
127
        return result
128
0.6.1 by Aaron Bentley
Fleshed out MockTree, fixed all test failures
129
    def contents_stats(self, file_id):
130
        if file_id not in self.contents:
131
            return None, None
132
        text_sha1 = sha_file(self.get_file(file_id))
133
        return text_sha1, len(self.contents[file_id])
134
135
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
136
class BTreeTester(TestCase):
137
    """A simple unittest tester for the BundleTree class."""
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
138
139
    def make_tree_1(self):
140
        mtree = MockTree()
141
        mtree.add_dir("a", "grandparent")
142
        mtree.add_dir("b", "grandparent/parent")
143
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
144
        mtree.add_dir("d", "grandparent/alt_parent")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
145
        return BundleTree(mtree, ''), mtree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
146
        
147
    def test_renames(self):
148
        """Ensure that file renames have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
149
        btree = self.make_tree_1()[0]
150
        self.assertEqual(btree.old_path("grandparent"), "grandparent")
151
        self.assertEqual(btree.old_path("grandparent/parent"), 
152
                         "grandparent/parent")
153
        self.assertEqual(btree.old_path("grandparent/parent/file"),
154
                         "grandparent/parent/file")
155
156
        self.assertEqual(btree.id2path("a"), "grandparent")
157
        self.assertEqual(btree.id2path("b"), "grandparent/parent")
158
        self.assertEqual(btree.id2path("c"), "grandparent/parent/file")
159
160
        self.assertEqual(btree.path2id("grandparent"), "a")
161
        self.assertEqual(btree.path2id("grandparent/parent"), "b")
162
        self.assertEqual(btree.path2id("grandparent/parent/file"), "c")
163
164
        assert btree.path2id("grandparent2") is None
165
        assert btree.path2id("grandparent2/parent") is None
166
        assert btree.path2id("grandparent2/parent/file") is None
167
168
        btree.note_rename("grandparent", "grandparent2")
169
        assert btree.old_path("grandparent") is None
170
        assert btree.old_path("grandparent/parent") is None
171
        assert btree.old_path("grandparent/parent/file") is None
172
173
        self.assertEqual(btree.id2path("a"), "grandparent2")
174
        self.assertEqual(btree.id2path("b"), "grandparent2/parent")
175
        self.assertEqual(btree.id2path("c"), "grandparent2/parent/file")
176
177
        self.assertEqual(btree.path2id("grandparent2"), "a")
178
        self.assertEqual(btree.path2id("grandparent2/parent"), "b")
179
        self.assertEqual(btree.path2id("grandparent2/parent/file"), "c")
180
181
        assert btree.path2id("grandparent") is None
182
        assert btree.path2id("grandparent/parent") is None
183
        assert btree.path2id("grandparent/parent/file") is None
184
185
        btree.note_rename("grandparent/parent", "grandparent2/parent2")
186
        self.assertEqual(btree.id2path("a"), "grandparent2")
187
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
188
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file")
189
190
        self.assertEqual(btree.path2id("grandparent2"), "a")
191
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
192
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), "c")
193
194
        assert btree.path2id("grandparent2/parent") is None
195
        assert btree.path2id("grandparent2/parent/file") is None
196
197
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
198
                          "grandparent2/parent2/file2")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
199
        self.assertEqual(btree.id2path("a"), "grandparent2")
200
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
201
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file2")
202
203
        self.assertEqual(btree.path2id("grandparent2"), "a")
204
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
205
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), "c")
206
207
        assert btree.path2id("grandparent2/parent2/file") is None
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
208
209
    def test_moves(self):
210
        """Ensure that file moves have the proper effect on children"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
211
        btree = self.make_tree_1()[0]
212
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
213
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
214
        self.assertEqual(btree.id2path("c"), "grandparent/alt_parent/file")
215
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), "c")
216
        assert btree.path2id("grandparent/parent/file") is None
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
217
218
    def unified_diff(self, old, new):
219
        out = StringIO()
220
        internal_diff("old", old, "new", new, out)
221
        out.seek(0,0)
222
        return out.read()
223
224
    def make_tree_2(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
225
        btree = self.make_tree_1()[0]
226
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
227
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
228
        assert btree.id2path("e") is None
229
        assert btree.path2id("grandparent/parent/file") is None
230
        btree.note_id("e", "grandparent/parent/file")
231
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
232
233
    def test_adds(self):
234
        """File/inventory adds"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
235
        btree = self.make_tree_2()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
236
        add_patch = self.unified_diff([], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
237
        btree.note_patch("grandparent/parent/file", add_patch)
238
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
239
        btree.note_target('grandparent/parent/symlink', 'venus')
240
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
241
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
242
    def adds_test(self, btree):
243
        self.assertEqual(btree.id2path("e"), "grandparent/parent/file")
244
        self.assertEqual(btree.path2id("grandparent/parent/file"), "e")
245
        self.assertEqual(btree.get_file("e").read(), "Extra cheese\n")
246
        self.assertEqual(btree.get_symlink_target('f'), 'venus')
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
247
248
    def test_adds2(self):
249
        """File/inventory adds, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
250
        btree = self.make_tree_2()
251
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
252
        add_patch = self.unified_diff(["Hello\n"], ["Extra cheese\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
253
        btree.note_patch("grandparent/parent/file", add_patch)
254
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
255
        btree.note_target('grandparent/parent/symlink', 'venus')
256
        self.adds_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
257
258
    def make_tree_3(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
259
        btree, mtree = self.make_tree_1()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
260
        mtree.add_file("e", "grandparent/parent/topping", "Anchovies\n")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
261
        btree.note_rename("grandparent/parent/file", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
262
                          "grandparent/alt_parent/file")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
263
        btree.note_rename("grandparent/parent/topping", 
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
264
                          "grandparent/alt_parent/stopping")
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
265
        return btree
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
266
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
267
    def get_file_test(self, btree):
268
        self.assertEqual(btree.get_file("e").read(), "Lemon\n")
269
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
270
271
    def test_get_file(self):
272
        """Get file contents"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
273
        btree = self.make_tree_3()
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
274
        mod_patch = self.unified_diff(["Anchovies\n"], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
275
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
276
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
277
278
    def test_get_file2(self):
279
        """Get file contents, with patch-compatibile renames"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
280
        btree = self.make_tree_3()
281
        btree.contents_by_id = False
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
282
        mod_patch = self.unified_diff([], ["Lemon\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
283
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
284
        mod_patch = self.unified_diff([], ["Hello\n"])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
285
        btree.note_patch("grandparent/alt_parent/file", mod_patch)
286
        self.get_file_test(btree)
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
287
288
    def test_delete(self):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
289
        "Deletion by bundle"
290
        btree = self.make_tree_1()[0]
291
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
292
        btree.note_deletion("grandparent/parent/file")
293
        assert btree.id2path("c") is None
294
        assert btree.path2id("grandparent/parent/file") is None
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
295
296
    def sorted_ids(self, tree):
297
        ids = list(tree)
298
        ids.sort()
299
        return ids
300
301
    def test_iteration(self):
302
        """Ensure that iteration through ids works properly"""
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
303
        btree = self.make_tree_1()[0]
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
304
        self.assertEqual(self.sorted_ids(btree),
305
            [inventory.ROOT_ID, 'a', 'b', 'c', 'd'])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
306
        btree.note_deletion("grandparent/parent/file")
307
        btree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
308
        btree.note_last_changed("grandparent/alt_parent/fool", 
1185.82.95 by Aaron Bentley
Restore path-orientation of ChangesetTree
309
                                "revisionidiguess")
1852.6.3 by Robert Collins
Make iter(Tree) consistent for all tree types.
310
        self.assertEqual(self.sorted_ids(btree),
311
            [inventory.ROOT_ID, 'a', 'b', 'd', 'e'])
0.5.66 by John Arbash Meinel
Refactoring, moving test code into test (switching back to assert is None)
312
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
313
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
314
class BundleTester1(TestCaseWithTransport):
315
316
    def test_mismatched_bundle(self):
317
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
318
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
319
        serializer = BundleSerializerV08('0.8')
320
        b = self.make_branch('.', format=format)
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
321
        self.assertRaises(errors.IncompatibleBundleFormat, serializer.write, 
1910.2.49 by Aaron Bentley
Ensure that 0.8 bundles aren't used with KnitRepository2
322
                          b.repository, [], {}, StringIO())
323
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
324
    def test_matched_bundle(self):
2067.3.1 by Martin Pool
Clean up BzrNewError, other exception classes and users.
325
        """Don't raise IncompatibleBundleFormat for knit2 and bundle0.9"""
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
326
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
327
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
328
        serializer = BundleSerializerV09('0.9')
329
        b = self.make_branch('.', format=format)
330
        serializer.write(b.repository, [], {}, StringIO())
331
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
332
    def test_mismatched_model(self):
333
        """Try copying a bundle from knit2 to knit1"""
334
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
335
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
336
        source = self.make_branch_and_tree('source', format=format)
337
        source.commit('one', rev_id='one-id')
338
        source.commit('two', rev_id='two-id')
339
        text = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
340
        write_bundle(source.branch.repository, 'two-id', 'null:', text,
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
341
                     format='0.9')
342
        text.seek(0)
343
344
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
345
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.60 by Aaron Bentley
Ensure that new-model revisions aren't installed into old-model repos
346
        target = self.make_branch('target', format=format)
347
        self.assertRaises(errors.IncompatibleRevision, install_bundle, 
348
                          target.repository, read_bundle(text))
349
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
350
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
351
class V08BundleTester(TestCaseWithTransport):
352
353
    format = '0.8'
354
355
    def bzrdir_format(self):
356
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
357
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
358
        return format
359
360
    def make_branch_and_tree(self, path, format=None):
361
        if format is None:
362
            format = self.bzrdir_format()
363
        return TestCaseWithTransport.make_branch_and_tree(self, path, format)
364
365
    def make_branch(self, path, format=None):
366
        if format is None:
367
            format = self.bzrdir_format()
368
        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.
369
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
370
    def create_bundle_text(self, base_rev_id, rev_id):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
371
        bundle_txt = StringIO()
372
        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
373
                               bundle_txt, format=self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
374
        bundle_txt.seek(0)
375
        self.assertEqual(bundle_txt.readline(), 
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
376
                         '# Bazaar revision bundle v%s\n' % self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
377
        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.
378
1185.82.14 by Aaron Bentley
API updates
379
        rev = self.b1.repository.get_revision(rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
380
        self.assertEqual(bundle_txt.readline().decode('utf-8'),
381
                         u'# message:\n')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
382
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
383
        open(',,bundle', 'wb').write(bundle_txt.getvalue())
384
        bundle_txt.seek(0)
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
385
        return bundle_txt, rev_ids
386
387
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
388
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
389
        Make sure that the text generated is valid, and that it
390
        can be applied against the base, and generate the same information.
391
        
392
        :return: The in-memory bundle 
393
        """
394
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
395
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
396
        # This should also validate the generated bundle 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
397
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
398
        repository = self.b1.repository
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
399
        for bundle_rev in bundle.real_revisions:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
400
            # These really should have already been checked when we read the
401
            # bundle, since it computes the sha1 hash for the revision, which
402
            # only will match if everything is okay, but lets be explicit about
403
            # it
404
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1185.82.33 by Aaron Bentley
Strengthen tests
405
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
406
                      'timestamp', 'timezone', 'message', 'committer', 
407
                      'parent_ids', 'properties'):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
408
                self.assertEqual(getattr(branch_rev, a), 
409
                                 getattr(bundle_rev, a))
410
            self.assertEqual(len(branch_rev.parent_ids), 
411
                             len(bundle_rev.parent_ids))
1185.82.47 by Aaron Bentley
Ensure all intended rev_ids end up in the revision
412
        self.assertEqual(rev_ids, 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
413
                         [r.revision_id for r in bundle.real_revisions])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
414
        self.valid_apply_bundle(base_rev_id, bundle,
1185.82.89 by Aaron Bentley
Remove auto_commit stuff
415
                                   checkout_dir=checkout_dir)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
416
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
417
        return bundle
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
418
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
419
    def get_invalid_bundle(self, base_rev_id, rev_id):
420
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
421
        Munge the text so that it's invalid.
422
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
423
        :return: The in-memory bundle
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
424
        """
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
425
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
426
        new_text = bundle_txt.getvalue().replace('executable:no', 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
427
                                               'executable:yes')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
428
        bundle_txt = StringIO(new_text)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
429
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
430
        self.valid_apply_bundle(base_rev_id, bundle)
431
        return bundle 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
432
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
433
    def test_non_bundle(self):
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
434
        self.assertRaises(NotABundle, read_bundle, StringIO('#!/bin/sh\n'))
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
435
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
436
    def test_malformed(self):
437
        self.assertRaises(BadBundle, read_bundle, 
438
                          StringIO('# Bazaar revision bundle v'))
439
440
    def test_crlf_bundle(self):
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
441
        try:
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
442
            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
443
        except BadBundle:
444
            # It is currently permitted for bundles with crlf line endings to
445
            # make read_bundle raise a BadBundle, but this should be fixed.
1793.2.10 by Aaron Bentley
Whitespace/comment fix
446
            # Anything else, especially NotABundle, is an error.
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
447
            pass
448
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
449
    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.
450
        """Get a new tree, with the specified revision in it.
451
        """
452
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
453
        if checkout_dir is None:
454
            checkout_dir = tempfile.mkdtemp(prefix='test-branch-', dir='.')
0.5.89 by John Arbash Meinel
Updating for explicitly defined directories.
455
        else:
456
            if not os.path.exists(checkout_dir):
457
                os.mkdir(checkout_dir)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
458
        tree = self.make_branch_and_tree(checkout_dir)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
459
        s = StringIO()
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
460
        ancestors = write_bundle(self.b1.repository, rev_id, 'null:', s,
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
461
                                 format=self.format)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
462
        s.seek(0)
1185.82.135 by Aaron Bentley
Ensure that bundles are bytestrings
463
        assert isinstance(s.getvalue(), str), (
464
            "Bundle isn't a bytestring:\n %s..." % repr(s.getvalue())[:40])
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
465
        install_bundle(tree.branch.repository, read_bundle(s))
1185.82.41 by Aaron Bentley
More work on installing changesets
466
        for ancestor in ancestors:
467
            old = self.b1.repository.revision_tree(ancestor)
468
            new = tree.branch.repository.revision_tree(ancestor)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
469
470
            # 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.
471
            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.
472
            self.assertFalse(delta.has_changed(),
473
                             'Revision %s not copied correctly.'
474
                             % (ancestor,))
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
475
476
            # Now check that the file contents are all correct
1185.82.41 by Aaron Bentley
More work on installing changesets
477
            for inventory_id in old:
478
                try:
479
                    old_file = old.get_file(inventory_id)
1910.2.3 by Aaron Bentley
All tests pass
480
                except NoSuchFile:
1185.82.41 by Aaron Bentley
More work on installing changesets
481
                    continue
482
                if old_file is None:
483
                    continue
484
                self.assertEqual(old_file.read(),
485
                                 new.get_file(inventory_id).read())
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
486
        if not _mod_revision.is_null(rev_id):
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
487
            rh = self.b1.revision_history()
488
            tree.branch.set_revision_history(rh[:rh.index(rev_id)+1])
489
            tree.update()
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
490
            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.
491
            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.
492
                             'Working tree has modifications: %s' % delta)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
493
        return tree
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
494
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
495
    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.
496
        """Get the base revision, apply the changes, and make
497
        sure everything matches the builtin branch.
498
        """
1185.82.17 by Aaron Bentley
More API updates
499
        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
500
        original_parents = to_tree.get_parent_ids()
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
501
        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.
502
        original_parents = to_tree.get_parent_ids()
1185.82.41 by Aaron Bentley
More work on installing changesets
503
        self.assertIs(repository.has_revision(base_rev_id), True)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
504
        for rev in info.real_revisions:
505
            self.assert_(not repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
506
                'Revision {%s} present before applying bundle' 
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
507
                % rev.revision_id)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
508
        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.
509
510
        for rev in info.real_revisions:
1185.82.17 by Aaron Bentley
More API updates
511
            self.assert_(repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
512
                '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.
513
                % rev.revision_id)
514
1185.82.17 by Aaron Bentley
More API updates
515
        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.
516
        # 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.
517
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
518
        self.assertEqual(original_parents + [info.target],
519
            to_tree.get_parent_ids())
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
520
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
521
        rev = info.real_revisions[-1]
1185.82.17 by Aaron Bentley
More API updates
522
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
523
        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.
524
        
525
        # 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.
526
        #       we might also check the working tree.
527
528
        base_files = list(base_tree.list_files())
529
        to_files = list(to_tree.list_files())
530
        self.assertEqual(len(base_files), len(to_files))
1185.82.66 by Aaron Bentley
Handle new executable files
531
        for base_file, to_file in zip(base_files, to_files):
532
            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.
533
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
534
        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.
535
            # Check that the meta information is the same
536
            self.assertEqual(base_tree.get_file_size(fileid),
537
                    to_tree.get_file_size(fileid))
538
            self.assertEqual(base_tree.get_file_sha1(fileid),
539
                    to_tree.get_file_sha1(fileid))
540
            # Check that the contents are the same
541
            # This is pretty expensive
542
            # self.assertEqual(base_tree.get_file(fileid).read(),
543
            #         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.
544
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
545
    def test_bundle(self):
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
546
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.14 by Aaron Bentley
API updates
547
        self.b1 = self.tree1.branch
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
548
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
549
        open('b1/one', 'wb').write('one\n')
1185.82.14 by Aaron Bentley
API updates
550
        self.tree1.add('one')
551
        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.
552
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
553
        bundle = self.get_valid_bundle('null:', 'a@cset-0-1')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
554
        # FIXME: The current write_bundle api no longer supports
555
        #        setting a custom summary message
556
        #        We should re-introduce the ability, and update
557
        #        the tests to make sure it works.
558
        # bundle = self.get_valid_bundle(None, 'a@cset-0-1',
559
        #         message='With a specialized message')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
560
561
        # Make sure we can handle files with spaces, tabs, other
562
        # bogus characters
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
563
        self.build_tree([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
564
                'b1/with space.txt'
565
                , 'b1/dir/'
566
                , 'b1/dir/filein subdir.c'
567
                , 'b1/dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
568
                , 'b1/dir/ pre space'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
569
                , 'b1/sub/'
570
                , 'b1/sub/sub/'
571
                , '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
572
                ])
0.5.84 by John Arbash Meinel
(broken) problem with removes.
573
        open('b1/sub/sub/emptyfile.txt', 'wb').close()
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
574
        open('b1/dir/nolastnewline.txt', 'wb').write('bloop')
1185.82.66 by Aaron Bentley
Handle new executable files
575
        tt = TreeTransform(self.tree1)
576
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
577
        tt.apply()
1185.82.14 by Aaron Bentley
API updates
578
        self.tree1.add([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
579
                'with space.txt'
580
                , 'dir'
581
                , 'dir/filein subdir.c'
582
                , 'dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
583
                , 'dir/ pre space'
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
584
                , 'dir/nolastnewline.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
585
                , 'sub'
586
                , 'sub/sub'
587
                , 'sub/sub/nonempty.txt'
588
                , 'sub/sub/emptyfile.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
589
                ])
1185.82.14 by Aaron Bentley
API updates
590
        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.
591
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
592
        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.
593
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
594
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
595
        bundle = self.get_valid_bundle('null:', 'a@cset-0-2')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
596
597
        # Now delete entries
1185.82.21 by Aaron Bentley
Stop using deprecated function
598
        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.
599
                ['sub/sub/nonempty.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
600
                , '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.
601
                , 'sub/sub'
602
                ])
1185.82.68 by Aaron Bentley
Handle execute bit on modified files
603
        tt = TreeTransform(self.tree1)
604
        trans_id = tt.trans_id_tree_file_id('exe-1')
605
        tt.set_executability(False, trans_id)
606
        tt.apply()
1185.82.19 by Aaron Bentley
More API updates
607
        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.
608
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
609
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
610
        self.assertRaises(TestamentMismatch, self.get_invalid_bundle, 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
611
                          'a@cset-0-2', 'a@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
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-3')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
614
615
        # Now move the directory
1185.82.19 by Aaron Bentley
More API updates
616
        self.tree1.rename_one('dir', 'sub/dir')
617
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
618
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
619
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
620
        # Check a rollup bundle 
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
621
        bundle = self.get_valid_bundle('null:', 'a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
622
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
623
        # Modified files
624
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
625
        open('b1/sub/dir/ pre space', 'ab').write('\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
626
        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.
627
        self.tree1.rename_one('sub/dir/ pre space', 
628
                              'sub/ start space')
1185.82.19 by Aaron Bentley
More API updates
629
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
630
        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.
631
1185.82.70 by Aaron Bentley
Handle renamed files better
632
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
633
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
634
        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.
635
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
636
                          verbose=False)
637
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
638
        other = self.get_checkout('a@cset-0-5')
1910.2.62 by Aaron Bentley
Cleanups
639
        tree1_inv = self.tree1.branch.repository.get_inventory_xml(
640
            'a@cset-0-5')
1910.2.54 by Aaron Bentley
Implement testament format 3 strict
641
        tree2_inv = other.branch.repository.get_inventory_xml('a@cset-0-5')
642
        self.assertEqualDiff(tree1_inv, tree2_inv)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
643
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
644
        other.commit('rename file', rev_id='a@cset-0-6b')
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
645
        _merge_helper([other.basedir, -1], [None, None],
646
                      this_dir=self.tree1.basedir)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
647
        self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
1185.82.70 by Aaron Bentley
Handle renamed files better
648
                          verbose=False)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
649
        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
650
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
651
    def test_symlink_bundle(self):
1185.82.87 by Aaron Bentley
Got symlink adding working
652
        if not has_symlinks():
653
            raise TestSkipped("No symlink support")
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
654
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.87 by Aaron Bentley
Got symlink adding working
655
        self.b1 = self.tree1.branch
656
        tt = TreeTransform(self.tree1)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
657
        tt.new_symlink('link', tt.root, 'bar/foo', 'link-1')
1185.82.87 by Aaron Bentley
Got symlink adding working
658
        tt.apply()
659
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
660
        self.get_valid_bundle('null:', 'l@cset-0-1')
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.adjust_path('link2', tt.root, trans_id)
664
        tt.delete_contents(trans_id)
665
        tt.create_symlink('mars', trans_id)
666
        tt.apply()
667
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
668
        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
669
        tt = TreeTransform(self.tree1)
670
        trans_id = tt.trans_id_tree_file_id('link-1')
671
        tt.delete_contents(trans_id)
672
        tt.create_symlink('jupiter', trans_id)
673
        tt.apply()
674
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
675
        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
676
        tt = TreeTransform(self.tree1)
677
        trans_id = tt.trans_id_tree_file_id('link-1')
678
        tt.delete_contents(trans_id)
679
        tt.apply()
680
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
681
        self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
1185.82.96 by Aaron Bentley
Got first binary test passing
682
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
683
    def test_binary_bundle(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
684
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.96 by Aaron Bentley
Got first binary test passing
685
        self.b1 = self.tree1.branch
686
        tt = TreeTransform(self.tree1)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
687
        
688
        # Add
689
        tt.new_file('file', tt.root, '\x00\n\x00\r\x01\n\x02\r\xff', 'binary-1')
690
        tt.new_file('file2', tt.root, '\x01\n\x02\r\x03\n\x04\r\xff', 'binary-2')
1185.82.96 by Aaron Bentley
Got first binary test passing
691
        tt.apply()
692
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
693
        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.
694
695
        # Delete
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
696
        tt = TreeTransform(self.tree1)
697
        trans_id = tt.trans_id_tree_file_id('binary-1')
698
        tt.delete_contents(trans_id)
699
        tt.apply()
700
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
701
        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.
702
703
        # Rename & modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
704
        tt = TreeTransform(self.tree1)
705
        trans_id = tt.trans_id_tree_file_id('binary-2')
706
        tt.adjust_path('file3', tt.root, trans_id)
707
        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.
708
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
709
        tt.apply()
710
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
711
        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.
712
713
        # Modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
714
        tt = TreeTransform(self.tree1)
715
        trans_id = tt.trans_id_tree_file_id('binary-2')
716
        tt.delete_contents(trans_id)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
717
        tt.create_file('\x00file\rcontents', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
718
        tt.apply()
719
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
720
        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
721
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
722
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
723
        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.
724
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
725
    def test_last_modified(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
726
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
727
        self.b1 = self.tree1.branch
728
        tt = TreeTransform(self.tree1)
729
        tt.new_file('file', tt.root, 'file', 'file')
730
        tt.apply()
731
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
732
733
        tt = TreeTransform(self.tree1)
734
        trans_id = tt.trans_id_tree_file_id('file')
735
        tt.delete_contents(trans_id)
736
        tt.create_file('file2', trans_id)
737
        tt.apply()
738
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
739
740
        other = self.get_checkout('a@lmod-0-1')
741
        tt = TreeTransform(other)
742
        trans_id = tt.trans_id_tree_file_id('file')
743
        tt.delete_contents(trans_id)
744
        tt.create_file('file2', trans_id)
745
        tt.apply()
746
        other.commit('modify text in another tree', rev_id='a@lmod-0-2b')
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
747
        _merge_helper([other.basedir, -1], [None, None],
748
                      this_dir=self.tree1.basedir)
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
749
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
750
                          verbose=False)
751
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
752
        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
753
754
    def test_hide_history(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
755
        self.tree1 = self.make_branch_and_tree('b1')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
756
        self.b1 = self.tree1.branch
757
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
758
        open('b1/one', 'wb').write('one\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
759
        self.tree1.add('one')
760
        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.
761
        open('b1/one', 'wb').write('two\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
762
        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.
763
        open('b1/one', 'wb').write('three\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
764
        self.tree1.commit('modify', rev_id='a@cset-0-3')
765
        bundle_file = StringIO()
766
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
767
                               '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
768
        self.assertNotContainsRe(bundle_file.getvalue(), '\btwo\b')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
769
        self.assertContainsRe(bundle_file.getvalue(), 'one')
770
        self.assertContainsRe(bundle_file.getvalue(), 'three')
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
771
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
772
    def test_unicode_bundle(self):
773
        # Handle international characters
774
        os.mkdir('b1')
775
        try:
776
            f = open(u'b1/with Dod\xe9', 'wb')
777
        except UnicodeEncodeError:
778
            raise TestSkipped("Filesystem doesn't support unicode")
779
780
        self.tree1 = self.make_branch_and_tree('b1')
781
        self.b1 = self.tree1.branch
782
783
        f.write((u'A file\n'
784
            u'With international man of mystery\n'
785
            u'William Dod\xe9\n').encode('utf-8'))
786
        f.close()
787
2386.1.1 by John Arbash Meinel
Update test_unicode_bundle, since we know how it fails on Mac OSX
788
        self.tree1.add([u'with Dod\xe9'], ['withdod-id'])
789
        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.
790
                          rev_id='i18n-1', committer=u'William Dod\xe9')
791
2386.1.1 by John Arbash Meinel
Update test_unicode_bundle, since we know how it fails on Mac OSX
792
        if sys.platform == 'darwin':
793
            # On Mac the '\xe9' gets changed to 'e\u0301'
794
            self.assertEqual([u'.bzr', u'with Dode\u0301'],
795
                             sorted(os.listdir(u'b1')))
796
            delta = self.tree1.changes_from(self.tree1.basis_tree())
797
            self.assertEqual([(u'with Dod\xe9', 'withdod-id', 'file')],
798
                             delta.removed)
799
            self.knownFailure("Mac OSX doesn't preserve unicode"
800
                              " combining characters.")
801
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
802
        # Add
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
803
        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.
804
805
        # Modified
806
        f = open(u'b1/with Dod\xe9', 'wb')
807
        f.write(u'Modified \xb5\n'.encode('utf8'))
808
        f.close()
809
        self.tree1.commit(u'modified', rev_id='i18n-2')
810
811
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
812
        
813
        # Renamed
814
        self.tree1.rename_one(u'with Dod\xe9', u'B\xe5gfors')
815
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
816
                          committer=u'Erik B\xe5gfors')
817
818
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
819
820
        # Removed
821
        self.tree1.remove([u'B\xe5gfors'])
822
        self.tree1.commit(u'removed', rev_id='i18n-4')
823
824
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
825
826
        # Rollup
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
827
        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.
828
829
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
830
    def test_whitespace_bundle(self):
831
        if sys.platform in ('win32', 'cygwin'):
832
            raise TestSkipped('Windows doesn\'t support filenames'
833
                              ' with tabs or trailing spaces')
834
        self.tree1 = self.make_branch_and_tree('b1')
835
        self.b1 = self.tree1.branch
836
837
        self.build_tree(['b1/trailing space '])
838
        self.tree1.add(['trailing space '])
839
        # TODO: jam 20060701 Check for handling files with '\t' characters
840
        #       once we actually support them
841
842
        # Added
843
        self.tree1.commit('funky whitespace', rev_id='white-1')
844
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
845
        bundle = self.get_valid_bundle('null:', 'white-1')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
846
847
        # Modified
848
        open('b1/trailing space ', 'ab').write('add some text\n')
849
        self.tree1.commit('add text', rev_id='white-2')
850
851
        bundle = self.get_valid_bundle('white-1', 'white-2')
852
853
        # Renamed
854
        self.tree1.rename_one('trailing space ', ' start and end space ')
855
        self.tree1.commit('rename', rev_id='white-3')
856
857
        bundle = self.get_valid_bundle('white-2', 'white-3')
858
859
        # Removed
860
        self.tree1.remove([' start and end space '])
861
        self.tree1.commit('removed', rev_id='white-4')
862
863
        bundle = self.get_valid_bundle('white-3', 'white-4')
864
        
865
        # Now test a complet roll-up
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
866
        bundle = self.get_valid_bundle('null:', 'white-4')
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
867
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
868
    def test_alt_timezone_bundle(self):
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
869
        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
870
        self.b1 = self.tree1.branch
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
871
        builder = treebuilder.TreeBuilder()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
872
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
873
        self.tree1.lock_write()
874
        builder.start_tree(self.tree1)
875
        builder.build(['newfile'])
876
        builder.finish_tree()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
877
878
        # Asia/Colombo offset = 5 hours 30 minutes
879
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
880
                          timezone=19800, timestamp=1152544886.0)
881
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
882
        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
883
        
884
        rev = bundle.revisions[0]
885
        self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
886
        self.assertEqual(19800, rev.timezone)
887
        self.assertEqual(1152544886.0, rev.timestamp)
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
888
        self.tree1.unlock()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
889
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
890
    def test_bundle_root_id(self):
891
        self.tree1 = self.make_branch_and_tree('b1')
892
        self.b1 = self.tree1.branch
893
        self.tree1.commit('message', rev_id='revid1')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
894
        bundle = self.get_valid_bundle('null:', 'revid1')
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
895
        tree = bundle.revision_tree(self.b1.repository, 'revid1')
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
896
        self.assertEqual('revid1', tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
897
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
898
    def test_install_revisions(self):
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
899
        self.tree1 = self.make_branch_and_tree('b1')
900
        self.b1 = self.tree1.branch
901
        self.tree1.commit('message', rev_id='rev2a')
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
902
        bundle = self.get_valid_bundle('null:', 'rev2a')
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
903
        branch2 = self.make_branch('b2')
904
        self.assertFalse(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
905
        target_revision = bundle.install_revisions(branch2.repository)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
906
        self.assertTrue(branch2.repository.has_revision('rev2a'))
1551.14.9 by Aaron Bentley
rename get_target_revision to install_revisions
907
        self.assertEqual('rev2a', target_revision)
1551.14.4 by Aaron Bentley
Change bundle reader and merge directive to both be 'mergeables'
908
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
909
    def test_bundle_empty_property(self):
910
        """Test serializing revision properties with an empty value."""
911
        tree = self.make_branch_and_memory_tree('tree')
912
        tree.lock_write()
913
        self.addCleanup(tree.unlock)
914
        tree.add([''], ['TREE_ROOT'])
915
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
916
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
917
        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'.
918
        self.assertContainsRe(bundle_sio.getvalue(),
919
                              '# properties:\n'
920
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
921
                              '#   empty: \n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
922
                              '#   one: two\n'
923
                             )
924
        bundle = read_bundle(bundle_sio)
925
        revision_info = bundle.revisions[0]
926
        self.assertEqual('rev1', revision_info.revision_id)
927
        rev = revision_info.as_revision()
928
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
929
                         rev.properties)
930
931
    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.
932
        """Test serializing revision properties with an empty value.
933
934
        Older readers had a bug when reading an empty property.
935
        They assumed that all keys ended in ': \n'. However they would write an
936
        empty value as ':\n'. This tests make sure that all newer bzr versions
937
        can handle th second form.
938
        """
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
939
        tree = self.make_branch_and_memory_tree('tree')
940
        tree.lock_write()
941
        self.addCleanup(tree.unlock)
942
        tree.add([''], ['TREE_ROOT'])
943
        tree.commit('One', revprops={'one':'two', 'empty':''}, rev_id='rev1')
944
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
945
        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'.
946
        txt = bundle_sio.getvalue()
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
947
        loc = txt.find('#   empty: ') + len('#   empty:')
948
        # Create a new bundle, which strips the trailing space after empty
949
        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'.
950
951
        self.assertContainsRe(bundle_sio.getvalue(),
952
                              '# properties:\n'
953
                              '#   branch-nick: tree\n'
2447.1.3 by John Arbash Meinel
Change the default serializer to include a trailing whitespace for empty properties.
954
                              '#   empty:\n'
2447.1.2 by John Arbash Meinel
Add tests that we handle empty values whether they end in ': \n' or ':\n'.
955
                              '#   one: two\n'
956
                             )
957
        bundle = read_bundle(bundle_sio)
958
        revision_info = bundle.revisions[0]
959
        self.assertEqual('rev1', revision_info.revision_id)
960
        rev = revision_info.as_revision()
961
        self.assertEqual({'branch-nick':'tree', 'empty':'', 'one':'two'},
962
                         rev.properties)
963
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
964
    def test_bundle_sorted_properties(self):
965
        """For stability the writer should write properties in sorted order."""
966
        tree = self.make_branch_and_memory_tree('tree')
967
        tree.lock_write()
968
        self.addCleanup(tree.unlock)
969
970
        tree.add([''], ['TREE_ROOT'])
971
        tree.commit('One', rev_id='rev1',
972
                    revprops={'a':'4', 'b':'3', 'c':'2', 'd':'1'})
973
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
974
        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.
975
        self.assertContainsRe(bundle_sio.getvalue(),
976
                              '# properties:\n'
977
                              '#   a: 4\n'
978
                              '#   b: 3\n'
979
                              '#   branch-nick: tree\n'
980
                              '#   c: 2\n'
981
                              '#   d: 1\n'
982
                             )
2447.1.4 by John Arbash Meinel
Add a test that we properly round-trip unicode properties.
983
        bundle = read_bundle(bundle_sio)
984
        revision_info = bundle.revisions[0]
985
        self.assertEqual('rev1', revision_info.revision_id)
986
        rev = revision_info.as_revision()
987
        self.assertEqual({'branch-nick':'tree', 'a':'4', 'b':'3', 'c':'2',
988
                          'd':'1'}, rev.properties)
989
990
    def test_bundle_unicode_properties(self):
991
        """We should be able to round trip a non-ascii property."""
992
        tree = self.make_branch_and_memory_tree('tree')
993
        tree.lock_write()
994
        self.addCleanup(tree.unlock)
995
996
        tree.add([''], ['TREE_ROOT'])
997
        # Revisions themselves do not require anything about revision property
998
        # keys, other than that they are a basestring, and do not contain
999
        # whitespace.
1000
        # However, Testaments assert than they are str(), and thus should not
1001
        # be Unicode.
1002
        tree.commit('One', rev_id='rev1',
1003
                    revprops={'omega':u'\u03a9', 'alpha':u'\u03b1'})
1004
        self.b1 = tree.branch
2598.5.3 by Aaron Bentley
Push NULL_REVISION deeper
1005
        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.
1006
        self.assertContainsRe(bundle_sio.getvalue(),
1007
                              '# properties:\n'
1008
                              '#   alpha: \xce\xb1\n'
1009
                              '#   branch-nick: tree\n'
1010
                              '#   omega: \xce\xa9\n'
1011
                             )
1012
        bundle = read_bundle(bundle_sio)
1013
        revision_info = bundle.revisions[0]
1014
        self.assertEqual('rev1', revision_info.revision_id)
1015
        rev = revision_info.as_revision()
1016
        self.assertEqual({'branch-nick':'tree', 'omega':u'\u03a9',
1017
                          'alpha':u'\u03b1'}, rev.properties)
2447.1.1 by John Arbash Meinel
For stability and ease of testing, write properties in sorted order.
1018
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1019
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1020
class V09BundleKnit2Tester(V08BundleTester):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1021
1022
    format = '0.9'
1023
1024
    def bzrdir_format(self):
1025
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
1026
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
1027
        return format
1028
1029
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1030
class V09BundleKnit1Tester(V08BundleTester):
1031
1032
    format = '0.9'
1033
1034
    def bzrdir_format(self):
1035
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1036
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
1037
        return format
1038
1039
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1040
class MungedBundleTester(TestCaseWithTransport):
1041
1042
    def build_test_bundle(self):
1043
        wt = self.make_branch_and_tree('b1')
1044
1045
        self.build_tree(['b1/one'])
1046
        wt.add('one')
1047
        wt.commit('add one', rev_id='a@cset-0-1')
1048
        self.build_tree(['b1/two'])
1049
        wt.add('two')
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1050
        wt.commit('add two', rev_id='a@cset-0-2',
1051
                  revprops={'branch-nick':'test'})
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1052
1053
        bundle_txt = StringIO()
1054
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
1055
                               'a@cset-0-1', bundle_txt)
1056
        self.assertEqual(['a@cset-0-2'], rev_ids)
1057
        bundle_txt.seek(0, 0)
1058
        return bundle_txt
1059
1060
    def check_valid(self, bundle):
1061
        """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
1062
        self.assertEqual(['a@cset-0-2'],
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1063
            [r.revision_id for r in bundle.real_revisions])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1064
1065
    def test_extra_whitespace(self):
1066
        bundle_txt = self.build_test_bundle()
1067
1068
        # Seek to the end of the file
1069
        # Adding one extra newline used to give us
1070
        # TypeError: float() argument must be a string or a number
1071
        bundle_txt.seek(0, 2)
1072
        bundle_txt.write('\n')
1073
        bundle_txt.seek(0)
1074
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1075
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1076
        self.check_valid(bundle)
1077
1078
    def test_extra_whitespace_2(self):
1079
        bundle_txt = self.build_test_bundle()
1080
1081
        # Seek to the end of the file
1082
        # Adding two extra newlines used to give us
1083
        # MalformedPatches: The first line of all patches should be ...
1084
        bundle_txt.seek(0, 2)
1085
        bundle_txt.write('\n\n')
1086
        bundle_txt.seek(0)
1087
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1088
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1089
        self.check_valid(bundle)
1090
1091
    def test_missing_trailing_whitespace(self):
1092
        bundle_txt = self.build_test_bundle()
1093
1094
        # Remove a trailing newline, it shouldn't kill the parser
1095
        raw = bundle_txt.getvalue()
1096
        # The contents of the bundle don't have to be this, but this
1097
        # test is concerned with the exact case where the serializer
1098
        # creates a blank line at the end, and fails if that
1099
        # line is stripped
1100
        self.assertEqual('\n\n', raw[-2:])
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1101
        bundle_txt = StringIO(raw[:-1])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1102
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
1103
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
1104
        self.check_valid(bundle)
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
1105
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
1106
    def test_opening_text(self):
1107
        bundle_txt = self.build_test_bundle()
1108
1109
        bundle_txt = StringIO("Some random\nemail comments\n"
1110
                              + bundle_txt.getvalue())
1111
1112
        bundle = read_bundle(bundle_txt)
1113
        self.check_valid(bundle)
1114
1115
    def test_trailing_text(self):
1116
        bundle_txt = self.build_test_bundle()
1117
1118
        bundle_txt = StringIO(bundle_txt.getvalue() +
1119
                              "Some trailing\nrandom\ntext\n")
1120
1121
        bundle = read_bundle(bundle_txt)
1122
        self.check_valid(bundle)
1123