mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-82632 Git: scan for roots only after VCS mappings are ready.
Move scanning of roots to a separate class: GitRootScanner. Perform only 1 scan at a time (and reject others while scanning - not-scanning is not critical). Scan only when project is initialized and VCS mappings are ready (i.e. the first VcsListener event is fired).
This commit is contained in:
@@ -15,30 +15,20 @@
|
||||
*/
|
||||
package git4idea.repo;
|
||||
|
||||
import com.intellij.ProjectTopics;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
import com.intellij.openapi.roots.ModuleRootListener;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vcs.AbstractVcs;
|
||||
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
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.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.concurrency.QueueProcessor;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.PlatformFacade;
|
||||
import git4idea.roots.GitRootProblemNotifier;
|
||||
import git4idea.roots.GitRootScanner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -60,16 +50,7 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme
|
||||
@NotNull private final Set<GitRepositoryChangeListener> myListeners = new HashSet<GitRepositoryChangeListener>();
|
||||
|
||||
@NotNull private final ReentrantReadWriteLock REPO_LOCK = new ReentrantReadWriteLock();
|
||||
|
||||
@NotNull private final Object ROOT_SCAN_STUB_OBJECT = new Object();
|
||||
@NotNull private final QueueProcessor<Object> myRootScanQueue = new QueueProcessor<Object>(new Consumer<Object>() {
|
||||
@Override
|
||||
public void consume(Object o) {
|
||||
if (!myProject.isDisposed()) {
|
||||
GitRootProblemNotifier.getInstance(myProject).rescanAndNotifyIfNeeded();
|
||||
}
|
||||
}
|
||||
});
|
||||
private GitRootScanner myRootScanner;
|
||||
|
||||
@Nullable
|
||||
public static GitRepositoryManager getInstance(@NotNull Project project) {
|
||||
@@ -85,16 +66,13 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme
|
||||
@Override
|
||||
public void initComponent() {
|
||||
Disposer.register(myProject, this);
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
|
||||
myRootScanner = new GitRootScanner(myProject, new DumbAwareRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final MessageBus messageBus = myProject.getMessageBus();
|
||||
final MyRepositoryCreationDeletionListener rootChangeListener = new MyRepositoryCreationDeletionListener();
|
||||
messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, rootChangeListener);
|
||||
messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, rootChangeListener);
|
||||
updateRepositoriesCollection();
|
||||
}
|
||||
});
|
||||
Disposer.register(this, myRootScanner);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,8 +189,6 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme
|
||||
finally {
|
||||
REPO_LOCK.writeLock().unlock();
|
||||
}
|
||||
|
||||
myRootScanQueue.add(ROOT_SCAN_STUB_OBJECT);
|
||||
}
|
||||
|
||||
private static boolean gitRootOK(@NotNull VirtualFile root) {
|
||||
@@ -233,28 +209,4 @@ public final class GitRepositoryManager extends AbstractProjectComponent impleme
|
||||
return "GitRepositoryManager{myRepositories: " + myRepositories + '}';
|
||||
}
|
||||
|
||||
private class MyRepositoryCreationDeletionListener implements BulkFileListener, ModuleRootListener {
|
||||
@Override
|
||||
public void before(@NotNull List<? extends VFileEvent> events) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
for (VFileEvent event : events) {
|
||||
VirtualFile file = event.getFile();
|
||||
if (file != null && file.getName().equalsIgnoreCase(".git") && file.isDirectory()) {
|
||||
updateRepositoriesCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeRootsChange(ModuleRootEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rootsChanged(ModuleRootEvent event) {
|
||||
updateRepositoriesCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.ProjectTopics;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAwareRunnable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootEvent;
|
||||
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.vfs.VirtualFile;
|
||||
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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class GitRootScanner implements BulkFileListener, ModuleRootListener, Disposable, VcsListener {
|
||||
|
||||
@NotNull private final Runnable myExecuteAfterScan;
|
||||
@NotNull private final GitRootProblemNotifier myRootProblemNotifier;
|
||||
|
||||
private volatile boolean myProjectIsInitialized;
|
||||
private volatile boolean myMappingsAreReady;
|
||||
private volatile boolean myScanning;
|
||||
@NotNull private final Object SCAN_LOCK = new Object();
|
||||
|
||||
public GitRootScanner(@NotNull Project project, @NotNull Runnable executeAfterScan) {
|
||||
myExecuteAfterScan = executeAfterScan;
|
||||
|
||||
StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myProjectIsInitialized = true;
|
||||
}
|
||||
});
|
||||
|
||||
final MessageBus messageBus = project.getMessageBus();
|
||||
messageBus.connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, this);
|
||||
messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, this);
|
||||
messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, this);
|
||||
|
||||
myRootProblemNotifier = GitRootProblemNotifier.getInstance(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void before(@NotNull List<? extends VFileEvent> events) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void after(@NotNull List<? extends VFileEvent> events) {
|
||||
for (VFileEvent event : events) {
|
||||
VirtualFile file = event.getFile();
|
||||
if (file != null && file.getName().equalsIgnoreCase(".git") && file.isDirectory()) {
|
||||
scanIfReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeRootsChange(ModuleRootEvent event) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rootsChanged(ModuleRootEvent event) {
|
||||
scanIfReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void directoryMappingChanged() {
|
||||
myMappingsAreReady = true;
|
||||
}
|
||||
|
||||
private void scanIfReady() {
|
||||
if (readyToScan()) {
|
||||
scan();
|
||||
}
|
||||
}
|
||||
|
||||
private void scan() {
|
||||
if (myScanning) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SwingUtilities.isEventDispatchThread()) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
scanWithLock();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
scanWithLock();
|
||||
}
|
||||
}
|
||||
|
||||
private void scanWithLock() {
|
||||
synchronized (SCAN_LOCK) {
|
||||
if (myScanning) {
|
||||
return;
|
||||
}
|
||||
myScanning = true;
|
||||
myRootProblemNotifier.rescanAndNotifyIfNeeded();
|
||||
myExecuteAfterScan.run();
|
||||
myScanning = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean readyToScan() {
|
||||
return myMappingsAreReady && myProjectIsInitialized;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user