751
def apply(self, no_conflicts=False, _mover=None):
752
"""Apply all changes to the inventory and filesystem.
754
If filesystem or inventory conflicts are present, MalformedTransform
757
If apply succeeds, finalize is not necessary.
759
:param no_conflicts: if True, the caller guarantees there are no
760
conflicts, so no check is made.
761
:param _mover: Supply an alternate FileMover, for testing
764
conflicts = self.find_conflicts()
765
if len(conflicts) != 0:
766
raise MalformedTransform(conflicts=conflicts)
767
inv = self._tree.inventory
769
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
776
child_pb.update('Apply phase', 0, 2)
777
self._apply_removals(inv, inventory_delta, mover)
778
child_pb.update('Apply phase', 1, 2)
779
modified_paths = self._apply_insertions(inv, inventory_delta,
785
mover.apply_deletions()
788
self._tree.apply_inventory_delta(inventory_delta)
791
return _TransformResults(modified_paths, self.rename_count)
793
751
def _limbo_name(self, trans_id):
794
752
"""Generate the limbo name of a file"""
823
781
self._limbo_files[trans_id] = limbo_name
824
782
return limbo_name
826
def _apply_removals(self, inv, inventory_delta, mover):
827
"""Perform tree operations that remove directory/inventory names.
829
That is, delete files that are to be deleted, and put any files that
830
need renaming into limbo. This must be done in strict child-to-parent
833
tree_paths = list(self._tree_path_ids.iteritems())
834
tree_paths.sort(reverse=True)
835
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
837
for num, data in enumerate(tree_paths):
838
path, trans_id = data
839
child_pb.update('removing file', num, len(tree_paths))
840
full_path = self._tree.abspath(path)
841
if trans_id in self._removed_contents:
842
mover.pre_delete(full_path, os.path.join(self._deletiondir,
844
elif trans_id in self._new_name or trans_id in \
847
mover.rename(full_path, self._limbo_name(trans_id))
849
if e.errno != errno.ENOENT:
852
self.rename_count += 1
853
if trans_id in self._removed_id:
854
if trans_id == self._new_root:
855
file_id = self._tree.get_root_id()
857
file_id = self.tree_file_id(trans_id)
858
assert file_id is not None
859
inventory_delta.append((path, None, file_id, None))
863
def _apply_insertions(self, inv, inventory_delta, mover):
864
"""Perform tree operations that insert directory/inventory names.
866
That is, create any files that need to be created, and restore from
867
limbo any files that needed renaming. This must be done in strict
868
parent-to-child order.
870
new_paths = self.new_paths()
872
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
874
for num, (path, trans_id) in enumerate(new_paths):
876
child_pb.update('adding file', num, len(new_paths))
878
kind = self._new_contents[trans_id]
880
kind = contents = None
881
if trans_id in self._new_contents or \
882
self.path_changed(trans_id):
883
full_path = self._tree.abspath(path)
884
if trans_id in self._needs_rename:
886
mover.rename(self._limbo_name(trans_id), full_path)
888
# We may be renaming a dangling inventory id
889
if e.errno != errno.ENOENT:
892
self.rename_count += 1
893
if trans_id in self._new_contents:
894
modified_paths.append(full_path)
895
del self._new_contents[trans_id]
897
if trans_id in self._new_id:
899
kind = file_kind(self._tree.abspath(path))
900
if trans_id in self._new_reference_revision:
901
new_entry = inventory.TreeReference(
902
self._new_id[trans_id],
903
self._new_name[trans_id],
904
self.final_file_id(self._new_parent[trans_id]),
905
None, self._new_reference_revision[trans_id])
907
new_entry = inventory.make_entry(kind,
908
self.final_name(trans_id),
909
self.final_file_id(self.final_parent(trans_id)),
910
self._new_id[trans_id])
912
if trans_id in self._new_name or trans_id in\
914
trans_id in self._new_executability:
915
file_id = self.final_file_id(trans_id)
916
if file_id is not None:
918
new_entry = entry.copy()
920
if trans_id in self._new_name or trans_id in\
922
if new_entry is not None:
923
new_entry.name = self.final_name(trans_id)
924
parent = self.final_parent(trans_id)
925
parent_id = self.final_file_id(parent)
926
new_entry.parent_id = parent_id
928
if trans_id in self._new_executability:
929
self._set_executability(path, new_entry, trans_id)
930
if new_entry is not None:
931
if new_entry.file_id in inv:
932
old_path = inv.id2path(new_entry.file_id)
935
inventory_delta.append((old_path, path,
940
return modified_paths
942
784
def _set_executability(self, path, entry, trans_id):
943
785
"""Set the executability of versioned files """
944
786
new_executability = self._new_executability[trans_id]
1208
1052
TreeTransformBase.__init__(self, tree, limbodir, pb)
1054
def apply(self, no_conflicts=False, _mover=None):
1055
"""Apply all changes to the inventory and filesystem.
1057
If filesystem or inventory conflicts are present, MalformedTransform
1060
If apply succeeds, finalize is not necessary.
1062
:param no_conflicts: if True, the caller guarantees there are no
1063
conflicts, so no check is made.
1064
:param _mover: Supply an alternate FileMover, for testing
1066
if not no_conflicts:
1067
conflicts = self.find_conflicts()
1068
if len(conflicts) != 0:
1069
raise MalformedTransform(conflicts=conflicts)
1070
inv = self._tree.inventory
1071
inventory_delta = []
1072
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1075
mover = _FileMover()
1079
child_pb.update('Apply phase', 0, 2)
1080
self._apply_removals(inv, inventory_delta, mover)
1081
child_pb.update('Apply phase', 1, 2)
1082
modified_paths = self._apply_insertions(inv, inventory_delta,
1088
mover.apply_deletions()
1091
self._tree.apply_inventory_delta(inventory_delta)
1093
self._TreeTransformBase__done = True
1095
return _TransformResults(modified_paths, self.rename_count)
1097
def _apply_removals(self, inv, inventory_delta, mover):
1098
"""Perform tree operations that remove directory/inventory names.
1100
That is, delete files that are to be deleted, and put any files that
1101
need renaming into limbo. This must be done in strict child-to-parent
1104
tree_paths = list(self._tree_path_ids.iteritems())
1105
tree_paths.sort(reverse=True)
1106
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1108
for num, data in enumerate(tree_paths):
1109
path, trans_id = data
1110
child_pb.update('removing file', num, len(tree_paths))
1111
full_path = self._tree.abspath(path)
1112
if trans_id in self._removed_contents:
1113
mover.pre_delete(full_path, os.path.join(self._deletiondir,
1115
elif trans_id in self._new_name or trans_id in \
1118
mover.rename(full_path, self._limbo_name(trans_id))
1120
if e.errno != errno.ENOENT:
1123
self.rename_count += 1
1124
if trans_id in self._removed_id:
1125
if trans_id == self._new_root:
1126
file_id = self._tree.get_root_id()
1128
file_id = self.tree_file_id(trans_id)
1129
assert file_id is not None
1130
inventory_delta.append((path, None, file_id, None))
1134
def _apply_insertions(self, inv, inventory_delta, mover):
1135
"""Perform tree operations that insert directory/inventory names.
1137
That is, create any files that need to be created, and restore from
1138
limbo any files that needed renaming. This must be done in strict
1139
parent-to-child order.
1141
new_paths = self.new_paths()
1143
child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
1145
for num, (path, trans_id) in enumerate(new_paths):
1147
child_pb.update('adding file', num, len(new_paths))
1149
kind = self._new_contents[trans_id]
1151
kind = contents = None
1152
if trans_id in self._new_contents or \
1153
self.path_changed(trans_id):
1154
full_path = self._tree.abspath(path)
1155
if trans_id in self._needs_rename:
1157
mover.rename(self._limbo_name(trans_id), full_path)
1159
# We may be renaming a dangling inventory id
1160
if e.errno != errno.ENOENT:
1163
self.rename_count += 1
1164
if trans_id in self._new_contents:
1165
modified_paths.append(full_path)
1166
del self._new_contents[trans_id]
1168
if trans_id in self._new_id:
1170
kind = file_kind(self._tree.abspath(path))
1171
if trans_id in self._new_reference_revision:
1172
new_entry = inventory.TreeReference(
1173
self._new_id[trans_id],
1174
self._new_name[trans_id],
1175
self.final_file_id(self._new_parent[trans_id]),
1176
None, self._new_reference_revision[trans_id])
1178
new_entry = inventory.make_entry(kind,
1179
self.final_name(trans_id),
1180
self.final_file_id(self.final_parent(trans_id)),
1181
self._new_id[trans_id])
1183
if trans_id in self._new_name or trans_id in\
1184
self._new_parent or\
1185
trans_id in self._new_executability:
1186
file_id = self.final_file_id(trans_id)
1187
if file_id is not None:
1188
entry = inv[file_id]
1189
new_entry = entry.copy()
1191
if trans_id in self._new_name or trans_id in\
1193
if new_entry is not None:
1194
new_entry.name = self.final_name(trans_id)
1195
parent = self.final_parent(trans_id)
1196
parent_id = self.final_file_id(parent)
1197
new_entry.parent_id = parent_id
1199
if trans_id in self._new_executability:
1200
self._set_executability(path, new_entry, trans_id)
1201
if new_entry is not None:
1202
if new_entry.file_id in inv:
1203
old_path = inv.id2path(new_entry.file_id)
1206
inventory_delta.append((old_path, path,
1211
return modified_paths
1211
1214
class TransformPreview(TreeTransformBase):