394
408
return pathjoin(self.basedir, filename)
396
410
def basis_tree(self):
397
"""Return RevisionTree for the current last revision."""
398
revision_id = self.last_revision()
399
if revision_id is not None:
411
"""Return RevisionTree for the current last revision.
413
If the left most parent is a ghost then the returned tree will be an
414
empty tree - one obtained by calling repository.revision_tree(None).
417
revision_id = self.get_parent_ids()[0]
419
# no parents, return an empty revision tree.
420
# in the future this should return the tree for
421
# 'empty:' - the implicit root empty tree.
422
return self.branch.repository.revision_tree(None)
401
425
xml = self.read_basis_inventory()
402
inv = bzrlib.xml5.serializer_v5.read_inventory_from_string(xml)
403
inv.root.revision = revision_id
406
if inv is not None and inv.revision_id == revision_id:
407
return bzrlib.tree.RevisionTree(self.branch.repository, inv,
409
# FIXME? RBC 20060403 should we cache the inventory here ?
410
return self.branch.repository.revision_tree(revision_id)
426
inv = bzrlib.xml6.serializer_v6.read_inventory_from_string(xml)
427
if inv is not None and inv.revision_id == revision_id:
428
return bzrlib.tree.RevisionTree(self.branch.repository,
430
except (NoSuchFile, errors.BadInventoryFormat):
432
# No cached copy available, retrieve from the repository.
433
# FIXME? RBC 20060403 should we cache the inventory locally
436
return self.branch.repository.revision_tree(revision_id)
437
except errors.RevisionNotPresent:
438
# the basis tree *may* be a ghost or a low level error may have
439
# occured. If the revision is present, its a problem, if its not
441
if self.branch.repository.has_revision(revision_id):
443
# the basis tree is a ghost so return an empty tree.
444
return self.branch.repository.revision_tree(None)
413
447
@deprecated_method(zero_eight)
644
684
self._write_inventory(inv)
686
@needs_tree_write_lock
687
def add_parent_tree_id(self, revision_id, allow_leftmost_as_ghost=False):
688
"""Add revision_id as a parent.
690
This is equivalent to retrieving the current list of parent ids
691
and setting the list to its value plus revision_id.
693
:param revision_id: The revision id to add to the parent list. It may
694
be a ghost revision as long as its not the first parent to be added,
695
or the allow_leftmost_as_ghost parameter is set True.
696
:param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
698
parents = self.get_parent_ids() + [revision_id]
699
self.set_parent_ids(parents,
700
allow_leftmost_as_ghost=len(parents) > 1 or allow_leftmost_as_ghost)
702
@needs_tree_write_lock
703
def add_parent_tree(self, parent_tuple, allow_leftmost_as_ghost=False):
704
"""Add revision_id, tree tuple as a parent.
706
This is equivalent to retrieving the current list of parent trees
707
and setting the list to its value plus parent_tuple. See also
708
add_parent_tree_id - if you only have a parent id available it will be
709
simpler to use that api. If you have the parent already available, using
710
this api is preferred.
712
:param parent_tuple: The (revision id, tree) to add to the parent list.
713
If the revision_id is a ghost, pass None for the tree.
714
:param allow_leftmost_as_ghost: Allow the first parent to be a ghost.
716
parent_ids = self.get_parent_ids() + [parent_tuple[0]]
717
if len(parent_ids) > 1:
718
# the leftmost may have already been a ghost, preserve that if it
720
allow_leftmost_as_ghost = True
721
self.set_parent_ids(parent_ids,
722
allow_leftmost_as_ghost=allow_leftmost_as_ghost)
724
@needs_tree_write_lock
647
725
def add_pending_merge(self, *revision_ids):
648
726
# TODO: Perhaps should check at this point that the
649
727
# history of the revision is actually present?
650
p = self.pending_merges()
728
parents = self.get_parent_ids()
652
730
for rev_id in revision_ids:
731
if rev_id in parents:
733
parents.append(rev_id)
658
self.set_pending_merges(p)
736
self.set_parent_ids(parents, allow_leftmost_as_ghost=True)
738
@deprecated_method(zero_eleven)
661
740
def pending_merges(self):
662
741
"""Return a list of pending merges.
664
743
These are revisions that have been merged into the working
665
744
directory but not yet committed.
668
merges_file = self._control_files.get_utf8('pending-merges')
672
for l in merges_file.readlines():
673
p.append(l.rstrip('\n'))
746
As of 0.11 this is deprecated. Please see WorkingTree.get_parent_ids()
747
instead - which is available on all tree objects.
749
return self.get_parent_ids()[1:]
751
@needs_tree_write_lock
752
def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
753
"""Set the parent ids to revision_ids.
755
See also set_parent_trees. This api will try to retrieve the tree data
756
for each element of revision_ids from the trees repository. If you have
757
tree data already available, it is more efficient to use
758
set_parent_trees rather than set_parent_ids. set_parent_ids is however
759
an easier API to use.
761
:param revision_ids: The revision_ids to set as the parent ids of this
762
working tree. Any of these may be ghosts.
764
if len(revision_ids) > 0:
765
leftmost_id = revision_ids[0]
766
if (not allow_leftmost_as_ghost and not
767
self.branch.repository.has_revision(leftmost_id)):
768
raise errors.GhostRevisionUnusableHere(leftmost_id)
769
self.set_last_revision(leftmost_id)
771
self.set_last_revision(None)
772
merges = revision_ids[1:]
773
self._control_files.put_utf8('pending-merges', '\n'.join(merges))
775
@needs_tree_write_lock
776
def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
777
"""Set the parents of the working tree.
779
:param parents_list: A list of (revision_id, tree) tuples.
780
If tree is None, then that element is treated as an unreachable
781
parent tree - i.e. a ghost.
783
# parent trees are not used in current format trees, delegate to
785
self.set_parent_ids([rev for (rev, tree) in parents_list],
786
allow_leftmost_as_ghost=allow_leftmost_as_ghost)
788
@needs_tree_write_lock
677
789
def set_pending_merges(self, rev_list):
678
self._control_files.put_utf8('pending-merges', '\n'.join(rev_list))
790
parents = self.get_parent_ids()
791
leftmost = parents[:1]
792
new_parents = leftmost + rev_list
793
self.set_parent_ids(new_parents)
795
@needs_tree_write_lock
681
796
def set_merge_modified(self, modified_hashes):
682
797
def iter_stanzas():
683
798
for file_id, hash in modified_hashes.iteritems():
684
799
yield Stanza(file_id=file_id, hash=hash)
685
800
self._put_rio('merge-hashes', iter_stanzas(), MERGE_MODIFIED_HEADER_1)
802
@needs_tree_write_lock
688
803
def _put_rio(self, filename, stanzas, header):
689
804
my_file = rio_file(stanzas, header)
690
805
self._control_files.put(filename, my_file)
807
@needs_write_lock # because merge pulls data into the branch.
808
def merge_from_branch(self, branch, to_revision=None):
809
"""Merge from a branch into this working tree.
811
:param branch: The branch to merge from.
812
:param to_revision: If non-None, the merge will merge to to_revision, but
813
not beyond it. to_revision does not need to be in the history of
814
the branch when it is supplied. If None, to_revision defaults to
815
branch.last_revision().
817
from bzrlib.merge import Merger, Merge3Merger
818
pb = bzrlib.ui.ui_factory.nested_progress_bar()
820
merger = Merger(self.branch, this_tree=self, pb=pb)
821
merger.pp = ProgressPhase("Merge phase", 5, pb)
822
merger.pp.next_phase()
823
# check that there are no
825
merger.check_basis(check_clean=True, require_commits=False)
826
if to_revision is None:
827
to_revision = branch.last_revision()
828
merger.other_rev_id = to_revision
829
if merger.other_rev_id is None:
830
raise error.NoCommits(branch)
831
self.branch.fetch(branch, last_revision=merger.other_rev_id)
832
merger.other_basis = merger.other_rev_id
833
merger.other_tree = self.branch.repository.revision_tree(
835
merger.pp.next_phase()
837
if merger.base_rev_id == merger.other_rev_id:
838
raise errors.PointlessMerge
839
merger.backup_files = False
840
merger.merge_type = Merge3Merger
841
merger.set_interesting_files(None)
842
merger.show_base = False
843
merger.reprocess = False
844
conflicts = merger.do_merge()
693
851
def merge_modified(self):
958
1115
for subp in self.extras():
959
1116
if not self.is_ignored(subp):
1119
@needs_tree_write_lock
1120
def unversion(self, file_ids):
1121
"""Remove the file ids in file_ids from the current versioned set.
1123
When a file_id is unversioned, all of its children are automatically
1126
:param file_ids: The file ids to stop versioning.
1127
:raises: NoSuchId if any fileid is not currently versioned.
1129
for file_id in file_ids:
1130
if self._inventory.has_id(file_id):
1131
self._inventory.remove_recursive_id(file_id)
1133
raise errors.NoSuchId(self, file_id)
1135
# in the future this should just set a dirty bit to wait for the
1136
# final unlock. However, until all methods of workingtree start
1137
# with the current in -memory inventory rather than triggering
1138
# a read, it is more complex - we need to teach read_inventory
1139
# to know when to read, and when to not read first... and possibly
1140
# to save first when the in memory one may be corrupted.
1141
# so for now, we just only write it if it is indeed dirty.
1143
self._write_inventory(self._inventory)
962
1145
@deprecated_method(zero_eight)
963
1146
def iter_conflicts(self):
964
1147
"""List all files in the tree that have text or content conflicts.
1403
1623
Do a 'normal' merge of the old branch basis if it is relevant.
1405
1625
old_tip = self.branch.update()
1406
if old_tip is not None:
1407
self.add_pending_merge(old_tip)
1408
self.branch.lock_read()
1626
# here if old_tip is not None, it is the old tip of the branch before
1627
# it was updated from the master branch. This should become a pending
1628
# merge in the working tree to preserve the user existing work. we
1629
# cant set that until we update the working trees last revision to be
1630
# one from the new branch, because it will just get absorbed by the
1631
# parent de-duplication logic.
1633
# We MUST save it even if an error occurs, because otherwise the users
1634
# local work is unreferenced and will appear to have been lost.
1411
if self.last_revision() != self.branch.last_revision():
1412
# merge tree state up to new branch tip.
1413
basis = self.basis_tree()
1414
to_tree = self.branch.basis_tree()
1415
result += merge_inner(self.branch,
1419
self.set_last_revision(self.branch.last_revision())
1420
if old_tip and old_tip != self.last_revision():
1421
# our last revision was not the prior branch last revision
1422
# and we have converted that last revision to a pending merge.
1423
# base is somewhere between the branch tip now
1424
# and the now pending merge
1425
from bzrlib.revision import common_ancestor
1427
base_rev_id = common_ancestor(self.branch.last_revision(),
1429
self.branch.repository)
1430
except errors.NoCommonAncestor:
1432
base_tree = self.branch.repository.revision_tree(base_rev_id)
1433
other_tree = self.branch.repository.revision_tree(old_tip)
1434
result += merge_inner(self.branch,
1440
self.branch.unlock()
1638
last_rev = self.get_parent_ids()[0]
1641
if last_rev != self.branch.last_revision():
1642
# merge tree state up to new branch tip.
1643
basis = self.basis_tree()
1644
to_tree = self.branch.basis_tree()
1645
result += merge_inner(self.branch,
1649
# TODO - dedup parents list with things merged by pull ?
1650
# reuse the tree we've updated to to set the basis:
1651
parent_trees = [(self.branch.last_revision(), to_tree)]
1652
merges = self.get_parent_ids()[1:]
1653
# Ideally we ask the tree for the trees here, that way the working
1654
# tree can decide whether to give us teh entire tree or give us a
1655
# lazy initialised tree. dirstate for instance will have the trees
1656
# in ram already, whereas a last-revision + basis-inventory tree
1657
# will not, but also does not need them when setting parents.
1658
for parent in merges:
1659
parent_trees.append(
1660
(parent, self.branch.repository.revision_tree(parent)))
1661
if old_tip is not None:
1662
parent_trees.append(
1663
(old_tip, self.branch.repository.revision_tree(old_tip)))
1664
self.set_parent_trees(parent_trees)
1665
last_rev = parent_trees[0][0]
1667
# the working tree had the same last-revision as the master
1668
# branch did. We may still have pivot local work from the local
1669
# branch into old_tip:
1670
if old_tip is not None:
1671
self.add_parent_tree_id(old_tip)
1672
if old_tip and old_tip != last_rev:
1673
# our last revision was not the prior branch last revision
1674
# and we have converted that last revision to a pending merge.
1675
# base is somewhere between the branch tip now
1676
# and the now pending merge
1677
from bzrlib.revision import common_ancestor
1679
base_rev_id = common_ancestor(self.branch.last_revision(),
1681
self.branch.repository)
1682
except errors.NoCommonAncestor:
1684
base_tree = self.branch.repository.revision_tree(base_rev_id)
1685
other_tree = self.branch.repository.revision_tree(old_tip)
1686
result += merge_inner(self.branch,
1692
@needs_tree_write_lock
1443
1693
def _write_inventory(self, inv):
1444
1694
"""Write inventory as the current inventory."""
1445
1695
sio = StringIO()