/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transform.py

  • Committer: Michael Hudson
  • Date: 2007-11-26 13:41:02 UTC
  • mto: (3008.1.10 tree-less-merge-diffs)
  • mto: This revision was merged to the branch mainline in revision 3189.
  • Revision ID: michael.hudson@canonical.com-20071126134102-w087qji4itfo6z6t
move apply and helpers to TreeTransform from TreeTransformBase
move get_preview_tree from PreviewTransform to TreeTransformBase

Show diffs side-by-side

added added

removed removed

Lines of Context:
747
747
                continue
748
748
            return True
749
749
        return False
750
 
            
751
 
    def apply(self, no_conflicts=False, _mover=None):
752
 
        """Apply all changes to the inventory and filesystem.
753
 
        
754
 
        If filesystem or inventory conflicts are present, MalformedTransform
755
 
        will be thrown.
756
 
 
757
 
        If apply succeeds, finalize is not necessary.
758
 
 
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
762
 
        """
763
 
        if not no_conflicts:
764
 
            conflicts = self.find_conflicts()
765
 
            if len(conflicts) != 0:
766
 
                raise MalformedTransform(conflicts=conflicts)
767
 
        inv = self._tree.inventory
768
 
        inventory_delta = []
769
 
        child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
770
 
        try:
771
 
            if _mover is None:
772
 
                mover = _FileMover()
773
 
            else:
774
 
                mover = _mover
775
 
            try:
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,
780
 
                                                        mover)
781
 
            except:
782
 
                mover.rollback()
783
 
                raise
784
 
            else:
785
 
                mover.apply_deletions()
786
 
        finally:
787
 
            child_pb.finished()
788
 
        self._tree.apply_inventory_delta(inventory_delta)
789
 
        self.__done = True
790
 
        self.finalize()
791
 
        return _TransformResults(modified_paths, self.rename_count)
792
750
 
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
825
783
 
826
 
    def _apply_removals(self, inv, inventory_delta, mover):
827
 
        """Perform tree operations that remove directory/inventory names.
828
 
        
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
831
 
        order.
832
 
        """
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()
836
 
        try:
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,
843
 
                                     trans_id))
844
 
                elif trans_id in self._new_name or trans_id in \
845
 
                    self._new_parent:
846
 
                    try:
847
 
                        mover.rename(full_path, self._limbo_name(trans_id))
848
 
                    except OSError, e:
849
 
                        if e.errno != errno.ENOENT:
850
 
                            raise
851
 
                    else:
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()
856
 
                    else:
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))
860
 
        finally:
861
 
            child_pb.finished()
862
 
 
863
 
    def _apply_insertions(self, inv, inventory_delta, mover):
864
 
        """Perform tree operations that insert directory/inventory names.
865
 
        
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.
869
 
        """
870
 
        new_paths = self.new_paths()
871
 
        modified_paths = []
872
 
        child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
873
 
        try:
874
 
            for num, (path, trans_id) in enumerate(new_paths):
875
 
                new_entry = None
876
 
                child_pb.update('adding file', num, len(new_paths))
877
 
                try:
878
 
                    kind = self._new_contents[trans_id]
879
 
                except KeyError:
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:
885
 
                        try:
886
 
                            mover.rename(self._limbo_name(trans_id), full_path)
887
 
                        except OSError, e:
888
 
                            # We may be renaming a dangling inventory id
889
 
                            if e.errno != errno.ENOENT:
890
 
                                raise
891
 
                        else:
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]
896
 
 
897
 
                if trans_id in self._new_id:
898
 
                    if kind is None:
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])
906
 
                    else:
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])
911
 
                else:
912
 
                    if trans_id in self._new_name or trans_id in\
913
 
                        self._new_parent or\
914
 
                        trans_id in self._new_executability:
915
 
                        file_id = self.final_file_id(trans_id)
916
 
                        if file_id is not None:
917
 
                            entry = inv[file_id]
918
 
                            new_entry = entry.copy()
919
 
 
920
 
                    if trans_id in self._new_name or trans_id in\
921
 
                        self._new_parent:
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
927
 
 
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)
933
 
                    else:
934
 
                        old_path = None
935
 
                    inventory_delta.append((old_path, path,
936
 
                                            new_entry.file_id,
937
 
                                            new_entry))
938
 
        finally:
939
 
            child_pb.finished()
940
 
        return modified_paths
