~bzr-pqm/bzr/bzr.dev

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