[git] IDEA-89552 Scary error message on 'Enable VCS integration' if executable is...
[idea/community.git] / plugins / git4idea / src / git4idea / roots / GitIntegrationEnabler.java
1 /*
2  * Copyright 2000-2012 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package git4idea.roots;
17
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.vcs.AbstractVcs;
21 import com.intellij.openapi.vcs.ProjectLevelVcsManager;
22 import com.intellij.openapi.vcs.VcsDirectoryMapping;
23 import com.intellij.openapi.vfs.VirtualFile;
24 import com.intellij.util.ui.UIUtil;
25 import git4idea.GitVcs;
26 import git4idea.Notificator;
27 import git4idea.PlatformFacade;
28 import git4idea.commands.Git;
29 import git4idea.commands.GitCommandResult;
30 import org.jetbrains.annotations.NotNull;
31
32 import java.util.*;
33
34 import static com.intellij.openapi.util.text.StringUtil.pluralize;
35 import static git4idea.util.GitUIUtil.joinRootsPaths;
36
37 /**
38  * @author Kirill Likhodedov
39  */
40 public class GitIntegrationEnabler {
41
42   private final @NotNull Project myProject;
43   private final @NotNull Git myGit;
44   private final @NotNull PlatformFacade myPlatformFacade;
45
46   private static final Logger LOG = Logger.getInstance(GitIntegrationEnabler.class);
47
48   public GitIntegrationEnabler(@NotNull Project project, @NotNull Git git, @NotNull PlatformFacade platformFacade) {
49     myProject = project;
50     myGit = git;
51     myPlatformFacade = platformFacade;
52   }
53
54   public void enable(@NotNull GitRootDetectInfo detectInfo) {
55     Notificator notificator = myPlatformFacade.getNotificator(myProject);
56     Collection<VirtualFile> roots = detectInfo.getRoots();
57     VirtualFile projectDir = myProject.getBaseDir();
58     assert projectDir != null : "Base dir is unexpectedly null for project: " + myProject;
59
60     if (detectInfo.empty()) {
61       boolean succeeded = gitInitOrNotifyError(notificator, projectDir);
62       if (succeeded) {
63         addVcsRoots(Collections.singleton(projectDir));
64       }
65     }
66     else {
67       assert !roots.isEmpty();
68       if (roots.size() > 1 || detectInfo.projectIsBelowGit()) {
69         notifyAddedRoots(notificator, roots);
70       }
71       addVcsRoots(roots);
72     }
73   }
74
75   private static void notifyAddedRoots(Notificator notificator, Collection<VirtualFile> roots) {
76     notificator.notifySuccess("", String.format("Added Git %s: %s", pluralize("root", roots.size()), joinRootsPaths(roots)));
77   }
78
79   private boolean gitInitOrNotifyError(@NotNull Notificator notificator, @NotNull final VirtualFile projectDir) {
80     GitCommandResult result = myGit.init(myProject, projectDir);
81     if (result.success()) {
82       refreshGitDir(projectDir);
83       notificator.notifySuccess("", "Created Git repository in " + projectDir.getPresentableUrl());
84       return true;
85     }
86     else {
87       if (((GitVcs)myPlatformFacade.getVcs(myProject)).getExecutableValidator().checkExecutableAndNotifyIfNeeded()) {
88         notificator.notifyError("Couldn't git init " + projectDir.getPresentableUrl(), result.getErrorOutputAsHtmlString());
89         LOG.info(result.getErrorOutputAsHtmlString());
90       }
91       return false;
92     }
93   }
94
95   private void refreshGitDir(final VirtualFile projectDir) {
96     UIUtil.invokeAndWaitIfNeeded(new Runnable() {
97       @Override public void run() {
98         myPlatformFacade.runReadAction(new Runnable() {
99           @Override public void run() {
100             myPlatformFacade.getLocalFileSystem().refreshAndFindFileByPath(projectDir.getPath() + "/.git");
101           }
102         });
103       }
104     });
105   }
106
107   private void addVcsRoots(@NotNull Collection<VirtualFile> roots) {
108     ProjectLevelVcsManager vcsManager = myPlatformFacade.getVcsManager(myProject);
109     AbstractVcs vcs = myPlatformFacade.getVcs(myProject);
110     List<VirtualFile> currentGitRoots = Arrays.asList(vcsManager.getRootsUnderVcs(vcs));
111
112     List<VcsDirectoryMapping> mappings = new ArrayList<VcsDirectoryMapping>(vcsManager.getDirectoryMappings(vcs));
113
114     for (VirtualFile root : roots) {
115       if (!currentGitRoots.contains(root)) {
116         mappings.add(new VcsDirectoryMapping(root.getPath(), vcs.getName()));
117       }
118     }
119     vcsManager.setDirectoryMappings(mappings);
120   }
121 }