[git] Fix blinking temporary notifications about "unregistered Git roots" IDEA-83015, IDEA-85606

PROBLEM CAUSE:
Notifications blinked because 2 events were arriving from different threads almost simultaneously: creating .git, and registering the mapping.
The first event initiated rescan => notification was shown.
The second event initiated another rescan => notification was hidden.

FIX:
Queue scan requests instead of immediate scanning, and add a delay before beginning the scan.
Use an Alarm (1s delay, pooled thread) instead of self-made state-aware handler.
Don't queue requests: only one (the latest) is needed, because consecutive scan won't add more information.
This commit is contained in:
Kirill Likhodedov
2012-11-26 19:59:29 +04:00
parent dc13fbb630
commit 6eb70944ea
@@ -17,7 +17,6 @@ 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;
@@ -28,12 +27,13 @@ import com.intellij.openapi.vcs.VcsListener;
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 javax.swing.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @author Kirill Likhodedov
@@ -45,11 +45,13 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
private volatile boolean myProjectIsInitialized;
private volatile boolean myMappingsAreReady;
private volatile boolean myScanning;
@NotNull private final Object SCAN_LOCK = new Object();
@NotNull private final Alarm myAlarm;
private static final long WAIT_BEFORE_SCAN = TimeUnit.SECONDS.toMillis(1);
public GitRootScanner(@NotNull Project project, @NotNull Runnable executeAfterScan) {
myExecuteAfterScan = executeAfterScan;
myRootProblemNotifier = GitRootProblemNotifier.getInstance(project);
StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() {
@Override
@@ -64,7 +66,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, this);
messageBus.connect().subscribe(ProjectTopics.PROJECT_ROOTS, this);
myRootProblemNotifier = GitRootProblemNotifier.getInstance(project);
myAlarm = new Alarm(Alarm.ThreadToUse.OWN_THREAD, project);
}
@Override
@@ -102,40 +104,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
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;
try {
myRootProblemNotifier.rescanAndNotifyIfNeeded();
myExecuteAfterScan.run();
}
finally {
myScanning = false;
}
scheduleScan();
}
}
@@ -143,4 +112,15 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis
return myMappingsAreReady && myProjectIsInitialized;
}
private void scheduleScan() {
myAlarm.cancelAllRequests(); // one scan is enough, no need to queue, they all do the same
myAlarm.addRequest(new Runnable() {
@Override
public void run() {
myRootProblemNotifier.rescanAndNotifyIfNeeded();
myExecuteAfterScan.run();
}
}, WAIT_BEFORE_SCAN);
}
}