~bzr-pqm/bzr/bzr.dev

2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
1
# Copyright (C) 2004, 2005, 2006, 2007 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.82.7 by John Arbash Meinel
Adding patches.py into bzrlib, including the tests into the test suite.
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
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,
1910.2.64 by Aaron Bentley
Changes from review
27
    treebuilder,
28
    )
1996.3.5 by John Arbash Meinel
Cleanup, deprecated, and get the tests passing again.
29
from bzrlib.builtins import _merge_helper
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
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
33
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
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
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
36
from bzrlib.branch import Branch
1185.82.90 by Aaron Bentley
Reorganized test suite
37
from bzrlib.diff import internal_diff
1910.2.3 by Aaron Bentley
All tests pass
38
from bzrlib.errors import (BzrError, TestamentMismatch, NotABundle, BadBundle, 
39
                           NoSuchFile,)
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
40
from bzrlib.merge import Merge3Merger
2241.1.5 by Martin Pool
Move KnitFormat2 into repofmt
41
from bzrlib.repofmt import knitrepo
1185.82.87 by Aaron Bentley
Got symlink adding working
42
from bzrlib.osutils import has_symlinks, sha_file
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
43
from bzrlib.tests import (TestCaseInTempDir, TestCaseWithTransport,
44
                          TestCase, TestSkipped)
