250
251
if self.parent_id is not None:
251
252
if not inv.has_id(self.parent_id):
252
raise errors.BzrCheckError(
253
'missing parent {%s} in inventory for revision {%s}' % (
254
self.parent_id, rev_id))
253
raise BzrCheckError('missing parent {%s} in inventory for revision {%s}'
254
% (self.parent_id, rev_id))
255
255
checker._add_entry_to_text_key_references(inv, self)
256
256
self._check(checker, rev_id)
718
718
# if we finished all children, pop it off the stack
721
def _preload_cache(self):
722
"""Populate any caches, we are about to access all items.
724
The default implementation does nothing, because CommonInventory doesn't
729
721
def iter_entries_by_dir(self, from_dir=None, specific_file_ids=None,
730
722
yield_parents=False):
731
723
"""Iterate over the entries in a directory first order.
744
736
specific_file_ids = set(specific_file_ids)
745
737
# TODO? Perhaps this should return the from_dir so that the root is
746
738
# yielded? or maybe an option?
747
if from_dir is None and specific_file_ids is None:
748
# They are iterating from the root, and have not specified any
749
# specific entries to look at. All current callers fully consume the
750
# iterator, so we can safely assume we are accessing all entries
751
self._preload_cache()
752
739
if from_dir is None:
753
740
if self.root is None:
822
809
file_id, self[file_id]))
812
def _get_mutable_inventory(self):
813
"""Returns a mutable copy of the object.
815
Some inventories are immutable, yet working trees, for example, needs
816
to mutate exisiting inventories instead of creating a new one.
818
raise NotImplementedError(self._get_mutable_inventory)
825
820
def make_entry(self, kind, name, parent_id, file_id=None):
826
821
"""Simple thunk to bzrlib.inventory.make_entry."""
827
822
return make_entry(kind, name, parent_id, file_id)
1170
1169
def _add_child(self, entry):
1171
1170
"""Add an entry to the inventory, without adding it to its parent"""
1172
1171
if entry.file_id in self._byid:
1173
raise errors.BzrError(
1174
"inventory already contains entry with id {%s}" %
1172
raise BzrError("inventory already contains entry with id {%s}" %
1176
1174
self._byid[entry.file_id] = entry
1177
1175
for child in getattr(entry, 'children', {}).itervalues():
1178
1176
self._add_child(child)
1343
1341
new_name = ensure_normalized_name(new_name)
1344
1342
if not is_valid_name(new_name):
1345
raise errors.BzrError("not an acceptable filename: %r" % new_name)
1343
raise BzrError("not an acceptable filename: %r" % new_name)
1347
1345
new_parent = self._byid[new_parent_id]
1348
1346
if new_name in new_parent.children:
1349
raise errors.BzrError("%r already exists in %r" %
1350
(new_name, self.id2path(new_parent_id)))
1347
raise BzrError("%r already exists in %r" % (new_name, self.id2path(new_parent_id)))
1352
1349
new_parent_idpath = self.get_idpath(new_parent_id)
1353
1350
if file_id in new_parent_idpath:
1354
raise errors.BzrError(
1355
"cannot move directory %r into a subdirectory of itself, %r"
1351
raise BzrError("cannot move directory %r into a subdirectory of itself, %r"
1356
1352
% (self.id2path(file_id), self.id2path(new_parent_id)))
1358
1354
file_ie = self._byid[file_id]
1607
1602
self._fileid_to_entry_cache[result.file_id] = result
1605
def _get_mutable_inventory(self):
1606
"""See CommonInventory._get_mutable_inventory."""
1607
entries = self.iter_entries()
1608
inv = Inventory(None, self.revision_id)
1609
for path, inv_entry in entries:
1610
inv.add(inv_entry.copy())
1610
1613
def create_by_apply_delta(self, inventory_delta, new_revision_id,
1611
1614
propagate_caches=False):
1612
1615
"""Create a new CHKInventory by applying inventory_delta to this one.
1967
1970
self._fileid_to_entry_cache[file_id] = ie
1970
def _preload_cache(self):
1971
"""Make sure all file-ids are in _fileid_to_entry_cache"""
1972
if self._fully_cached:
1973
return # No need to do it again
1974
# The optimal sort order is to use iteritems() directly
1975
cache = self._fileid_to_entry_cache
1976
for key, entry in self.id_to_entry.iteritems():
1978
if file_id not in cache:
1979
ie = self._bytes_to_entry(entry)
1983
last_parent_id = last_parent_ie = None
1984
pid_items = self.parent_id_basename_to_file_id.iteritems()
1985
for key, child_file_id in pid_items:
1986
if key == ('', ''): # This is the root
1987
if child_file_id != self.root_id:
1988
raise ValueError('Data inconsistency detected.'
1989
' We expected data with key ("","") to match'
1990
' the root id, but %s != %s'
1991
% (child_file_id, self.root_id))
1993
parent_id, basename = key
1994
ie = cache[child_file_id]
1995
if parent_id == last_parent_id:
1996
parent_ie = last_parent_ie
1998
parent_ie = cache[parent_id]
1999
if parent_ie.kind != 'directory':
2000
raise ValueError('Data inconsistency detected.'
2001
' An entry in the parent_id_basename_to_file_id map'
2002
' has parent_id {%s} but the kind of that object'
2003
' is %r not "directory"' % (parent_id, parent_ie.kind))
2004
if parent_ie._children is None:
2005
parent_ie._children = {}
2006
basename = basename.decode('utf-8')
2007
if basename in parent_ie._children:
2008
existing_ie = parent_ie._children[basename]
2009
if existing_ie != ie:
2010
raise ValueError('Data inconsistency detected.'
2011
' Two entries with basename %r were found'
2012
' in the parent entry {%s}'
2013
% (basename, parent_id))
2014
if basename != ie.name:
2015
raise ValueError('Data inconsistency detected.'
2016
' In the parent_id_basename_to_file_id map, file_id'
2017
' {%s} is listed as having basename %r, but in the'
2018
' id_to_entry map it is %r'
2019
% (child_file_id, basename, ie.name))
2020
parent_ie._children[basename] = ie
2021
self._fully_cached = True
2023
1973
def iter_changes(self, basis):
2024
1974
"""Generate a Tree.iter_changes change list between this and basis.
2380
2334
raise errors.InconsistentDelta(new_path, item[1],
2381
2335
"new_path with no entry")
2385
def mutable_inventory_from_tree(tree):
2386
"""Create a new inventory that has the same contents as a specified tree.
2388
:param tree: Revision tree to create inventory from
2390
entries = tree.iter_entries_by_dir()
2391
inv = Inventory(None, tree.get_revision_id())
2392
for path, inv_entry in entries:
2393
inv.add(inv_entry.copy())