GitRootConverter: cache detected roots

* GitRepositoryManager.GIT_ROOTS_CHANGE message bus Topic - to notify about git roots changes.
* Fire the GIT_ROOTS_CHANGE event on every scan in GitRootScanner.
* Listen to events in GitRootConverter and update the detected roots list.
* Supply the GitRootDetectInfo to the GitRootErrorsFinder for better control on when to detect.
This commit is contained in:
Kirill Likhodedov
2012-03-14 19:24:13 +04:00
parent 9b3286f9c4
commit 9a7b237aeb
8 changed files with 78 additions and 19 deletions
@@ -21,40 +21,50 @@ import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.VcsDirectoryMapping;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
import git4idea.roots.GitRootDetectInfo;
import git4idea.repo.GitRepositoryManager;
import git4idea.roots.GitRootDetector;
import git4idea.roots.GitRootsListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Given VFS content roots, filters them and returns only those, which are actual Git roots.
*/
public class GitRootConverter implements AbstractVcs.RootsConvertor {
public class GitRootConverter implements AbstractVcs.RootsConvertor, GitRootsListener {
@NotNull private final Project myProject;
@NotNull private final PlatformFacade myPlatformFacade;
@Nullable private Collection<VirtualFile> myDetectedRoots;
public GitRootConverter(@NotNull Project project, @NotNull PlatformFacade facade) {
myProject = project;
myPlatformFacade = facade;
myProject.getMessageBus().connect().subscribe(GitRepositoryManager.GIT_ROOTS_CHANGE, this);
}
@NotNull
public List<VirtualFile> convertRoots(@NotNull List<VirtualFile> result) {
GitRootDetectInfo detectInfo = new GitRootDetector(myProject, myPlatformFacade).detect();
if (myDetectedRoots == null) {
myDetectedRoots = new GitRootDetector(myProject, myPlatformFacade).detect().getRoots();
}
ArrayList<VirtualFile> roots = new ArrayList<VirtualFile>();
if (hasProjectMapping()) {
roots.addAll(detectInfo.getRoots());
roots.addAll(myDetectedRoots);
}
HashSet<VirtualFile> listed = new HashSet<VirtualFile>();
for (VirtualFile f : result) {
VirtualFile r = GitUtil.gitRootOrNull(f);
if (r != null && listed.add(r)) {
roots.add(r);
if (!roots.contains(r)) {
roots.add(r);
}
}
}
return roots;
@@ -69,4 +79,9 @@ public class GitRootConverter implements AbstractVcs.RootsConvertor {
return false;
}
@Override
public void gitRootsChanged(Collection<VirtualFile> roots) {
myDetectedRoots = roots;
}
}
@@ -16,6 +16,8 @@
package git4idea.repo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.messages.Topic;
import git4idea.roots.GitRootsListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,6 +29,8 @@ import java.util.List;
*/
public interface GitRepositoryManager {
Topic<GitRootsListener> GIT_ROOTS_CHANGE = Topic.create("Git Roots change", GitRootsListener.class);
/**
* Returns the {@link GitRepository} which tracks the Git repository located in the given directory,
* or {@code null} if the given file is not a Git root known to this {@link com.intellij.openapi.project.Project}.
@@ -35,7 +35,7 @@ public class GitRootChecker implements VcsRootChecker {
private final boolean myProjectMappingIsInvalid;
public GitRootChecker(@NotNull Project project, @NotNull PlatformFacade platformFacade) {
myErrors = new GitRootErrorsFinder(project, platformFacade).find();
myErrors = new GitRootErrorsFinder(project, platformFacade).find(new GitRootDetector(project, platformFacade).detect());
myProjectMappingIsInvalid = isProjectMappingInvalid();
}
@@ -48,9 +48,9 @@ public class GitRootErrorsFinder {
}
@NotNull
public Collection<VcsRootError> find() {
public Collection<VcsRootError> find(@NotNull GitRootDetectInfo rootDetectInfo) {
List<VcsDirectoryMapping> mappings = myVcsManager.getDirectoryMappings(myVcs);
Collection<VirtualFile> gitRoots = new GitRootDetector(myProject, myPlatformFacade).detect().getRoots();
Collection<VirtualFile> gitRoots = rootDetectInfo.getRoots();
Collection<VcsRootError> errors = new ArrayList<VcsRootError>();
Collection<String> gitPaths = rootsToPaths(gitRoots);
@@ -67,17 +67,19 @@ public class GitRootProblemNotifier {
mySettings = VcsConfiguration.getInstance(myProject);
}
public void rescanAndNotifyIfNeeded() {
public GitRootDetectInfo rescanAndNotifyIfNeeded() {
GitRootDetectInfo detectInfo = new GitRootDetector(myProject, myPlatformFacade).detect();
if (!mySettings.SHOW_VCS_ERROR_NOTIFICATIONS) {
return;
return detectInfo;
}
Collection<VcsRootError> errors = scan();
Collection<VcsRootError> errors = scan(detectInfo);
if (errors.isEmpty()) {
synchronized (NOTIFICATION_LOCK) {
expireNotification();
}
return;
return detectInfo;
}
Collection<String> unregisteredRoots = getUnregisteredRoots(errors);
@@ -89,9 +91,10 @@ public class GitRootProblemNotifier {
synchronized (NOTIFICATION_LOCK) {
expireNotification();
myNotification = createNotification(IMPORTANT_ERROR_NOTIFICATION, title, description, ERROR,
new MyNotificationListener(myProject, mySettings));
new MyNotificationListener(myProject, mySettings, myPlatformFacade));
myPlatformFacade.getNotificator(myProject).notify(myNotification);
}
return detectInfo;
}
private void expireNotification() {
@@ -109,8 +112,8 @@ public class GitRootProblemNotifier {
}
@NotNull
private Collection<VcsRootError> scan() {
return new GitRootErrorsFinder(myProject, myPlatformFacade).find();
private Collection<VcsRootError> scan(GitRootDetectInfo detectInfo) {
return new GitRootErrorsFinder(myProject, myPlatformFacade).find(detectInfo);
}
@SuppressWarnings("StringConcatenationInsideStringBufferAppend")
@@ -195,10 +198,12 @@ public class GitRootProblemNotifier {
@NotNull private final Project myProject;
@NotNull private final VcsConfiguration mySettings;
@NotNull private final PlatformFacade myPlatformFacade;
private MyNotificationListener(@NotNull Project project, @NotNull VcsConfiguration settings) {
private MyNotificationListener(@NotNull Project project, @NotNull VcsConfiguration settings, @NotNull PlatformFacade facade) {
myProject = project;
mySettings = settings;
myPlatformFacade = facade;
}
@Override
@@ -206,7 +211,8 @@ public class GitRootProblemNotifier {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
if (event.getDescription().equals("configure")) {
ShowSettingsUtil.getInstance().showSettingsDialog(myProject, ActionsBundle.message("group.VcsGroup.text"));
Collection<VcsRootError> errorsAfterPossibleFix = GitRootProblemNotifier.getInstance(myProject).scan();
Collection<VcsRootError> errorsAfterPossibleFix = GitRootProblemNotifier.getInstance(myProject).scan(
new GitRootDetector(myProject, myPlatformFacade).detect());
if (errorsAfterPossibleFix.isEmpty() && !notification.isExpired()) {
notification.expire();
}
@@ -30,6 +30,7 @@ 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.messages.MessageBus;
import git4idea.repo.GitRepositoryManager;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -40,6 +41,7 @@ import java.util.List;
*/
public class GitRootScanner implements BulkFileListener, ModuleRootListener, Disposable, VcsListener {
@NotNull private final Project myProject;
@NotNull private final Runnable myExecuteAfterScan;
@NotNull private final GitRootProblemNotifier myRootProblemNotifier;
@@ -49,6 +51,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
@NotNull private final Object SCAN_LOCK = new Object();
public GitRootScanner(@NotNull Project project, @NotNull Runnable executeAfterScan) {
myProject = project;
myExecuteAfterScan = executeAfterScan;
StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
@@ -129,7 +132,8 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
return;
}
myScanning = true;
myRootProblemNotifier.rescanAndNotifyIfNeeded();
GitRootDetectInfo detectInfo = myRootProblemNotifier.rescanAndNotifyIfNeeded();
myProject.getMessageBus().syncPublisher(GitRepositoryManager.GIT_ROOTS_CHANGE).gitRootsChanged(detectInfo.getRoots());
myExecuteAfterScan.run();
myScanning = false;
}
@@ -0,0 +1,29 @@
/*
* 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.vfs.VirtualFile;
import java.util.Collection;
/**
* @author Kirill Likhodedov
*/
public interface GitRootsListener {
void gitRootsChanged(Collection<VirtualFile> roots);
}
@@ -172,7 +172,8 @@ class GitRootErrorsFinderTest extends AbstractGitRootTest {
expected.addAll map.errors.unreg.collect { unreg(it) }
expected.addAll map.errors.extra.collect { extra(it) }
Collection<VcsRootError> actual = new GitRootErrorsFinder(myProject, myPlatformFacade).find()
Collection<VcsRootError> actual = new GitRootErrorsFinder(myProject, myPlatformFacade).find(
new GitRootDetector(myProject, myPlatformFacade).detect())
assertEquals expected.toSet(), actual.toSet()
}