860
865
return _PreviewTree(self)
867
def commit(self, branch, message, merge_parents=None, strict=False):
868
"""Commit the result of this TreeTransform to a branch.
870
:param branch: The branch to commit to.
871
:param message: The message to attach to the commit.
872
:param merge_parents: Additional parents specified by pending merges.
873
:return: The revision_id of the revision committed.
875
self._check_malformed()
877
unversioned = set(self._new_contents).difference(set(self._new_id))
878
for trans_id in unversioned:
879
if self.final_file_id(trans_id) is None:
880
raise errors.StrictCommitFailed()
882
revno, last_rev_id = branch.last_revision_info()
883
if last_rev_id == _mod_revision.NULL_REVISION:
884
if merge_parents is not None:
885
raise ValueError('Cannot supply merge parents for first'
889
parent_ids = [last_rev_id]
890
if merge_parents is not None:
891
parent_ids.extend(merge_parents)
892
if self._tree.get_revision_id() != last_rev_id:
893
raise ValueError('TreeTransform not based on branch basis: %s' %
894
self._tree.get_revision_id())
895
builder = branch.get_commit_builder(parent_ids)
896
preview = self.get_preview_tree()
897
list(builder.record_iter_changes(preview, last_rev_id,
898
self.iter_changes()))
899
builder.finish_inventory()
900
revision_id = builder.commit(message)
901
branch.set_last_revision_info(revno + 1, revision_id)
862
904
def _text_parent(self, trans_id):
863
905
file_id = self.tree_file_id(trans_id)
995
1037
self._new_contents.iteritems()]
996
1038
entries.sort(reverse=True)
997
1039
for path, trans_id, kind in entries:
998
if kind == "directory":
1003
os.rmdir(self._limbodir)
1042
delete_any(self._limbodir)
1004
1043
except OSError:
1005
1044
# We don't especially care *why* the dir is immortal.
1006
1045
raise ImmortalLimbo(self._limbodir)
1008
1047
if self._deletiondir is not None:
1009
os.rmdir(self._deletiondir)
1048
delete_any(self._deletiondir)
1010
1049
except OSError:
1011
1050
raise errors.ImmortalPendingDeletion(self._deletiondir)
1682
1718
def __iter__(self):
1683
1719
return iter(self.all_file_ids())
1685
def has_id(self, file_id):
1721
def _has_id(self, file_id, fallback_check):
1686
1722
if file_id in self._transform._r_new_id:
1688
1724
elif file_id in set([self._transform.tree_file_id(trans_id) for
1689
1725
trans_id in self._transform._removed_id]):
1692
return self._transform._tree.has_id(file_id)
1728
return fallback_check(file_id)
1730
def has_id(self, file_id):
1731
return self._has_id(file_id, self._transform._tree.has_id)
1733
def has_or_had_id(self, file_id):
1734
return self._has_id(file_id, self._transform._tree.has_or_had_id)
1694
1736
def _path2trans_id(self, path):
1695
1737
# We must not use None here, because that is a valid value to store.
1748
1790
if self._transform.final_file_id(trans_id) is None:
1749
1791
yield self._final_paths._determine_path(trans_id)
1751
def _make_inv_entries(self, ordered_entries, specific_file_ids):
1793
def _make_inv_entries(self, ordered_entries, specific_file_ids=None,
1794
yield_parents=False):
1752
1795
for trans_id, parent_file_id in ordered_entries:
1753
1796
file_id = self._transform.final_file_id(trans_id)
1754
1797
if file_id is None:
1780
1823
ordered_ids.append((trans_id, parent_file_id))
1781
1824
return ordered_ids
1783
def iter_entries_by_dir(self, specific_file_ids=None):
1826
def iter_entries_by_dir(self, specific_file_ids=None, yield_parents=False):
1784
1827
# This may not be a maximally efficient implementation, but it is
1785
1828
# reasonably straightforward. An implementation that grafts the
1786
1829
# TreeTransform changes onto the tree's iter_entries_by_dir results
1789
1832
ordered_ids = self._list_files_by_dir()
1790
1833
for entry, trans_id in self._make_inv_entries(ordered_ids,
1792
yield unicode(self._final_paths.get_path(trans_id)), entry
1794
def list_files(self, include_root=False):
1795
"""See Tree.list_files."""
1834
specific_file_ids, yield_parents=yield_parents):
1835
yield unicode(self._final_paths.get_path(trans_id)), entry
1837
def _iter_entries_for_dir(self, dir_path):
1838
"""Return path, entry for items in a directory without recursing down."""
1839
dir_file_id = self.path2id(dir_path)
1841
for file_id in self.iter_children(dir_file_id):
1842
trans_id = self._transform.trans_id_file_id(file_id)
1843
ordered_ids.append((trans_id, file_id))
1844
for entry, trans_id in self._make_inv_entries(ordered_ids):
1845
yield unicode(self._final_paths.get_path(trans_id)), entry
1847
def list_files(self, include_root=False, from_dir=None, recursive=True):
1848
"""See WorkingTree.list_files."""
1796
1849
# XXX This should behave like WorkingTree.list_files, but is really
1797
1850
# more like RevisionTree.list_files.
1798
for path, entry in self.iter_entries_by_dir():
1799
if entry.name == '' and not include_root:
1801
yield path, 'V', entry.kind, entry.file_id, entry
1854
prefix = from_dir + '/'
1855
entries = self.iter_entries_by_dir()
1856
for path, entry in entries:
1857
if entry.name == '' and not include_root:
1860
if not path.startswith(prefix):
1862
path = path[len(prefix):]
1863
yield path, 'V', entry.kind, entry.file_id, entry
1865
if from_dir is None and include_root is True:
1866
root_entry = inventory.make_entry('directory', '',
1867
ROOT_PARENT, self.get_root_id())
1868
yield '', 'V', 'directory', root_entry.file_id, root_entry
1869
entries = self._iter_entries_for_dir(from_dir or '')
1870
for path, entry in entries:
1871
yield path, 'V', entry.kind, entry.file_id, entry
1803
1873
def kind(self, file_id):
1804
1874
trans_id = self._transform.trans_id_file_id(file_id)
1938
2008
return old_annotation
1939
2009
if not changed_content:
1940
2010
return old_annotation
2011
# TODO: This is doing something similar to what WT.annotate_iter is
2012
# doing, however it fails slightly because it doesn't know what
2013
# the *other* revision_id is, so it doesn't know how to give the
2014
# other as the origin for some lines, they all get
2015
# 'default_revision'
2016
# It would be nice to be able to use the new Annotator based
2017
# approach, as well.
1941
2018
return annotate.reannotate([old_annotation],
1942
2019
self.get_file(file_id).readlines(),
1943
2020
default_revision)