~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_bundle.py

  • Committer: Aaron Bentley
  • Date: 2006-05-30 15:18:12 UTC
  • mto: This revision was merged to the branch mainline in revision 1738.
  • Revision ID: abentley@panoramicfeedback.com-20060530151812-0e3e9b78cc15a804
Rename changesets to revision bundles

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
from StringIO import StringIO
18
18
 
19
 
from bzrlib.builtins import merge_changeset, merge
 
19
from bzrlib.builtins import merge
20
20
from bzrlib.bzrdir import BzrDir
21
 
from bzrlib.changeset.apply_changeset import install_changeset
22
 
from bzrlib.changeset.read_changeset import ChangesetTree, ChangesetReader
23
 
from bzrlib.changeset.serializer import write_changeset
 
21
from bzrlib.bundle.apply_bundle import install_bundle, merge_bundle
 
22
from bzrlib.bundle.read_bundle import BundleTree, BundleReader
 
23
from bzrlib.bundle.serializer import write_bundle
24
24
from bzrlib.diff import internal_diff
25
25
from bzrlib.errors import BzrError, TestamentMismatch
26
26
from bzrlib.merge import Merge3Merger
118
118
        return text_sha1, len(self.contents[file_id])
119
119
 
120
120
 
121
 
class CTreeTester(TestCase):
122
 
    """A simple unittest tester for the ChangesetTree class."""
 
121
class BTreeTester(TestCase):
 
122
    """A simple unittest tester for the BundleTree class."""
123
123
 
124
124
    def make_tree_1(self):
125
125
        mtree = MockTree()
127
127
        mtree.add_dir("b", "grandparent/parent")
128
128
        mtree.add_file("c", "grandparent/parent/file", "Hello\n")
129
129
        mtree.add_dir("d", "grandparent/alt_parent")
130
 
        return ChangesetTree(mtree, ''), mtree
 
130
        return BundleTree(mtree, ''), mtree
131
131
        
132
132
    def test_renames(self):
133
133
        """Ensure that file renames have the proper effect on children"""
134
 
        ctree = self.make_tree_1()[0]
135
 
        self.assertEqual(ctree.old_path("grandparent"), "grandparent")
136
 
        self.assertEqual(ctree.old_path("grandparent/parent"), "grandparent/parent")
137
 
        self.assertEqual(ctree.old_path("grandparent/parent/file"),
138
 
            "grandparent/parent/file")
139
 
 
140
 
        self.assertEqual(ctree.id2path("a"), "grandparent")
141
 
        self.assertEqual(ctree.id2path("b"), "grandparent/parent")
142
 
        self.assertEqual(ctree.id2path("c"), "grandparent/parent/file")
143
 
 
144
 
        self.assertEqual(ctree.path2id("grandparent"), "a")
145
 
        self.assertEqual(ctree.path2id("grandparent/parent"), "b")
146
 
        self.assertEqual(ctree.path2id("grandparent/parent/file"), "c")
147
 
 
148
 
        assert ctree.path2id("grandparent2") is None
149
 
        assert ctree.path2id("grandparent2/parent") is None
150
 
        assert ctree.path2id("grandparent2/parent/file") is None
151
 
 
152
 
        ctree.note_rename("grandparent", "grandparent2")
153
 
        assert ctree.old_path("grandparent") is None
154
 
        assert ctree.old_path("grandparent/parent") is None
155
 
        assert ctree.old_path("grandparent/parent/file") is None
156
 
 
157
 
        self.assertEqual(ctree.id2path("a"), "grandparent2")
158
 
        self.assertEqual(ctree.id2path("b"), "grandparent2/parent")
159
 
        self.assertEqual(ctree.id2path("c"), "grandparent2/parent/file")
160
 
 
161
 
        self.assertEqual(ctree.path2id("grandparent2"), "a")
162
 
        self.assertEqual(ctree.path2id("grandparent2/parent"), "b")
163
 
        self.assertEqual(ctree.path2id("grandparent2/parent/file"), "c")
164
 
 
165
 
        assert ctree.path2id("grandparent") is None
166
 
        assert ctree.path2id("grandparent/parent") is None
167
 
        assert ctree.path2id("grandparent/parent/file") is None
168
 
 
169
 
        ctree.note_rename("grandparent/parent", "grandparent2/parent2")
170
 
        self.assertEqual(ctree.id2path("a"), "grandparent2")
171
 
        self.assertEqual(ctree.id2path("b"), "grandparent2/parent2")
172
 
        self.assertEqual(ctree.id2path("c"), "grandparent2/parent2/file")
