1
# Copyright (C) 2006, 2007, 2008 Canonical Ltd
1
# Copyright (C) 2006, 2007, 2008, 2009 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
442
442
conflicts.extend(self._overwrite_conflicts())
445
def _check_malformed(self):
446
conflicts = self.find_conflicts()
447
if len(conflicts) != 0:
448
raise MalformedTransform(conflicts=conflicts)
445
450
def _add_tree_children(self):
446
451
"""Add all the children of all active parents to the known paths.
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):
1752
1794
for trans_id, parent_file_id in ordered_entries:
1753
1795
file_id = self._transform.final_file_id(trans_id)
1754
1796
if file_id is None:
1791
1833
specific_file_ids):
1792
1834
yield unicode(self._final_paths.get_path(trans_id)), entry
1794
def list_files(self, include_root=False):
1795
"""See Tree.list_files."""
1836
def _iter_entries_for_dir(self, dir_path):
1837
"""Return path, entry for items in a directory without recursing down."""
1838
dir_file_id = self.path2id(dir_path)
1840
for file_id in self.iter_children(dir_file_id):
1841
trans_id = self._transform.trans_id_file_id(file_id)
1842
ordered_ids.append((trans_id, file_id))
1843
for entry, trans_id in self._make_inv_entries(ordered_ids):
1844
yield unicode(self._final_paths.get_path(trans_id)), entry
1846
def list_files(self, include_root=False, from_dir=None, recursive=True):
1847
"""See WorkingTree.list_files."""
1796
1848
# XXX This should behave like WorkingTree.list_files, but is really
1797
1849
# 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
1853
prefix = from_dir + '/'
1854
entries = self.iter_entries_by_dir()
1855
for path, entry in entries:
1856
if entry.name == '' and not include_root:
1859
if not path.startswith(prefix):
1861
path = path[len(prefix):]
1862
yield path, 'V', entry.kind, entry.file_id, entry
1864
if from_dir is None and include_root is True:
1865
root_entry = inventory.make_entry('directory', '',
1866
ROOT_PARENT, self.get_root_id())
1867
yield '', 'V', 'directory', root_entry.file_id, root_entry
1868
entries = self._iter_entries_for_dir(from_dir or '')
1869
for path, entry in entries:
1870
yield path, 'V', entry.kind, entry.file_id, entry
1803
1872
def kind(self, file_id):
1804
1873
trans_id = self._transform.trans_id_file_id(file_id)
1938
2007
return old_annotation
1939
2008
if not changed_content:
1940
2009
return old_annotation
2010
# TODO: This is doing something similar to what WT.annotate_iter is
2011
# doing, however it fails slightly because it doesn't know what
2012
# the *other* revision_id is, so it doesn't know how to give the
2013
# other as the origin for some lines, they all get
2014
# 'default_revision'
2015
# It would be nice to be able to use the new Annotator based
2016
# approach, as well.
1941
2017
return annotate.reannotate([old_annotation],
1942
2018
self.get_file(file_id).readlines(),
1943
2019
default_revision)
2009
2085
self.transform = transform
2011
2087
def _determine_path(self, trans_id):
2012
if trans_id == self.transform.root:
2088
if (trans_id == self.transform.root or trans_id == ROOT_PARENT):
2014
2090
name = self.transform.final_name(trans_id)
2015
2091
parent_id = self.transform.final_parent(trans_id)