/brz/remove-bazaar

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