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.
16 package git4idea
.actions
;
18 import com
.intellij
.openapi
.actionSystem
.AnActionEvent
;
19 import com
.intellij
.openapi
.actionSystem
.DataContext
;
20 import com
.intellij
.openapi
.actionSystem
.PlatformDataKeys
;
21 import com
.intellij
.openapi
.actionSystem
.Presentation
;
22 import com
.intellij
.openapi
.application
.ApplicationManager
;
23 import com
.intellij
.openapi
.fileEditor
.FileDocumentManager
;
24 import com
.intellij
.openapi
.project
.DumbAwareAction
;
25 import com
.intellij
.openapi
.project
.Project
;
26 import com
.intellij
.openapi
.vcs
.AbstractVcsHelper
;
27 import com
.intellij
.openapi
.vcs
.ProjectLevelVcsManager
;
28 import com
.intellij
.openapi
.vcs
.TransactionRunnable
;
29 import com
.intellij
.openapi
.vcs
.VcsException
;
30 import com
.intellij
.openapi
.vfs
.VirtualFile
;
31 import git4idea
.GitUtil
;
32 import git4idea
.GitVcs
;
33 import org
.jetbrains
.annotations
.NotNull
;
35 import java
.util
.ArrayList
;
36 import java
.util
.Arrays
;
37 import java
.util
.List
;
40 * Basic abstract action handler for all Git actions to extend.
42 public abstract class BasicAction
extends DumbAwareAction
{
45 public void actionPerformed(@NotNull AnActionEvent event
) {
46 final Project project
= event
.getData(PlatformDataKeys
.PROJECT
);
47 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
49 FileDocumentManager
.getInstance().saveAllDocuments();
52 final VirtualFile
[] vFiles
= event
.getData(PlatformDataKeys
.VIRTUAL_FILE_ARRAY
);
53 assert vFiles
!= null : "The action is only available when files are selected";
55 assert project
!= null;
56 final GitVcs vcs
= GitVcs
.getInstance(project
);
57 if (!ProjectLevelVcsManager
.getInstance(project
).checkAllFilesAreUnder(vcs
, vFiles
)) {
61 String actionName
= getActionName();
62 AbstractVcsHelper helper
= AbstractVcsHelper
.getInstance(project
);
64 //Runs the runnable inside the vcs transaction (if needed), collects all exceptions, commits/rollbacks transaction and returns all exceptions together.
65 List
<VcsException
> exceptions
= helper
.runTransactionRunnable(vcs
, new TransactionRunnable() {
66 public void run(List
<VcsException
> exceptions
) {
67 final VirtualFile
[] affectedFiles
= collectAffectedFiles(project
, vFiles
);
68 //noinspection unchecked
70 perform(project
, vcs
, exceptions
, affectedFiles
);
72 catch (VcsException e
) {
75 GitUtil
.refreshFiles(project
, Arrays
.asList(affectedFiles
));
79 vcs
.showErrors(exceptions
, actionName
);
83 protected abstract void perform(@NotNull Project project
,
85 @NotNull List
<VcsException
> exceptions
,
86 @NotNull VirtualFile
[] affectedFiles
) throws VcsException
;
89 * given a list of action-target files, returns ALL the files that should be
90 * subject to the action Does not keep directories, but recursively adds
93 * @param project the project subject of the action
94 * @param files the root selection
95 * @return the complete set of files this action should apply to
98 protected VirtualFile
[] collectAffectedFiles(@NotNull Project project
, @NotNull VirtualFile
[] files
) {
99 List
<VirtualFile
> affectedFiles
= new ArrayList
<VirtualFile
>(files
.length
);
100 ProjectLevelVcsManager projectLevelVcsManager
= ProjectLevelVcsManager
.getInstance(project
);
101 for (VirtualFile file
: files
) {
102 if (!file
.isDirectory() && projectLevelVcsManager
.getVcsFor(file
) instanceof GitVcs
) {
103 affectedFiles
.add(file
);
105 else if (file
.isDirectory() && isRecursive()) {
106 addChildren(project
, affectedFiles
, file
);
110 return affectedFiles
.toArray(new VirtualFile
[affectedFiles
.size()]);
114 * recursively adds all the children of file to the files list, for which
115 * this action makes sense ({@link #appliesTo(Project, VirtualFile)}
118 * @param project the project subject of the action
119 * @param files result list
120 * @param file the file whose children should be added to the result list
123 private void addChildren(@NotNull Project project
, @NotNull List
<VirtualFile
> files
, @NotNull VirtualFile file
) {
124 VirtualFile
[] children
= file
.getChildren();
125 for (VirtualFile child
: children
) {
126 if (!child
.isDirectory() && appliesTo(project
, child
)) {
129 else if (child
.isDirectory() && isRecursive()) {
130 addChildren(project
, files
, child
);
136 protected abstract String
getActionName();
138 @SuppressWarnings({"MethodMayBeStatic"})
139 protected boolean isRecursive() {
143 @SuppressWarnings({"MethodMayBeStatic", "UnusedDeclaration"})
144 protected boolean appliesTo(@NotNull Project project
, @NotNull VirtualFile file
) {
145 return !file
.isDirectory();
149 * Disable the action if the event does not apply in this context.
151 * @param e The update event
154 public void update(@NotNull AnActionEvent e
) {
156 Presentation presentation
= e
.getPresentation();
157 DataContext dataContext
= e
.getDataContext();
158 Project project
= (Project
)dataContext
.getData(PlatformDataKeys
.PROJECT
.getName());
159 if (project
== null) {
160 presentation
.setEnabled(false);
161 presentation
.setVisible(false);
165 VirtualFile
[] vFiles
= (VirtualFile
[])dataContext
.getData(PlatformDataKeys
.VIRTUAL_FILE_ARRAY
.getName());
166 if (vFiles
== null || vFiles
.length
== 0) {
167 presentation
.setEnabled(false);
168 presentation
.setVisible(true);
171 GitVcs vcs
= GitVcs
.getInstance(project
);
172 boolean enabled
= ProjectLevelVcsManager
.getInstance(project
).checkAllFilesAreUnder(vcs
, vFiles
) && isEnabled(project
, vcs
, vFiles
);
173 // only enable action if all the targets are under the vcs and the action supports all of them
175 presentation
.setEnabled(enabled
);
176 presentation
.setVisible(enabled
);
179 protected abstract boolean isEnabled(@NotNull Project project
, @NotNull GitVcs vcs
, @NotNull VirtualFile
... vFiles
);
181 public static void saveAll() {
182 ApplicationManager
.getApplication().runWriteAction(new Runnable() {
184 FileDocumentManager
.getInstance().saveAllDocuments();