revert "fix com.intellij.dvcs.repo.VcsRepositoryManager requested as a service, but...
authorVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Fri, 24 Jul 2015 14:11:00 +0000 (16:11 +0200)
committerVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Fri, 24 Jul 2015 14:12:33 +0000 (16:12 +0200)
platform/dvcs-impl/src/META-INF/dvcs.xml
platform/dvcs-impl/src/com/intellij/dvcs/push/VcsPushAction.java
platform/dvcs-impl/src/com/intellij/dvcs/repo/VcsRepositoryManager.java
platform/dvcs-impl/testSrc/com.intellij.dvcs/VcsRepositoryManagerTest.java

index 84b6777d1ed1e54cdc8f7621a43e0ef8995e46b5..c045e58a9e3a106dc07c155d4fb92c76001cea36 100644 (file)
       <add-to-group group-id="VcsGeneral.KeymapGroup"/>
     </group>
   </actions>
+  <project-components>
+    <component>
+      <implementation-class>com.intellij.dvcs.repo.VcsRepositoryManager</implementation-class>
+    </component>
+  </project-components>
+
   <extensions defaultExtensionNs="com.intellij">
     <projectService serviceImplementation="com.intellij.dvcs.push.PushSettings"/>
-    <projectService serviceImplementation="com.intellij.dvcs.repo.VcsRepositoryManager"/>
-    <postStartupActivity implementation="com.intellij.dvcs.repo.VcsRepositoryManager$MyStartUpActivity"/>
   </extensions>
 </idea-plugin>
 
index 46f88b04758fc4bb8f6d2cea31390e824b506fe8..8d9b79410071800b61fd0f258b5932506988a9e0 100644 (file)
@@ -21,6 +21,7 @@ import com.intellij.dvcs.repo.Repository;
 import com.intellij.dvcs.repo.VcsRepositoryManager;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.components.ServiceManager;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -36,7 +37,7 @@ public class VcsPushAction extends DumbAwareAction {
   @Override
   public void actionPerformed(@NotNull AnActionEvent e) {
     Project project = e.getRequiredData(CommonDataKeys.PROJECT);
-    VcsRepositoryManager manager = VcsRepositoryManager.getInstance(project);
+    VcsRepositoryManager manager = ServiceManager.getService(project, VcsRepositoryManager.class);
     Collection<Repository> repositories = e.getData(CommonDataKeys.EDITOR) != null
                                           ? ContainerUtil.<Repository>emptyList()
                                           : collectRepositories(manager, e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY));
@@ -64,6 +65,6 @@ public class VcsPushAction extends DumbAwareAction {
     super.update(e);
     Project project = e.getProject();
     e.getPresentation()
-      .setEnabledAndVisible(project != null && !VcsRepositoryManager.getInstance(project).getRepositories().isEmpty());
+      .setEnabledAndVisible(project != null && !ServiceManager.getService(project, VcsRepositoryManager.class).getRepositories().isEmpty());
   }
 }
index 62a069125c2afab636010a347d6ad636eb0428c8..0f162242be0b60c497a61c107d74bee757d73f41 100644 (file)
  */
 package com.intellij.dvcs.repo;
 
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.components.AbstractProjectComponent;
 import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.startup.StartupActivity;
 import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.vcs.AbstractVcs;
 import com.intellij.openapi.vcs.ProjectLevelVcsManager;
 import com.intellij.openapi.vcs.VcsListener;
@@ -31,56 +31,53 @@ import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
 
 import java.util.*;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
- * VcsRepositoryManager creates, stores and updates all Repositories information using registered {@link VcsRepositoryCreator}
+ * VcsRepositoryManager creates,stores and updates all Repositories information using registered {@link VcsRepositoryCreator}
  * extension point in a thread safe way.
  */
