877
877
self.revision_id = revision_id
880
return "<Inventory object at %x, contents=%r>" % (id(self), self._byid)
882
def apply_delta(self, delta):
883
"""Apply a delta to this inventory.
885
:param delta: A list of changes to apply. After all the changes are
886
applied the final inventory must be internally consistent, but it
887
is ok to supply changes which, if only half-applied would have an
888
invalid result - such as supplying two changes which rename two
889
files, 'A' and 'B' with each other : [('A', 'B', 'A-id', a_entry),
890
('B', 'A', 'B-id', b_entry)].
892
Each change is a tuple, of the form (old_path, new_path, file_id,
895
When new_path is None, the change indicates the removal of an entry
896
from the inventory and new_entry will be ignored (using None is
897
appropriate). If new_path is not None, then new_entry must be an
898
InventoryEntry instance, which will be incorporated into the
899
inventory (and replace any existing entry with the same file id).
901
When old_path is None, the change indicates the addition of
902
a new entry to the inventory.
904
When neither new_path nor old_path are None, the change is a
905
modification to an entry, such as a rename, reparent, kind change
908
The children attribute of new_entry is ignored. This is because
909
this method preserves children automatically across alterations to
910
the parent of the children, and cases where the parent id of a
911
child is changing require the child to be passed in as a separate
912
change regardless. E.g. in the recursive deletion of a directory -
913
the directory's children must be included in the delta, or the
914
final inventory will be invalid.
917
# Remove all affected items which were in the original inventory,
918
# starting with the longest paths, thus ensuring parents are examined
919
# after their children, which means that everything we examine has no
920
# modified children remaining by the time we examine it.
921
for old_path, file_id in sorted(((op, f) for op, np, f, e in delta
922
if op is not None), reverse=True):
923
if file_id not in self:
926
# Preserve unaltered children of file_id for later reinsertion.
927
children[file_id] = getattr(self[file_id], 'children', {})
928
# Remove file_id and the unaltered children. If file_id is not
929
# being deleted it will be reinserted back later.
930
self.remove_recursive_id(file_id)
931
# Insert all affected which should be in the new inventory, reattaching
932
# their children if they had any. This is done from shortest path to
933
# longest, ensuring that items which were modified and whose parents in
934
# the resulting inventory were also modified, are inserted after their
936
for new_path, new_entry in sorted((np, e) for op, np, f, e in
937
delta if np is not None):
938
if new_entry.kind == 'directory':
939
new_entry.children = children.get(new_entry.file_id, {})
879
942
def _set_root(self, ie):
881
944
self._byid = {self.root.file_id: self.root}