1185.82.66 by Aaron Bentley
Handle new executable files
45
from bzrlib.transform import TreeTransform
1185.82.17 by Aaron Bentley
More API updates
46
from bzrlib.workingtree import WorkingTree
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()
339
        write_bundle(source.branch.repository, 'two-id', None, text, 
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
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
350
class V08BundleTester(TestCaseWithTransport):
351
352
    format = '0.8'
353
354
    def bzrdir_format(self):
355
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
356
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
357
        return format
358
359
    def make_branch_and_tree(self, path, format=None):
360
        if format is None:
361
            format = self.bzrdir_format()
362
        return TestCaseWithTransport.make_branch_and_tree(self, path, format)
363
364
    def make_branch(self, path, format=None):
365
        if format is None:
366
            format = self.bzrdir_format()
367
        return TestCaseWithTransport.make_branch(self, path, format)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
368
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
369
    def create_bundle_text(self, base_rev_id, rev_id):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
370
        bundle_txt = StringIO()
371
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
372
                               bundle_txt, format=self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
373
        bundle_txt.seek(0)
374
        self.assertEqual(bundle_txt.readline(), 
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
375
                         '# Bazaar revision bundle v%s\n' % self.format)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
376
        self.assertEqual(bundle_txt.readline(), '#\n')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
377
1185.82.14 by Aaron Bentley
API updates
378
        rev = self.b1.repository.get_revision(rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
379
        self.assertEqual(bundle_txt.readline().decode('utf-8'),
380
                         u'# message:\n')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
381
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
382
        open(',,bundle', 'wb').write(bundle_txt.getvalue())
383
        bundle_txt.seek(0)
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
384
        return bundle_txt, rev_ids
385
386
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None):
387
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
388
        Make sure that the text generated is valid, and that it
389
        can be applied against the base, and generate the same information.
390
        
391
        :return: The in-memory bundle 
392
        """
393
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
394
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
395
        # This should also validate the generated bundle 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
396
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
397
        repository = self.b1.repository
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
398
        for bundle_rev in bundle.real_revisions:
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
399
            # These really should have already been checked when we read the
400
            # bundle, since it computes the sha1 hash for the revision, which
401
            # only will match if everything is okay, but lets be explicit about
402
            # it
403
            branch_rev = repository.get_revision(bundle_rev.revision_id)
1185.82.33 by Aaron Bentley
Strengthen tests
404
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
405
                      'timestamp', 'timezone', 'message', 'committer', 
406
                      'parent_ids', 'properties'):
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
407
                self.assertEqual(getattr(branch_rev, a), 
408
                                 getattr(bundle_rev, a))
409
            self.assertEqual(len(branch_rev.parent_ids), 
410
                             len(bundle_rev.parent_ids))
1185.82.47 by Aaron Bentley
Ensure all intended rev_ids end up in the revision
411
        self.assertEqual(rev_ids, 
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
412
                         [r.revision_id for r in bundle.real_revisions])
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
413
        self.valid_apply_bundle(base_rev_id, bundle,
1185.82.89 by Aaron Bentley
Remove auto_commit stuff
414
                                   checkout_dir=checkout_dir)
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
415
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
416
        return bundle
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
417
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
418
    def get_invalid_bundle(self, base_rev_id, rev_id):
419
        """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
420
        Munge the text so that it's invalid.
421
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
422
        :return: The in-memory bundle
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
423
        """
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
424
        bundle_txt, rev_ids = self.create_bundle_text(base_rev_id, rev_id)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
425
        new_text = bundle_txt.getvalue().replace('executable:no', 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
426
                                               'executable:yes')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
427
        bundle_txt = StringIO(new_text)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
428
        bundle = read_bundle(bundle_txt)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
429
        self.valid_apply_bundle(base_rev_id, bundle)
430
        return bundle 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
431
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
432
    def test_non_bundle(self):
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
433
        self.assertRaises(NotABundle, read_bundle, StringIO('#!/bin/sh\n'))
1185.82.139 by Aaron Bentley
Raise NotABundle when a non-bundle is supplied
434
1793.2.7 by Aaron Bentley
Fix reporting of malformed, (especially, crlf) bundles
435
    def test_malformed(self):
436
        self.assertRaises(BadBundle, read_bundle, 
437
                          StringIO('# Bazaar revision bundle v'))
438
439
    def test_crlf_bundle(self):
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
440
        try:
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
441
            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
442
        except BadBundle:
443
            # It is currently permitted for bundles with crlf line endings to
444
            # make read_bundle raise a BadBundle, but this should be fixed.
1793.2.10 by Aaron Bentley
Whitespace/comment fix
445
            # Anything else, especially NotABundle, is an error.
1793.2.9 by Aaron Bentley
Don't use assertNotRaises-- instead, catch BadBundle and pass
446
            pass
447
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
448
    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.
449
        """Get a new tree, with the specified revision in it.
450
        """
451
0.5.88 by John Arbash Meinel
Fixed a bug in the rename code, added more tests.
452
        if checkout_dir is None:
453
            checkout_dir = tempfile.mkdtemp(prefix='test-branch-', dir='.')
0.5.89 by John Arbash Meinel
Updating for explicitly defined directories.
454
        else:
455
            if not os.path.exists(checkout_dir):
456
                os.mkdir(checkout_dir)
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
457
        tree = self.make_branch_and_tree(checkout_dir)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
458
        s = StringIO()
1910.2.64 by Aaron Bentley
Changes from review
459
        ancestors = write_bundle(self.b1.repository, rev_id, None, s,
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
460
                                 format=self.format)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
461
        s.seek(0)
1185.82.135 by Aaron Bentley
Ensure that bundles are bytestrings
462
        assert isinstance(s.getvalue(), str), (
463
            "Bundle isn't a bytestring:\n %s..." % repr(s.getvalue())[:40])
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
464
        install_bundle(tree.branch.repository, read_bundle(s))
1185.82.41 by Aaron Bentley
More work on installing changesets
465
        for ancestor in ancestors:
466
            old = self.b1.repository.revision_tree(ancestor)
467
            new = tree.branch.repository.revision_tree(ancestor)
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
468
469
            # 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.
470
            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.
471
            self.assertFalse(delta.has_changed(),
472
                             'Revision %s not copied correctly.'
473
                             % (ancestor,))
1711.7.27 by John Arbash Meinel
Investigating why test_bundle fails, something isn't transmitting properly.
474
475
            # Now check that the file contents are all correct
1185.82.41 by Aaron Bentley
More work on installing changesets
476
            for inventory_id in old:
477
                try:
478
                    old_file = old.get_file(inventory_id)
1910.2.3 by Aaron Bentley
All tests pass
479
                except NoSuchFile:
1185.82.41 by Aaron Bentley
More work on installing changesets
480
                    continue
481
                if old_file is None:
482
                    continue
483
                self.assertEqual(old_file.read(),
484
                                 new.get_file(inventory_id).read())
1185.82.44 by Aaron Bentley
Switch to merge_changeset in test suite
485
        if rev_id is not None:
486
            rh = self.b1.revision_history()
487
            tree.branch.set_revision_history(rh[:rh.index(rev_id)+1])
488
            tree.update()
1852.10.3 by Robert Collins
Remove all uses of compare_trees and replace with Tree.changes_from throughout bzrlib.
489
            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.
490
            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.
491
                             'Working tree has modifications: %s' % delta)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
492
        return tree
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
493
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
494
    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.
495
        """Get the base revision, apply the changes, and make
496
        sure everything matches the builtin branch.
497
        """
1185.82.17 by Aaron Bentley
More API updates
498
        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
499
        original_parents = to_tree.get_parent_ids()
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
500
        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.
501
        original_parents = to_tree.get_parent_ids()
1185.82.41 by Aaron Bentley
More work on installing changesets
502
        self.assertIs(repository.has_revision(base_rev_id), True)
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
503
        for rev in info.real_revisions:
504
            self.assert_(not repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
505
                'Revision {%s} present before applying bundle' 
1185.82.40 by Aaron Bentley
Started work on testing install_revisions/handling empty changesets
506
                % rev.revision_id)
1793.2.2 by Aaron Bentley
Move BundleReader into v07 serializer
507
        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.
508
509
        for rev in info.real_revisions:
1185.82.17 by Aaron Bentley
More API updates
510
            self.assert_(repository.has_revision(rev.revision_id),
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
511
                '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.
512
                % rev.revision_id)
513
1185.82.17 by Aaron Bentley
More API updates
514
        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.
515
        # 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.
516
1908.6.4 by Robert Collins
Update to replaced parent checking api bzrlib/merge.py
517
        self.assertEqual(original_parents + [info.target],
518
            to_tree.get_parent_ids())
0.5.86 by John Arbash Meinel
Updated the auto-commit functionality, and adding to pending-merges, more testing.
519
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
520
        rev = info.real_revisions[-1]
1185.82.17 by Aaron Bentley
More API updates
521
        base_tree = self.b1.repository.revision_tree(rev.revision_id)
522
        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.
523
        
524
        # 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.
525
        #       we might also check the working tree.
526
527
        base_files = list(base_tree.list_files())
528
        to_files = list(to_tree.list_files())
529
        self.assertEqual(len(base_files), len(to_files))
1185.82.66 by Aaron Bentley
Handle new executable files
530
        for base_file, to_file in zip(base_files, to_files):
531
            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.
532
0.5.117 by John Arbash Meinel
Almost there. Just need to track down a few remaining bugs.
533
        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.
534
            # Check that the meta information is the same
535
            self.assertEqual(base_tree.get_file_size(fileid),
536
                    to_tree.get_file_size(fileid))
537
            self.assertEqual(base_tree.get_file_sha1(fileid),
538
                    to_tree.get_file_sha1(fileid))
539
            # Check that the contents are the same
540
            # This is pretty expensive
541
            # self.assertEqual(base_tree.get_file(fileid).read(),
542
            #         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.
543
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
544
    def test_bundle(self):
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
545
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.14 by Aaron Bentley
API updates
546
        self.b1 = self.tree1.branch
0.5.78 by John Arbash Meinel
Working on test cases, starting with the empty project issues.
547
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
548
        open('b1/one', 'wb').write('one\n')
1185.82.14 by Aaron Bentley
API updates
549
        self.tree1.add('one')
550
        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.
551
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
552
        bundle = self.get_valid_bundle(None, 'a@cset-0-1')
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
553
        # FIXME: The current write_bundle api no longer supports
554
        #        setting a custom summary message
555
        #        We should re-introduce the ability, and update
556
        #        the tests to make sure it works.
557
        # bundle = self.get_valid_bundle(None, 'a@cset-0-1',
558
        #         message='With a specialized message')
0.5.80 by John Arbash Meinel
Starting to write tests for changeset, discovering some errors as I go.
559
560
        # Make sure we can handle files with spaces, tabs, other
561
        # bogus characters
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
562
        self.build_tree([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
563
                'b1/with space.txt'
564
                , 'b1/dir/'
565
                , 'b1/dir/filein subdir.c'
566
                , 'b1/dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
567
                , 'b1/dir/ pre space'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
568
                , 'b1/sub/'
569
                , 'b1/sub/sub/'
570
                , '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
571
                ])
0.5.84 by John Arbash Meinel
(broken) problem with removes.
572
        open('b1/sub/sub/emptyfile.txt', 'wb').close()
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
573
        open('b1/dir/nolastnewline.txt', 'wb').write('bloop')
1185.82.66 by Aaron Bentley
Handle new executable files
574
        tt = TreeTransform(self.tree1)
575
        tt.new_file('executable', tt.root, '#!/bin/sh\n', 'exe-1', True)
576
        tt.apply()
1185.82.14 by Aaron Bentley
API updates
577
        self.tree1.add([
0.5.84 by John Arbash Meinel
(broken) problem with removes.
578
                'with space.txt'
579
                , 'dir'
580
                , 'dir/filein subdir.c'
581
                , 'dir/WithCaps.txt'
1711.7.32 by John Arbash Meinel
Switch from a trailing space to a beginning space, which is supported everywhere.
582
                , 'dir/ pre space'
0.5.94 by Aaron Bentley
Switched to native patch application, added tests for terminating newlines
583
                , 'dir/nolastnewline.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
584
                , 'sub'
585
                , 'sub/sub'
586
                , 'sub/sub/nonempty.txt'
587
                , 'sub/sub/emptyfile.txt'
0.5.82 by John Arbash Meinel
Lots of changes, changing separators, updating tests, updated ChangesetTree to include text_ids
588
                ])
1185.82.14 by Aaron Bentley
API updates
589
        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.
590
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
591
        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.
592
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
593
        # Check a rollup bundle 
594
        bundle = self.get_valid_bundle(None, 'a@cset-0-2')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
595
596
        # Now delete entries
1185.82.21 by Aaron Bentley
Stop using deprecated function
597
        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.
598
                ['sub/sub/nonempty.txt'
0.5.84 by John Arbash Meinel
(broken) problem with removes.
599
                , '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.
600
                , 'sub/sub'
601
                ])
1185.82.68 by Aaron Bentley
Handle execute bit on modified files
602
        tt = TreeTransform(self.tree1)
603
        trans_id = tt.trans_id_tree_file_id('exe-1')
604
        tt.set_executability(False, trans_id)
605
        tt.apply()
1185.82.19 by Aaron Bentley
More API updates
606
        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.
607
        
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
608
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
609
        self.assertRaises(TestamentMismatch, self.get_invalid_bundle, 
1185.82.118 by Aaron Bentley
Ensure that StrictTestament handles execute bit differences
610
                          'a@cset-0-2', 'a@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
611
        # Check a rollup bundle 
612
        bundle = self.get_valid_bundle(None, 'a@cset-0-3')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
613
614
        # Now move the directory
1185.82.19 by Aaron Bentley
More API updates
615
        self.tree1.rename_one('dir', 'sub/dir')
616
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
617
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
618
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
619
        # Check a rollup bundle 
620
        bundle = self.get_valid_bundle(None, 'a@cset-0-4')
0.5.84 by John Arbash Meinel
(broken) problem with removes.
621
0.5.87 by John Arbash Meinel
Handling international characters, added more test cases.
622
        # Modified files
623
        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.
624
        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
625
        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.
626
        self.tree1.rename_one('sub/dir/ pre space', 
627
                              'sub/ start space')
1185.82.19 by Aaron Bentley
More API updates
628
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
629
        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.
630
1185.82.70 by Aaron Bentley
Handle renamed files better
631
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
632
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
633
        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.
634
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-6',
635
                          verbose=False)
636
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
637
        other = self.get_checkout('a@cset-0-5')
1910.2.62 by Aaron Bentley
Cleanups
638
        tree1_inv = self.tree1.branch.repository.get_inventory_xml(
639
            'a@cset-0-5')
1910.2.54 by Aaron Bentley
Implement testament format 3 strict
640
        tree2_inv = other.branch.repository.get_inventory_xml('a@cset-0-5')
641
        self.assertEqualDiff(tree1_inv, tree2_inv)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
642
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
643
        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.
644
        _merge_helper([other.basedir, -1], [None, None],
645
                      this_dir=self.tree1.basedir)
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
646
        self.tree1.commit(u'Merge', rev_id='a@cset-0-7',
1185.82.70 by Aaron Bentley
Handle renamed files better
647
                          verbose=False)
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
648
        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
649
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
650
    def test_symlink_bundle(self):
1185.82.87 by Aaron Bentley
Got symlink adding working
651
        if not has_symlinks():
652
            raise TestSkipped("No symlink support")
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
653
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.87 by Aaron Bentley
Got symlink adding working
654
        self.b1 = self.tree1.branch
655
        tt = TreeTransform(self.tree1)
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
656
        tt.new_symlink('link', tt.root, 'bar/foo', 'link-1')
1185.82.87 by Aaron Bentley
Got symlink adding working
657
        tt.apply()
658
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
659
        self.get_valid_bundle(None, 'l@cset-0-1')
1185.82.88 by Aaron Bentley
Get symlink modification, renames and deletion under test
660
        tt = TreeTransform(self.tree1)
661
        trans_id = tt.trans_id_tree_file_id('link-1')
662
        tt.adjust_path('link2', tt.root, trans_id)
663
        tt.delete_contents(trans_id)
664
        tt.create_symlink('mars', trans_id)
665
        tt.apply()
666
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
667
        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
668
        tt = TreeTransform(self.tree1)
669
        trans_id = tt.trans_id_tree_file_id('link-1')
670
        tt.delete_contents(trans_id)
671
        tt.create_symlink('jupiter', trans_id)
672
        tt.apply()
673
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
674
        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
675
        tt = TreeTransform(self.tree1)
676
        trans_id = tt.trans_id_tree_file_id('link-1')
677
        tt.delete_contents(trans_id)
678
        tt.apply()
679
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
680
        self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
1185.82.96 by Aaron Bentley
Got first binary test passing
681
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
682
    def test_binary_bundle(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
683
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.96 by Aaron Bentley
Got first binary test passing
684
        self.b1 = self.tree1.branch
685
        tt = TreeTransform(self.tree1)
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
686
        
687
        # Add
688
        tt.new_file('file', tt.root, '\x00\n\x00\r\x01\n\x02\r\xff', 'binary-1')
689
        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
690
        tt.apply()
691
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
692
        self.get_valid_bundle(None, 'b@cset-0-1')
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
693
694
        # Delete
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
695
        tt = TreeTransform(self.tree1)
696
        trans_id = tt.trans_id_tree_file_id('binary-1')
697
        tt.delete_contents(trans_id)
698
        tt.apply()
699
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
700
        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.
701
702
        # Rename & modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
703
        tt = TreeTransform(self.tree1)
704
        trans_id = tt.trans_id_tree_file_id('binary-2')
705
        tt.adjust_path('file3', tt.root, trans_id)
706
        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.
707
        tt.create_file('file\rcontents\x00\n\x00', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
708
        tt.apply()
709
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
710
        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.
711
712
        # Modify
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
713
        tt = TreeTransform(self.tree1)
714
        trans_id = tt.trans_id_tree_file_id('binary-2')
715
        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.
716
        tt.create_file('\x00file\rcontents', trans_id)
1185.82.97 by Aaron Bentley
Got binary files working for adds, renames, modifications
717
        tt.apply()
718
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
719
        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
720
1848.1.1 by John Arbash Meinel
fix bug in bundle handling of binary files with just '\r' in them.
721
        # Rollup
722
        self.get_valid_bundle(None, 'b@cset-0-4')
723
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
724
    def test_last_modified(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
725
        self.tree1 = self.make_branch_and_tree('b1')
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
726
        self.b1 = self.tree1.branch
727
        tt = TreeTransform(self.tree1)
728
        tt.new_file('file', tt.root, 'file', 'file')
729
        tt.apply()
730
        self.tree1.commit('create file', rev_id='a@lmod-0-1')
731
732
        tt = TreeTransform(self.tree1)
733
        trans_id = tt.trans_id_tree_file_id('file')
734
        tt.delete_contents(trans_id)
735
        tt.create_file('file2', trans_id)
736
        tt.apply()
737
        self.tree1.commit('modify text', rev_id='a@lmod-0-2a')
738
739
        other = self.get_checkout('a@lmod-0-1')
740
        tt = TreeTransform(other)
741
        trans_id = tt.trans_id_tree_file_id('file')
742
        tt.delete_contents(trans_id)
743
        tt.create_file('file2', trans_id)
744
        tt.apply()
745
        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.
746
        _merge_helper([other.basedir, -1], [None, None],
747
                      this_dir=self.tree1.basedir)
1185.82.115 by Aaron Bentley
Add test for last-changed special cases
748
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
749
                          verbose=False)
750
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
1185.82.130 by Aaron Bentley
Rename changesets to revision bundles
751
        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
752
753
    def test_hide_history(self):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
754
        self.tree1 = self.make_branch_and_tree('b1')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
755
        self.b1 = self.tree1.branch
756
1793.3.1 by John Arbash Meinel
Clean up the bundle tests a little bit.
757
        open('b1/one', 'wb').write('one\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
758
        self.tree1.add('one')
759
        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.
760
        open('b1/one', 'wb').write('two\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
761
        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.
762
        open('b1/one', 'wb').write('three\n')
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
763
        self.tree1.commit('modify', rev_id='a@cset-0-3')
764
        bundle_file = StringIO()
765
        rev_ids = write_bundle(self.tree1.branch.repository, 'a@cset-0-3',
1910.2.51 by Aaron Bentley
Bundles now corrupt repositories
766
                               'a@cset-0-1', bundle_file, format=self.format)
1185.84.3 by Aaron Bentley
Hide diffs for old revisions in bundles
767
        self.assertNotContainsRe(bundle_file.getvalue(), 'two')
768
        self.assertContainsRe(bundle_file.getvalue(), 'one')
769
        self.assertContainsRe(bundle_file.getvalue(), 'three')
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
770
1711.7.35 by John Arbash Meinel
Factor out i18n bundle tests, so we don't always skip.
771
    def test_unicode_bundle(self):
772
        # Handle international characters
773
        os.mkdir('b1')
774
        try:
775
            f = open(u'b1/with Dod\xe9', 'wb')
776
        except UnicodeEncodeError:
777
            raise TestSkipped("Filesystem doesn't support unicode")
778
779
        self.tree1 = self.make_branch_and_tree('b1')
780
        self.b1 = self.tree1.branch
781
782
        f.write((u'A file\n'
783
            u'With international man of mystery\n'
784
            u'William Dod\xe9\n').encode('utf-8'))
785
        f.close()
786
787
        self.tree1.add([u'with Dod\xe9'])
788
        self.tree1.commit(u'i18n commit from William Dod\xe9', 
789
                          rev_id='i18n-1', committer=u'William Dod\xe9')
790
791
        # Add
792
        bundle = self.get_valid_bundle(None, 'i18n-1')
793
794
        # Modified
795
        f = open(u'b1/with Dod\xe9', 'wb')
796
        f.write(u'Modified \xb5\n'.encode('utf8'))
797
        f.close()
798
        self.tree1.commit(u'modified', rev_id='i18n-2')
799
800
        bundle = self.get_valid_bundle('i18n-1', 'i18n-2')
801
        
802
        # Renamed
803
        self.tree1.rename_one(u'with Dod\xe9', u'B\xe5gfors')
804
        self.tree1.commit(u'renamed, the new i18n man', rev_id='i18n-3',
805
                          committer=u'Erik B\xe5gfors')
806
807
        bundle = self.get_valid_bundle('i18n-2', 'i18n-3')
808
809
        # Removed
810
        self.tree1.remove([u'B\xe5gfors'])
811
        self.tree1.commit(u'removed', rev_id='i18n-4')
812
813
        bundle = self.get_valid_bundle('i18n-3', 'i18n-4')
814
815
        # Rollup
816
        bundle = self.get_valid_bundle(None, 'i18n-4')
817
818
1711.7.34 by John Arbash Meinel
Include a test to ensure bundles handle trailing whitespace.
819
    def test_whitespace_bundle(self):
820
        if sys.platform in ('win32', 'cygwin'):
821
            raise TestSkipped('Windows doesn\'t support filenames'
822
                              ' with tabs or trailing spaces')
823
        self.tree1 = self.make_branch_and_tree('b1')
824
        self.b1 = self.tree1.branch
825
826
        self.build_tree(['b1/trailing space '])
827
        self.tree1.add(['trailing space '])
828
        # TODO: jam 20060701 Check for handling files with '\t' characters
829
        #       once we actually support them
830
831
        # Added
832
        self.tree1.commit('funky whitespace', rev_id='white-1')
833
834
        bundle = self.get_valid_bundle(None, 'white-1')
835
836
        # Modified
837
        open('b1/trailing space ', 'ab').write('add some text\n')
838
        self.tree1.commit('add text', rev_id='white-2')
839
840
        bundle = self.get_valid_bundle('white-1', 'white-2')
841
842
        # Renamed
843
        self.tree1.rename_one('trailing space ', ' start and end space ')
844
        self.tree1.commit('rename', rev_id='white-3')
845
846
        bundle = self.get_valid_bundle('white-2', 'white-3')
847
848
        # Removed
849
        self.tree1.remove([' start and end space '])
850
        self.tree1.commit('removed', rev_id='white-4')
851
852
        bundle = self.get_valid_bundle('white-3', 'white-4')
853
        
854
        # Now test a complet roll-up
855
        bundle = self.get_valid_bundle(None, 'white-4')
856
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
857
    def test_alt_timezone_bundle(self):
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
858
        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
859
        self.b1 = self.tree1.branch
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
860
        builder = treebuilder.TreeBuilder()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
861
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
862
        self.tree1.lock_write()
863
        builder.start_tree(self.tree1)
864
        builder.build(['newfile'])
865
        builder.finish_tree()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
866
867
        # Asia/Colombo offset = 5 hours 30 minutes
868
        self.tree1.commit('non-hour offset timezone', rev_id='tz-1',
869
                          timezone=19800, timestamp=1152544886.0)
870
871
        bundle = self.get_valid_bundle(None, 'tz-1')
872
        
873
        rev = bundle.revisions[0]
874
        self.assertEqual('Mon 2006-07-10 20:51:26.000000000 +0530', rev.date)
875
        self.assertEqual(19800, rev.timezone)
876
        self.assertEqual(1152544886.0, rev.timestamp)
1986.1.2 by Robert Collins
Various changes to allow non-workingtree specific tests to run entirely
877
        self.tree1.unlock()
1793.3.9 by John Arbash Meinel
Add a test to timezone for non integer tz offsets
878
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
879
    def test_bundle_root_id(self):
880
        self.tree1 = self.make_branch_and_tree('b1')
881
        self.b1 = self.tree1.branch
882
        self.tree1.commit('message', rev_id='revid1')
883
        bundle = self.get_valid_bundle(None, 'revid1')
884
        tree = bundle.revision_tree(self.b1.repository, 'revid1')
1910.2.6 by Aaron Bentley
Update for merge review, handle deprecations
885
        self.assertEqual('revid1', tree.inventory.root.revision)
1910.2.1 by Aaron Bentley
Ensure root entry always has a revision
886
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
887
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
888
class V09BundleKnit2Tester(V08BundleTester):
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
889
890
    format = '0.9'
891
892
    def bzrdir_format(self):
893
        format = bzrdir.BzrDirMetaFormat1()
2255.2.211 by Robert Collins
Remove knit2 repository format- it has never been supported.
894
        format.repository_format = knitrepo.RepositoryFormatKnit3()
1910.2.50 by Aaron Bentley
start work on format 0.9 serializer
895
        return format
896
897
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
898
class V09BundleKnit1Tester(V08BundleTester):
899
900
    format = '0.9'
901
902
    def bzrdir_format(self):
903
        format = bzrdir.BzrDirMetaFormat1()
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
904
        format.repository_format = knitrepo.RepositoryFormatKnit1()
1910.2.59 by Aaron Bentley
Test 0.9 bundles for knit format1 and knit format2
905
        return format
906
907
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
908
class MungedBundleTester(TestCaseWithTransport):
909
910
    def build_test_bundle(self):
911
        wt = self.make_branch_and_tree('b1')
912
913
        self.build_tree(['b1/one'])
914
        wt.add('one')
915
        wt.commit('add one', rev_id='a@cset-0-1')
916
        self.build_tree(['b1/two'])
917
        wt.add('two')
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
918
        wt.commit('add two', rev_id='a@cset-0-2',
919
                  revprops={'branch-nick':'test'})
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
920
921
        bundle_txt = StringIO()
922
        rev_ids = write_bundle(wt.branch.repository, 'a@cset-0-2',
923
                               'a@cset-0-1', bundle_txt)
924
        self.assertEqual(['a@cset-0-2'], rev_ids)
925
        bundle_txt.seek(0, 0)
926
        return bundle_txt
927
928
    def check_valid(self, bundle):
929
        """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
930
        self.assertEqual(['a@cset-0-2'],
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
931
            [r.revision_id for r in bundle.real_revisions])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
932
933
    def test_extra_whitespace(self):
934
        bundle_txt = self.build_test_bundle()
935
936
        # Seek to the end of the file
937
        # Adding one extra newline used to give us
938
        # TypeError: float() argument must be a string or a number
939
        bundle_txt.seek(0, 2)
940
        bundle_txt.write('\n')
941
        bundle_txt.seek(0)
942
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
943
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
944
        self.check_valid(bundle)
945
946
    def test_extra_whitespace_2(self):
947
        bundle_txt = self.build_test_bundle()
948
949
        # Seek to the end of the file
950
        # Adding two extra newlines used to give us
951
        # MalformedPatches: The first line of all patches should be ...
952
        bundle_txt.seek(0, 2)
953
        bundle_txt.write('\n\n')
954
        bundle_txt.seek(0)
955
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
956
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
957
        self.check_valid(bundle)
958
959
    def test_missing_trailing_whitespace(self):
960
        bundle_txt = self.build_test_bundle()
961
962
        # Remove a trailing newline, it shouldn't kill the parser
963
        raw = bundle_txt.getvalue()
964
        # The contents of the bundle don't have to be this, but this
965
        # test is concerned with the exact case where the serializer
966
        # creates a blank line at the end, and fails if that
967
        # line is stripped
968
        self.assertEqual('\n\n', raw[-2:])
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
969
        bundle_txt = StringIO(raw[:-1])
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
970
1793.3.4 by John Arbash Meinel
[merge] bzr.dev 1804 and fix conflicts.
971
        bundle = read_bundle(bundle_txt)
1793.3.2 by John Arbash Meinel
(failing) add some tests which munge trailing whitespace
972
        self.check_valid(bundle)
1793.3.14 by John Arbash Meinel
Actually fix the bug with missing trailing newline bug #49182
973
1793.3.16 by John Arbash Meinel
Add tests to ensure that we gracefully handle opening and trailing non-bundle text.
974
    def test_opening_text(self):
975
        bundle_txt = self.build_test_bundle()
976
977
        bundle_txt = StringIO("Some random\nemail comments\n"
978
                              + bundle_txt.getvalue())
979
980
        bundle = read_bundle(bundle_txt)
981
        self.check_valid(bundle)
982
983
    def test_trailing_text(self):
984
        bundle_txt = self.build_test_bundle()
985
986
        bundle_txt = StringIO(bundle_txt.getvalue() +
987
                              "Some trailing\nrandom\ntext\n")
988
989
        bundle = read_bundle(bundle_txt)
990
        self.check_valid(bundle)
991