738
738
        conflicts = self.find_conflicts()
 
739
739
        if len(conflicts) != 0:
 
740
740
            raise MalformedTransform(conflicts=conflicts)
 
742
741
        inv = self._tree.inventory
 
743
743
        child_pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
745
745
            child_pb.update('Apply phase', 0, 2)
 
746
 
            self._apply_removals(inv, limbo_inv)
 
 
746
            self._apply_removals(inv, inventory_delta)
 
747
747
            child_pb.update('Apply phase', 1, 2)
 
748
 
            modified_paths = self._apply_insertions(inv, limbo_inv)
 
 
748
            modified_paths = self._apply_insertions(inv, inventory_delta)
 
750
750
            child_pb.finished()
 
751
 
        self._tree._write_inventory(inv)
 
 
751
        self._tree.apply_inventory_delta(inventory_delta)
 
752
752
        self.__done = True
 
754
754
        return _TransformResults(modified_paths)
 
 
757
757
        """Generate the limbo name of a file"""
 
758
758
        return pathjoin(self._limbodir, trans_id)
 
760
 
    def _apply_removals(self, inv, limbo_inv):
 
 
760
    def _apply_removals(self, inv, inventory_delta):
 
761
761
        """Perform tree operations that remove directory/inventory names.
 
763
763
        That is, delete files that are to be deleted, and put any files that
 
 
786
786
                        file_id = self._tree.inventory.root.file_id
 
788
788
                        file_id = self.tree_file_id(trans_id)
 
790
 
                elif trans_id in self._new_name or trans_id in self._new_parent:
 
791
 
                    file_id = self.tree_file_id(trans_id)
 
792
 
                    if file_id is not None:
 
793
 
                        limbo_inv[trans_id] = inv[file_id]
 
794
 
                        inv.remove_recursive_id(file_id)
 
 
789
                    assert file_id is not None
 
 
790
                    inventory_delta.append((path, None, file_id, None))
 
796
792
            child_pb.finished()
 
798
 
    def _apply_insertions(self, inv, limbo_inv):
 
 
794
    def _apply_insertions(self, inv, inventory_delta):
 
799
795
        """Perform tree operations that insert directory/inventory names.
 
801
797
        That is, create any files that need to be created, and restore from
 
 
830
827
                        kind = file_kind(self._tree.abspath(path))
 
831
828
                    if trans_id in self._new_reference_revision:
 
832
 
                        entry = inventory.TreeReference(self._new_id[trans_id], 
 
 
829
                        new_entry = inventory.TreeReference(
 
 
830
                            self._new_id[trans_id],
 
833
831
                            self._new_name[trans_id], 
 
834
832
                            self.final_file_id(self._new_parent[trans_id]),
 
835
833
                            None, self._new_reference_revision[trans_id])
 
838
 
                        inv.add_path(path, kind, self._new_id[trans_id])
 
839
 
                elif trans_id in self._new_name or trans_id in\
 
841
 
                    entry = limbo_inv.get(trans_id)
 
842
 
                    if entry is not None:
 
843
 
                        entry.name = self.final_name(trans_id)
 
844
 
                        parent_path = os.path.dirname(path)
 
846
 
                            self._tree.inventory.path2id(parent_path)
 
849
 
                # requires files and inventory entries to be in place
 
 
835
                        new_entry = inventory.make_entry(kind,
 
 
836
                            self.final_name(trans_id),
 
 
837
                            self.final_file_id(self.final_parent(trans_id)),
 
 
838
                            self._new_id[trans_id])
 
 
840
                    if trans_id in self._new_name or trans_id in\
 
 
842
                        trans_id in self._new_executability:
 
 
843
                        file_id = self.final_file_id(trans_id)
 
 
844
                        if file_id is not None:
 
 
846
                            new_entry = entry.copy()
 
 
848
                    if trans_id in self._new_name or trans_id in\
 
 
850
                            if new_entry is not None:
 
 
851
                                new_entry.name = self.final_name(trans_id)
 
 
852
                                parent = self.final_parent(trans_id)
 
 
853
                                parent_id = self.final_file_id(parent)
 
 
854
                                new_entry.parent_id = parent_id
 
850
856
                if trans_id in self._new_executability:
 
851
 
                    self._set_executability(path, inv, trans_id)
 
 
857
                    self._set_executability(path, new_entry, trans_id)
 
 
858
                if new_entry is not None:
 
 
859
                    if new_entry.file_id in inv:
 
 
860
                        old_path = inv.id2path(new_entry.file_id)
 
 
863
                    inventory_delta.append((old_path, path,
 
853
867
            child_pb.finished()
 
854
868
        return modified_paths
 
856
 
    def _set_executability(self, path, inv, trans_id):
 
 
870
    def _set_executability(self, path, entry, trans_id):
 
857
871
        """Set the executability of versioned files """
 
858
 
        file_id = inv.path2id(path)
 
859
872
        new_executability = self._new_executability[trans_id]
 
860
 
        inv[file_id].executable = new_executability
 
 
873
        entry.executable = new_executability
 
861
874
        if supports_executable():
 
862
875
            abspath = self._tree.abspath(path)
 
863
876
            current_mode = os.stat(abspath).st_mode