/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/workingtree_implementations/test_parents.py

  • Committer: Daniel Watkins
  • Date: 2007-11-06 09:33:05 UTC
  • mfrom: (2967 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2993.
  • Revision ID: d.m.watkins@warwick.ac.uk-20071106093305-zfef3c0jbcvunnuz
Merged bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Tests of the parent related functions of WorkingTrees."""
18
18
 
 
19
from errno import EEXIST
19
20
import os
20
21
 
21
22
from bzrlib import (
22
23
    errors,
 
24
    osutils,
23
25
    revision as _mod_revision,
24
26
    symbol_versioning,
25
27
    )
 
28
from bzrlib.inventory import (
 
29
    Inventory,
 
30
    InventoryFile,
 
31
    InventoryDirectory,
 
32
    InventoryLink,
 
33
    )
 
34
from bzrlib.revision import Revision
 
35
from bzrlib.tests import SymlinkFeature, TestNotApplicable
26
36
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
27
37
from bzrlib.uncommit import uncommit
28
38
 
237
247
        first_revision = tree.commit('first post')
238
248
        tree.add_parent_tree(('second', None))
239
249
        self.assertConsistentParents([first_revision, 'second'], tree)
 
250
 
 
251
 
 
252
class UpdateToOneParentViaDeltaTests(TestParents):
 
253
    """Tests for the update_basis_by_delta call.
 
254
    
 
255
    This is intuitively defined as 'apply an inventory delta to the basis and
 
256
    discard other parents', but for trees that have an inventory that is not
 
257
    managed as a tree-by-id, the implementation requires roughly duplicated
 
258
    tests with those for apply_inventory_delta on the main tree.
 
259
    """
 
260
 
 
261
    def assertDeltaApplicationResultsInExpectedBasis(self, tree, revid, delta,
 
262
        expected_inventory):
 
263
        tree.lock_write()
 
264
        try:
 
265
            tree.update_basis_by_delta(revid, delta)
 
266
        finally:
 
267
            tree.unlock()
 
268
        # check the last revision was adjusted to rev_id
 
269
        self.assertEqual(revid, tree.last_revision())
 
270
        # check the parents are what we expect
 
271
        self.assertEqual([revid], tree.get_parent_ids())
 
272
        # check that the basis tree has the inventory we expect from applying
 
273
        # the delta.
 
274
        result_basis = tree.basis_tree()
 
275
        result_basis.lock_read()
 
276
        self.addCleanup(result_basis.unlock)
 
277
        self.assertEqual(expected_inventory, result_basis.inventory)
 
278
 
 
279
    def make_inv_delta(self, old, new):
 
280
        """Make an inventory delta from two inventories."""
 
281
        old_ids = set(old._byid.iterkeys())
 
282
        new_ids = set(new._byid.iterkeys())
 
283
        adds = new_ids - old_ids
 
284
        deletes = old_ids - new_ids
 
285
        common = old_ids.intersection(new_ids)
 
286
        delta = []
 
287
        for file_id in deletes:
 
288
            delta.append((old.id2path(file_id), None, file_id, None))
 
289
        for file_id in adds:
 
290
            delta.append((None, new.id2path(file_id), file_id, new[file_id]))
 
291
        for file_id in common:
 
292
            if old[file_id] != new[file_id]:
 
293
                delta.append((old.id2path(file_id), new.id2path(file_id),
 
294
                    file_id, new[file_id]))
 
295
        return delta
 
296
 
 
297
    def fake_up_revision(self, tree, revid, shape):
 
298
        tree.lock_write()
 
299
        try:
 
300
            tree.branch.repository.start_write_group()
 
301
            try:
 
302
                if shape.root.revision is None:
 
303
                    shape.root.revision = revid
 
304
                sha1 = tree.branch.repository.add_inventory(revid, shape, [])
 
305
                rev = Revision(timestamp=0,
 
306
                               timezone=None,
 
307
                               committer="Foo Bar <foo@example.com>",
 
308
                               message="Message",
 
309
                               inventory_sha1=sha1,
 
310
                               revision_id=revid)
 
311
                tree.branch.repository.add_revision(revid, rev)
 
312
            except:
 
313
                tree.branch.repository.abort_write_group()
 
314
                raise
 
315
            else:
 
316
                tree.branch.repository.commit_write_group()
 
317
        finally:
 
318
            tree.unlock()
 
319
 
 
320
    def add_entry(self, inv, rev_id, entry):
 
321
        entry.revision = rev_id
 
322
        inv.add(entry)
 
323
 
 
324
    def add_dir(self, inv, rev_id, file_id, parent_id, name):
 
325
        new_dir = InventoryDirectory(file_id, name, parent_id)
 
326
        self.add_entry(inv, rev_id, new_dir)
 
327
 
 
328
    def add_file(self, inv, rev_id, file_id, parent_id, name, sha, size):
 
329
        new_file = InventoryFile(file_id, name, parent_id)
 
330
        new_file.text_sha1 = sha
 
331
        new_file.text_size = size
 
332
        self.add_entry(inv, rev_id, new_file)
 
333
 
 
334
    def add_link(self, inv, rev_id, file_id, parent_id, name, target):
 
335
        new_link = InventoryLink(file_id, name, parent_id)
 
336
        new_link.symlink_target = target
 
337
        self.add_entry(inv, rev_id, new_link)
 
338
 
 
339
    def add_new_root(self, new_shape, old_revid, new_revid):
 
340
        if self.bzrdir_format.repository_format.rich_root_data:
 
341
            self.add_dir(new_shape, old_revid, 'root-id', None, '')
 
342
        else:
 
343
            self.add_dir(new_shape, new_revid, 'root-id', None, '')
 
344
 
 
345
    def assertTransitionFromBasisToShape(self, basis_shape, basis_revid,
 
346
        new_shape, new_revid, extra_parent=None):
 
347
        # set the inventory revision ids.
 
348
        basis_shape.revision_id = basis_revid
 
349
        new_shape.revision_id = new_revid
 
350
        delta = self.make_inv_delta(basis_shape, new_shape)
 
351
        tree = self.make_branch_and_tree('tree')
 
352
        # the shapes need to be in the tree's repository to be able to set them
 
353
        # as a parent, but the file content is not needed.
 
354
        if basis_revid is not None:
 
355
            self.fake_up_revision(tree, basis_revid, basis_shape)
 
356
            parents = [basis_revid]
 
357
            if extra_parent is not None:
 
358
                parents.append(extra_parent)
 
359
            tree.set_parent_ids(parents)
 
360
        self.fake_up_revision(tree, new_revid, new_shape)
 
361
        # give tree an inventory of new_shape
 
362
        tree._write_inventory(new_shape)
 
363
        self.assertDeltaApplicationResultsInExpectedBasis(tree, new_revid,
 
364
            delta, new_shape)
 
365
        # The tree should be internally consistent; while this is a moderately
 
366
        # large hammer, this is a particularly sensitive area of code, so the
 
367
        # extra assurance is well worth it.
 
368
        tree._validate()
 
369
        osutils.rmtree('tree')
 
370
 
 
371
    def test_no_parents_just_root(self):
 
372
        """Test doing an empty commit - no parent, set a root only."""
 
373
        basis_shape = Inventory(root_id=None) # empty tree
 
374
        new_shape = Inventory() # tree with a root
 
375
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
 
376
            'new_parent')
 
377
 
 
378
    def test_no_parents_full_tree(self):
 
379
        """Test doing a regular initial commit with files and dirs."""
 
380
        basis_shape = Inventory(root_id=None) # empty tree
 
381
        revid = 'new-parent'
 
382
        new_shape = Inventory(root_id=None)
 
383
        self.add_dir(new_shape, revid, 'root-id', None, '')
 
384
        self.add_link(new_shape, revid, 'link-id', 'root-id', 'link', 'target')
 
385
        self.add_file(new_shape, revid, 'file-id', 'root-id', 'file', '1' * 32,
 
386
            12)
 
387
        self.add_dir(new_shape, revid, 'dir-id', 'root-id', 'dir')
 
388
        self.add_file(new_shape, revid, 'subfile-id', 'dir-id', 'subfile',
 
389
            '2' * 32, 24)
 
390
        self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
 
391
            revid)
 
392
 
 
393
    def test_file_content_change(self):
 
394
        old_revid = 'old-parent'
 
395
        basis_shape = Inventory(root_id=None)
 
396
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
397
        self.add_file(basis_shape, old_revid, 'file-id', 'root-id', 'file',
 
398
            '1' * 32, 12)
 
399
        new_revid = 'new-parent'
 
400
        new_shape = Inventory(root_id=None)
 
401
        self.add_new_root(new_shape, old_revid, new_revid)
 
402
        self.add_file(new_shape, new_revid, 'file-id', 'root-id', 'file',
 
403
            '2' * 32, 24)
 
404
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
405
            new_shape, new_revid)
 
406
 
 
407
    def test_link_content_change(self):
 
408
        old_revid = 'old-parent'
 
409
        basis_shape = Inventory(root_id=None)
 
410
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
411
        self.add_link(basis_shape, old_revid, 'link-id', 'root-id', 'link',
 
412
            'old-target')
 
413
        new_revid = 'new-parent'
 
414
        new_shape = Inventory(root_id=None)
 
415
        self.add_new_root(new_shape, old_revid, new_revid)
 
416
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
 
417
            'new-target')
 
418
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
419
            new_shape, new_revid)
 
420
 
 
421
    def test_kind_changes(self):
 
422
        def do_file(inv, revid):
 
423
            self.add_file(inv, revid, 'path-id', 'root-id', 'path', '1' * 32,
 
424
                12)
 
425
        def do_link(inv, revid):
 
426
            self.add_link(inv, revid, 'path-id', 'root-id', 'path', 'target')
 
427
        def do_dir(inv, revid):
 
428
            self.add_dir(inv, revid, 'path-id', 'root-id', 'path')
 
429
        for old_factory in (do_file, do_link, do_dir):
 
430
            for new_factory in (do_file, do_link, do_dir):
 
431
                if old_factory == new_factory:
 
432
                    continue
 
433
                old_revid = 'old-parent'
 
434
                basis_shape = Inventory(root_id=None)
 
435
                self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
436
                old_factory(basis_shape, old_revid)
 
437
                new_revid = 'new-parent'
 
438
                new_shape = Inventory(root_id=None)
 
439
                self.add_new_root(new_shape, old_revid, new_revid)
 
440
                new_factory(new_shape, new_revid)
 
441
                self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
442
                    new_shape, new_revid)
 
443
 
 
444
    def test_content_from_second_parent_is_dropped(self):
 
445
        left_revid = 'left-parent'
 
446
        basis_shape = Inventory(root_id=None)
 
447
        self.add_dir(basis_shape, left_revid, 'root-id', None, '')
 
448
        self.add_link(basis_shape, left_revid, 'link-id', 'root-id', 'link',
 
449
            'left-target')
 
450
        # the right shape has content - file, link, subdir with a child,
 
451
        # that should all be discarded by the call.
 
452
        right_revid = 'right-parent'
 
453
        right_shape = Inventory(root_id=None)
 
454
        self.add_dir(right_shape, left_revid, 'root-id', None, '')
 
455
        self.add_link(right_shape, right_revid, 'link-id', 'root-id', 'link',
 
456
            'some-target')
 
457
        self.add_dir(right_shape, right_revid, 'subdir-id', 'root-id', 'dir')
 
458
        self.add_file(right_shape, right_revid, 'file-id', 'subdir-id', 'file',
 
459
            '2' * 32, 24)
 
460
        new_revid = 'new-parent'
 
461
        new_shape = Inventory(root_id=None)
 
462
        self.add_new_root(new_shape, left_revid, new_revid)
 
463
        self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
 
464
            'new-target')
 
465
        self.assertTransitionFromBasisToShape(basis_shape, left_revid,
 
466
            new_shape, new_revid, right_revid)
 
467
 
 
468
    def test_parent_id_changed(self):
 
469
        # test that when the only change to an entry is its parent id changing
 
470
        # that it is handled correctly (that is it keeps the same path)
 
471
        old_revid = 'old-parent'
 
472
        basis_shape = Inventory(root_id=None)
 
473
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
474
        self.add_dir(basis_shape, old_revid, 'orig-parent-id', 'root-id', 'dir')
 
475
        self.add_dir(basis_shape, old_revid, 'dir-id', 'orig-parent-id', 'dir')
 
476
        new_revid = 'new-parent'
 
477
        new_shape = Inventory(root_id=None)
 
478
        self.add_new_root(new_shape, old_revid, new_revid)
 
479
        self.add_dir(new_shape, new_revid, 'new-parent-id', 'root-id', 'dir')
 
480
        self.add_dir(new_shape, new_revid, 'dir-id', 'new-parent-id', 'dir')
 
481
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
482
            new_shape, new_revid)
 
483
 
 
484
    def test_name_changed(self):
 
485
        # test that when the only change to an entry is its name changing that
 
486
        # it is handled correctly (that is it keeps the same parent id)
 
487
        old_revid = 'old-parent'
 
488
        basis_shape = Inventory(root_id=None)
 
489
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
490
        self.add_dir(basis_shape, old_revid, 'parent-id', 'root-id', 'origdir')
 
491
        self.add_dir(basis_shape, old_revid, 'dir-id', 'parent-id', 'olddir')
 
492
        new_revid = 'new-parent'
 
493
        new_shape = Inventory(root_id=None)
 
494
        self.add_new_root(new_shape, old_revid, new_revid)
 
495
        self.add_dir(new_shape, new_revid, 'parent-id', 'root-id', 'newdir')
 
496
        self.add_dir(new_shape, new_revid, 'dir-id', 'parent-id', 'newdir')
 
497
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
498
            new_shape, new_revid)
 
499
 
 
500
    def test_parent_child_swap(self):
 
501
        # test a A->A/B and A/B->A path swap.
 
502
        old_revid = 'old-parent'
 
503
        basis_shape = Inventory(root_id=None)
 
504
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
505
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
506
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
 
507
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
 
508
        new_revid = 'new-parent'
 
509
        new_shape = Inventory(root_id=None)
 
510
        self.add_new_root(new_shape, old_revid, new_revid)
 
511
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
 
512
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'dir-id-B', 'B')
 
513
        self.add_link(new_shape, new_revid, 'link-id-C', 'dir-id-A', 'C', 'C')
 
514
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
515
            new_shape, new_revid)
 
516
 
 
517
    def test_path_swap(self):
 
518
        # test a A->B and B->A path swap.
 
519
        old_revid = 'old-parent'
 
520
        basis_shape = Inventory(root_id=None)
 
521
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
522
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
523
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'root-id', 'B')
 
524
        self.add_link(basis_shape, old_revid, 'link-id-C', 'root-id', 'C', 'C')
 
525
        self.add_link(basis_shape, old_revid, 'link-id-D', 'root-id', 'D', 'D')
 
526
        self.add_file(basis_shape, old_revid, 'file-id-E', 'root-id', 'E',
 
527
            '1' * 32, 12)
 
528
        self.add_file(basis_shape, old_revid, 'file-id-F', 'root-id', 'F',
 
529
            '2' * 32, 24)
 
530
        new_revid = 'new-parent'
 
531
        new_shape = Inventory(root_id=None)
 
532
        self.add_new_root(new_shape, old_revid, new_revid)
 
533
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
 
534
        self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
 
535
        self.add_link(new_shape, new_revid, 'link-id-C', 'root-id', 'D', 'C')
 
536
        self.add_link(new_shape, new_revid, 'link-id-D', 'root-id', 'C', 'D')
 
537
        self.add_file(new_shape, new_revid, 'file-id-E', 'root-id', 'F',
 
538
            '1' * 32, 12)
 
539
        self.add_file(new_shape, new_revid, 'file-id-F', 'root-id', 'E',
 
540
            '2' * 32, 24)
 
541
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
542
            new_shape, new_revid)
 
543
 
 
544
    def test_adds(self):
 
545
        # test adding paths and dirs, including adding to a newly added dir.
 
546
        old_revid = 'old-parent'
 
547
        basis_shape = Inventory(root_id=None)
 
548
        # with a root, so its a commit after the first.
 
549
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
550
        new_revid = 'new-parent'
 
551
        new_shape = Inventory(root_id=None)
 
552
        self.add_new_root(new_shape, old_revid, new_revid)
 
553
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
 
554
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
 
555
        self.add_file(new_shape, new_revid, 'file-id-C', 'root-id', 'C',
 
556
            '1' * 32, 12)
 
557
        self.add_file(new_shape, new_revid, 'file-id-D', 'dir-id-A', 'D',
 
558
            '2' * 32, 24)
 
559
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
560
            new_shape, new_revid)
 
561
 
 
562
    def test_removes(self):
 
563
        # test removing paths, including paths that are within other also
 
564
        # removed paths.
 
565
        old_revid = 'old-parent'
 
566
        basis_shape = Inventory(root_id=None)
 
567
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
568
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
569
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
 
570
        self.add_file(basis_shape, old_revid, 'file-id-C', 'root-id', 'C',
 
571
            '1' * 32, 12)
 
572
        self.add_file(basis_shape, old_revid, 'file-id-D', 'dir-id-A', 'D',
 
573
            '2' * 32, 24)
 
574
        new_revid = 'new-parent'
 
575
        new_shape = Inventory(root_id=None)
 
576
        self.add_new_root(new_shape, old_revid, new_revid)
 
577
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
578
            new_shape, new_revid)
 
579
 
 
580
    def test_move_to_added_dir(self):
 
581
        old_revid = 'old-parent'
 
582
        basis_shape = Inventory(root_id=None)
 
583
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
584
        self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
 
585
        new_revid = 'new-parent'
 
586
        new_shape = Inventory(root_id=None)
 
587
        self.add_new_root(new_shape, old_revid, new_revid)
 
588
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
 
589
        self.add_link(new_shape, new_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
 
590
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
591
            new_shape, new_revid)
 
592
 
 
593
    def test_move_from_removed_dir(self):
 
594
        old_revid = 'old-parent'
 
595
        basis_shape = Inventory(root_id=None)
 
596
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
597
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
598
        self.add_link(basis_shape, old_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
 
599
        new_revid = 'new-parent'
 
600
        new_shape = Inventory(root_id=None)
 
601
        self.add_new_root(new_shape, old_revid, new_revid)
 
602
        self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
 
603
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
604
            new_shape, new_revid)
 
605
 
 
606
    def test_move_moves_children_recursively(self):
 
607
        old_revid = 'old-parent'
 
608
        basis_shape = Inventory(root_id=None)
 
609
        self.add_dir(basis_shape, old_revid, 'root-id', None, '')
 
610
        self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
 
611
        self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
 
612
        self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
 
613
        new_revid = 'new-parent'
 
614
        new_shape = Inventory(root_id=None)
 
615
        self.add_new_root(new_shape, old_revid, new_revid)
 
616
        # the moved path:
 
617
        self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
 
618
        # unmoved children.
 
619
        self.add_dir(new_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
 
620
        self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
 
621
        self.assertTransitionFromBasisToShape(basis_shape, old_revid,
 
622
            new_shape, new_revid)