2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Created by IntelliJ IDEA.
23 package com.intellij.openapi.vcs.changes.actions;
25 import com.intellij.openapi.actionSystem.ActionPlaces;
26 import com.intellij.openapi.actionSystem.AnAction;
27 import com.intellij.openapi.actionSystem.AnActionEvent;
28 import com.intellij.openapi.actionSystem.PlatformDataKeys;
29 import com.intellij.openapi.fileEditor.FileDocumentManager;
30 import com.intellij.openapi.progress.ProcessCanceledException;
31 import com.intellij.openapi.progress.ProgressIndicator;
32 import com.intellij.openapi.progress.ProgressManager;
33 import com.intellij.openapi.project.DumbAware;
34 import com.intellij.openapi.project.Project;
35 import com.intellij.openapi.ui.Messages;
36 import com.intellij.openapi.vcs.*;
37 import com.intellij.openapi.vcs.changes.Change;
38 import com.intellij.openapi.vcs.changes.ChangeListManager;
39 import com.intellij.openapi.vcs.changes.ChangesUtil;
40 import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
41 import com.intellij.openapi.vcs.changes.ui.ChangesListView;
42 import com.intellij.openapi.vcs.changes.ui.RollbackChangesDialog;
43 import com.intellij.openapi.vcs.changes.ui.RollbackProgressModifier;
44 import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
45 import com.intellij.openapi.vfs.VirtualFile;
46 import com.intellij.openapi.vfs.VirtualFileManager;
47 import com.intellij.util.containers.CollectionFactory;
48 import org.jetbrains.annotations.Nullable;
52 public class RollbackAction extends AnAction implements DumbAware {
53 public void update(AnActionEvent e) {
54 Project project = e.getData(PlatformDataKeys.PROJECT);
55 final boolean visible = project != null && ProjectLevelVcsManager.getInstance(project).hasActiveVcss();
56 e.getPresentation().setVisible(visible);
57 if (! visible) return;
59 final Change[] leadSelection = e.getData(VcsDataKeys.CHANGE_LEAD_SELECTION);
60 boolean isEnabled = (leadSelection != null && leadSelection.length > 0) ||
61 Boolean.TRUE.equals(e.getData(VcsDataKeys.HAVE_LOCALLY_DELETED)) ||
62 Boolean.TRUE.equals(e.getData(VcsDataKeys.HAVE_MODIFIED_WITHOUT_EDITING)) ||
63 Boolean.TRUE.equals(e.getData(VcsDataKeys.HAVE_SELECTED_CHANGES));
65 final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
67 final FileStatusManager fileStatusManager = FileStatusManager.getInstance(project);
68 for (VirtualFile file : files) {
69 final FileStatus status = fileStatusManager.getStatus(file);
70 if (FileStatus.UNKNOWN.equals(status) || FileStatus.IGNORED.equals(status) || FileStatus.NOT_CHANGED.equals(status)) {
78 e.getPresentation().setEnabled(isEnabled);
80 final AbstractVcs[] vcss = ProjectLevelVcsManager.getInstance(project).getAllActiveVcss();
81 for (AbstractVcs vcs : vcss) {
82 final RollbackEnvironment rollbackEnvironment = vcs.getRollbackEnvironment();
83 if (rollbackEnvironment != null) {
84 e.getPresentation().setText(rollbackEnvironment.getRollbackOperationName());
91 public void actionPerformed(AnActionEvent e) {
92 Project project = e.getData(PlatformDataKeys.PROJECT);
93 if (project == null) {
96 final String title = ActionPlaces.CHANGES_VIEW_TOOLBAR.equals(e.getPlace()) ? null : "Can not rollback now";
97 if (ChangeListManager.getInstance(project).isFreezedWithNotification(title)) return;
98 FileDocumentManager.getInstance().saveAllDocuments();
100 List<FilePath> missingFiles = e.getData(ChangesListView.MISSING_FILES_DATA_KEY);
101 boolean hasChanges = false;
102 if (missingFiles != null && !missingFiles.isEmpty()) {
104 new RollbackDeletionAction().actionPerformed(e);
107 LinkedHashSet<VirtualFile> modifiedWithoutEditing = getModifiedWithoutEditing(e, project);
108 if (modifiedWithoutEditing != null && !modifiedWithoutEditing.isEmpty()) {
110 rollbackModifiedWithoutEditing(project, modifiedWithoutEditing);
113 List<Change> changes = getChanges(project, e);
114 if (changes != null) {
115 if (modifiedWithoutEditing != null) {
116 for (Iterator<Change> iterator = changes.iterator(); iterator.hasNext(); ) {
117 Change next = iterator.next();
118 if (modifiedWithoutEditing.contains(next.getVirtualFile())) {
123 if (!changes.isEmpty() || !hasChanges) {
124 RollbackChangesDialog.rollbackChanges(project, changes);
129 private static class ChangesCheckHelper {
130 private Change[] myChanges;
131 private final boolean myChangesSet;
133 public ChangesCheckHelper(final Project project, final AnActionEvent e) {
134 Change[] changes = e.getData(VcsDataKeys.CHANGES);
135 if (changes == null) {
136 final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
138 final ChangeListManager clManager = ChangeListManager.getInstance(project);
139 final List<Change> changesList = new LinkedList<Change>();
140 for (VirtualFile vf : files) {
141 changesList.addAll(clManager.getChangesIn(vf));
143 if (! changesList.isEmpty()) {
144 changes = changesList.toArray(new Change[changesList.size()]);
148 myChangesSet = changes != null && changes.length > 0;
150 if (ChangesUtil.allChangesInOneListOrWholeListsSelected(project, changes)) {
156 public boolean isChangesSet() {
160 public Change[] getChanges() {
166 private static List<Change> getChanges(final Project project, final AnActionEvent e) {
167 final ChangesCheckHelper helper = new ChangesCheckHelper(project, e);
168 if (helper.isChangesSet()) return CollectionFactory.arrayList(helper.getChanges());
170 final VirtualFile[] virtualFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
171 if (virtualFiles != null && virtualFiles.length > 0) {
172 List<Change> result = new ArrayList<Change>();
173 for(VirtualFile file: virtualFiles) {
174 result.addAll(ChangeListManager.getInstance(project).getChangesIn(file));
182 private static LinkedHashSet<VirtualFile> getModifiedWithoutEditing(final AnActionEvent e, Project project) {
183 final List<VirtualFile> modifiedWithoutEditing = e.getData(VcsDataKeys.MODIFIED_WITHOUT_EDITING_DATA_KEY);
184 if (modifiedWithoutEditing != null && modifiedWithoutEditing.size() > 0) {
185 return new LinkedHashSet<VirtualFile>(modifiedWithoutEditing);
188 final VirtualFile[] virtualFiles = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
189 if (virtualFiles != null && virtualFiles.length > 0) {
190 LinkedHashSet<VirtualFile> result = new LinkedHashSet<VirtualFile>(Arrays.asList(virtualFiles));
191 result.retainAll(ChangeListManager.getInstance(project).getModifiedWithoutEditing());
198 private static void rollbackModifiedWithoutEditing(final Project project, final LinkedHashSet<VirtualFile> modifiedWithoutEditing) {
199 String message = (modifiedWithoutEditing.size() == 1)
200 ? VcsBundle.message("rollback.modified.without.editing.confirm.single", modifiedWithoutEditing.iterator().next().getPresentableUrl())
201 : VcsBundle.message("rollback.modified.without.editing.confirm.multiple", modifiedWithoutEditing.size());
202 int rc = Messages.showYesNoDialog(project, message, VcsBundle.message("changes.action.rollback.title"), Messages.getQuestionIcon());
206 final List<VcsException> exceptions = new ArrayList<VcsException>();
208 final ProgressManager progressManager = ProgressManager.getInstance();
209 final Runnable action = new Runnable() {
211 final ProgressIndicator indicator = progressManager.getProgressIndicator();
213 ChangesUtil.processVirtualFilesByVcs(project, modifiedWithoutEditing, new ChangesUtil.PerVcsProcessor<VirtualFile>() {
214 public void process(final AbstractVcs vcs, final List<VirtualFile> items) {
215 final RollbackEnvironment rollbackEnvironment = vcs.getRollbackEnvironment();
216 if (rollbackEnvironment != null) {
217 if (indicator != null) {
218 indicator.setText(vcs.getDisplayName() + ": performing rollback...");
219 indicator.setIndeterminate(false);
221 rollbackEnvironment.rollbackModifiedWithoutCheckout(items, exceptions, new RollbackProgressModifier(items.size(), indicator));
222 if (indicator != null) {
223 indicator.setText2("");
229 catch (ProcessCanceledException e) {
232 if (!exceptions.isEmpty()) {
233 AbstractVcsHelper.getInstance(project).showErrors(exceptions, VcsBundle.message("rollback.modified.without.checkout.error.tab"));
235 VirtualFileManager.getInstance().refresh(true, new Runnable() {
237 for(VirtualFile virtualFile: modifiedWithoutEditing) {
238 VcsDirtyScopeManager.getInstance(project).fileDirty(virtualFile);
244 progressManager.runProcessWithProgressSynchronously(action, VcsBundle.message("changes.action.rollback.text"), true, project);