393
394
return pathjoin(self.basedir, filename)
395
396
def basis_tree(self):
396
"""Return RevisionTree for the current last revision."""
397
"""Return RevisionTree for the current last revision.
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).
397
402
revision_id = self.last_revision()
398
403
if revision_id is not None:
400
405
xml = self.read_basis_inventory()
401
406
inv = bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
407
inv.root.revision = revision_id
402
408
except NoSuchFile:
404
410
if inv is not None and inv.revision_id == revision_id:
405
411
return bzrlib.tree.RevisionTree(self.branch.repository, inv,
407
413
# FIXME? RBC 20060403 should we cache the inventory here ?
408
return self.branch.repository.revision_tree(revision_id)
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
420
if self.branch.repository.has_revision(revision_id):
422
# the basis tree is a ghost so return an empty tree.
423
return self.branch.repository.revision_tree(None)
411
426
@deprecated_method(zero_eight)
643
664
self._write_inventory(inv)
645
666
@needs_write_lock
646
def add_parent_tree_id(self, revision_id):
667
def add_parent_tree_id(self, revision_id, allow_leftmost_as_ghost=False):
647
668
"""Add revision_id as a parent.
649
670
This is equivalent to retrieving the current list of parent ids
650
671
and setting the list to its value plus revision_id.
652
673
:param revision_id: The revision id to add to the parent list. It may
674
be a ghost revision as long as its not the first parent to be added,
675
or the allow_leftmost_as_ghost parameter is set True.
676
:param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
655
self.set_parent_ids(self.get_parent_ids() + [revision_id])
678
parents = self.get_parent_ids() + [revision_id]
679
self.set_parent_ids(parents,
680
allow_leftmost_as_ghost=len(parents) > 1 or allow_leftmost_as_ghost)
657
682
@needs_write_lock
658
def add_parent_tree(self, parent_tuple):
683
def add_parent_tree(self, parent_tuple, allow_leftmost_as_ghost=False):
659
684
"""Add revision_id, tree tuple as a parent.
661
686
This is equivalent to retrieving the current list of parent trees
664
689
simpler to use that api. If you have the parent already available, using
665
690
this api is preferred.
667
:param parent_tuple: The (revision id, tree) to add to the parent list. If the revision_id is a ghost, pass None for the tree.
692
:param parent_tuple: The (revision id, tree) to add to the parent list.
693
If the revision_id is a ghost, pass None for the tree.
694
:param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
669
self.set_parent_ids(self.get_parent_ids() + [parent_tuple[0]])
696
self.set_parent_ids(self.get_parent_ids() + [parent_tuple[0]],
697
allow_leftmost_as_ghost=allow_leftmost_as_ghost)
671
699
@needs_write_lock
672
700
def add_pending_merge(self, *revision_ids):
673
701
# TODO: Perhaps should check at this point that the
674
702
# history of the revision is actually present?
675
p = self.pending_merges()
703
parents = self.get_parent_ids()
677
705
for rev_id in revision_ids:
706
if rev_id in parents:
708
parents.append(rev_id)
683
self.set_pending_merges(p)
711
self.set_parent_ids(parents, allow_leftmost_as_ghost=True)
686
714
def pending_merges(self):
711
732
:param revision_ids: The revision_ids to set as the parent ids of this
712
733
working tree. Any of these may be ghosts.
715
for rev_id in revision_ids:
718
(rev_id, self.branch.repository.revision_tree(rev_id)))
719
except errors.RevisionNotPresent:
720
trees.append((rev_id, None))
722
self.set_parent_trees(trees)
735
if len(revision_ids) > 0:
736
leftmost_id = revision_ids[0]
737
if (not allow_leftmost_as_ghost and not
738
self.branch.repository.has_revision(leftmost_id)):
739
raise errors.GhostRevisionUnusableHere(leftmost_id)
740
self.set_last_revision(leftmost_id)
742
self.set_last_revision(None)
743
merges = revision_ids[1:]
744
self._control_files.put_utf8('pending-merges', '\n'.join(merges))
724
746
@needs_write_lock
725
def set_parent_trees(self, parents_list):
747
def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
726
748
"""Set the parents of the working tree.
728
750
:param parents_list: A list of (revision_id, tree) tuples.
729
751
If tree is None, then that element is treated as an unreachable
730
752
parent tree - i.e. a ghost.
732
parent = parents_list[:1]
734
self.set_last_revision(parent[0][0])
736
self.set_last_revision(None)
737
merges = parents_list[1:]
738
self.set_pending_merges([revid for revid, tree in merges])
754
# parent trees are not used in current format trees, delegate to
756
self.set_parent_ids([rev for (rev, tree) in parents_list],
757
allow_leftmost_as_ghost=allow_leftmost_as_ghost)
740
759
@needs_write_lock
741
760
def set_pending_merges(self, rev_list):
742
self._control_files.put_utf8('pending-merges', '\n'.join(rev_list))
761
parents = self.get_parent_ids()
762
leftmost = parents[:1]
763
new_parents = leftmost + rev_list
764
self.set_parent_ids(new_parents)
744
766
@needs_write_lock
745
767
def set_merge_modified(self, modified_hashes):
1479
1501
Do a 'normal' merge of the old branch basis if it is relevant.
1481
1503
old_tip = self.branch.update()
1482
if old_tip is not None:
1483
self.add_pending_merge(old_tip)
1484
self.branch.lock_read()
1487
if self.last_revision() != self.branch.last_revision():
1488
# merge tree state up to new branch tip.
1489
basis = self.basis_tree()
1490
to_tree = self.branch.basis_tree()
1491
result += merge_inner(self.branch,
1495
self.set_last_revision(self.branch.last_revision())
1496
# TODO - dedup parents list with things merged by pull ?
1497
# reuse the tree we've updated to to set the basis:
1498
parent_trees = [(self.branch.last_revision(), to_tree)]
1499
merges = self.get_parent_ids()[1:]
1500
# pull the other trees out of the repository. This could be
1501
# better expressed - for instance by inserting a parent, and
1502
# that would remove duplication.
1503
parent_trees.extend([
1504
(parent, self.branch.repository.revision_tree(parent)) for
1506
self.set_parent_trees(parent_trees)
1507
if old_tip and old_tip != self.last_revision():
1508
# our last revision was not the prior branch last revision
1509
# and we have converted that last revision to a pending merge.
1510
# base is somewhere between the branch tip now
1511
# and the now pending merge
1512
from bzrlib.revision import common_ancestor
1514
base_rev_id = common_ancestor(self.branch.last_revision(),
1516
self.branch.repository)
1517
except errors.NoCommonAncestor:
1519
base_tree = self.branch.repository.revision_tree(base_rev_id)
1520
other_tree = self.branch.repository.revision_tree(old_tip)
1521
result += merge_inner(self.branch,
1527
self.branch.unlock()
1504
# here if old_tip is not None, it is the old tip of the branch before
1505
# it was updated from the master branch. This should become a pending
1506
# merge in the working tree to preserve the user existing work. we
1507
# cant set that until we update the working trees last revision to be
1508
# one from the new branch, because it will just get absorbed by the
1509
# parent de-duplication logic.
1511
# We MUST save it even if an error occurs, because otherwise the users
1512
# local work is unreferenced and will appear to have been lost.
1515
if self.last_revision() != self.branch.last_revision():
1516
# merge tree state up to new branch tip.
1517
basis = self.basis_tree()
1518
to_tree = self.branch.basis_tree()
1519
result += merge_inner(self.branch,
1523
# TODO - dedup parents list with things merged by pull ?
1524
# reuse the tree we've updated to to set the basis:
1525
parent_trees = [(self.branch.last_revision(), to_tree)]
1526
merges = self.get_parent_ids()[1:]
1527
# Ideally we ask the tree for the trees here, that way the working
1528
# tree can decide whether to give us teh entire tree or give us a
1529
# lazy initialised tree. dirstate for instance will have the trees
1530
# in ram already, whereas a last-revision + basis-inventory tree
1531
# will not, but also does not need them when setting parents.
1532
for parent in merges:
1533
parent_trees.append(
1534
(parent, self.branch.repository.revision_tree(parent)))
1535
if old_tip is not None:
1536
parent_trees.append(
1537
(old_tip, self.branch.repository.revision_tree(old_tip)))
1538
self.set_parent_trees(parent_trees)
1540
# the working tree had the same last-revision as the master
1541
# branch did. We may still have pivot local work from the local
1542
# branch into old_tip:
1543
if old_tip is not None:
1544
self.add_parent_tree_id(old_tip)
1545
if old_tip and old_tip != self.last_revision():
1546
# our last revision was not the prior branch last revision
1547
# and we have converted that last revision to a pending merge.
1548
# base is somewhere between the branch tip now
1549
# and the now pending merge
1550
from bzrlib.revision import common_ancestor
1552
base_rev_id = common_ancestor(self.branch.last_revision(),
1554
self.branch.repository)
1555
except errors.NoCommonAncestor:
1557
base_tree = self.branch.repository.revision_tree(base_rev_id)
1558
other_tree = self.branch.repository.revision_tree(old_tip)
1559
result += merge_inner(self.branch,
1529
1565
@needs_write_lock
1530
1566
def _write_inventory(self, inv):