/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/workingtree.py

Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
394
394
        return pathjoin(self.basedir, filename)
395
395
    
396
396
    def basis_tree(self):
397
 
        """Return RevisionTree for the current last revision."""
 
397
        """Return RevisionTree for the current last revision.
 
398
        
 
399
        If the left most parent is a ghost then the returned tree will be an
 
400
        empty tree - one obtained by calling repository.revision_tree(None).
 
401
        """
398
402
        revision_id = self.last_revision()
399
403
        if revision_id is not None:
400
404
            try:
407
411
                return bzrlib.tree.RevisionTree(self.branch.repository, inv,
408
412
                                                revision_id)
409
413
        # FIXME? RBC 20060403 should we cache the inventory here ?
410
 
        return self.branch.repository.revision_tree(revision_id)
 
414
        try:
 
415
            return self.branch.repository.revision_tree(revision_id)
 
416
        except errors.RevisionNotPresent:
 
417
            # the basis tree *may* be a ghost or a low level error may have
 
418
            # occured. If the revision is present, its a problem, if its not
 
419
            # its a ghost.
 
420
            if self.branch.repository.has_revision(revision_id):
 
421
                raise
 
422
            # the basis tree is a ghost so return an empty tree.
 
423
            return self.branch.repository.revision_tree(None)
411
424
 
412
425
    @staticmethod
413
426
    @deprecated_method(zero_eight)
478
491
            parents = []
479
492
        else:
480
493
            parents = [last_rev]
481
 
        other_parents = self.pending_merges()
482
 
        return parents + other_parents
 
494
        try:
 
495
            merges_file = self._control_files.get_utf8('pending-merges')
 
496
        except NoSuchFile:
 
497
            pass
 
498
        else:
 
499
            for l in merges_file.readlines():
 
500
                parents.append(l.rstrip('\n'))
 
501
        return parents
483
502
 
484
503
    def get_root_id(self):
485
504
        """Return the id of this trees root"""
520
539
        if revision_id is None:
521
540
            transform_tree(tree, self)
522
541
        else:
523
 
            # TODO now merge from tree.last_revision to revision
 
542
            # TODO now merge from tree.last_revision to revision (to preserve
 
543
            # user local changes)
524
544
            transform_tree(tree, self)
525
 
            tree.set_last_revision(revision_id)
 
545
            tree.set_parent_ids([revision_id])
526
546
 
527
547
    @needs_write_lock
528
548
    def commit(self, message=None, revprops=None, *args, **kwargs):
645
665
        self._write_inventory(inv)
646
666
 
647
667
    @needs_write_lock
 
668
    def add_parent_tree_id(self, revision_id, allow_leftmost_as_ghost=False):
 
669
        """Add revision_id as a parent.
 
670
 
 
671
        This is equivalent to retrieving the current list of parent ids
 
672
        and setting the list to its value plus revision_id.
 
673
 
 
674
        :param revision_id: The revision id to add to the parent list. It may
 
675
        be a ghost revision as long as its not the first parent to be added,
 
676
        or the allow_leftmost_as_ghost parameter is set True.
 
677
        :param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
 
678
        """
 
679
        parents = self.get_parent_ids() + [revision_id]
 
680
        self.set_parent_ids(parents,
 
681
            allow_leftmost_as_ghost=len(parents) > 1 or allow_leftmost_as_ghost)
 
682
 
 
683
    @needs_write_lock
 
684
    def add_parent_tree(self, parent_tuple, allow_leftmost_as_ghost=False):
 
685
        """Add revision_id, tree tuple as a parent.
 
686
 
 
687
        This is equivalent to retrieving the current list of parent trees
 
688
        and setting the list to its value plus parent_tuple. See also
 
689
        add_parent_tree_id - if you only have a parent id available it will be
 
690
        simpler to use that api. If you have the parent already available, using
 
691
        this api is preferred.
 
692
 
 
693
        :param parent_tuple: The (revision id, tree) to add to the parent list.
 
694
            If the revision_id is a ghost, pass None for the tree.
 
695
        :param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
 
696
        """
 
