~bzr-pqm/bzr/bzr.dev

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