mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Root Checker and Root Problem Notifier
*Extension Point for rootChecker created;
*api changed and moved form git directory to common platform;
*platform facade remove from root subdirectory exclude integration enabler;
* root scanner started in ProjectLevelVcsManager;
*vcs name stored in VcsRootError;
*java tests created instead of groovy test;
*UsefulTestCase class used as a base class for test instead of light test;
*platform facade removed (except IntegrationEnablerTest);
*IntegrationsEnabler test switched off;
*check that chosen vcs in mapping root is supported for this kind of root;
*filter git roots in integration enabler
*do not start scanner in unit test mode or if there are no root checkers in
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
<extensionPoints>
|
||||
<extensionPoint name="checkoutProvider"
|
||||
interface="com.intellij.openapi.vcs.CheckoutProvider"/>
|
||||
<extensionPoint name="vcsRootChecker"
|
||||
interface="com.intellij.openapi.vcs.VcsRootChecker"/>
|
||||
<extensionPoint name="checkoutListener"
|
||||
interface="com.intellij.openapi.vcs.checkout.CheckoutListener"/>
|
||||
<extensionPoint name="vcsAwareCheckoutListener"
|
||||
|
||||
@@ -429,11 +429,6 @@ public abstract class AbstractVcs<ComList extends CommittedChangeList> extends S
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VcsRootChecker getRootChecker() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VcsRootSettings createEmptyVcsRootSettings() {
|
||||
return null;
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Checks VCS roots, revealing invalid roots (registered in the settings, but not related to real VCS roots on disk)
|
||||
@@ -25,18 +26,31 @@ import java.util.Collection;
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public interface VcsRootChecker {
|
||||
public abstract class VcsRootChecker {
|
||||
|
||||
@NonNls public static final ExtensionPointName<VcsRootChecker> EXTENSION_POINT_NAME =
|
||||
new ExtensionPointName<VcsRootChecker>("com.intellij.vcsRootChecker");
|
||||
|
||||
/**
|
||||
* @return Paths to VCS roots which are not registered in the Settings | Version Control.
|
||||
* @param path path to check if it is vcs root directory
|
||||
* @return true if it is vcs root
|
||||
*/
|
||||
@NotNull
|
||||
Collection<String> getUnregisteredRoots();
|
||||
public boolean isRoot(@NotNull String path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - return vcs for current checker
|
||||
*/
|
||||
public abstract VcsKey getSupportedVcs();
|
||||
|
||||
/**
|
||||
* Check if the "dot" directory changed during scan
|
||||
*
|
||||
* @param directory root to be checked.
|
||||
* @return true if the given directory is not a VCS root.
|
||||
* @param path - path to check
|
||||
* @return true if it is a DOT_DIR
|
||||
*/
|
||||
boolean isInvalidMapping(@NotNull VcsDirectoryMapping mapping);
|
||||
public boolean isVcsDir(@Nullable String path) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,24 +20,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* Incorrect VCS root definition: either an unregistered, or an incorrectly registered VCS root.
|
||||
*
|
||||
* @see VcsRootChecker
|
||||
* @see AbstractVcs#getRootChecker
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
* @see VcsRootChecker
|
||||
*/
|
||||
public class VcsRootError {
|
||||
|
||||
private final @NotNull Type myType;
|
||||
private final @NotNull String myMapping;
|
||||
private final @NotNull VcsKey myVcsKey;
|
||||
|
||||
public enum Type {
|
||||
EXTRA_MAPPING,
|
||||
UNREGISTERED_ROOT
|
||||
}
|
||||
|
||||
public VcsRootError(@NotNull Type type, @NotNull String mapping) {
|
||||
public VcsRootError(@NotNull Type type, @NotNull String mapping, @NotNull String key) {
|
||||
myType = type;
|
||||
myMapping = mapping;
|
||||
myVcsKey = new VcsKey(key);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -50,6 +50,11 @@ public class VcsRootError {
|
||||
return myMapping;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VcsKey getVcsKey() {
|
||||
return myVcsKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("VcsRootError{%s - %s}", myType, myMapping);
|
||||
|
||||
+29
-27
@@ -17,6 +17,7 @@
|
||||
package com.intellij.openapi.vcs.configurable;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -25,6 +26,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.impl.DefaultVcsRootPolicy;
|
||||
import com.intellij.openapi.vcs.impl.VcsDescriptor;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootErrorsFinder;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.*;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
@@ -125,7 +127,8 @@ public class VcsDirectoryConfigurationPanel extends JPanel implements Configurab
|
||||
private boolean mappingIsError(VcsDirectoryMapping mapping) {
|
||||
String vcs = mapping.getVcs();
|
||||
VcsRootChecker checker = myCheckers.get(vcs);
|
||||
return checker != null && checker.isInvalidMapping(mapping);
|
||||
return checker != null &&
|
||||
(mapping.isDefaultMapping() ? !checker.isRoot(myProject.getBasePath()) : !checker.isRoot(mapping.getDirectory()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,16 +266,14 @@ public class VcsDirectoryConfigurationPanel extends JPanel implements Configurab
|
||||
|
||||
private void updateRootCheckers() {
|
||||
myCheckers.clear();
|
||||
for (VcsDescriptor descriptor : myVcsManager.getAllVcss()) {
|
||||
String name = descriptor.getName();
|
||||
AbstractVcs vcs = myVcsManager.findVcsByName(name);
|
||||
VcsRootChecker[] checkers = Extensions.getExtensions(VcsRootChecker.EXTENSION_POINT_NAME);
|
||||
for (VcsRootChecker checker : checkers) {
|
||||
VcsKey key = checker.getSupportedVcs();
|
||||
AbstractVcs vcs = myVcsManager.findVcsByName(key.getName());
|
||||
if (vcs == null) {
|
||||
continue;
|
||||
}
|
||||
VcsRootChecker checker = vcs.getRootChecker();
|
||||
if (checker != null) {
|
||||
myCheckers.put(name, checker);
|
||||
}
|
||||
myCheckers.put(key.getName(), checker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,27 +417,28 @@ public class VcsDirectoryConfigurationPanel extends JPanel implements Configurab
|
||||
final JComponent errorPanel = Box.createVerticalBox();
|
||||
final JBScrollPane pane = new JBScrollPane(errorPanel);
|
||||
|
||||
for (Map.Entry<String, VcsRootChecker> entry : myCheckers.entrySet()) {
|
||||
VcsRootChecker checker = entry.getValue();
|
||||
for (final String root : checker.getUnregisteredRoots()) {
|
||||
final String vcs = entry.getKey();
|
||||
String title = "Unregistered " + vcs + " root: " + FileUtil.toSystemDependentName(root);
|
||||
final VcsRootErrorLabel vcsRootErrorLabel = new VcsRootErrorLabel(title);
|
||||
vcsRootErrorLabel.setAddRootLinkHandler(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addMapping(new VcsDirectoryMapping(root, vcs));
|
||||
errorPanel.remove(vcsRootErrorLabel);
|
||||
if (errorPanel.getComponentCount() == 0) {
|
||||
pane.setVisible(false);
|
||||
}
|
||||
pane.setMinimumSize(new Dimension(-1, calcMinHeight(errorPanel, DEFAULT_HEIGHT)));
|
||||
validate();
|
||||
Collection<VcsRootError> myErrors = VcsRootErrorsFinder.getInstance(myProject).find();
|
||||
for (final VcsRootError root : myErrors) {
|
||||
final VcsKey vcsKey = root.getVcsKey();
|
||||
final VcsDescriptor vcsDescriptor = myAllVcss.get(vcsKey.getName());
|
||||
String displayVcsName = vcsDescriptor.getDisplayName();
|
||||
String title = "Unregistered " + displayVcsName + " root: " + FileUtil.toSystemDependentName(root.getMapping());
|
||||
final VcsRootErrorLabel vcsRootErrorLabel = new VcsRootErrorLabel(title);
|
||||
vcsRootErrorLabel.setAddRootLinkHandler(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addMapping(new VcsDirectoryMapping(root.getMapping(), vcsKey.getName()));
|
||||
errorPanel.remove(vcsRootErrorLabel);
|
||||
if (errorPanel.getComponentCount() == 0) {
|
||||
pane.setVisible(false);
|
||||
}
|
||||
});
|
||||
errorPanel.add(vcsRootErrorLabel);
|
||||
}
|
||||
pane.setMinimumSize(new Dimension(-1, calcMinHeight(errorPanel, DEFAULT_HEIGHT)));
|
||||
validate();
|
||||
}
|
||||
});
|
||||
errorPanel.add(vcsRootErrorLabel);
|
||||
}
|
||||
|
||||
if (errorPanel.getComponentCount() == 0) {
|
||||
pane.setVisible(false);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.EditorSettings;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -44,6 +45,7 @@ import com.intellij.openapi.vcs.checkout.CompositeCheckoutListener;
|
||||
import com.intellij.openapi.vcs.ex.ProjectLevelVcsManagerEx;
|
||||
import com.intellij.openapi.vcs.history.VcsHistoryCache;
|
||||
import com.intellij.openapi.vcs.impl.projectlevelman.*;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootScanner;
|
||||
import com.intellij.openapi.vcs.update.ActionInfo;
|
||||
import com.intellij.openapi.vcs.update.UpdateInfoTree;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
@@ -240,6 +242,12 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme
|
||||
else {
|
||||
myContentManager = ContentFactory.SERVICE.getInstance().createContentManager(true, myProject);
|
||||
}
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
VcsRootChecker[] checkers = Extensions.getExtensions(VcsRootChecker.EXTENSION_POINT_NAME);
|
||||
if (checkers.length != 0) {
|
||||
VcsRootScanner.start(myProject, checkers);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,54 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vcs.VcsRoot;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* The result of root detection.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class VcsRootDetectInfo {
|
||||
|
||||
private final @NotNull Collection<VirtualFile> myRoots;
|
||||
private final @NotNull Collection<VcsRoot> myRoots;
|
||||
private final boolean myFull;
|
||||
private final boolean myBelow;
|
||||
|
||||
/**
|
||||
* @param roots Git roots important for the project.
|
||||
* @param full Pass true to indicate that the project is fully under Git.
|
||||
* @param below Pass true to indicate that the project dir is below Git dir,
|
||||
* i.e. .git is above the project dir, and there is no .git directly under the project dir.
|
||||
* @param roots Vcs roots important for the project.
|
||||
* @param full Pass true to indicate that the project is fully under Vcs.
|
||||
* @param below Pass true to indicate that the project dir is below Vcs dir,
|
||||
* i.e. .git is above the project dir, and there is no DOT dir directly under the project dir.
|
||||
*/
|
||||
public VcsRootDetectInfo(@NotNull Collection<VirtualFile> roots, boolean full, boolean below) {
|
||||
myRoots = new ArrayList<VirtualFile>(roots);
|
||||
public VcsRootDetectInfo(@NotNull Collection<VcsRoot> roots, boolean full, boolean below) {
|
||||
myRoots = new ArrayList<VcsRoot>(roots);
|
||||
myFull = full;
|
||||
myBelow = below;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the project is fully under Git.
|
||||
* It is true if .git is directly inside or above the project dir.
|
||||
* @return True if the project is fully under Vcs.
|
||||
* It is true if f.e. .git is directly inside or above the project dir.
|
||||
*/
|
||||
public boolean totallyUnderGit() {
|
||||
public boolean totallyUnderVcs() {
|
||||
return myFull;
|
||||
}
|
||||
|
||||
@@ -57,17 +40,17 @@ public class VcsRootDetectInfo {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<VirtualFile> getRoots() {
|
||||
return new ArrayList<VirtualFile>(myRoots);
|
||||
public Collection<VcsRoot> getRoots() {
|
||||
return new ArrayList<VcsRoot>(myRoots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Below implies totally under Git.
|
||||
* @return true if the uppermost interesting Git root is above the project dir,
|
||||
* false if all .git directories are immediately under the project dir or deeper.
|
||||
* 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 projectIsBelowGit() {
|
||||
public boolean projectIsBelowVcs() {
|
||||
return myBelow;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +1,32 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsRoot;
|
||||
import com.intellij.openapi.vcs.VcsRootChecker;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Scans the file system looking for Git roots, which contain the Project or its parts,
|
||||
* and returns the information enclosed to the {@link com.intellij.openapi.vcs.roots.VcsRootDetectInfo}.
|
||||
* The main part of the information are Git roots which will be proposed to the user to be added as VCS roots.
|
||||
* </p>
|
||||
* <p>
|
||||
* Linked sources are not scanned. User should add Git roots for them explicitly.
|
||||
* </p>
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class VcsRootDetector {
|
||||
|
||||
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) {
|
||||
myProject = project;
|
||||
myProjectManager = ProjectRootManager.getInstance(project);
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(project);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -58,43 +37,49 @@ public class VcsRootDetector {
|
||||
@NotNull
|
||||
public VcsRootDetectInfo detect(@Nullable VirtualFile startDir) {
|
||||
if (startDir == null) {
|
||||
return new VcsRootDetectInfo(Collections.<VirtualFile>emptyList(), false, false);
|
||||
return new VcsRootDetectInfo(Collections.<VcsRoot>emptyList(), false, false);
|
||||
}
|
||||
|
||||
final Set<VirtualFile> roots = scanForRootsInsideDir(startDir);
|
||||
final Set<VcsRoot> roots = scanForRootsInsideDir(startDir);
|
||||
roots.addAll(scanForRootsInContentRoots());
|
||||
|
||||
if (roots.contains(startDir)) {
|
||||
return new VcsRootDetectInfo(roots, true, false);
|
||||
for (VcsRoot root : roots) {
|
||||
if (startDir.equals(root.getPath())) {
|
||||
return new VcsRootDetectInfo(roots, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
VirtualFile rootAbove = scanForSingleRootAboveDir(startDir);
|
||||
if (rootAbove != null) {
|
||||
roots.add(rootAbove);
|
||||
List<VcsRoot> rootsAbove = scanForSingleRootAboveDir(startDir);
|
||||
if (!rootsAbove.isEmpty()) {
|
||||
roots.addAll(rootsAbove);
|
||||
return new VcsRootDetectInfo(roots, true, true);
|
||||
}
|
||||
return new VcsRootDetectInfo(roots, false, false);
|
||||
}
|
||||
|
||||
private Set<VirtualFile> scanForRootsInContentRoots() {
|
||||
Set<VirtualFile> gitRoots = new HashSet<VirtualFile>();
|
||||
@NotNull
|
||||
private Set<VcsRoot> scanForRootsInContentRoots() {
|
||||
Set<VcsRoot> gitRoots = new HashSet<VcsRoot>();
|
||||
VirtualFile[] roots = myProjectManager.getContentRoots();
|
||||
for (VirtualFile contentRoot : roots) {
|
||||
Set<VirtualFile> rootsInsideRoot = scanForRootsInsideDir(contentRoot);
|
||||
if (!rootsInsideRoot.contains(contentRoot)) {
|
||||
VirtualFile rootAbove = scanForSingleRootAboveDir(contentRoot);
|
||||
if (rootAbove != null) {
|
||||
rootsInsideRoot.add(rootAbove);
|
||||
|
||||
Set<VcsRoot> rootsInsideRoot = scanForRootsInsideDir(contentRoot);
|
||||
boolean shouldScanAbove = true;
|
||||
for (VcsRoot root : rootsInsideRoot) {
|
||||
if (contentRoot.equals(root.getPath())) {
|
||||
shouldScanAbove = false;
|
||||
}
|
||||
}
|
||||
if (shouldScanAbove) {
|
||||
List<VcsRoot> rootsAbove = scanForSingleRootAboveDir(contentRoot);
|
||||
rootsInsideRoot.addAll(rootsAbove);
|
||||
}
|
||||
gitRoots.addAll(rootsInsideRoot);
|
||||
}
|
||||
return gitRoots;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<VirtualFile> scanForRootsInsideDir(@NotNull final VirtualFile dir, final int depth) {
|
||||
final Set<VirtualFile> roots = new HashSet<VirtualFile>();
|
||||
private Set<VcsRoot> scanForRootsInsideDir(@NotNull final VirtualFile dir, final int depth) {
|
||||
final Set<VcsRoot> roots = new HashSet<VcsRoot>();
|
||||
if (depth > MAXIMUM_SCAN_DEPTH) {
|
||||
// performance optimization via limitation: don't scan deep though the whole VFS, 2 levels under a content root is enough
|
||||
return roots;
|
||||
@@ -103,8 +88,9 @@ public class VcsRootDetector {
|
||||
if (myProject.isDisposed() || !dir.isDirectory()) {
|
||||
return roots;
|
||||
}
|
||||
if (hasGitDir(dir)) {
|
||||
roots.add(dir);
|
||||
List<AbstractVcs> vcsList = getVcsListFor(dir);
|
||||
for (AbstractVcs vcs : vcsList) {
|
||||
roots.add(new VcsRoot(vcs, dir));
|
||||
}
|
||||
for (VirtualFile child : dir.getChildren()) {
|
||||
roots.addAll(scanForRootsInsideDir(child, depth + 1));
|
||||
@@ -113,28 +99,40 @@ public class VcsRootDetector {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<VirtualFile> scanForRootsInsideDir(@NotNull VirtualFile dir) {
|
||||
private Set<VcsRoot> scanForRootsInsideDir(@NotNull VirtualFile dir) {
|
||||
return scanForRootsInsideDir(dir, 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFile scanForSingleRootAboveDir(@NotNull final VirtualFile dir) {
|
||||
@NotNull
|
||||
private List<VcsRoot> scanForSingleRootAboveDir(@NotNull final VirtualFile dir) {
|
||||
List<VcsRoot> roots = new ArrayList<VcsRoot>();
|
||||
if (myProject.isDisposed()) {
|
||||
return null;
|
||||
return roots;
|
||||
}
|
||||
|
||||
VirtualFile par = dir.getParent();
|
||||
while (par != null) {
|
||||
if (hasGitDir(par)) {
|
||||
return par;
|
||||
List<AbstractVcs> vcsList = getVcsListFor(par);
|
||||
for (AbstractVcs vcs : vcsList) {
|
||||
roots.add(new VcsRoot(vcs, par));
|
||||
}
|
||||
if (!roots.isEmpty()) {
|
||||
return roots;
|
||||
}
|
||||
par = par.getParent();
|
||||
}
|
||||
return null;
|
||||
return roots;
|
||||
}
|
||||
|
||||
private static boolean hasGitDir(@NotNull VirtualFile dir) {
|
||||
VirtualFile gitDir = dir.findChild(".git");
|
||||
return gitDir != null && gitDir.exists();
|
||||
@NotNull
|
||||
private List<AbstractVcs> getVcsListFor(@NotNull VirtualFile dir) {
|
||||
VcsRootChecker[] checkers = Extensions.getExtensions(VcsRootChecker.EXTENSION_POINT_NAME);
|
||||
List<AbstractVcs> vcsList = new ArrayList<AbstractVcs>();
|
||||
for (VcsRootChecker checker : checkers) {
|
||||
if (checker.isRoot(dir.getPath())) {
|
||||
vcsList.add(myVcsManager.findVcsByName(checker.getSupportedVcs().getName()));
|
||||
}
|
||||
}
|
||||
return vcsList;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,24 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsDirectoryMapping;
|
||||
import com.intellij.openapi.vcs.VcsRootError;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Detects actual Git roots and compares them to the ones registered in Settings | Version Control.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class VcsRootErrorsFinder {
|
||||
|
||||
private final @NotNull Project myProject;
|
||||
private final @NotNull ProjectLevelVcsManager myVcsManager;
|
||||
|
||||
@@ -46,61 +30,67 @@ public class VcsRootErrorsFinder {
|
||||
@NotNull
|
||||
public Collection<VcsRootError> find() {
|
||||
List<VcsDirectoryMapping> mappings = myVcsManager.getDirectoryMappings();
|
||||
Collection<VirtualFile> gitRoots = new VcsRootDetector(myProject).detect().getRoots();
|
||||
Collection<VcsRoot> vcsRoots = new VcsRootDetector(myProject).detect().getRoots();
|
||||
|
||||
Collection<VcsRootError> errors = new ArrayList<VcsRootError>();
|
||||
Collection<String> gitPaths = rootsToPaths(gitRoots);
|
||||
errors.addAll(findExtraMappings(mappings, gitPaths));
|
||||
errors.addAll(findUnregisteredRoots(mappings, gitPaths));
|
||||
errors.addAll(findExtraMappings(mappings, vcsRoots.isEmpty()));
|
||||
errors.addAll(findUnregisteredRoots(mappings, vcsRoots));
|
||||
return errors;
|
||||
}
|
||||
|
||||
private Collection<VcsRootError> findUnregisteredRoots(List<VcsDirectoryMapping> mappings, Collection<String> gitPaths) {
|
||||
@NotNull
|
||||
private Collection<VcsRootError> findUnregisteredRoots(@NotNull List<VcsDirectoryMapping> mappings,
|
||||
@NotNull Collection<VcsRoot> vcsRoots) {
|
||||
Collection<VcsRootError> errors = new ArrayList<VcsRootError>();
|
||||
List<String> mappedPaths = mappingsToPaths(mappings);
|
||||
for (String gitPath : gitPaths) {
|
||||
if (!mappedPaths.contains(gitPath)) {
|
||||
errors.add(new VcsRootError(VcsRootError.Type.UNREGISTERED_ROOT, gitPath));
|
||||
List<String> mappedPaths = mappingsToPathsWithSelectedVcs(mappings);
|
||||
for (VcsRoot root : vcsRoots) {
|
||||
VirtualFile virtualFileFromRoot = root.getPath();
|
||||
if (virtualFileFromRoot == null) {
|
||||
continue;
|
||||
}
|
||||
String vcsPath = virtualFileFromRoot.getPath();
|
||||
if (!mappedPaths.contains(vcsPath) && root.getVcs() != null) {
|
||||
errors.add(new VcsRootError(VcsRootError.Type.UNREGISTERED_ROOT, vcsPath, root.getVcs().getName()));
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
private static Collection<VcsRootError> findExtraMappings(List<VcsDirectoryMapping> mappings, Collection<String> gitPaths) {
|
||||
@NotNull
|
||||
private Collection<VcsRootError> findExtraMappings(@NotNull List<VcsDirectoryMapping> mappings, boolean isEmptyVcsRoots) {
|
||||
Collection<VcsRootError> errors = new ArrayList<VcsRootError>();
|
||||
for (VcsDirectoryMapping mapping : mappings) {
|
||||
if (mapping.isDefaultMapping()) {
|
||||
if (gitPaths.isEmpty()) {
|
||||
errors.add(new VcsRootError(VcsRootError.Type.EXTRA_MAPPING, VcsDirectoryMapping.PROJECT_CONSTANT));
|
||||
if (isEmptyVcsRoots && !StringUtil.isEmptyOrSpaces(mapping.getVcs())) {
|
||||
errors.add(new VcsRootError(VcsRootError.Type.EXTRA_MAPPING, VcsDirectoryMapping.PROJECT_CONSTANT, mapping.getVcs()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
String mappedPath = mapping.systemIndependentPath();
|
||||
if (!gitPaths.contains(mappedPath) && !hasGitDir(mappedPath)) {
|
||||
errors.add(new VcsRootError(VcsRootError.Type.EXTRA_MAPPING, mappedPath));
|
||||
if (!isRoot(mapping)) {
|
||||
errors.add(new VcsRootError(VcsRootError.Type.EXTRA_MAPPING, mappedPath, mapping.getVcs()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
private static boolean hasGitDir(String path) {
|
||||
File file = new File(path, ".git");
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<String> rootsToPaths(@NotNull Collection<VirtualFile> gitRoots) {
|
||||
Collection<String> gitPaths = new ArrayList<String>(gitRoots.size());
|
||||
for (VirtualFile root : gitRoots) {
|
||||
gitPaths.add(root.getPath());
|
||||
}
|
||||
return gitPaths;
|
||||
public static Collection<VirtualFile> vcsRootsToVirtualFiles(@NotNull Collection<VcsRoot> vcsRoots) {
|
||||
return ContainerUtil.map(vcsRoots, new Function<VcsRoot, VirtualFile>() {
|
||||
@Override
|
||||
public VirtualFile fun(VcsRoot root) {
|
||||
return root.getPath();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<String> mappingsToPaths(List<VcsDirectoryMapping> mappings) {
|
||||
private List<String> mappingsToPathsWithSelectedVcs(@NotNull List<VcsDirectoryMapping> mappings) {
|
||||
List<String> paths = new ArrayList<String>();
|
||||
for (VcsDirectoryMapping mapping : mappings) {
|
||||
if (StringUtil.isEmptyOrSpaces(mapping.getVcs())) {
|
||||
continue;
|
||||
}
|
||||
if (!mapping.isDefaultMapping()) {
|
||||
paths.add(mapping.systemIndependentPath());
|
||||
}
|
||||
@@ -113,4 +103,19 @@ public class VcsRootErrorsFinder {
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
public static VcsRootErrorsFinder getInstance(Project project) {
|
||||
return new VcsRootErrorsFinder(project);
|
||||
}
|
||||
|
||||
private boolean isRoot(@NotNull final VcsDirectoryMapping mapping) {
|
||||
VcsRootChecker[] checkers = Extensions.getExtensions(VcsRootChecker.EXTENSION_POINT_NAME);
|
||||
final String pathToCheck = mapping.isDefaultMapping() ? myProject.getBasePath() : mapping.getDirectory();
|
||||
return ContainerUtil.find(checkers, new Condition<VcsRootChecker>() {
|
||||
@Override
|
||||
public boolean value(VcsRootChecker checker) {
|
||||
return checker.getSupportedVcs().getName().equals(mapping.getVcs()) && checker.isRoot(pathToCheck);
|
||||
}
|
||||
}) != null;
|
||||
}
|
||||
}
|
||||
|
||||
+47
-49
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -13,15 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.roots;
|
||||
package com.intellij.openapi.vcs.roots;
|
||||
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationGroup;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -29,9 +25,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsConfiguration;
|
||||
import com.intellij.openapi.vcs.VcsDirectoryMapping;
|
||||
import com.intellij.openapi.vcs.VcsRootError;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootErrorsFinder;
|
||||
import com.intellij.util.Function;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -42,33 +36,31 @@ import java.util.Collection;
|
||||
import static com.intellij.notification.NotificationType.ERROR;
|
||||
import static com.intellij.notification.NotificationType.INFORMATION;
|
||||
import static com.intellij.openapi.util.text.StringUtil.pluralize;
|
||||
import static git4idea.GitVcs.IMPORTANT_ERROR_NOTIFICATION;
|
||||
import static git4idea.GitVcs.MINOR_NOTIFICATION;
|
||||
import static git4idea.Notificator.createNotification;
|
||||
|
||||
/**
|
||||
* Searches for Git roots problems via {@link com.intellij.openapi.vcs.roots.VcsRootErrorsFinder} and notifies about them.
|
||||
* Searches for Vcs roots problems via {@link VcsRootErrorsFinder} and notifies about them.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class GitRootProblemNotifier {
|
||||
public class VcsRootProblemNotifier {
|
||||
|
||||
private final @NotNull Project myProject;
|
||||
private final @NotNull GitPlatformFacade myPlatformFacade;
|
||||
private final @NotNull VcsConfiguration mySettings;
|
||||
|
||||
private @Nullable Notification myNotification;
|
||||
private final @NotNull Object NOTIFICATION_LOCK = new Object();
|
||||
|
||||
public static GitRootProblemNotifier getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, GitRootProblemNotifier.class);
|
||||
public static final NotificationGroup IMPORTANT_ERROR_NOTIFICATION = new NotificationGroup(
|
||||
"Vcs Important Messages", NotificationDisplayType.STICKY_BALLOON, true);
|
||||
public static final NotificationGroup MINOR_NOTIFICATION = new NotificationGroup(
|
||||
"Vcs Minor Notifications", NotificationDisplayType.BALLOON, true);
|
||||
|
||||
public static VcsRootProblemNotifier getInstance(@NotNull Project project) {
|
||||
return new VcsRootProblemNotifier(project);
|
||||
}
|
||||
|
||||
// registered as a project service
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private GitRootProblemNotifier(@NotNull Project project, @NotNull GitPlatformFacade platformFacade) {
|
||||
private VcsRootProblemNotifier(@NotNull Project project) {
|
||||
myProject = project;
|
||||
myPlatformFacade = platformFacade;
|
||||
mySettings = VcsConfiguration.getInstance(myProject);
|
||||
}
|
||||
|
||||
@@ -85,8 +77,8 @@ public class GitRootProblemNotifier {
|
||||
return;
|
||||
}
|
||||
|
||||
Collection<String> unregisteredRoots = getUnregisteredRoots(errors);
|
||||
Collection<String> invalidRoots = getInvalidRoots(errors);
|
||||
Collection<VcsRootError> unregisteredRoots = getUnregisteredRoots(errors);
|
||||
Collection<VcsRootError> invalidRoots = getInvalidRoots(errors);
|
||||
|
||||
String title = makeTitle(unregisteredRoots, invalidRoots);
|
||||
String description = makeDescription(unregisteredRoots, invalidRoots);
|
||||
@@ -95,9 +87,9 @@ public class GitRootProblemNotifier {
|
||||
expireNotification();
|
||||
NotificationGroup notificationGroup = invalidRoots.isEmpty() ? MINOR_NOTIFICATION : IMPORTANT_ERROR_NOTIFICATION;
|
||||
NotificationType notificationType = invalidRoots.isEmpty() ? INFORMATION : ERROR;
|
||||
myNotification = createNotification(notificationGroup, title, description, notificationType,
|
||||
new MyNotificationListener(myProject, mySettings));
|
||||
myPlatformFacade.getNotificator(myProject).notify(myNotification);
|
||||
myNotification = notificationGroup.createNotification(title, description, notificationType,
|
||||
new MyNotificationListener(myProject, mySettings));
|
||||
myNotification.notify(myProject);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,25 +113,29 @@ public class GitRootProblemNotifier {
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringConcatenationInsideStringBufferAppend")
|
||||
private static String makeDescription(@NotNull Collection<String> unregisteredRoots, @NotNull Collection<String> invalidRoots) {
|
||||
Function<String, String> rootToDisplayableString = new Function<String, String>() {
|
||||
@NotNull
|
||||
private static String makeDescription(@NotNull Collection<VcsRootError> unregisteredRoots,
|
||||
@NotNull Collection<VcsRootError> invalidRoots) {
|
||||
Function<VcsRootError, String> rootToDisplayableString = new Function<VcsRootError, String>() {
|
||||
@Override
|
||||
public String fun(String path) {
|
||||
if (path.equals(VcsDirectoryMapping.PROJECT_CONSTANT)) {
|
||||
return StringUtil.escapeXml(path);
|
||||
public String fun(VcsRootError rootError) {
|
||||
if (rootError.getMapping().equals(VcsDirectoryMapping.PROJECT_CONSTANT)) {
|
||||
return StringUtil.escapeXml(rootError.getMapping());
|
||||
}
|
||||
return FileUtil.toSystemDependentName(path);
|
||||
return FileUtil.toSystemDependentName(rootError.getMapping());
|
||||
}
|
||||
};
|
||||
|
||||
StringBuilder description = new StringBuilder();
|
||||
if (!invalidRoots.isEmpty()) {
|
||||
if (invalidRoots.size() == 1) {
|
||||
description.append("The directory " + rootToDisplayableString.fun(invalidRoots.iterator().next()) + " is registered as a Git root, " +
|
||||
"but no Git repositories were found there.");
|
||||
VcsRootError rootError = invalidRoots.iterator().next();
|
||||
description
|
||||
.append("The directory " + rootToDisplayableString.fun(rootError) + " is registered as a " + rootError.getVcsKey() + " root, " +
|
||||
"but no " + rootError.getVcsKey() + " repositories were found there.");
|
||||
}
|
||||
else {
|
||||
description.append("The following directories are registered as Git roots, but they are not: <br/>" +
|
||||
description.append("The following directories are registered as Vcs roots, but they are not: <br/>" +
|
||||
StringUtil.join(invalidRoots, rootToDisplayableString, ", "));
|
||||
}
|
||||
description.append("<br/>");
|
||||
@@ -147,11 +143,13 @@ public class GitRootProblemNotifier {
|
||||
|
||||
if (!unregisteredRoots.isEmpty()) {
|
||||
if (unregisteredRoots.size() == 1) {
|
||||
description.append("The directory " + rootToDisplayableString.fun(unregisteredRoots.iterator().next()) + " is under Git, " +
|
||||
"but is not registered in the Settings.");
|
||||
VcsRootError unregisteredRoot = unregisteredRoots.iterator().next();
|
||||
description
|
||||
.append("The directory " + rootToDisplayableString.fun(unregisteredRoot) + " is under " + unregisteredRoot.getVcsKey() + ", " +
|
||||
"but is not registered in the Settings.");
|
||||
}
|
||||
else {
|
||||
description.append("The following directories are roots of Git repositories, but they are not registered in the Settings: <br/>" +
|
||||
description.append("The following directories are roots of Vcs repositories, but they are not registered in the Settings: <br/>" +
|
||||
StringUtil.join(unregisteredRoots, rootToDisplayableString, ", "));
|
||||
}
|
||||
description.append("<br/>");
|
||||
@@ -163,36 +161,36 @@ public class GitRootProblemNotifier {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String makeTitle(@NotNull Collection<String> unregisteredRoots, @NotNull Collection<String> invalidRoots) {
|
||||
private static String makeTitle(@NotNull Collection<VcsRootError> unregisteredRoots, @NotNull Collection<VcsRootError> invalidRoots) {
|
||||
String title;
|
||||
if (unregisteredRoots.isEmpty()) {
|
||||
title = "Invalid Git root " + pluralize("mapping", invalidRoots.size());
|
||||
title = "Invalid Vcs root " + pluralize("mapping", invalidRoots.size());
|
||||
}
|
||||
else if (invalidRoots.isEmpty()) {
|
||||
title = "Unregistered Git " + pluralize("root", unregisteredRoots.size()) + " detected";
|
||||
title = "Unregistered Vcs " + pluralize("root", unregisteredRoots.size()) + " detected";
|
||||
}
|
||||
else {
|
||||
title = "Git root configuration problems";
|
||||
title = "Vcs root configuration problems";
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<String> getUnregisteredRoots(@NotNull Collection<VcsRootError> errors) {
|
||||
private static Collection<VcsRootError> getUnregisteredRoots(@NotNull Collection<VcsRootError> errors) {
|
||||
return filterErrorsByType(errors, VcsRootError.Type.UNREGISTERED_ROOT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<String> getInvalidRoots(@NotNull Collection<VcsRootError> errors) {
|
||||
private static Collection<VcsRootError> getInvalidRoots(@NotNull Collection<VcsRootError> errors) {
|
||||
return filterErrorsByType(errors, VcsRootError.Type.EXTRA_MAPPING);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<String> filterErrorsByType(@NotNull Collection<VcsRootError> errors, @NotNull VcsRootError.Type type) {
|
||||
Collection<String> roots = new ArrayList<String>();
|
||||
private static Collection<VcsRootError> filterErrorsByType(@NotNull Collection<VcsRootError> errors, @NotNull VcsRootError.Type type) {
|
||||
Collection<VcsRootError> roots = new ArrayList<VcsRootError>();
|
||||
for (VcsRootError error : errors) {
|
||||
if (error.getType() == type) {
|
||||
roots.add(error.getMapping());
|
||||
roots.add(error);
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
@@ -213,7 +211,7 @@ public class GitRootProblemNotifier {
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if (event.getDescription().equals("configure") && !myProject.isDisposed()) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(myProject, ActionsBundle.message("group.VcsGroup.text"));
|
||||
Collection<VcsRootError> errorsAfterPossibleFix = GitRootProblemNotifier.getInstance(myProject).scan();
|
||||
Collection<VcsRootError> errorsAfterPossibleFix = getInstance(myProject).scan();
|
||||
if (errorsAfterPossibleFix.isEmpty() && !notification.isExpired()) {
|
||||
notification.expire();
|
||||
}
|
||||
+17
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -13,10 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.roots;
|
||||
package com.intellij.openapi.vcs.roots;
|
||||
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
@@ -24,23 +23,24 @@ import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsListener;
|
||||
import com.intellij.openapi.vcs.VcsRootChecker;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import git4idea.GitUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class GitRootScanner implements BulkFileListener, ModuleRootListener, VcsListener {
|
||||
public class VcsRootScanner implements BulkFileListener, ModuleRootListener, VcsListener {
|
||||
|
||||
@NotNull private final GitRootProblemNotifier myRootProblemNotifier;
|
||||
@NotNull private final VcsRootProblemNotifier myRootProblemNotifier;
|
||||
@NotNull private final VcsRootChecker[] myCheckers;
|
||||
|
||||
private volatile boolean myProjectIsInitialized;
|
||||
private volatile boolean myMappingsAreReady;
|
||||
@@ -48,12 +48,13 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Vcs
|
||||
@NotNull private final Alarm myAlarm;
|
||||
private static final long WAIT_BEFORE_SCAN = TimeUnit.SECONDS.toMillis(1);
|
||||
|
||||
public static void start(@NotNull Project project) {
|
||||
new GitRootScanner(project);
|
||||
public static void start(@NotNull Project project, @NotNull VcsRootChecker[] checkers) {
|
||||
new VcsRootScanner(project, checkers);
|
||||
}
|
||||
|
||||
private GitRootScanner(@NotNull Project project) {
|
||||
myRootProblemNotifier = GitRootProblemNotifier.getInstance(project);
|
||||
private VcsRootScanner(@NotNull Project project, @NotNull VcsRootChecker[] checkers) {
|
||||
myRootProblemNotifier = VcsRootProblemNotifier.getInstance(project);
|
||||
myCheckers = checkers;
|
||||
|
||||
StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
|
||||
@Override
|
||||
@@ -79,8 +80,11 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Vcs
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
for (VFileEvent event : events) {
|
||||
String filePath = event.getPath();
|
||||
if (filePath != null && filePath.toLowerCase().endsWith(GitUtil.DOT_GIT)) {
|
||||
scanIfReady();
|
||||
for (VcsRootChecker checker : myCheckers) {
|
||||
if (checker.isVcsDir(filePath)) {
|
||||
scanIfReady();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,5 +127,4 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Vcs
|
||||
}
|
||||
}, WAIT_BEFORE_SCAN);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -109,6 +109,7 @@
|
||||
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
|
||||
<vcs name="Git" vcsClass="git4idea.GitVcs" displayName="Git" administrativeAreaName=".git"/>
|
||||
<checkoutProvider implementation="git4idea.checkout.GitCheckoutProvider"/>
|
||||
<vcsRootChecker implementation="git4idea.roots.GitRootChecker"/>
|
||||
<vcsPopupProvider implementation="git4idea.actions.GitQuickListContentProvider"/>
|
||||
<vcsCheckinHandlerFactory implementation="git4idea.checkin.GitCheckinHandlerFactory"/>
|
||||
<checkinHandlerFactory implementation="git4idea.checkin.UnresolvedMergeCheckFactory"/>
|
||||
@@ -160,8 +161,6 @@
|
||||
serviceImplementation="git4idea.Notificator"/>
|
||||
<projectService serviceInterface="git4idea.history.wholeTree.GitLogSettings"
|
||||
serviceImplementation="git4idea.history.wholeTree.GitLogSettings"/>
|
||||
<projectService serviceInterface="git4idea.roots.GitRootProblemNotifier"
|
||||
serviceImplementation="git4idea.roots.GitRootProblemNotifier"/>
|
||||
<projectService serviceInterface="git4idea.branch.GitBrancher"
|
||||
serviceImplementation="git4idea.branch.GitBrancherImpl"/>
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ 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.ui.VcsBalloonProblemNotifier;
|
||||
import com.intellij.openapi.vcs.update.UpdateEnvironment;
|
||||
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
|
||||
@@ -77,9 +79,6 @@ import git4idea.i18n.GitBundle;
|
||||
import git4idea.merge.GitMergeProvider;
|
||||
import git4idea.rollback.GitRollbackEnvironment;
|
||||
import git4idea.roots.GitIntegrationEnabler;
|
||||
import git4idea.roots.GitRootChecker;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetector;
|
||||
import git4idea.status.GitChangeProvider;
|
||||
import git4idea.ui.branch.GitBranchWidget;
|
||||
import git4idea.update.GitUpdateEnvironment;
|
||||
@@ -320,11 +319,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
return dir.isDirectory() && GitUtil.gitRootOrNull(dir) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VcsRootChecker getRootChecker() {
|
||||
return new GitRootChecker(myProject, myPlatformFacade);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start() throws VcsException {
|
||||
}
|
||||
|
||||
@@ -16,13 +16,11 @@
|
||||
package git4idea.repo;
|
||||
|
||||
import com.intellij.dvcs.repo.AbstractRepositoryManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.roots.GitRootScanner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -32,25 +30,15 @@ public class GitRepositoryManager extends AbstractRepositoryManager<GitRepositor
|
||||
|
||||
@NotNull private final GitPlatformFacade myPlatformFacade;
|
||||
|
||||
public GitRepositoryManager(@NotNull Project project,
|
||||
@NotNull GitPlatformFacade platformFacade,
|
||||
public GitRepositoryManager(@NotNull Project project, @NotNull GitPlatformFacade platformFacade,
|
||||
@NotNull ProjectLevelVcsManager vcsManager) {
|
||||
super(project, vcsManager, platformFacade.getVcs(project), GitUtil.DOT_GIT);
|
||||
myPlatformFacade = platformFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() {
|
||||
super.initComponent();
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
GitRootScanner.start(myProject);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected GitRepository createRepository(@NotNull VirtualFile root) {
|
||||
return GitRepositoryImpl.getFullInstance(root, myProject, myPlatformFacade, this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,11 +17,15 @@ package git4idea.roots;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
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.VirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.GitVcs;
|
||||
@@ -54,11 +58,18 @@ public class GitIntegrationEnabler {
|
||||
|
||||
public void enable(@NotNull VcsRootDetectInfo detectInfo) {
|
||||
Notificator notificator = myPlatformFacade.getNotificator(myProject);
|
||||
Collection<VirtualFile> roots = detectInfo.getRoots();
|
||||
Collection<VcsRoot> gitRoots = ContainerUtil.filter(detectInfo.getRoots(), new Condition<VcsRoot>() {
|
||||
@Override
|
||||
public boolean value(VcsRoot root) {
|
||||
AbstractVcs gitVcs = root.getVcs();
|
||||
return gitVcs != null && gitVcs.getKeyInstanceMethod().equals(GitVcs.getKey());
|
||||
}
|
||||
});
|
||||
Collection<VirtualFile> roots = VcsRootErrorsFinder.vcsRootsToVirtualFiles(gitRoots);
|
||||
VirtualFile projectDir = myProject.getBaseDir();
|
||||
assert projectDir != null : "Base dir is unexpectedly null for project: " + myProject;
|
||||
|
||||
if (detectInfo.empty()) {
|
||||
if (gitRoots.isEmpty()) {
|
||||
boolean succeeded = gitInitOrNotifyError(notificator, projectDir);
|
||||
if (succeeded) {
|
||||
addVcsRoots(Collections.singleton(projectDir));
|
||||
@@ -66,7 +77,7 @@ public class GitIntegrationEnabler {
|
||||
}
|
||||
else {
|
||||
assert !roots.isEmpty();
|
||||
if (roots.size() > 1 || detectInfo.projectIsBelowGit()) {
|
||||
if (roots.size() > 1 || detectInfo.projectIsBelowVcs()) {
|
||||
notifyAddedRoots(notificator, roots);
|
||||
}
|
||||
addVcsRoots(roots);
|
||||
@@ -95,9 +106,11 @@ public class GitIntegrationEnabler {
|
||||
|
||||
private void refreshGitDir(final VirtualFile projectDir) {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override public void run() {
|
||||
@Override
|
||||
public void run() {
|
||||
myPlatformFacade.runReadAction(new Runnable() {
|
||||
@Override public void run() {
|
||||
@Override
|
||||
public void run() {
|
||||
myPlatformFacade.getLocalFileSystem().refreshAndFindFileByPath(projectDir.getPath() + "/.git");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -15,62 +15,33 @@
|
||||
*/
|
||||
package git4idea.roots;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsDirectoryMapping;
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vcs.VcsRootChecker;
|
||||
import com.intellij.openapi.vcs.VcsRootError;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootErrorsFinder;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.GitVcs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitRootChecker implements VcsRootChecker {
|
||||
public class GitRootChecker extends VcsRootChecker {
|
||||
|
||||
@NotNull private final Collection<VcsRootError> myErrors;
|
||||
private final boolean myProjectMappingIsInvalid;
|
||||
|
||||
public GitRootChecker(@NotNull Project project, @NotNull GitPlatformFacade platformFacade) {
|
||||
myErrors = new VcsRootErrorsFinder(project).find();
|
||||
myProjectMappingIsInvalid = isProjectMappingInvalid();
|
||||
}
|
||||
|
||||
private boolean isProjectMappingInvalid() {
|
||||
for (VcsRootError error : myErrors) {
|
||||
if (error.getType() == VcsRootError.Type.EXTRA_MAPPING && error.getMapping().equals(VcsDirectoryMapping.PROJECT_CONSTANT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@Override
|
||||
public boolean isRoot(@NotNull String path) {
|
||||
return new File(path, GitUtil.DOT_GIT).exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<String> getUnregisteredRoots() {
|
||||
Collection<String> roots = new ArrayList<String>();
|
||||
for (VcsRootError error : myErrors) {
|
||||
if (error.getType() == VcsRootError.Type.UNREGISTERED_ROOT) {
|
||||
roots.add(error.getMapping());
|
||||
}
|
||||
}
|
||||
return roots;
|
||||
public VcsKey getSupportedVcs() {
|
||||
return GitVcs.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvalidMapping(@NotNull VcsDirectoryMapping mapping) {
|
||||
// this information is available in myErrors,
|
||||
// but the method may be called in VcsDirectoryConfigurationPanel after adding a mapping (to highlight errors right away)
|
||||
// in which case ProjectLevelVcsManager#getAllVcsRoots() is not aware of new roots yet,
|
||||
// while VcsRootErrorsFinder relies on the set of roots returned from ProjectLevelVcsManager.
|
||||
if (mapping.isDefaultMapping()) {
|
||||
return myProjectMappingIsInvalid;
|
||||
}
|
||||
return !new File(mapping.getDirectory(), GitUtil.DOT_GIT).exists();
|
||||
public boolean isVcsDir(@Nullable String path) {
|
||||
return path != null && path.toLowerCase().endsWith(GitUtil.DOT_GIT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package git4idea.roots;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsDirectoryMapping;
|
||||
import com.intellij.openapi.vcs.VcsRoot;
|
||||
import com.intellij.openapi.vcs.VcsRootFinder;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetector;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import git4idea.GitPlatformFacade;
|
||||
import git4idea.GitVcs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -20,25 +20,26 @@ import java.util.Collections;
|
||||
*/
|
||||
public class GitRootFinder implements VcsRootFinder {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final GitPlatformFacade myPlatformFacade;
|
||||
@NotNull private final Project myProject;
|
||||
|
||||
public GitRootFinder(@NotNull Project project, @NotNull GitPlatformFacade platformFacade) {
|
||||
public GitRootFinder(@NotNull Project project) {
|
||||
myProject = project;
|
||||
myPlatformFacade = platformFacade;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<VcsDirectoryMapping> findRoots(@NotNull VirtualFile root) {
|
||||
VcsRootDetectInfo info = new VcsRootDetector(myProject).detect(root);
|
||||
Collection<VirtualFile> roots = info.getRoots();
|
||||
Collection<VcsRoot> roots = info.getRoots();
|
||||
if (roots.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Collection<VcsDirectoryMapping> result = ContainerUtilRt.newArrayList();
|
||||
for (VirtualFile file : roots) {
|
||||
result.add(new VcsDirectoryMapping(file.getPath(), GitVcs.getKey().getName()));
|
||||
for (VcsRoot vcsRoot : roots) {
|
||||
VirtualFile vFile = vcsRoot.getPath();
|
||||
if (vFile != null) {
|
||||
result.add(new VcsDirectoryMapping(vFile.getPath(), GitVcs.getKey().getName()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 git4idea.roots
|
||||
import com.intellij.dvcs.test.MockProject
|
||||
import com.intellij.dvcs.test.MockProjectRootManager
|
||||
import com.intellij.dvcs.test.MockVirtualFile
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import git4idea.test.GitLightTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
/**
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
class AbstractGitRootTest extends GitLightTest {
|
||||
|
||||
static File baseDir
|
||||
|
||||
@Before
|
||||
void setUp() {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@After
|
||||
void tearDown() {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the necessary temporary directories in the filesystem with empty ".git" directories for given roots.
|
||||
* And creates an instance of the project.
|
||||
* @param gitRoots path to actual .git roots, relative to the project dir.
|
||||
*/
|
||||
Project initProject(Collection<String> gitRoots, Collection<String> projectStructure, Collection<String> contentRoots = []) {
|
||||
String projectDir = createDirs(gitRoots)
|
||||
Project project = new MockProject(projectDir)
|
||||
createProjectStructure(project, projectStructure);
|
||||
createProjectStructure(project, contentRoots);
|
||||
|
||||
contentRoots.each {
|
||||
((MockProjectRootManager)myPlatformFacade.getProjectRootManager(project)).myContentRoots << MockVirtualFile.fromPath(it, project)
|
||||
}
|
||||
|
||||
project
|
||||
}
|
||||
|
||||
static void createProjectStructure(Project project, Collection<String> paths) {
|
||||
paths.each { String path ->
|
||||
File file = new File(project.baseDir.path + "/" + path)
|
||||
file.mkdir()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return path to the project
|
||||
*/
|
||||
private static String createDirs(Collection<String> gitRoots) {
|
||||
if (gitRoots.empty) {
|
||||
return baseDir = FileUtil.createTempDirectory("grdt", null);
|
||||
}
|
||||
|
||||
baseDir = createBaseTempDir()
|
||||
int maxDepth = findMaxDepthAboveProject(gitRoots)
|
||||
File projectDir = createChild(baseDir, maxDepth)
|
||||
gitRoots.each { String path ->
|
||||
File file = new File(projectDir.path + "/" + path)
|
||||
file.mkdirs()
|
||||
file.deleteOnExit()
|
||||
|
||||
File gitDir = new File(file, ".git")
|
||||
gitDir.mkdir()
|
||||
gitDir.deleteOnExit()
|
||||
}
|
||||
return projectDir.path
|
||||
}
|
||||
|
||||
private static File createBaseTempDir() {
|
||||
FileUtil.createTempDirectory("pref", null)
|
||||
}
|
||||
|
||||
private static File createChild(File base, int depth) {
|
||||
File dir = base
|
||||
depth.times { dir = FileUtil.createTempDirectory(dir, "grdt", null)}
|
||||
dir
|
||||
}
|
||||
|
||||
// Assuming that there are no ".." inside the path - only in the beginning
|
||||
static int findMaxDepthAboveProject(Collection<String> paths) {
|
||||
def len = { String path -> path.split("/").count("..") }
|
||||
len(paths.max(len))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import com.intellij.notification.Notification
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetectInfo
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import git4idea.test.GitLightTest
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import git4idea.test.TestNotificator
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@@ -28,18 +28,20 @@ import org.junit.Test
|
||||
|
||||
import static git4idea.test.GitGTestUtil.toAbsolute
|
||||
import static junit.framework.Assert.*
|
||||
import static org.junit.Assume.assumeTrue
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
class GitIntegrationEnablerTest extends GitLightTest {
|
||||
class GitIntegrationEnablerTest extends UsefulTestCase {
|
||||
|
||||
public static final String TEST_NOTIFICATION_GROUP = "Test"
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
assumeTrue(false);
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@@ -157,5 +159,4 @@ class GitIntegrationEnablerTest extends GitLightTest {
|
||||
void assertNotificationShown(String title, String message, NotificationType type) {
|
||||
assertNotificationShown(new Notification(TEST_NOTIFICATION_GROUP, title, message, type))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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 git4idea.roots;
|
||||
|
||||
import com.intellij.ide.highlighter.ModuleFileType;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.module.EmptyModuleType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.impl.ModuleRootManagerImpl;
|
||||
import com.intellij.openapi.roots.impl.RootModelImpl;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
|
||||
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static com.intellij.dvcs.test.Executor.*;
|
||||
|
||||
/**
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public abstract class GitPlatformTest extends UsefulTestCase {
|
||||
|
||||
protected Project myProject;
|
||||
protected VirtualFile myProjectRoot;
|
||||
protected VirtualFile myRepository;
|
||||
public static final String myRepositoryFolderName = "repository";
|
||||
private RootModelImpl myRootModel;
|
||||
protected static final Collection<File> myFilesToDelete = new HashSet<File>();
|
||||
|
||||
protected IdeaProjectTestFixture myProjectFixture;
|
||||
|
||||
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
|
||||
protected GitPlatformTest() {
|
||||
PlatformTestCase.initPlatformLangPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getTestName(true)).getFixture();
|
||||
myProjectFixture.setUp();
|
||||
|
||||
myProject = myProjectFixture.getProject();
|
||||
myProjectRoot = myProject.getBaseDir();
|
||||
cd(myProjectRoot);
|
||||
Module module = doCreateRealModuleIn("foo", myProject, EmptyModuleType
|
||||
.getInstance());
|
||||
myRootModel = ((ModuleRootManagerImpl)ModuleRootManager.getInstance(module)).getRootModel();
|
||||
mkdir(myRepositoryFolderName);
|
||||
myRepository = myProjectRoot.findChild(myRepositoryFolderName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
for (File file : myFilesToDelete) {
|
||||
delete(file);
|
||||
}
|
||||
myProjectFixture.tearDown();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
private static void delete(File file) {
|
||||
boolean b = FileUtil.delete(file);
|
||||
if (!b && file.exists()) {
|
||||
fail("Can't delete " + file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the necessary temporary directories in the filesystem with empty ".git" directories for given roots.
|
||||
* And creates an instance of the project.
|
||||
*
|
||||
* @param gitRoots path to actual .git roots, relative to the project dir.
|
||||
*/
|
||||
public void initProject(@NotNull Collection<String> gitRoots,
|
||||
@NotNull Collection<String> projectStructure,
|
||||
@NotNull Collection<String> contentRoots)
|
||||
throws IOException {
|
||||
createDirs(gitRoots);
|
||||
createProjectStructure(myProject, projectStructure);
|
||||
createProjectStructure(myProject, contentRoots);
|
||||
if (!contentRoots.isEmpty()) {
|
||||
for (String root : contentRoots) {
|
||||
VirtualFile f = myProjectRoot.findFileByRelativePath(root);
|
||||
if (f != null) {
|
||||
myRootModel.addContentEntry(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createProjectStructure(@NotNull Project project, @NotNull Collection<String> paths) {
|
||||
for (String path : paths) {
|
||||
cd(project.getBaseDir().getPath());
|
||||
File f = new File(project.getBaseDir().getPath(), path);
|
||||
f.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Module doCreateRealModuleIn(@NotNull String moduleName,
|
||||
@NotNull final Project project,
|
||||
@NotNull final ModuleType moduleType) {
|
||||
final VirtualFile baseDir = project.getBaseDir();
|
||||
assertNotNull(baseDir);
|
||||
final File moduleFile = new File(baseDir.getPath().replace('/', File.separatorChar),
|
||||
moduleName + ModuleFileType.DOT_DEFAULT_EXTENSION);
|
||||
FileUtil.createIfDoesntExist(moduleFile);
|
||||
myFilesToDelete.add(moduleFile);
|
||||
return new WriteAction<Module>() {
|
||||
@Override
|
||||
protected void run(Result<Module> result) throws Throwable {
|
||||
final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(moduleFile);
|
||||
assert virtualFile != null;
|
||||
Module module = ModuleManager.getInstance(project).newModule(virtualFile.getPath(), moduleType.getId());
|
||||
module.getModuleFile();
|
||||
result.setResult(module);
|
||||
}
|
||||
}.execute().getResultObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return path to the project
|
||||
*/
|
||||
private void createDirs(@NotNull Collection<String> gitRoots) throws IOException {
|
||||
File baseDir;
|
||||
if (gitRoots.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
baseDir = VfsUtilCore.virtualToIoFile(myProject.getBaseDir());
|
||||
int maxDepth = findMaxDepthAboveProject(gitRoots);
|
||||
File projectDir = createChild(baseDir, maxDepth - 1);
|
||||
cd(projectDir.getPath());
|
||||
for (String path : gitRoots) {
|
||||
File file = new File(projectDir, path);
|
||||
file.mkdirs();
|
||||
File gitDir = new File(file, ".git");
|
||||
gitDir.mkdirs();
|
||||
myFilesToDelete.add(gitDir);
|
||||
gitDir.deleteOnExit();
|
||||
cd(gitDir.getPath());
|
||||
touch("HEAD", "ref: refs/heads/master");
|
||||
File head = new File(gitDir, "HEAD");
|
||||
myFilesToDelete.add(head);
|
||||
touch("config", "");
|
||||
File config = new File(gitDir, "config");
|
||||
myFilesToDelete.add(config);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static File createChild(@NotNull File base, int depth) throws IOException {
|
||||
File dir = base;
|
||||
if (depth < 0) {
|
||||
return dir;
|
||||
}
|
||||
for (int i = 0; i < depth; ++i) {
|
||||
dir = FileUtil.createTempDirectory(dir, "grdt", null);
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
// Assuming that there are no ".." inside the path - only in the beginning
|
||||
static int findMaxDepthAboveProject(@NotNull Collection<String> paths) {
|
||||
int max = 0;
|
||||
for (String path : paths) {
|
||||
String[] splits = path.split("/");
|
||||
int count = 0;
|
||||
for (String split : splits) {
|
||||
if (split.equals("..")) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > max) {
|
||||
max = count;
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 git4idea.roots
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetectInfo
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetector
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import git4idea.test.GitGTestUtil
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
import static org.junit.Assert.assertEquals
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
class GitRootDetectorTest extends AbstractGitRootTest {
|
||||
|
||||
Project myProject
|
||||
|
||||
@Before
|
||||
void setUp() {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@After
|
||||
void tearDown() {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Test
|
||||
void "no roots in project"() {
|
||||
doTest gits: [],
|
||||
expected: [],
|
||||
full: false,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
void "project under single Git"() {
|
||||
doTest "."
|
||||
}
|
||||
|
||||
@Test
|
||||
void "project with Git under it"() {
|
||||
doTest project: [".idea", "bin", "src", "community"],
|
||||
gits: ["community"],
|
||||
expected: ["community"],
|
||||
full: false,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
public void "project with all subdirs under Git should still be not fully controlled"() {
|
||||
doTest gits: [".idea", "src", "community"],
|
||||
expected: [".idea", "src", "community"],
|
||||
full: false,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
void "project under Git above it"() {
|
||||
doTest gits: [".."],
|
||||
expected: [".."],
|
||||
full: true,
|
||||
below: true
|
||||
}
|
||||
|
||||
@Test
|
||||
void "IDEA project"() {
|
||||
doTest ".", "./community", "./contrib"
|
||||
}
|
||||
|
||||
@Test
|
||||
void "one above and one under"() {
|
||||
doTest gits: ["..", "./community"],
|
||||
expected: ["..", "./community"],
|
||||
full: true,
|
||||
below: true
|
||||
}
|
||||
|
||||
@Test
|
||||
void "one above and one for project should show only project root"() {
|
||||
doTest gits: ["..", "."],
|
||||
expected: ["."],
|
||||
full: true,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
void "one above and several under project"() {
|
||||
doTest gits: ["..", "./community", "./contrib"],
|
||||
expected: ["..", "./community", "./contrib"],
|
||||
full: true,
|
||||
below: true
|
||||
}
|
||||
|
||||
@Test
|
||||
void "multiple above should be detected as one above"() {
|
||||
doTest gits: ["..", "../.."],
|
||||
expected: [".."],
|
||||
full: true,
|
||||
below: true
|
||||
}
|
||||
|
||||
@Test
|
||||
void "unrelated root should not be detected"() {
|
||||
doTest gits: ["../neighbour"],
|
||||
expected: [],
|
||||
full: false,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
void "linked source root alone should be detected"() {
|
||||
doTest content_roots: ["../linked_root"],
|
||||
gits: ["../linked_root"],
|
||||
expected: ["../linked_root"],
|
||||
full: false,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
void "linked source root and project root should be detected"() {
|
||||
doTest content_roots: ["../linked_root"],
|
||||
gits: [".", "../linked_root"],
|
||||
expected: [".", "../linked_root"],
|
||||
full: true,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
void "linked source below Git"() {
|
||||
doTest content_roots: ["../linked_root/src"],
|
||||
gits: [".", "../linked_root"],
|
||||
expected: [".", "../linked_root"],
|
||||
full: true,
|
||||
below: false
|
||||
}
|
||||
|
||||
@Test
|
||||
// This is a test of performance optimization via limitation: don't scan deep though the whole VFS, i.e. don't detect deep roots
|
||||
void "don't scan deeper than 2 levels below a content root"() {
|
||||
doTest content_roots: ["content_root"],
|
||||
gits: ["community", "content_root/lev1/lev2", "content_root2/lev1/lev2/lev3"],
|
||||
expected: ["community", "content_root/lev1/lev2"],
|
||||
full: false,
|
||||
below: false
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform test. Map contains actual Git repositories to be created on disk,
|
||||
* and Git repositories expected to be detected by the VcsRootDetector.
|
||||
* @param map
|
||||
*/
|
||||
private void doTest(Map map) {
|
||||
myProject = initProject(map.gits, map.project, map.content_roots)
|
||||
testInfo empty: map.expected.empty,
|
||||
full : map.full,
|
||||
roots: map.expected,
|
||||
below: map.below
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand, when all Git roots are expected to be detected, and project is fully under Git.
|
||||
* @param roots paths relative to the project dir. "..", ".", "./community" are accepted.
|
||||
*/
|
||||
private void doTest(String... roots = []) {
|
||||
doTest gits: roots.toList(),
|
||||
expected: roots.toList(),
|
||||
full: true,
|
||||
below: false
|
||||
}
|
||||
|
||||
void testInfo(Map expected) {
|
||||
assertInfo(expected, detect())
|
||||
}
|
||||
|
||||
void assertInfo(Map expected, VcsRootDetectInfo actual) {
|
||||
assertEquals(expected.empty, actual.empty())
|
||||
if (expected.full ^ actual.totallyUnderGit()) {
|
||||
fail("The project is unexpectedly ${actual.totallyUnderGit() ? "" : "not "}under Git${roots(actual.roots)}")
|
||||
}
|
||||
if (expected.below ^ actual.projectIsBelowGit()) {
|
||||
fail("The project is unexpectedly ${actual.projectIsBelowGit() ? "below" : "not below"} Git${roots(actual.roots)}")
|
||||
}
|
||||
assertRoots(expected.roots, actual.roots)
|
||||
}
|
||||
|
||||
static String roots(Collection roots) {
|
||||
"\nRoots:${roots.collect {"\n * $it"}}\n"
|
||||
}
|
||||
|
||||
void assertRoots(Collection<String> expectedRelativePaths, Collection<VirtualFile> actual) {
|
||||
assertEquals(GitGTestUtil.toAbsolute(expectedRelativePaths, myProject).toSet(), getPaths(actual).toSet())
|
||||
}
|
||||
|
||||
static Collection<String> getPaths(Collection<VirtualFile> files) {
|
||||
files.collect { it.path }
|
||||
}
|
||||
|
||||
private VcsRootDetectInfo detect() {
|
||||
new VcsRootDetector(myProject).detect()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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 git4idea.roots;
|
||||
|
||||
import com.intellij.dvcs.test.Executor;
|
||||
import com.intellij.dvcs.test.TestRepositoryUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.VcsRoot;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetectInfo;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootDetector;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.dvcs.test.Executor.cd;
|
||||
|
||||
|
||||
/**
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class GitRootDetectorTest extends GitPlatformTest {
|
||||
|
||||
public void testNoRootsInProject() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Collections.<String>emptyList());
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, null, Collections.<String>emptyList(), false, false);
|
||||
}
|
||||
|
||||
public void testProjectUnderSingleGit() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("."));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, myProjectRoot, Arrays.asList("."), true, false);
|
||||
}
|
||||
|
||||
public void testProjectWithGitUnderIt() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("community"));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
cd(myProjectRoot);
|
||||
Executor.mkdir("src");
|
||||
Executor.mkdir(".idea");
|
||||
doTest(map, myProjectRoot, Arrays.asList("community"), false, false);
|
||||
}
|
||||
|
||||
public void testProjectWithAllSubdirsUnderGitShouldStillBeNotFullyControlled() throws IOException {
|
||||
String[] dirNames = {".idea", "src", "community"};
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(dirNames));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, myProjectRoot, Arrays.asList(dirNames), false, false);
|
||||
}
|
||||
|
||||
|
||||
public void testProjectUnderVcsAboveIt() throws IOException {
|
||||
String subdir = "insideRepo";
|
||||
cd(myRepository);
|
||||
Executor.mkdir(subdir);
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(myRepository.getName()));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
VirtualFile vfile = myRepository.findChild(subdir);
|
||||
doTest(map, vfile, Arrays.asList(myRepository.getName()),
|
||||
true, true);
|
||||
}
|
||||
|
||||
|
||||
public void testIDEAProject() throws IOException {
|
||||
String[] names = {"community", "contrib", "."};
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(names));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, myProjectRoot, Arrays.asList(names), true, false);
|
||||
}
|
||||
|
||||
|
||||
public void testOneAboveAndOneUnder() throws IOException {
|
||||
String[] names = {myRepository.getName() + "/community", "."};
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(names));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, myRepository, Arrays.asList(names), true, true);
|
||||
}
|
||||
|
||||
public void testOneAboveAndOneForProjectShouldShowOnlyProjectRoot() throws IOException {
|
||||
String[] names = {myRepository.getName(), "."};
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(names));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, myRepository, Arrays.asList(myRepository.getName()), true, false);
|
||||
}
|
||||
|
||||
public void testOneAboveAndSeveralUnderProject() throws IOException {
|
||||
String[] names = {".", myRepository.getName() + "/community", myRepository.getName() + "/contrib"};
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(names));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, myRepository, Arrays.asList(names), true, true);
|
||||
}
|
||||
|
||||
|
||||
public void testMultipleAboveShouldBeDetectedAsOneAbove() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", myRepository.getName()));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
String subdir = "insideRepo";
|
||||
cd(myRepository);
|
||||
Executor.mkdir(subdir);
|
||||
VirtualFile vfile = myRepository.findChild(subdir);
|
||||
doTest(map, vfile, Arrays.asList(myRepository.getName()), true, true);
|
||||
}
|
||||
|
||||
public void testUnrelatedRootShouldNotBeDetected() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("another"));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, myRepository, Collections.<String>emptyList(), false, false);
|
||||
}
|
||||
|
||||
|
||||
public void testLinkedSourceRootAloneShouldBeDetected() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("linked_root"));
|
||||
map.put("content_roots", Arrays.asList("linked_root"));
|
||||
doTest(map, myRepository, Arrays.asList("linked_root"), false, false);
|
||||
}
|
||||
|
||||
public void testLinkedSourceRootAndProjectRootShouldBeDetected() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "linked_root"));
|
||||
map.put("content_roots", Arrays.asList("linked_root"));
|
||||
doTest(map, myProjectRoot, Arrays.asList(".", "linked_root"), true, false);
|
||||
}
|
||||
|
||||
public void testLinkedSourceBelowGit() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "linked_root"));
|
||||
map.put("content_roots", Arrays.asList("linked_root/src"));
|
||||
doTest(map, myProjectRoot, Arrays.asList(".", "linked_root"), true, false);
|
||||
}
|
||||
|
||||
// This is a test of performance optimization via limitation: don't scan deep though the whole VFS, i.e. don't detect deep roots
|
||||
public void testDontScanDeeperThan2LevelsBelowAContentRoot() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("community", "content_root/lev1/lev2", "content_root2/lev1/lev2/lev3"));
|
||||
map.put("content_roots", Arrays.asList("content_root"));
|
||||
doTest(map, myProjectRoot, Arrays.asList("community", "content_root/lev1/lev2"), false, false);
|
||||
}
|
||||
|
||||
void assertRoots(Collection<String> expectedRelativePaths, Collection<String> actual) {
|
||||
TestRepositoryUtil.assertEqualCollections(actual, toAbsolute(expectedRelativePaths, myProject));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<String> toAbsolute(Collection<String> relPaths, final Project project) {
|
||||
return ContainerUtil.map(relPaths, new Function<String, String>() {
|
||||
@Override
|
||||
public String fun(String s) {
|
||||
try {
|
||||
return FileUtil.toSystemIndependentName(new File(project.getBaseDir().getPath(), s).getCanonicalPath());
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail();
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static Collection<String> getPaths(@NotNull Collection<VcsRoot> files) {
|
||||
return ContainerUtil.map(files, new Function<VcsRoot, String>() {
|
||||
@Override
|
||||
public String fun(VcsRoot root) {
|
||||
VirtualFile file = root.getPath();
|
||||
assert file != null;
|
||||
return FileUtil.toSystemIndependentName(file.getPath());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private VcsRootDetectInfo detect(@Nullable VirtualFile startDir) {
|
||||
return new VcsRootDetector(myProject).detect(startDir);
|
||||
}
|
||||
|
||||
public void doTest(@NotNull Map<String, Collection<String>> map,
|
||||
@Nullable VirtualFile startDir,
|
||||
@NotNull Collection<String> expectedPaths,
|
||||
boolean expectedFull,
|
||||
boolean expectedBelow)
|
||||
throws IOException {
|
||||
initProject(map.get("git"), Collections.<String>emptyList(), map.get("content_roots"));
|
||||
|
||||
VcsRootDetectInfo info = detect(startDir);
|
||||
assertRoots(expectedPaths, getPaths(info.getRoots()));
|
||||
assertEquals(expectedFull, info.totallyUnderVcs());
|
||||
assertEquals(expectedBelow, info.projectIsBelowVcs());
|
||||
}
|
||||
}
|
||||
@@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 git4idea.roots
|
||||
|
||||
import com.intellij.openapi.vcs.VcsDirectoryMapping
|
||||
import com.intellij.openapi.vcs.VcsRootError
|
||||
import com.intellij.openapi.vcs.roots.VcsRootErrorsFinder
|
||||
import git4idea.test.GitMockVcsManager
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
import static git4idea.test.GitGTestUtil.toAbsolute
|
||||
import static junit.framework.Assert.assertEquals
|
||||
/**
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
class GitRootErrorsFinderTest extends AbstractGitRootTest {
|
||||
|
||||
static final String PROJECT = VcsDirectoryMapping.PROJECT_CONSTANT
|
||||
|
||||
GitMockVcsManager myVcsManager
|
||||
|
||||
@Before
|
||||
void setUp() {
|
||||
super.setUp()
|
||||
}
|
||||
|
||||
@After
|
||||
void tearDown() {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@Test
|
||||
void "No roots, then no errors"() {
|
||||
doTest git: [],
|
||||
roots: [],
|
||||
errors: []
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Same 1 root in both, then no errors"() {
|
||||
doTest git: ["."],
|
||||
roots: ["."],
|
||||
errors: []
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Same 2 roots in both, then no errors"() {
|
||||
doTest git: ["..", "community"],
|
||||
roots: ["..", "community"],
|
||||
errors: []
|
||||
}
|
||||
|
||||
@Test
|
||||
void "One git, no VCS roots, then error"() {
|
||||
doTest git: ["."],
|
||||
roots: [],
|
||||
errors: [unreg : ["."]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "One VCS root, no gits, then error"() {
|
||||
doTest git: [],
|
||||
roots: ["."],
|
||||
errors: [extra: ["."]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "One root, but different, then 2 errors"() {
|
||||
doTest git: ["."],
|
||||
roots: ["community"],
|
||||
errors: [unreg: ["."], extra: ["community"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Two roots, one matching, one different, then 2 errors"() {
|
||||
doTest git: [".", "community"],
|
||||
roots: [".", "contrib"],
|
||||
errors: [unreg: ["community"], extra: ["contrib"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Two roots in git, one matching in VCS, then error"() {
|
||||
doTest git: [".", "community"],
|
||||
roots: ["."],
|
||||
errors: [unreg: ["community"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Two roots, both not matching, then 4 errors"() {
|
||||
doTest git: ["..", "community"],
|
||||
roots: [".", "contrib"],
|
||||
errors: [unreg: ["..", "community"], extra: [".", "contrib"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Project root, no gits, then error about extra root"() {
|
||||
doTest content_roots: ["."],
|
||||
git: [],
|
||||
roots: [PROJECT],
|
||||
errors: [extra: [PROJECT]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Project root, full under git, then correct"() {
|
||||
doTest content_roots: ["."],
|
||||
git: ["."],
|
||||
roots: [PROJECT],
|
||||
errors: []
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Project root, git for a content root below project, then error"() {
|
||||
doTest content_roots: [".", "content_root"],
|
||||
git: ["content_root"],
|
||||
roots: [PROJECT],
|
||||
errors: [unreg: ["content_root"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Project root, git below project folder not in a content root, then unregistered root error"() {
|
||||
// this is to be fixed: auto-detection of Git repositories in subfolders for the <Project> mapping
|
||||
doTest content_roots: ["."],
|
||||
git: ["community"],
|
||||
roots: [PROJECT],
|
||||
errors: [unreg: ["community"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Project root, git for full project, content root, linked source, folder below project, then errors"() {
|
||||
doTest content_roots: [".", "content_root", "../linked_source_root"],
|
||||
git: [".", "content_root", "../linked_source_root", "folder"],
|
||||
roots: [PROJECT],
|
||||
errors: [unreg: ["content_root", "../linked_source_root", "folder"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Project root, root for folder, git for full project, content root, linked source, folder below project, then errors"() {
|
||||
doTest content_roots: [".", "content_root", "../linked_source_root"],
|
||||
git: [".", "content_root", "../linked_source_root", "folder"],
|
||||
roots: [PROJECT, "folder"],
|
||||
errors: [unreg: ["content_root", "../linked_source_root"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Project root, git like in IDEA project, then correct"() {
|
||||
doTest content_roots: [".", "community", "contrib"],
|
||||
git: [".", "community", "contrib"],
|
||||
roots: [PROJECT],
|
||||
errors: [unreg: ["community", "contrib"]]
|
||||
}
|
||||
|
||||
@Test
|
||||
void "Real Git root deeper than 3 levels should be detected"() {
|
||||
doTest content_roots: [".", "community", "contrib"],
|
||||
git: [".", "community", "contrib", "community/level1/level2/level3"],
|
||||
roots: [PROJECT, "community/level1/level2/level3"],
|
||||
errors: [unreg: ["community", "contrib"]]
|
||||
}
|
||||
|
||||
private void doTest(Map map) {
|
||||
myProject = initProject(map.git, [], map.content_roots)
|
||||
myVcsManager = (GitMockVcsManager) myPlatformFacade.getVcsManager(myProject)
|
||||
|
||||
addVcsRoots(map.roots)
|
||||
|
||||
Collection<VcsRootError> expected = new ArrayList<VcsRootError>();
|
||||
expected.addAll map.errors.unreg.collect { unreg(it) }
|
||||
expected.addAll map.errors.extra.collect { extra(it) }
|
||||
|
||||
Collection<VcsRootError> actual = new VcsRootErrorsFinder(myProject).find()
|
||||
assertEquals expected.toSet(), actual.toSet()
|
||||
}
|
||||
|
||||
void addVcsRoots(Collection<String> relativeRoots) {
|
||||
relativeRoots.each {
|
||||
if (it.equals(PROJECT)) {
|
||||
myVcsManager.setProjectRootMapping()
|
||||
}
|
||||
else {
|
||||
String root = toAbsolute(it, myProject)
|
||||
myVcsManager.addRoots(root)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VcsRootError unreg(String path) {
|
||||
return new VcsRootError(VcsRootError.Type.UNREGISTERED_ROOT, toAbsolute(path, myProject))
|
||||
}
|
||||
|
||||
VcsRootError extra(String path) {
|
||||
return new VcsRootError(VcsRootError.Type.EXTRA_MAPPING, path.equals(PROJECT) ? PROJECT : toAbsolute(path, myProject))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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 git4idea.roots;
|
||||
|
||||
import com.intellij.dvcs.test.TestRepositoryUtil;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vcs.VcsDirectoryMapping;
|
||||
import com.intellij.openapi.vcs.VcsRootError;
|
||||
import com.intellij.openapi.vcs.roots.VcsRootErrorsFinder;
|
||||
import git4idea.GitVcs;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import static git4idea.test.GitGTestUtil.toAbsolute;
|
||||
|
||||
/**
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class GitRootErrorsFinderTest extends GitPlatformTest {
|
||||
|
||||
static final String PROJECT = VcsDirectoryMapping.PROJECT_CONSTANT;
|
||||
@NotNull private ProjectLevelVcsManager myVcsManager;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myVcsManager = ProjectLevelVcsManager.getInstance(myProject);
|
||||
}
|
||||
|
||||
public void testNoRootsThenNoErrors() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Collections.<String>emptyList());
|
||||
map.put("roots", Collections.<String>emptyList());
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, Collections.<String, Collection<String>>emptyMap());
|
||||
}
|
||||
|
||||
public void testSameOneRootInBothThenNoErrors() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("."));
|
||||
map.put("roots", Arrays.asList("."));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, Collections.<String, Collection<String>>emptyMap());
|
||||
}
|
||||
|
||||
public void testSameTwoRootsInBothThenNoErrors() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "community"));
|
||||
map.put("roots", Arrays.asList(".", "community"));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, Collections.<String, Collection<String>>emptyMap());
|
||||
}
|
||||
|
||||
public void testOneGitNoVCSRootsThenError() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("."));
|
||||
map.put("roots", Collections.<String>emptyList());
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("."));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testOneVCSRootNoGitsThenError() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("roots", Arrays.asList("."));
|
||||
map.put("git", Collections.<String>emptyList());
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("extra", Arrays.asList("."));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testOneRootButDifferentThenTwoErrors() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("."));
|
||||
map.put("roots", Arrays.asList("community"));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("extra", Arrays.asList("community"));
|
||||
errorsMap.put("unreg", Arrays.asList("."));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testTwoRootsOneMatchingOneDifferentThenTwoErrors() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "community"));
|
||||
map.put("roots", Arrays.asList(".", "contrib"));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("extra", Arrays.asList("contrib"));
|
||||
errorsMap.put("unreg", Arrays.asList("community"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testTwoRootsInGitOneMatchingInVCSThenError() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "community"));
|
||||
map.put("roots", Arrays.asList("."));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("community"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testTwoRootsBothNotMatchingThenFourErrors() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "community"));
|
||||
map.put("roots", Arrays.asList("another", "contrib"));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("extra", Arrays.asList("contrib", "another"));
|
||||
errorsMap.put("unreg", Arrays.asList("community", "."));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testProjectRootNoGitsThenErrorAboutExtraRoot() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Collections.<String>emptyList());
|
||||
map.put("roots", Arrays.asList(PROJECT));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("extra", Arrays.asList(PROJECT));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testProjectRootFullUnderGitThenCorrect() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("."));
|
||||
map.put("roots", Arrays.asList(".", PROJECT));
|
||||
map.put("content_roots", Collections.<String>emptyList());
|
||||
doTest(map, Collections.<String, Collection<String>>emptyMap());
|
||||
}
|
||||
|
||||
public void testProjectRootGitForAContentRootBelowProjectThenError() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("content_root"));
|
||||
map.put("roots", Arrays.asList(PROJECT));
|
||||
map.put("content_roots", Arrays.asList("content_root"));
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("content_root"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testProjectRootGitBelowProjectFolderNotInAContentRootThenUnregisteredRootError() throws IOException {
|
||||
// this is to be fixed: auto-detection of Git repositories in subfolders for the <Project> mapping
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList("community"));
|
||||
map.put("roots", Arrays.asList(PROJECT));
|
||||
map.put("content_roots", Arrays.asList("."));
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("community"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testProjectRootGitForFullProjectContentRootLinkedSourceFolderBelowProjectThenErrors() throws IOException
|
||||
|
||||
{
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "content_root", "../linked_source_root", "folder"));
|
||||
map.put("roots", Arrays.asList(PROJECT));
|
||||
map.put("content_roots", Arrays.asList(".", "content_root", "../linked_source_root"));
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("content_root", "../linked_source_root", "folder"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testProjectRootRootForFolderGitForFullProjectContentRootLinkedSourceFolderBelowProjectThenErrors() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "content_root", "../linked_source_root", "folder"));
|
||||
map.put("roots", Arrays.asList(PROJECT, "folder"));
|
||||
map.put("content_roots", Arrays.asList(".", "content_root", "../linked_source_root"));
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("content_root", "../linked_source_root"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testProjectRootGitLikeInIDEAProjectThenError() throws IOException {
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "community", "contrib"));
|
||||
map.put("roots", Arrays.asList(PROJECT));
|
||||
map.put("content_roots", Arrays.asList(".", "community", "contrib"));
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("community", "contrib"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
public void testRealGitRootDeeperThanThreeLevelsShouldBeDetected() throws IOException {
|
||||
|
||||
Map<String, Collection<String>> map = new HashMap<String, Collection<String>>();
|
||||
map.put("git", Arrays.asList(".", "community", "contrib", "community/level1/level2/level3"));
|
||||
map.put("roots", Arrays.asList(PROJECT, "community/level1/level2/level3"));
|
||||
map.put("content_roots", Arrays.asList(".", "community", "contrib"));
|
||||
Map<String, Collection<String>> errorsMap = new HashMap<String, Collection<String>>();
|
||||
errorsMap.put("unreg", Arrays.asList("community", "contrib"));
|
||||
doTest(map, errorsMap);
|
||||
}
|
||||
|
||||
private void doTest(@NotNull Map<String, Collection<String>> map, @NotNull Map<String, Collection<String>> errors) throws IOException {
|
||||
initProject(map.get("git"), Collections.<String>emptyList(), map.get("content_roots"));
|
||||
addVcsRoots(map.get("roots"));
|
||||
|
||||
Collection<VcsRootError> expected = new ArrayList<VcsRootError>();
|
||||
Collection<String> unregPaths = errors.get("unreg");
|
||||
Collection<String> extraPaths = errors.get("extra");
|
||||
if (unregPaths != null) {
|
||||
expected.addAll(unregAll(unregPaths));
|
||||
}
|
||||
if (extraPaths != null) {
|
||||
expected.addAll(extraAll(extraPaths));
|
||||
}
|
||||
Collection<VcsRootError> actual = new VcsRootErrorsFinder(myProject).find();
|
||||
TestRepositoryUtil.assertEqualCollections(actual, expected);
|
||||
}
|
||||
|
||||
void addVcsRoots(@NotNull Collection<String> relativeRoots) {
|
||||
for (String root : relativeRoots) {
|
||||
if (root.equals(PROJECT)) {
|
||||
myVcsManager.setDirectoryMapping("", GitVcs.NAME);
|
||||
}
|
||||
else {
|
||||
String absoluteRoot = toAbsolute(root, myProject);
|
||||
myVcsManager.setDirectoryMapping(absoluteRoot, GitVcs.NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Collection<VcsRootError> unregAll(@NotNull Collection<String> paths) {
|
||||
Collection<VcsRootError> unregRoots = new ArrayList<VcsRootError>();
|
||||
for (String path : paths) {
|
||||
unregRoots.add(unreg(path));
|
||||
}
|
||||
return unregRoots;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Collection<VcsRootError> extraAll(@NotNull Collection<String> paths) {
|
||||
Collection<VcsRootError> extraRoots = new ArrayList<VcsRootError>();
|
||||
for (String path : paths) {
|
||||
extraRoots.add(extra(path));
|
||||
}
|
||||
return extraRoots;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
VcsRootError unreg(@NotNull String path) {
|
||||
return new VcsRootError(VcsRootError.Type.UNREGISTERED_ROOT, toAbsolute(path, myProject), GitVcs.NAME);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
VcsRootError extra(@NotNull String path) {
|
||||
return new VcsRootError(VcsRootError.Type.EXTRA_MAPPING, PROJECT.equals(path) ? PROJECT : toAbsolute(path, myProject), GitVcs.NAME);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<vcs name="hg4idea" vcsClass="org.zmlx.hg4idea.HgVcs" displayName="Mercurial" administrativeAreaName=".hg"/>
|
||||
<checkoutProvider implementation="org.zmlx.hg4idea.provider.HgCheckoutProvider"/>
|
||||
<vcsRootChecker implementation="org.zmlx.hg4idea.roots.HgRootChecker"/>
|
||||
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
|
||||
<vcsPopupProvider implementation="org.zmlx.hg4idea.provider.HgQuickListProvider"/>
|
||||
<logProvider implementation="org.zmlx.hg4idea.log.HgLogProvider"/>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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 org.zmlx.hg4idea.roots;
|
||||
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vcs.VcsRootChecker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.zmlx.hg4idea.HgVcs;
|
||||
import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class HgRootChecker extends VcsRootChecker {
|
||||
|
||||
@Override
|
||||
public boolean isRoot(@NotNull String path) {
|
||||
return new File(path, HgUtil.DOT_HG).exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VcsKey getSupportedVcs() {
|
||||
return HgVcs.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVcsDir(String path) {
|
||||
return path != null && path.toLowerCase().endsWith(HgUtil.DOT_HG);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user