941
 
 
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]
1148
990
                   (from_executable, to_executable)))
1149
991
        return iter(sorted(results, key=lambda x:x[1]))
1150
992
 
 
993
    def get_preview_tree(self):
 
994
        return PreviewTree(self)
1151
995
 
1152
996
class TreeTransform(TreeTransformBase):
1153
997
    """Represent a tree transformation.
1207
1051
            raise
1208
1052
        TreeTransformBase.__init__(self, tree, limbodir, pb)
1209
1053
 
 
1054
    def apply(self, no_conflicts=False, _mover=None):
 
1055
        """Apply all changes to the inventory and filesystem.
 
1056
        
 
1057
        If filesystem or inventory conflicts are present, MalformedTransform
 
1058
        will be thrown.
 
1059
 
 
1060
        If apply succeeds, finalize is not necessary.
 
1061
 
 
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
 
1065
        """
 
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()
 
1073
        try:
 
1074
            if _mover is None:
 
1075
                mover = _FileMover()
 
1076
            else:
 
1077
                mover = _mover
 
1078
            try:
 
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,
 
1083
                                                        mover)
 
1084
            except:
 
1085
                mover.rollback()
 
1086
                raise
 
1087
            else:
 
1088
                mover.apply_deletions()
 
1089
        finally:
 
1090
            child_pb.finished()
 
1091
        self._tree.apply_inventory_delta(inventory_delta)
 
1092
        # XXX OW!
 
1093
        self._TreeTransformBase__done = True
 
1094
        self.finalize()
 
1095
        return _TransformResults(modified_paths, self.rename_count)
 
1096
 
 
1097
    def _apply_removals(self, inv, inventory_delta, mover):
 
1098
        """Perform tree operations that remove directory/inventory names.
 
1099
        
 
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
 
1102
        order.
 
1103
        """
 
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()
 
1107
        try:
 
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,
 
1114
                                     trans_id))
 
1115
                elif trans_id in self._new_name or trans_id in \
 
1116
                    self._new_parent:
 
1117
                    try:
 
1118
                        mover.rename(full_path, self._limbo_name(trans_id))
 
1119
                    except OSError, e:
 
1120
                        if e.errno != errno.ENOENT:
 
1121
                            raise
 
1122
                    else:
 
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()
 
1127
                    else:
 
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))
 
1131
        finally:
 
1132
            child_pb.finished()
 
1133
 
 
1134
    def _apply_insertions(self, inv, inventory_delta, mover):
 
1135
        """Perform tree operations that insert directory/inventory names.
 
1136
        
 
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.
 
1140
        """
 
1141
        new_paths = self.new_paths()
 
1142
        modified_paths = []
 
1143
        child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
1144
        try:
 
1145
            for num, (path, trans_id) in enumerate(new_paths):
 
1146
                new_entry = None
 
1147
                child_pb.update('adding file', num, len(new_paths))
 
1148
                try:
 
1149
                    kind = self._new_contents[trans_id]
 
1150
                except KeyError:
 
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:
 
1156
                        try:
 
1157
                            mover.rename(self._limbo_name(trans_id), full_path)
 
1158
                        except OSError, e:
 
1159
                            # We may be renaming a dangling inventory id
 
1160
                            if e.errno != errno.ENOENT:
 
1161
                                raise
 
1162
                        else:
 
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]
 
1167
 
 
1168
                if trans_id in self._new_id:
 
1169
                    if kind is None:
 
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])
 
1177
                    else:
 
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])
 
1182
                else:
 
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()
 
1190
 
 
1191
                    if trans_id in self._new_name or trans_id in\
 
1192
                        self._new_parent:
 
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
 
1198
 
 
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)
 
1204
                    else:
 
1205
                        old_path = None
 
1206
                    inventory_delta.append((old_path, path,
 
1207
                                            new_entry.file_id,
 
1208
                                            new_entry))
 
1209
        finally:
 
1210
            child_pb.finished()
 
1211
        return modified_paths
 
1212
 
1210
1213
 
1211
1214
class TransformPreview(TreeTransformBase):
1212
1215
 
1217
1220
    def canonical_path(self, path):
1218
1221
        return path
1219
1222
 
1220
 
    def get_preview_tree(self):
1221
 
        return PreviewTree(self)
1222
 
 
1223
1223
 
1224
1224
class PreviewTree(object):
1225
1225