697
        self.set_parent_ids(self.get_parent_ids() + [parent_tuple[0]],
 
698
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
 
699
 
 
700
    @needs_write_lock
648
701
    def add_pending_merge(self, *revision_ids):
649
702
        # TODO: Perhaps should check at this point that the
650
703
        # history of the revision is actually present?
651
 
        p = self.pending_merges()
 
704
        parents = self.get_parent_ids()
652
705
        updated = False
653
706
        for rev_id in revision_ids:
654
 
            if rev_id in p:
 
707
            if rev_id in parents:
655
708
                continue
656
 
            p.append(rev_id)
 
709
            parents.append(rev_id)
657
710
            updated = True
658
711
        if updated:
659
 
            self.set_pending_merges(p)
 
712
            self.set_parent_ids(parents, allow_leftmost_as_ghost=True)
660
713
 
661
714
    @needs_read_lock
662
715
    def pending_merges(self):
665
718
        These are revisions that have been merged into the working
666
719
        directory but not yet committed.
667
720
        """
668
 
        try:
669
 
            merges_file = self._control_files.get_utf8('pending-merges')
670
 
        except NoSuchFile:
671
 
            return []
672
 
        p = []
673
 
        for l in merges_file.readlines():
674
 
            p.append(l.rstrip('\n'))
675
 
        return p
 
721
        return self.get_parent_ids()[1:]
 
722
 
 
723
    @needs_write_lock
 
724
    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
 
725
        """Set the parent ids to revision_ids.
 
726
        
 
727
        See also set_parent_trees. This api will try to retrieve the tree data
 
728
        for each element of revision_ids from the trees repository. If you have
 
729
        tree data already available, it is more efficient to use
 
730
        set_parent_trees rather than set_parent_ids. set_parent_ids is however
 
731
        an easier API to use.
 
732
 
 
733
        :param revision_ids: The revision_ids to set as the parent ids of this
 
734
            working tree. Any of these may be ghosts.
 
735
        """
 
736
        if len(revision_ids) > 0:
 
737
            leftmost_id = revision_ids[0]
 
738
            if (not allow_leftmost_as_ghost and not
 
739
                self.branch.repository.has_revision(leftmost_id)):
 
740
                raise errors.GhostRevisionUnusableHere(leftmost_id)
 
741
            self.set_last_revision(leftmost_id)
 
742
        else:
 
743
            self.set_last_revision(None)
 
744
        merges = revision_ids[1:]
 
745
        self._control_files.put_utf8('pending-merges', '\n'.join(merges))
 
746
 
 
747
    @needs_write_lock
 
748
    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
 
749
        """Set the parents of the working tree.
 
750
 
 
751
        :param parents_list: A list of (revision_id, tree) tuples. 
 
752
            If tree is None, then that element is treated as an unreachable
 
753
            parent tree - i.e. a ghost.
 
754
        """
 
755
        # parent trees are not used in current format trees, delegate to
 
756
        # set_parent_ids
 
757
        self.set_parent_ids([rev for (rev, tree) in parents_list],
 
758
            allow_leftmost_as_ghost=allow_leftmost_as_ghost)
676
759
 
677
760
    @needs_write_lock
678
761
    def set_pending_merges(self, rev_list):
679
 
        self._control_files.put_utf8('pending-merges', '\n'.join(rev_list))
 
762
        parents = self.get_parent_ids()
 
763
        leftmost = parents[:1]
 
764
        new_parents = leftmost + rev_list
 
765
        self.set_parent_ids(new_parents)
680
766
 
681
767
    @needs_write_lock
682
768
    def set_merge_modified(self, modified_hashes):
999
1085
                repository = self.branch.repository
1000
1086
                pb = bzrlib.ui.ui_factory.nested_progress_bar()
1001
1087
                try:
1002
 
                    branch_basis = self.branch.basis_tree() 
1003
 
                    merge_inner(self.branch, branch_basis, basis_tree,
1004
 
                                this_tree=self, pb=pb)
 
1088
                    new_basis_tree = self.branch.basis_tree()
 
1089
                    merge_inner(self.branch,
 
1090
                                new_basis_tree,
 
1091
                                basis_tree,
 
1092
                                this_tree=self,
 
1093
                                pb=pb)
1005
1094
                    if (basis_tree.inventory.root is None and
1006
 
                        branch_basis.inventory.root is not None):
1007
 
                        self.set_root_id(branch_basis.inventory.root.file_id)
 
1095
                        new_basis_tree.inventory.root is not None):
 
1096
                        self.set_root_id(new_basis_tree.inventory.root.file_id)
1008
1097
                finally:
1009
1098
                    pb.finished()
1010
 
                self.set_last_revision(self.branch.last_revision())
 
1099
                # TODO - dedup parents list with things merged by pull ?
 
1100
                # reuse the revisiontree we merged against to set the new
 
1101
                # tree data.
 
1102
                parent_trees = [(self.branch.last_revision(), new_basis_tree)]
 
1103
                # we have to pull the merge trees out again, because 
 
1104
                # merge_inner has set the ids. - this corner is not yet 
 
1105
                # layered well enough to prevent double handling.
 
1106
                merges = self.get_parent_ids()[1:]
 
1107
                parent_trees.extend([
 
1108
                    (parent, repository.revision_tree(parent)) for
 
1109
                     parent in merges])
 
1110
                self.set_parent_trees(parent_trees)
1011
1111
            return count
1012
1112
        finally:
1013
1113
            source.unlock()
1167
1267
        for regex, mapping in rules:
1168
1268
            match = regex.match(filename)
1169
1269
            if match is not None:
1170
 
                # one or more of the groups in mapping will have a non-None group 
1171
 
                # match.
 
1270
                # one or more of the groups in mapping will have a non-None
 
1271
                # group match.
1172
1272
                groups = match.groups()
1173
1273
                rules = [mapping[group] for group in 
1174
1274
                    mapping if groups[group] is not None]
1330
1430
            old_tree = self.basis_tree()
1331
1431
        conflicts = revert(self, old_tree, filenames, backups, pb)
1332
1432
        if not len(filenames):
1333
 
            self.set_pending_merges([])
 
1433
            self.set_parent_ids(self.get_parent_ids()[:1])
1334
1434
            resolve(self)
1335
1435
        else:
1336
1436
            resolve(self, filenames, ignore_misses=True)
1413
1513
        - Do a 'normal' merge of the old branch basis if it is relevant.
1414
1514
        """
1415
1515
        old_tip = self.branch.update()
1416
 
        if old_tip is not None:
1417
 
            self.add_pending_merge(old_tip)
1418
 
        self.branch.lock_read()
1419
 
        try:
1420
 
            result = 0
1421
 
            if self.last_revision() != self.branch.last_revision():
1422
 
                # merge tree state up to new branch tip.
1423
 
                basis = self.basis_tree()
1424
 
                to_tree = self.branch.basis_tree()
1425
 
                if basis.inventory.root is None:
1426
 
                    self.set_root_id(to_tree.inventory.root.file_id)
1427
 
                result += merge_inner(self.branch,
1428
 
                                      to_tree,
1429
 
                                      basis,
1430
 
                                      this_tree=self)
1431
 
                self.set_last_revision(self.branch.last_revision())
1432
 
            if old_tip and old_tip != self.last_revision():
1433
 
                # our last revision was not the prior branch last revision
1434
 
                # and we have converted that last revision to a pending merge.
1435
 
                # base is somewhere between the branch tip now
1436
 
                # and the now pending merge
1437
 
                from bzrlib.revision import common_ancestor
1438
 
                try:
1439
 
                    base_rev_id = common_ancestor(self.branch.last_revision(),
1440
 
                                                  old_tip,
1441
 
                                                  self.branch.repository)
1442
 
                except errors.NoCommonAncestor:
1443
 
                    base_rev_id = None
1444
 
                base_tree = self.branch.repository.revision_tree(base_rev_id)
1445
 
                other_tree = self.branch.repository.revision_tree(old_tip)
1446
 
                result += merge_inner(self.branch,
1447
 
                                      other_tree,
1448
 
                                      base_tree,
1449
 
                                      this_tree=self)
1450
 
            return result
1451
 
        finally:
1452
 
            self.branch.unlock()
 
1516
 
 
1517
        # here if old_tip is not None, it is the old tip of the branch before
 
1518
        # it was updated from the master branch. This should become a pending
 
1519
        # merge in the working tree to preserve the user existing work.  we
 
1520
        # cant set that until we update the working trees last revision to be
 
1521
        # one from the new branch, because it will just get absorbed by the
 
1522
        # parent de-duplication logic.
 
1523
        # 
 
1524
        # We MUST save it even if an error occurs, because otherwise the users
 
1525
        # local work is unreferenced and will appear to have been lost.
 
1526
        # 
 
1527
        result = 0
 
1528
        if self.last_revision() != self.branch.last_revision():
 
1529
            # merge tree state up to new branch tip.
 
1530
            basis = self.basis_tree()
 
1531
            to_tree = self.branch.basis_tree()
 
1532
            if basis.inventory.root is None:
 
1533
                self.set_root_id(to_tree.inventory.root.file_id)
 
1534
            result += merge_inner(self.branch,
 
1535
                                  to_tree,
 
1536
                                  basis,
 
1537
                                  this_tree=self)
 
1538
            # TODO - dedup parents list with things merged by pull ?
 
1539
            # reuse the tree we've updated to to set the basis:
 
1540
            parent_trees = [(self.branch.last_revision(), to_tree)]
 
1541
            merges = self.get_parent_ids()[1:]
 
1542
            # Ideally we ask the tree for the trees here, that way the working
 
1543
            # tree can decide whether to give us teh entire tree or give us a
 
1544
            # lazy initialised tree. dirstate for instance will have the trees
 
1545
            # in ram already, whereas a last-revision + basis-inventory tree
 
1546
            # will not, but also does not need them when setting parents.
 
1547
            for parent in merges:
 
1548
                parent_trees.append(
 
1549
                    (parent, self.branch.repository.revision_tree(parent)))
 
1550
            if old_tip is not None:
 
1551
                parent_trees.append(
 
1552
                    (old_tip, self.branch.repository.revision_tree(old_tip)))
 
1553
            self.set_parent_trees(parent_trees)
 
1554
        else:
 
1555
            # the working tree had the same last-revision as the master
 
1556
            # branch did. We may still have pivot local work from the local
 
1557
            # branch into old_tip:
 
1558
            if old_tip is not None:
 
1559
                self.add_parent_tree_id(old_tip)
 
1560
        if old_tip and old_tip != self.last_revision():
 
1561
            # our last revision was not the prior branch last revision
 
1562
            # and we have converted that last revision to a pending merge.
 
1563
            # base is somewhere between the branch tip now
 
1564
            # and the now pending merge
 
1565
            from bzrlib.revision import common_ancestor
 
1566
            try:
 
1567
                base_rev_id = common_ancestor(self.branch.last_revision(),
 
1568
                                              old_tip,
 
1569
                                              self.branch.repository)
 
1570
            except errors.NoCommonAncestor:
 
1571
                base_rev_id = None
 
1572
            base_tree = self.branch.repository.revision_tree(base_rev_id)
 
1573
            other_tree = self.branch.repository.revision_tree(old_tip)
 
1574
            result += merge_inner(self.branch,
 
1575
                                  other_tree,
 
1576
                                  base_tree,
 
1577
                                  this_tree=self)
 
1578
        return result
1453
1579
 
1454
1580
    @needs_write_lock
1455
1581
    def _write_inventory(self, inv):
1714
1840
            finally:
1715
1841
                branch.unlock()
1716
1842
        revision = branch.last_revision()
1717
 
        inv = Inventory(root_id=gen_root_id()) 
 
1843
        inv = Inventory()
1718
1844
        wt = WorkingTree2(a_bzrdir.root_transport.local_abspath('.'),
1719
1845
                         branch,
1720
1846
                         inv,
1726
1852
        if basis_tree.inventory.root is not None:
1727
1853
            inv.root.file_id = basis_tree.inventory.root.file_id
1728
1854
        wt._write_inventory(inv)
1729
 
        wt.set_pending_merges([])
 
1855
        wt.set_parent_trees([(revision, basis_tree)])
1730
1856
        build_tree(basis_tree, wt)
1731
1857
        return wt
1732
1858
 
1808
1934
            wt.set_last_revision(revision_id)
1809
1935
            basis_tree = wt.basis_tree()
1810
1936
            wt._write_inventory(inv)
1811
 
            if basis_tree.inventory.root is not None:
1812
 
                inv.root.file_id = basis_tree.inventory.root.file_id
1813
1937
            wt.set_pending_merges([])
 
1938
            if revision_id == bzrlib.revision.NULL_REVISION:
 
1939
                wt.set_parent_trees([])
 
1940
            else:
 
1941
                wt.set_parent_trees([(revision_id, basis_tree)])
1814
1942
            build_tree(basis_tree, wt)
1815
1943
        finally:
1816
1944
            wt.unlock()