173
 
 
174
 
        self.assertEqual(ctree.path2id("grandparent2"), "a")
175
 
        self.assertEqual(ctree.path2id("grandparent2/parent2"), "b")
176
 
        self.assertEqual(ctree.path2id("grandparent2/parent2/file"), "c")
177
 
 
178
 
        assert ctree.path2id("grandparent2/parent") is None
179
 
        assert ctree.path2id("grandparent2/parent/file") is None
180
 
 
181
 
        ctree.note_rename("grandparent/parent/file", 
 
134
        btree = self.make_tree_1()[0]
 
135
        self.assertEqual(btree.old_path("grandparent"), "grandparent")
 
136
        self.assertEqual(btree.old_path("grandparent/parent"), 
 
137
                         "grandparent/parent")
 
138
        self.assertEqual(btree.old_path("grandparent/parent/file"),
 
139
                         "grandparent/parent/file")
 
140
 
 
141
        self.assertEqual(btree.id2path("a"), "grandparent")
 
142
        self.assertEqual(btree.id2path("b"), "grandparent/parent")
 
143
        self.assertEqual(btree.id2path("c"), "grandparent/parent/file")
 
144
 
 
145
        self.assertEqual(btree.path2id("grandparent"), "a")
 
146
        self.assertEqual(btree.path2id("grandparent/parent"), "b")
 
147
        self.assertEqual(btree.path2id("grandparent/parent/file"), "c")
 
148
 
 
149
        assert btree.path2id("grandparent2") is None
 
150
        assert btree.path2id("grandparent2/parent") is None
 
151
        assert btree.path2id("grandparent2/parent/file") is None
 
152
 
 
153
        btree.note_rename("grandparent", "grandparent2")
 
154
        assert btree.old_path("grandparent") is None
 
155
        assert btree.old_path("grandparent/parent") is None
 
156
        assert btree.old_path("grandparent/parent/file") is None
 
157
 
 
158
        self.assertEqual(btree.id2path("a"), "grandparent2")
 
159
        self.assertEqual(btree.id2path("b"), "grandparent2/parent")
 
160
        self.assertEqual(btree.id2path("c"), "grandparent2/parent/file")
 
161
 
 
162
        self.assertEqual(btree.path2id("grandparent2"), "a")
 
163
        self.assertEqual(btree.path2id("grandparent2/parent"), "b")
 
164
        self.assertEqual(btree.path2id("grandparent2/parent/file"), "c")
 
165
 
 
166
        assert btree.path2id("grandparent") is None
 
167
        assert btree.path2id("grandparent/parent") is None
 
168
        assert btree.path2id("grandparent/parent/file") is None
 
169
 
 
170
        btree.note_rename("grandparent/parent", "grandparent2/parent2")
 
171
        self.assertEqual(btree.id2path("a"), "grandparent2")
 
172
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
 
173
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file")
 
174
 
 
175
        self.assertEqual(btree.path2id("grandparent2"), "a")
 
176
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
 
177
        self.assertEqual(btree.path2id("grandparent2/parent2/file"), "c")
 
178
 
 
179
        assert btree.path2id("grandparent2/parent") is None
 
180
        assert btree.path2id("grandparent2/parent/file") is None
 
181
 
 
182
        btree.note_rename("grandparent/parent/file", 
182
183
                          "grandparent2/parent2/file2")
183
 
        self.assertEqual(ctree.id2path("a"), "grandparent2")
184
 
        self.assertEqual(ctree.id2path("b"), "grandparent2/parent2")
185
 
        self.assertEqual(ctree.id2path("c"), "grandparent2/parent2/file2")
186
 
 
187
 
        self.assertEqual(ctree.path2id("grandparent2"), "a")
188
 
        self.assertEqual(ctree.path2id("grandparent2/parent2"), "b")
189
 
        self.assertEqual(ctree.path2id("grandparent2/parent2/file2"), "c")
190
 
 
191
 
        assert ctree.path2id("grandparent2/parent2/file") is None
 
184
        self.assertEqual(btree.id2path("a"), "grandparent2")
 
185
        self.assertEqual(btree.id2path("b"), "grandparent2/parent2")
 
186
        self.assertEqual(btree.id2path("c"), "grandparent2/parent2/file2")
 
187
 
 
188
        self.assertEqual(btree.path2id("grandparent2"), "a")
 
189
        self.assertEqual(btree.path2id("grandparent2/parent2"), "b")
 
190
        self.assertEqual(btree.path2id("grandparent2/parent2/file2"), "c")
 
191
 
 
192
        assert btree.path2id("grandparent2/parent2/file") is None
192
193
 
193
194
    def test_moves(self):
194
195
        """Ensure that file moves have the proper effect on children"""
195
 
        ctree = self.make_tree_1()[0]
196
 
        ctree.note_rename("grandparent/parent/file", 
 
196
        btree = self.make_tree_1()[0]
 
197
        btree.note_rename("grandparent/parent/file", 
197
198
                          "grandparent/alt_parent/file")
198
 
        self.assertEqual(ctree.id2path("c"), "grandparent/alt_parent/file")
199
 
        self.assertEqual(ctree.path2id("grandparent/alt_parent/file"), "c")
200
 
        assert ctree.path2id("grandparent/parent/file") is None
 
199
        self.assertEqual(btree.id2path("c"), "grandparent/alt_parent/file")
 
200
        self.assertEqual(btree.path2id("grandparent/alt_parent/file"), "c")
 
201
        assert btree.path2id("grandparent/parent/file") is None
201
202
 
202
203
    def unified_diff(self, old, new):
203
204
        out = StringIO()
206
207
        return out.read()
207
208
 
208
209
    def make_tree_2(self):
209
 
        ctree = self.make_tree_1()[0]
210
 
        ctree.note_rename("grandparent/parent/file", 
 
210
        btree = self.make_tree_1()[0]
 
211
        btree.note_rename("grandparent/parent/file", 
211
212
                          "grandparent/alt_parent/file")
212
 
        assert ctree.id2path("e") is None
213
 
        assert ctree.path2id("grandparent/parent/file") is None
214
 
        ctree.note_id("e", "grandparent/parent/file")
215
 
        return ctree
 
213
        assert btree.id2path("e") is None
 
214
        assert btree.path2id("grandparent/parent/file") is None
 
215
        btree.note_id("e", "grandparent/parent/file")
 
216
        return btree
216
217
 
217
218
    def test_adds(self):
218
219
        """File/inventory adds"""
219
 
        ctree = self.make_tree_2()
 
220
        btree = self.make_tree_2()
220
221
        add_patch = self.unified_diff([], ["Extra cheese\n"])
221
 
        ctree.note_patch("grandparent/parent/file", add_patch)
222
 
        ctree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
223
 
        ctree.note_target('grandparent/parent/symlink', 'venus')
224
 
        self.adds_test(ctree)
 
222
        btree.note_patch("grandparent/parent/file", add_patch)
 
223
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
 
224
        btree.note_target('grandparent/parent/symlink', 'venus')
 
225
        self.adds_test(btree)
225
226
 
226
 
    def adds_test(self, ctree):
227
 
        self.assertEqual(ctree.id2path("e"), "grandparent/parent/file")
228
 
        self.assertEqual(ctree.path2id("grandparent/parent/file"), "e")
229
 
        self.assertEqual(ctree.get_file("e").read(), "Extra cheese\n")
230
 
        self.assertEqual(ctree.get_symlink_target('f'), 'venus')
 
227
    def adds_test(self, btree):
 
228
        self.assertEqual(btree.id2path("e"), "grandparent/parent/file")
 
229
        self.assertEqual(btree.path2id("grandparent/parent/file"), "e")
 
230
        self.assertEqual(btree.get_file("e").read(), "Extra cheese\n")
 
231
        self.assertEqual(btree.get_symlink_target('f'), 'venus')
231
232
 
232
233
    def test_adds2(self):
233
234
        """File/inventory adds, with patch-compatibile renames"""
234
 
        ctree = self.make_tree_2()
235
 
        ctree.contents_by_id = False
 
235
        btree = self.make_tree_2()
 
236
        btree.contents_by_id = False
236
237
        add_patch = self.unified_diff(["Hello\n"], ["Extra cheese\n"])
237
 
        ctree.note_patch("grandparent/parent/file", add_patch)
238
 
        ctree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
239
 
        ctree.note_target('grandparent/parent/symlink', 'venus')
240
 
        self.adds_test(ctree)
 
238
        btree.note_patch("grandparent/parent/file", add_patch)
 
239
        btree.note_id('f', 'grandparent/parent/symlink', kind='symlink')
 
240
        btree.note_target('grandparent/parent/symlink', 'venus')
 
241
        self.adds_test(btree)
241
242
 
242
243
    def make_tree_3(self):
243
 
        ctree, mtree = self.make_tree_1()
 
244
        btree, mtree = self.make_tree_1()
244
245
        mtree.add_file("e", "grandparent/parent/topping", "Anchovies\n")
245
 
        ctree.note_rename("grandparent/parent/file", 
 
246
        btree.note_rename("grandparent/parent/file", 
246
247
                          "grandparent/alt_parent/file")
247
 
        ctree.note_rename("grandparent/parent/topping", 
 
248
        btree.note_rename("grandparent/parent/topping", 
248
249
                          "grandparent/alt_parent/stopping")
249
 
        return ctree
 
250
        return btree
250
251
 
251
 
    def get_file_test(self, ctree):
252
 
        self.assertEqual(ctree.get_file("e").read(), "Lemon\n")
253
 
        self.assertEqual(ctree.get_file("c").read(), "Hello\n")
 
252
    def get_file_test(self, btree):
 
253
        self.assertEqual(btree.get_file("e").read(), "Lemon\n")
 
254
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
254
255
 
255
256
    def test_get_file(self):
256
257
        """Get file contents"""
257
 
        ctree = self.make_tree_3()
 
258
        btree = self.make_tree_3()
258
259
        mod_patch = self.unified_diff(["Anchovies\n"], ["Lemon\n"])
259
 
        ctree.note_patch("grandparent/alt_parent/stopping", mod_patch)
260
 
        self.get_file_test(ctree)
 
260
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
 
261
        self.get_file_test(btree)
261
262
 
262
263
    def test_get_file2(self):
263
264
        """Get file contents, with patch-compatibile renames"""
264
 
        ctree = self.make_tree_3()
265
 
        ctree.contents_by_id = False
 
265
        btree = self.make_tree_3()
 
266
        btree.contents_by_id = False
266
267
        mod_patch = self.unified_diff([], ["Lemon\n"])
267
 
        ctree.note_patch("grandparent/alt_parent/stopping", mod_patch)
 
268
        btree.note_patch("grandparent/alt_parent/stopping", mod_patch)
268
269
        mod_patch = self.unified_diff([], ["Hello\n"])
269
 
        ctree.note_patch("grandparent/alt_parent/file", mod_patch)
270
 
        self.get_file_test(ctree)
 
270
        btree.note_patch("grandparent/alt_parent/file", mod_patch)
 
271
        self.get_file_test(btree)
271
272
 
272
273
    def test_delete(self):
273
 
        "Deletion by changeset"
274
 
        ctree = self.make_tree_1()[0]
275
 
        self.assertEqual(ctree.get_file("c").read(), "Hello\n")
276
 
        ctree.note_deletion("grandparent/parent/file")
277
 
        assert ctree.id2path("c") is None
278
 
        assert ctree.path2id("grandparent/parent/file") is None
 
274
        "Deletion by bundle"
 
275
        btree = self.make_tree_1()[0]
 
276
        self.assertEqual(btree.get_file("c").read(), "Hello\n")
 
277
        btree.note_deletion("grandparent/parent/file")
 
278
        assert btree.id2path("c") is None
 
279
        assert btree.path2id("grandparent/parent/file") is None
279
280
 
280
281
    def sorted_ids(self, tree):
281
282
        ids = list(tree)
284
285
 
285
286
    def test_iteration(self):
286
287
        """Ensure that iteration through ids works properly"""
287
 
        ctree = self.make_tree_1()[0]
288
 
        self.assertEqual(self.sorted_ids(ctree), ['a', 'b', 'c', 'd'])
289
 
        ctree.note_deletion("grandparent/parent/file")
290
 
        ctree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
291
 
        ctree.note_last_changed("grandparent/alt_parent/fool", 
 
288
        btree = self.make_tree_1()[0]
 
289
        self.assertEqual(self.sorted_ids(btree), ['a', 'b', 'c', 'd'])
 
290
        btree.note_deletion("grandparent/parent/file")
 
291
        btree.note_id("e", "grandparent/alt_parent/fool", kind="directory")
 
292
        btree.note_last_changed("grandparent/alt_parent/fool", 
292
293
                                "revisionidiguess")
293
 
        self.assertEqual(self.sorted_ids(ctree), ['a', 'b', 'd', 'e'])
 
294
        self.assertEqual(self.sorted_ids(btree), ['a', 'b', 'd', 'e'])
294
295
 
295
296
 
296
297
class CSetTester(TestCaseInTempDir):
297
298
 
298
 
    def get_valid_cset(self, base_rev_id, rev_id,
299
 
            checkout_dir=None, message=None):
300
 
        """Create a changeset from base_rev_id -> rev_id in built-in branch.
 
299
    def get_valid_bundle(self, base_rev_id, rev_id, checkout_dir=None,
 
300
                         message=None):
 
301
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
301
302
        Make sure that the text generated is valid, and that it
302
303
        can be applied against the base, and generate the same information.
303
304
        
304
 
        :return: The in-memory changeset
 
305
        :return: The in-memory bundle 
305
306
        """
306
307
        from cStringIO import StringIO
307
308
 
308
 
        cset_txt = StringIO()
309
 
        rev_ids = write_changeset(self.b1.repository, rev_id, base_rev_id, 
310
 
                                  cset_txt)
311
 
        cset_txt.seek(0)
312
 
        self.assertEqual(cset_txt.readline(), '# Bazaar changeset v0.7\n')
313
 
        self.assertEqual(cset_txt.readline(), '#\n')
 
309
        bundle_txt = StringIO()
 
310
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
 
311
                               bundle_txt)
 
312
        bundle_txt.seek(0)
 
313
        self.assertEqual(bundle_txt.readline(), 
 
314
                         '# Bazaar revision bundle v0.7\n')
 
315
        self.assertEqual(bundle_txt.readline(), '#\n')
314
316
 
315
317
        rev = self.b1.repository.get_revision(rev_id)
316
 
        self.assertEqual(cset_txt.readline().decode('utf-8'),
317
 
                u'# message:\n')
 
318
        self.assertEqual(bundle_txt.readline().decode('utf-8'),
 
319
                         u'# message:\n')
318
320
 
319
 
        open(',,cset', 'wb').write(cset_txt.getvalue())
320
 
        cset_txt.seek(0)
321
 
        # This should also validate the generate changeset
322
 
        cset = ChangesetReader(cset_txt)
323
 
        for cset_rev in cset.info.real_revisions:
324
 
            # These really should have already been checked in read_changeset
325
 
            # since it computes the sha1 hash for the revision, which
326
 
            # only will match if everything is okay, but lets be
327
 
            # explicit about it
328
 
            branch_rev = self.b1.repository.get_revision(cset_rev.revision_id)
 
321
        open(',,bundle', 'wb').write(bundle_txt.getvalue())
 
322
        bundle_txt.seek(0)
 
323
        # This should also validate the generated bundle 
 
324
        bundle = BundleReader(bundle_txt)
 
325
        repository = self.b1.repository
 
326
        for bundle_rev in bundle.info.real_revisions:
 
327
            # These really should have already been checked when we read the
 
328
            # bundle, since it computes the sha1 hash for the revision, which
 
329
            # only will match if everything is okay, but lets be explicit about
 
330
            # it
 
331
            branch_rev = repository.get_revision(bundle_rev.revision_id)
329
332
            for a in ('inventory_sha1', 'revision_id', 'parent_ids',
330
333
                      'timestamp', 'timezone', 'message', 'committer', 
331
334
                      'parent_ids', 'properties'):
332
 
                self.assertEqual(getattr(branch_rev, a), getattr(cset_rev, a))
333
 
            self.assertEqual(len(branch_rev.parent_ids), len(cset_rev.parent_ids))
 
335
                self.assertEqual(getattr(branch_rev, a), 
 
336
                                 getattr(bundle_rev, a))
 
337
            self.assertEqual(len(branch_rev.parent_ids), 
 
338
                             len(bundle_rev.parent_ids))
334
339
        self.assertEqual(rev_ids, 
335
 
                         [r.revision_id for r in cset.info.real_revisions])
336
 
        self.valid_apply_changeset(base_rev_id, cset,
 
340
                         [r.revision_id for r in bundle.info.real_revisions])
 
341
        self.valid_apply_bundle(base_rev_id, bundle,
337
342
                                   checkout_dir=checkout_dir)
338
343
 
339
 
        return cset
 
344
        return bundle
340
345
 
341
 
    def get_invalid_cset(self, base_rev_id, rev_id):
342
 
        """Create a changeset from base_rev_id -> rev_id in built-in branch.
 
346
    def get_invalid_bundle(self, base_rev_id, rev_id):
 
347
        """Create a bundle from base_rev_id -> rev_id in built-in branch.
343
348
        Munge the text so that it's invalid.
344
349
        
345
 
        :return: The in-memory changeset
 
350
        :return: The in-memory bundle
346
351
        """
347
352
        from cStringIO import StringIO
348
353
 
349
 
        cset_txt = StringIO()
350
 
        rev_ids = write_changeset(self.b1.repository, rev_id, base_rev_id, 
351
 
                                  cset_txt)
352
 
        cset_txt.seek(0)
353
 
        open(',,cset', 'wb').write(cset_txt.getvalue())
354
 
        cset_txt.seek(0)
355
 
        new_text = cset_txt.getvalue().replace('executable:no', 
 
354
        bundle_txt = StringIO()
 
355
        rev_ids = write_bundle(self.b1.repository, rev_id, base_rev_id, 
 
356
                               bundle_txt)
 
357
        bundle_txt.seek(0)
 
358
        open(',,bundle', 'wb').write(bundle_txt.getvalue())
 
359
        bundle_txt.seek(0)
 
360
        new_text = bundle_txt.getvalue().replace('executable:no', 
356
361
                                               'executable:yes')
357
 
        cset_txt = StringIO(new_text)
358
 
        cset = ChangesetReader(cset_txt)
359
 
        self.valid_apply_changeset(base_rev_id, cset)
360
 
        return cset
 
362
        bundle_txt = StringIO(new_text)
 
363
        bundle = BundleReader(bundle_txt)
 
364
        self.valid_apply_bundle(base_rev_id, bundle)
 
365
        return bundle 
361
366
 
362
367
    def get_checkout(self, rev_id, checkout_dir=None):
363
368
        """Get a new tree, with the specified revision in it.
373
378
                os.mkdir(checkout_dir)
374
379
        tree = BzrDir.create_standalone_workingtree(checkout_dir)
375
380
        s = StringIO()
376
 
        ancestors = write_changeset(self.b1.repository, rev_id, None, s)
 
381
        ancestors = write_bundle(self.b1.repository, rev_id, None, s)
377
382
        s.seek(0)
378
 
        install_changeset(tree.branch.repository, ChangesetReader(s))
 
383
        install_bundle(tree.branch.repository, BundleReader(s))
379
384
        for ancestor in ancestors:
380
385
            old = self.b1.repository.revision_tree(ancestor)
381
386
            new = tree.branch.repository.revision_tree(ancestor)
394
399
            tree.update()
395
400
        return tree
396
401
 
397
 
    def valid_apply_changeset(self, base_rev_id, reader, checkout_dir=None):
 
402
    def valid_apply_bundle(self, base_rev_id, reader, checkout_dir=None):
398
403
        """Get the base revision, apply the changes, and make
399
404
        sure everything matches the builtin branch.
400
405
        """
404
409
        info = reader.info
405
410
        for rev in info.real_revisions:
406
411
            self.assert_(not repository.has_revision(rev.revision_id),
407
 
                'Revision {%s} present before applying changeset' 
 
412
                'Revision {%s} present before applying bundle' 
408
413
                % rev.revision_id)
409
 
        merge_changeset(reader, to_tree, True, Merge3Merger, False, False)
 
414
        merge_bundle(reader, to_tree, True, Merge3Merger, False, False)
410
415
 
411
416
        for rev in info.real_revisions:
412
417
            self.assert_(repository.has_revision(rev.revision_id),
413
 
                'Missing revision {%s} after applying changeset' 
 
418
                'Missing revision {%s} after applying bundle' 
414
419
                % rev.revision_id)
415
420
 
416
421
        self.assert_(to_tree.branch.repository.has_revision(info.target))
443
448
            # self.assertEqual(base_tree.get_file(fileid).read(),
444
449
            #         to_tree.get_file(fileid).read())
445
450
 
446
 
    def test_changeset(self):
 
451
    def test_bundle(self):
447
452
 
448
453
        import os, sys
449
454
        pjoin = os.path.join
455
460
        self.tree1.add('one')
456
461
        self.tree1.commit('add one', rev_id='a@cset-0-1')
457
462
 
458
 
        cset = self.get_valid_cset(None, 'a@cset-0-1')
459
 
        cset = self.get_valid_cset(None, 'a@cset-0-1',
 
463
        bundle = self.get_valid_bundle(None, 'a@cset-0-1')
 
464
        bundle = self.get_valid_bundle(None, 'a@cset-0-1',
460
465
                message='With a specialized message')
461
466
 
462
467
        # Make sure we can handle files with spaces, tabs, other
492
497
                ])
493
498
        self.tree1.commit('add whitespace', rev_id='a@cset-0-2')
494
499
 
495
 
        cset = self.get_valid_cset('a@cset-0-1', 'a@cset-0-2')
 
500
        bundle = self.get_valid_bundle('a@cset-0-1', 'a@cset-0-2')
496
501
 
497
 
        # Check a rollup changeset
498
 
        cset = self.get_valid_cset(None, 'a@cset-0-2')
 
502
        # Check a rollup bundle 
 
503
        bundle = self.get_valid_bundle(None, 'a@cset-0-2')
499
504
 
500
505
        # Now delete entries
501
506
        self.tree1.remove(
509
514
        tt.apply()
510
515
        self.tree1.commit('removed', rev_id='a@cset-0-3')
511
516
        
512
 
        cset = self.get_valid_cset('a@cset-0-2', 'a@cset-0-3')
513
 
        self.assertRaises(TestamentMismatch, self.get_invalid_cset, 
 
517
        bundle = self.get_valid_bundle('a@cset-0-2', 'a@cset-0-3')
 
518
        self.assertRaises(TestamentMismatch, self.get_invalid_bundle, 
514
519
                          'a@cset-0-2', 'a@cset-0-3')
515
 
        # Check a rollup changeset
516
 
        cset = self.get_valid_cset(None, 'a@cset-0-3')
 
520
        # Check a rollup bundle 
 
521
        bundle = self.get_valid_bundle(None, 'a@cset-0-3')
517
522
 
518
523
 
519
524
        # Now move the directory
520
525
        self.tree1.rename_one('dir', 'sub/dir')
521
526
        self.tree1.commit('rename dir', rev_id='a@cset-0-4')
522
527
 
523
 
        cset = self.get_valid_cset('a@cset-0-3', 'a@cset-0-4')
524
 
        # Check a rollup changeset
525
 
        cset = self.get_valid_cset(None, 'a@cset-0-4')
 
528
        bundle = self.get_valid_bundle('a@cset-0-3', 'a@cset-0-4')
 
529
        # Check a rollup bundle 
 
530
        bundle = self.get_valid_bundle(None, 'a@cset-0-4')
526
531
 
527
532
        # Modified files
528
533
        open('b1/sub/dir/WithCaps.txt', 'ab').write('\nAdding some text\n')
531
536
        self.tree1.rename_one('sub/dir/trailing space ', 
532
537
                              'sub/ start and end space ')
533
538
        self.tree1.commit('Modified files', rev_id='a@cset-0-5')
534
 
        cset = self.get_valid_cset('a@cset-0-4', 'a@cset-0-5')
 
539
        bundle = self.get_valid_bundle('a@cset-0-4', 'a@cset-0-5')
535
540
 
536
541
        # Handle international characters
537
542
        f = open(u'b1/with Dod\xe9', 'wb')
544
549
        self.tree1.commit(u'i18n commit from William Dod\xe9', 
545
550
                          rev_id='a@cset-0-6', committer=u'William Dod\xe9',
546
551
                          verbose=False)
547
 
        cset = self.get_valid_cset('a@cset-0-5', 'a@cset-0-6')
 
552
        bundle = self.get_valid_bundle('a@cset-0-5', 'a@cset-0-6')
548
553
        self.tree1.rename_one('sub/dir/WithCaps.txt', 'temp')
549
554
        self.tree1.rename_one('with space.txt', 'WithCaps.txt')
550
555
        self.tree1.rename_one('temp', 'with space.txt')
551
556
        self.tree1.commit(u'swap filenames', rev_id='a@cset-0-7',
552
557
                          verbose=False)
553
 
        cset = self.get_valid_cset('a@cset-0-6', 'a@cset-0-7')
 
558
        bundle = self.get_valid_bundle('a@cset-0-6', 'a@cset-0-7')
554
559
        other = self.get_checkout('a@cset-0-6')
555
560
        other.rename_one('sub/dir/nolastnewline.txt', 'sub/nolastnewline.txt')
556
561
        other.commit('rename file', rev_id='a@cset-0-7b')
557
562
        merge([other.basedir, -1], [None, None], this_dir=self.tree1.basedir)
558
563
        self.tree1.commit(u'Merge', rev_id='a@cset-0-8',
559
564
                          verbose=False)
560
 
        cset = self.get_valid_cset('a@cset-0-7', 'a@cset-0-8')
 
565
        bundle = self.get_valid_bundle('a@cset-0-7', 'a@cset-0-8')
561
566
 
562
 
    def test_symlink_cset(self):
 
567
    def test_symlink_bundle(self):
563
568
        if not has_symlinks():
564
569
            raise TestSkipped("No symlink support")
565
570
        self.tree1 = BzrDir.create_standalone_workingtree('b1')
568
573
        tt.new_symlink('link', tt.root, 'bar/foo', 'link-1')
569
574
        tt.apply()
570
575
        self.tree1.commit('add symlink', rev_id='l@cset-0-1')
571
 
        self.get_valid_cset(None, 'l@cset-0-1')
 
576
        self.get_valid_bundle(None, 'l@cset-0-1')
572
577
        tt = TreeTransform(self.tree1)
573
578
        trans_id = tt.trans_id_tree_file_id('link-1')
574
579
        tt.adjust_path('link2', tt.root, trans_id)
576
581
        tt.create_symlink('mars', trans_id)
577
582
        tt.apply()
578
583
        self.tree1.commit('rename and change symlink', rev_id='l@cset-0-2')
579
 
        self.get_valid_cset('l@cset-0-1', 'l@cset-0-2')
 
584
        self.get_valid_bundle('l@cset-0-1', 'l@cset-0-2')
580
585
        tt = TreeTransform(self.tree1)
581
586
        trans_id = tt.trans_id_tree_file_id('link-1')
582
587
        tt.delete_contents(trans_id)
583
588
        tt.create_symlink('jupiter', trans_id)
584
589
        tt.apply()
585
590
        self.tree1.commit('just change symlink target', rev_id='l@cset-0-3')
586
 
        self.get_valid_cset('l@cset-0-2', 'l@cset-0-3')
 
591
        self.get_valid_bundle('l@cset-0-2', 'l@cset-0-3')
587
592
        tt = TreeTransform(self.tree1)
588
593
        trans_id = tt.trans_id_tree_file_id('link-1')
589
594
        tt.delete_contents(trans_id)
590
595
        tt.apply()
591
596
        self.tree1.commit('Delete symlink', rev_id='l@cset-0-4')
592
 
        self.get_valid_cset('l@cset-0-3', 'l@cset-0-4')
 
597
        self.get_valid_bundle('l@cset-0-3', 'l@cset-0-4')
593
598
 
594
 
    def test_binary_cset(self):
 
599
    def test_binary_bundle(self):
595
600
        self.tree1 = BzrDir.create_standalone_workingtree('b1')
596
601
        self.b1 = self.tree1.branch
597
602
        tt = TreeTransform(self.tree1)
599
604
        tt.new_file('file2', tt.root, '\x00\xff', 'binary-2')
600
605
        tt.apply()
601
606
        self.tree1.commit('add binary', rev_id='b@cset-0-1')
602
 
        self.get_valid_cset(None, 'b@cset-0-1')
 
607
        self.get_valid_bundle(None, 'b@cset-0-1')
603
608
        tt = TreeTransform(self.tree1)
604
609
        trans_id = tt.trans_id_tree_file_id('binary-1')
605
610
        tt.delete_contents(trans_id)
606
611
        tt.apply()
607
612
        self.tree1.commit('delete binary', rev_id='b@cset-0-2')
608
 
        self.get_valid_cset('b@cset-0-1', 'b@cset-0-2')
 
613
        self.get_valid_bundle('b@cset-0-1', 'b@cset-0-2')
609
614
        tt = TreeTransform(self.tree1)
610
615
        trans_id = tt.trans_id_tree_file_id('binary-2')
611
616
        tt.adjust_path('file3', tt.root, trans_id)
613
618
        tt.create_file('filecontents\x00', trans_id)
614
619
        tt.apply()
615
620
        self.tree1.commit('rename and modify binary', rev_id='b@cset-0-3')
616
 
        self.get_valid_cset('b@cset-0-2', 'b@cset-0-3')
 
621
        self.get_valid_bundle('b@cset-0-2', 'b@cset-0-3')
617
622
        tt = TreeTransform(self.tree1)
618
623
        trans_id = tt.trans_id_tree_file_id('binary-2')
619
624
        tt.delete_contents(trans_id)
620
625
        tt.create_file('\x00filecontents', trans_id)
621
626
        tt.apply()
622
627
        self.tree1.commit('just modify binary', rev_id='b@cset-0-4')
623
 
        self.get_valid_cset('b@cset-0-3', 'b@cset-0-4')
 
628
        self.get_valid_bundle('b@cset-0-3', 'b@cset-0-4')
624
629
 
625
630
    def test_last_modified(self):
626
631
        self.tree1 = BzrDir.create_standalone_workingtree('b1')
648
653
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-3',
649
654
                          verbose=False)
650
655
        self.tree1.commit(u'Merge', rev_id='a@lmod-0-4')
651
 
        cset = self.get_valid_cset('a@lmod-0-2a', 'a@lmod-0-4')
 
656
        bundle = self.get_valid_bundle('a@lmod-0-2a', 'a@lmod-0-4')