diff --git a/platform/platform-resources/src/META-INF/VcsExtensions.xml b/platform/platform-resources/src/META-INF/VcsExtensions.xml
index b2d032028189..664a9b35c7fc 100644
--- a/platform/platform-resources/src/META-INF/VcsExtensions.xml
+++ b/platform/platform-resources/src/META-INF/VcsExtensions.xml
@@ -13,6 +13,8 @@
+
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetectInfo.java b/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetectInfo.java
deleted file mode 100644
index eae6956f1893..000000000000
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetectInfo.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.intellij.openapi.vcs.roots;
-
-import com.intellij.openapi.vcs.VcsRoot;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * @author Nadya Zabrodina
- */
-public class VcsRootDetectInfo {
-
- private final @NotNull Collection myRoots;
- private final boolean myBelow;
-
- /**
- * @param roots Vcs roots important for the project.
- * @param below Pass true to indicate that the project dir is below Vcs dir,
- */
- public VcsRootDetectInfo(@NotNull Collection roots, boolean below) {
- myRoots = new ArrayList(roots);
- myBelow = below;
- }
-
- public boolean empty() {
- return myRoots.isEmpty();
- }
-
- @NotNull
- public Collection getRoots() {
- return new ArrayList(myRoots);
- }
-
- /**
- * Below implies totally under Vcs.
- *
- * @return true if the uppermost interesting Vcs root is above the project dir,
- * false if all vcs internal directories are immediately under the project dir or deeper.
- */
- public boolean projectIsBelowVcs() {
- return myBelow;
- }
-}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetectorI.java b/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetectorI.java
new file mode 100644
index 000000000000..493eaec0928c
--- /dev/null
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetectorI.java
@@ -0,0 +1,28 @@
+package com.intellij.openapi.vcs.roots;
+
+import com.intellij.openapi.vcs.VcsRoot;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+/**
+ * Interface for detecting VCS roots in the project.
+ *
+ * @author Nadya Zabrodina
+ */
+public interface VcsRootDetectorI {
+
+ /**
+ * Detect vcs roots for whole project
+ */
+ @NotNull
+ Collection detect();
+
+ /**
+ * Detect vcs roots for startDir
+ */
+ @NotNull
+ Collection detect(@Nullable VirtualFile startDir);
+}
diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
index bcec7b54a340..05e8461dd195 100644
--- a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
+++ b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -37,13 +38,11 @@ import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
-import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
-import com.intellij.openapi.vcs.roots.VcsRootDetector;
+import com.intellij.openapi.vcs.roots.VcsRootDetectorI;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.util.ConcurrencyUtil;
-import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -630,8 +629,7 @@ public class VcsUtil {
+ rootDir.getParent()
);
}
- VcsRootDetectInfo info = new VcsRootDetector(project).detect(rootDir);
- Collection roots = info.getRoots();
+ Collection roots = ServiceManager.getService(project, VcsRootDetectorI.class).detect(rootDir);
Collection result = ContainerUtilRt.newArrayList();
for (VcsRoot vcsRoot : roots) {
VirtualFile vFile = vcsRoot.getPath();
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetector.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootDetectorImpl.java
similarity index 75%
rename from platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetector.java
rename to platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootDetectorImpl.java
index a9524e53d6e3..753b4d3ff4c1 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/roots/VcsRootDetector.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootDetectorImpl.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2000-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.intellij.openapi.vcs.roots;
import com.intellij.openapi.extensions.Extensions;
@@ -16,43 +31,42 @@ import java.util.*;
/**
* @author Nadya Zabrodina
*/
-public class VcsRootDetector {
+public class VcsRootDetectorImpl implements VcsRootDetectorI {
private static final int MAXIMUM_SCAN_DEPTH = 2;
@NotNull private final Project myProject;
@NotNull private final ProjectRootManager myProjectManager;
@NotNull private final ProjectLevelVcsManager myVcsManager;
- public VcsRootDetector(@NotNull Project project) {
+ public VcsRootDetectorImpl(@NotNull Project project,
+ @NotNull ProjectRootManager projectRootManager,
+ @NotNull ProjectLevelVcsManager projectLevelVcsManager) {
myProject = project;
- myProjectManager = ProjectRootManager.getInstance(project);
- myVcsManager = ProjectLevelVcsManager.getInstance(project);
+ myProjectManager = projectRootManager;
+ myVcsManager = projectLevelVcsManager;
}
@NotNull
- public VcsRootDetectInfo detect() {
+ public Collection detect() {
return detect(myProject.getBaseDir());
}
@NotNull
- public VcsRootDetectInfo detect(@Nullable VirtualFile startDir) {
+ public Collection detect(@Nullable VirtualFile startDir) {
if (startDir == null) {
- return new VcsRootDetectInfo(Collections.emptyList(), false);
+ return Collections.emptyList();
}
final Set roots = scanForRootsInsideDir(startDir);
roots.addAll(scanForRootsInContentRoots());
for (VcsRoot root : roots) {
if (startDir.equals(root.getPath())) {
- return new VcsRootDetectInfo(roots, false);
+ return roots;
}
}
List rootsAbove = scanForSingleRootAboveDir(startDir);
- if (!rootsAbove.isEmpty()) {
- roots.addAll(rootsAbove);
- return new VcsRootDetectInfo(roots, true);
- }
- return new VcsRootDetectInfo(roots, false);
+ roots.addAll(rootsAbove);
+ return roots;
}
@NotNull
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
index 14be8a0d24be..2742b1897601 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/roots/VcsRootErrorsFinder.java
@@ -1,5 +1,6 @@
package com.intellij.openapi.vcs.roots;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
@@ -30,7 +31,7 @@ public class VcsRootErrorsFinder {
@NotNull
public Collection find() {
List mappings = myVcsManager.getDirectoryMappings();
- Collection vcsRoots = new VcsRootDetector(myProject).detect().getRoots();
+ Collection vcsRoots = ServiceManager.getService(myProject, VcsRootDetectorI.class).detect();
Collection errors = new ArrayList();
errors.addAll(findExtraMappings(mappings));
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java
index a5a3abdf1ff1..a7118f2346ad 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.vcs.roots;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
@@ -169,8 +170,8 @@ public class VcsRootDetectorTest extends VcsRootPlatformTest {
}
@NotNull
- private VcsRootDetectInfo detect(@Nullable VirtualFile startDir) {
- return new VcsRootDetector(myProject).detect(startDir);
+ private Collection detect(@Nullable VirtualFile startDir) {
+ return ServiceManager.getService(myProject, VcsRootDetectorI.class).detect(startDir);
}
public void doTest(@NotNull VcsRootConfiguration vcsRootConfiguration,
@@ -178,9 +179,9 @@ public class VcsRootDetectorTest extends VcsRootPlatformTest {
@NotNull Collection expectedPaths)
throws IOException {
initProject(vcsRootConfiguration);
- VcsRootDetectInfo info = detect(startDir);
+ Collection vcsRoots = detect(startDir);
assertRoots(expectedPaths, getPaths(
- ContainerUtil.filter(info.getRoots(), new Condition() {
+ ContainerUtil.filter(vcsRoots, new Condition() {
@Override
public boolean value(VcsRoot root) {
assert root.getVcs() != null;
diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java
index 6d62a07bf422..99c43f93ee13 100644
--- a/plugins/git4idea/src/git4idea/GitVcs.java
+++ b/plugins/git4idea/src/git4idea/GitVcs.java
@@ -46,8 +46,7 @@ import com.intellij.openapi.vcs.history.VcsHistoryProvider;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.merge.MergeProvider;
import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
-import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
-import com.intellij.openapi.vcs.roots.VcsRootDetector;
+import com.intellij.openapi.vcs.roots.VcsRootDetectorI;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vcs.update.UpdateEnvironment;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
@@ -89,6 +88,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.text.SimpleDateFormat;
+import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@@ -586,8 +586,8 @@ public class GitVcs extends AbstractVcs {
public void enableIntegration() {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
public void run() {
- VcsRootDetectInfo detectInfo = new VcsRootDetector(myProject).detect();
- new GitIntegrationEnabler(myProject, myGit, myPlatformFacade).enable(detectInfo);
+ Collection roots = ServiceManager.getService(myProject, VcsRootDetectorI.class).detect();
+ new GitIntegrationEnabler(myProject, myGit, myPlatformFacade).enable(roots);
}
});
}
diff --git a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java
index 15c98d9c8e92..c06a0aec1ed7 100644
--- a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java
+++ b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java
@@ -22,8 +22,8 @@ import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsDirectoryMapping;
import com.intellij.openapi.vcs.VcsRoot;
-import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
import com.intellij.openapi.vcs.roots.VcsRootErrorsFinder;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
@@ -56,9 +56,9 @@ public class GitIntegrationEnabler {
myPlatformFacade = platformFacade;
}
- public void enable(@NotNull VcsRootDetectInfo detectInfo) {
+ public void enable(@NotNull Collection vcsRoots) {
Notificator notificator = myPlatformFacade.getNotificator(myProject);
- Collection gitRoots = ContainerUtil.filter(detectInfo.getRoots(), new Condition() {
+ Collection gitRoots = ContainerUtil.filter(vcsRoots, new Condition() {
@Override
public boolean value(VcsRoot root) {
AbstractVcs vcs = root.getVcs();
@@ -77,13 +77,24 @@ public class GitIntegrationEnabler {
}
else {
assert !roots.isEmpty();
- if (roots.size() > 1 || detectInfo.projectIsBelowVcs()) {
+ if (roots.size() > 1 || isProjectBelowVcs(roots)) {
notifyAddedRoots(notificator, roots);
}
addVcsRoots(roots);
}
}
+ private boolean isProjectBelowVcs(@NotNull Collection gitRoots) {
+ //check if there are vcs roots strictly above the project dir
+ VirtualFile baseDir = myProject.getBaseDir();
+ for (VirtualFile root : gitRoots) {
+ if (VfsUtilCore.isAncestor(root, baseDir, true)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static void notifyAddedRoots(Notificator notificator, Collection roots) {
notificator.notifySuccess("", String.format("Added Git %s: %s", pluralize("root", roots.size()), joinRootsPaths(roots)));
}
diff --git a/plugins/git4idea/tests/git4idea/roots/GitIntegrationEnablerTest.java b/plugins/git4idea/tests/git4idea/roots/GitIntegrationEnablerTest.java
index 8643348ba2f5..37b1d926303a 100644
--- a/plugins/git4idea/tests/git4idea/roots/GitIntegrationEnablerTest.java
+++ b/plugins/git4idea/tests/git4idea/roots/GitIntegrationEnablerTest.java
@@ -22,7 +22,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.VcsRoot;
import com.intellij.openapi.vcs.VcsTestUtil;
-import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -38,7 +37,7 @@ import org.junit.Test;
import java.io.File;
import java.util.*;
-import static junit.framework.Assert.*;
+import static org.junit.Assert.*;
/**
* @author Nadya Zabrodina
@@ -63,7 +62,7 @@ public class GitIntegrationEnablerTest extends GitLightTest {
public void oneRootForTheWholeProjectThenJustAddVcsrRoot() {
Map> map = new HashMap>();
map.put("git_init", Collections.emptyList());
- doTest(given(Arrays.asList("."), false),
+ doTest(given(Arrays.asList(".")),
map, null);
}
@@ -74,7 +73,7 @@ public class GitIntegrationEnablerTest extends GitLightTest {
map.put("vcs_roots", VcsTestUtil.toAbsolute(Arrays.asList("."), myProject));
- doTest(given(Collections.emptyList(), false),
+ doTest(given(Collections.emptyList()),
map, notification("Created Git repository in " + myProjectRoot));
}
@@ -83,7 +82,7 @@ public class GitIntegrationEnablerTest extends GitLightTest {
Map> map = new HashMap>();
map.put("git_init", Collections.emptyList());
- doTest(given(Arrays.asList(".."), true),
+ doTest(given(Arrays.asList("..")),
map, notification("Added Git root: " + myTestRoot));
}
@@ -92,7 +91,7 @@ public class GitIntegrationEnablerTest extends GitLightTest {
Map> map = new HashMap>();
map.put("git_init", Collections.emptyList());
- doTest(given(Arrays.asList(".", "community"), false),
+ doTest(given(Arrays.asList(".", "community")),
map, notification("Added Git roots: " + myProjectRoot + ", " + getPresentationForRoot("community")));
}
@@ -101,7 +100,7 @@ public class GitIntegrationEnablerTest extends GitLightTest {
Map> map = new HashMap>();
map.put("git_init", Collections.emptyList());
- doTest(given(Arrays.asList("..", "community"), true),
+ doTest(given(Arrays.asList("..", "community")),
map, notification("Added Git roots: " + myTestRoot + ", " + getPresentationForRoot("community")));
}
@@ -110,16 +109,16 @@ public class GitIntegrationEnablerTest extends GitLightTest {
Map> map = new HashMap>();
map.put("git_init", Collections.emptyList());
- doTest(given(Arrays.asList("community", "contrib"), false),
+ doTest(given(Arrays.asList("community", "contrib")),
map, notification(
"Added Git roots: " + getPresentationForRoot("community") + ", " + getPresentationForRoot("contrib")));
}
- private void doTest(@NotNull VcsRootDetectInfo detectInfo, @NotNull Map> map, @Nullable Notification notification) {
+ private void doTest(@NotNull Collection vcsRoots, @NotNull Map> map, @Nullable Notification notification) {
//default
if (map.get("vcs_roots") == null) {
- map.put("vcs_roots", ContainerUtil.map(detectInfo.getRoots(), new Function() {
+ map.put("vcs_roots", ContainerUtil.map(vcsRoots, new Function() {
@Override
public String fun(VcsRoot root) {
@@ -129,7 +128,7 @@ public class GitIntegrationEnablerTest extends GitLightTest {
}));
}
- new GitIntegrationEnabler(myProject, myGit, myPlatformFacade).enable(detectInfo);
+ new GitIntegrationEnabler(myProject, myGit, myPlatformFacade).enable(vcsRoots);
assertVcsRoots(map.get("vcs_roots"));
assertGitInit(map.get("git_init"));
@@ -148,14 +147,14 @@ public class GitIntegrationEnablerTest extends GitLightTest {
VcsTestUtil.assertEqualCollections(expectedVcsRoots, getPaths(actualRoots));
}
- VcsRootDetectInfo given(@NotNull Collection roots, boolean below) {
- return new VcsRootDetectInfo(ContainerUtil.map(roots, new Function() {
+ Collection given(@NotNull Collection roots) {
+ return ContainerUtil.map(roots, new Function() {
@Override
public VcsRoot fun(String s) {
return new VcsRoot(myVcs, new MockVirtualFile(VcsTestUtil.toAbsolute(s, myProject)));
}
- }), below);
+ });
}
Notification notification(String content) {