-public class VcsRepositoryManager {
+public class VcsRepositoryManager extends AbstractProjectComponent implements Disposable, VcsListener {
   @NotNull private final ProjectLevelVcsManager myVcsManager;
 
-  @NotNull private final ReentrantReadWriteLock repoLock = new ReentrantReadWriteLock();
-  @NotNull private final ReentrantReadWriteLock.WriteLock modifyLock = new ReentrantReadWriteLock().writeLock();
+  @NotNull private final ReentrantReadWriteLock REPO_LOCK = new ReentrantReadWriteLock();
+  @NotNull private final ReentrantReadWriteLock.WriteLock MODIFY_LOCK = new ReentrantReadWriteLock().writeLock();
 
   @NotNull private final Map<VirtualFile, Repository> myRepositories = ContainerUtil.newHashMap();
   @NotNull private final Map<VirtualFile, Repository> myExternalRepositories = ContainerUtil.newHashMap();
   @NotNull private final List<VcsRepositoryCreator> myRepositoryCreators;
 
+  private volatile boolean myDisposed;
+
   public VcsRepositoryManager(@NotNull Project project, @NotNull ProjectLevelVcsManager vcsManager) {
+    super(project);
     myVcsManager = vcsManager;
     myRepositoryCreators = Arrays.asList(Extensions.getExtensions(VcsRepositoryCreator.EXTENSION_POINT_NAME, project));
   }
 
-  public static VcsRepositoryManager getInstance(@NotNull Project project) {
-    return ServiceManager.getService(project, VcsRepositoryManager.class);
+  @Override
+  public void initComponent() {
+    Disposer.register(myProject, this);
+    myProject.getMessageBus().connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, this);
   }
 
-  public static final class MyStartUpActivity implements StartupActivity, DumbAware {
-    @Override
-    public void runActivity(@NotNull final Project project) {
-      if (!project.isDefault() && !ApplicationManager.getApplication().isUnitTestMode()) {
-        project.getMessageBus().connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, new VcsListener() {
-          @Override
-          public void directoryMappingChanged() {
-            getInstance(project).checkAndUpdateRepositoriesCollection(null);
-          }
-        });
-      }
+  @Override
+  public void dispose() {
+    myDisposed = true;
+    try {
+      REPO_LOCK.writeLock().lock();
+      myRepositories.clear();
+    }
+    finally {
+      REPO_LOCK.writeLock().unlock();
     }
   }
 
-  @TestOnly
-  public void addListener(@NotNull Project project) {
-    project.getMessageBus().connect().subscribe(ProjectLevelVcsManager.VCS_CONFIGURATION_CHANGED, new VcsListener() {
-      @Override
-      public void directoryMappingChanged() {
-        checkAndUpdateRepositoriesCollection(null);
-      }
-    });
+  @Override
+  public void directoryMappingChanged() {
+    checkAndUpdateRepositoriesCollection(null);
   }
 
   @Nullable
@@ -104,23 +101,26 @@ public class VcsRepositoryManager {
     if (root == null) return null;
     Repository result;
     try {
-      repoLock.readLock().lock();
+      REPO_LOCK.readLock().lock();
+      if (myDisposed) {
+        throw new ProcessCanceledException();
+      }
       Repository repo = myRepositories.get(root);
       result = repo != null ? repo : myExternalRepositories.get(root);
     }
     finally {
-      repoLock.readLock().unlock();
+      REPO_LOCK.readLock().unlock();
     }
     // if we didn't find appropriate repository, request update mappings if needed and try again
     // may be this should not be called  from several places (for example: branch widget updating from edt).
     if (updateIfNeeded && result == null && ArrayUtil.contains(root, myVcsManager.getAllVersionedRoots())) {
       checkAndUpdateRepositoriesCollection(root);
       try {
-        repoLock.readLock().lock();
+        REPO_LOCK.readLock().lock();
         return myRepositories.get(root);
       }
       finally {
-        repoLock.readLock().unlock();
+        REPO_LOCK.readLock().unlock();
       }
     }
     else {
@@ -129,43 +129,43 @@ public class VcsRepositoryManager {
   }
 
   public void addExternalRepository(@NotNull VirtualFile root, @NotNull Repository repository) {
-    repoLock.writeLock().lock();
+    REPO_LOCK.writeLock().lock();
     try {
       myExternalRepositories.put(root, repository);
     }
     finally {
-      repoLock.writeLock().unlock();
+      REPO_LOCK.writeLock().unlock();
     }
   }
 
   public void removeExternalRepository(@NotNull VirtualFile root) {
-    repoLock.writeLock().lock();
+    REPO_LOCK.writeLock().lock();
     try {
       myExternalRepositories.remove(root);
     }
     finally {
-      repoLock.writeLock().unlock();
+      REPO_LOCK.writeLock().unlock();
     }
   }
 
   public boolean isExternal(@NotNull Repository repository) {
     try {
-      repoLock.readLock().lock();
+      REPO_LOCK.readLock().lock();
       return !myRepositories.containsValue(repository) && myExternalRepositories.containsValue(repository);
     }
     finally {
-      repoLock.readLock().unlock();
+      REPO_LOCK.readLock().unlock();
     }
   }
 
   @NotNull
   public Collection<Repository> getRepositories() {
     try {
-      repoLock.readLock().lock();
+      REPO_LOCK.readLock().lock();
       return Collections.unmodifiableCollection(myRepositories.values());
     }
     finally {
-      repoLock.readLock().unlock();
+      REPO_LOCK.readLock().unlock();
     }
   }
 
@@ -173,16 +173,14 @@ public class VcsRepositoryManager {
   private void checkAndUpdateRepositoriesCollection(@Nullable VirtualFile checkedRoot) {
     Map<VirtualFile, Repository> repositories;
     try {
-      modifyLock.lock();
+      MODIFY_LOCK.lock();
       try {
-        repoLock.readLock().lock();
-        if (myRepositories.containsKey(checkedRoot)) {
-          return;
-        }
+        REPO_LOCK.readLock().lock();
+        if (myRepositories.containsKey(checkedRoot)) return;
         repositories = ContainerUtil.newHashMap(myRepositories);
       }
       finally {
-        repoLock.readLock().unlock();
+        REPO_LOCK.readLock().unlock();
       }
 
       Collection<VirtualFile> invalidRoots = findInvalidRoots(repositories.keySet());
@@ -190,17 +188,19 @@ public class VcsRepositoryManager {
       Map<VirtualFile, Repository> newRoots = findNewRoots(repositories.keySet());
       repositories.putAll(newRoots);
 
-      repoLock.writeLock().lock();
+      REPO_LOCK.writeLock().lock();
       try {
-        myRepositories.clear();
-        myRepositories.putAll(repositories);
+        if (!myDisposed) {
+          myRepositories.clear();
+          myRepositories.putAll(repositories);
+        }
       }
       finally {
-        repoLock.writeLock().unlock();
+        REPO_LOCK.writeLock().unlock();
       }
     }
     finally {
-      modifyLock.unlock();
+      MODIFY_LOCK.unlock();
     }
   }
 
index 20e9616ba74eff796630eb1e49cbb45f3a38edf2..64c222910ad7023e755bbb41783bf6b68ae3ff97 100644 (file)
@@ -82,7 +82,7 @@ public class VcsRepositoryManagerTest extends UsefulTestCase {
       point.registerExtension(myMockCreator);
 
       myGlobalRepositoryManager = new VcsRepositoryManager(myProject, myProjectLevelVcsManager);
-      myGlobalRepositoryManager.addListener(myProject);
+      myGlobalRepositoryManager.initComponent();
     }
     catch (Exception e) {
       tearDown();
@@ -126,16 +126,18 @@ public class VcsRepositoryManagerTest extends UsefulTestCase {
     FutureTask<Boolean> modifyRepositoryMapping = new FutureTask<Boolean>(new Callable<Boolean>() {
       @Override
       public Boolean call() throws Exception {
-        myProjectLevelVcsManager.setDirectoryMappings(VcsUtil.addMapping(myProjectLevelVcsManager.getDirectoryMappings(), myProjectRoot.getPath(), myVcs.getName()));
+        myProjectLevelVcsManager
+          .setDirectoryMappings(
+            VcsUtil.addMapping(myProjectLevelVcsManager.getDirectoryMappings(), myProjectRoot.getPath(), myVcs.getName()));
         return !myGlobalRepositoryManager.getRepositories().isEmpty();
       }
     });
-    new Thread(modifyRepositoryMapping, "vcs modify").start();
+    new Thread(modifyRepositoryMapping,"vcs modify").start();
 
     //wait until modification starts
     assertTrue(LOCK_ERROR_TEXT, READY_TO_READ.await(1, TimeUnit.SECONDS));
 
-    new Thread(readExistingRepo, "vcs read").start();
+    new Thread(readExistingRepo,"vcs read").start();
     assertNotNull(readExistingRepo.get(1, TimeUnit.SECONDS));
     CONTINUE_MODIFY.countDown();
     assertTrue(modifyRepositoryMapping.get(1, TimeUnit.SECONDS));