package com.intellij.dvcs.repo;

import com.intellij.openapi.vcs.AbstractVcs;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;

public abstract class AbstractRepositoryManager<T extends Repository>
  implements RepositoryManager<T> {

  @NotNull private final AbstractVcs myVcs;
  @NotNull private final String myRepoDirName;
  @NotNull private final VcsRepositoryManager myGlobalRepositoryManager;

  protected AbstractRepositoryManager(@NotNull VcsRepositoryManager globalRepositoryManager,
                                      @NotNull AbstractVcs vcs,
                                      @NotNull String repoDirName) {
    myGlobalRepositoryManager = globalRepositoryManager;
    myVcs = vcs;
    myRepoDirName = repoDirName;
  }

  @Override
  @Nullable
  public T getRepositoryForRoot(@Nullable VirtualFile root) {
    return validateAndGetRepository(myGlobalRepositoryManager.getRepositoryForRoot(root));
  }

  @Nullable
  public T getRepositoryForRootQuick(@Nullable VirtualFile root) {
    return validateAndGetRepository(myGlobalRepositoryManager.getRepositoryForRootQuick(root));
  }

  @Override
  public void addExternalRepository(@NotNull VirtualFile root, @NotNull T repository) {
    myGlobalRepositoryManager.addExternalRepository(root, repository);
  }

  @Override
  public void removeExternalRepository(@NotNull VirtualFile root) {
    myGlobalRepositoryManager.removeExternalRepository(root);
  }

  @Override
  public boolean isExternal(@NotNull T repository) {
    return myGlobalRepositoryManager.isExternal(repository);
  }

  @Override
  @Nullable
  public T getRepositoryForFile(@NotNull VirtualFile file) {
    return validateAndGetRepository(myGlobalRepositoryManager.getRepositoryForFile(file));
  }

  /**
   * @Deprecated to delete in 2017.X
   */
  @Nullable
  @Deprecated
  public T getRepositoryForFileQuick(@NotNull VirtualFile file) {
    return validateAndGetRepository(myGlobalRepositoryManager.getRepositoryForFileQuick(file));
  }

  @Override
  @Nullable
  public T getRepositoryForFile(@NotNull FilePath file) {
    VirtualFile vFile = ChangesUtil.findValidParentAccurately(file);
    return vFile != null ? getRepositoryForFile(vFile) : null;
  }

  @NotNull
  protected List<T> getRepositories(Class<T> type) {
    return ContainerUtil.findAll(myGlobalRepositoryManager.getRepositories(), type);
  }

  @NotNull
  @Override
  public abstract List<T> getRepositories();

  @Override
  public boolean moreThanOneRoot() {
    return getRepositories().size() > 1;
  }

  @Override
  public void updateRepository(@Nullable VirtualFile root) {
    T repo = getRepositoryForRoot(root);
    if (repo != null) {
      repo.update();
    }
  }

  @Override
  public void updateAllRepositories() {
    ContainerUtil.process(getRepositories(), repo -> {
      repo.update();
      return true;
    });
  }

  @Nullable
  private T validateAndGetRepository(@Nullable Repository repository) {
    if (repository == null || !myVcs.equals(repository.getVcs())) return null;
    VirtualFile vcsDir = repository.getRoot().findChild(myRepoDirName);
    //noinspection unchecked
    return vcsDir != null && vcsDir.exists() ? (T)repository : null;
  }

  @Override
  @NotNull
  public AbstractVcs getVcs() {
    return myVcs;
  }

}

@@ -26,16 +26,68 @@
 .repo;%0A%0A
+import com.intellij.openapi.application.ReadAction;%0A
 import c
@@ -3303,16 +3303,56 @@
 n null;%0A
+    return ReadAction.compute(() -%3E %7B%0A  
     Virt
@@ -3359,22 +3359,20 @@
 ualFile 
-vcsDir
+root
  = repos
@@ -3386,16 +3386,79 @@
 etRoot()
+;%0A      if (root.isValid()) %7B%0A        VirtualFile vcsDir = root
 .findChi
@@ -3480,16 +3480,20 @@
 e);%0A    
+ 
+   
 //noinsp
@@ -3509,24 +3509,28 @@
 checked%0A    
+ 
+   
 return vcsDi
@@ -3574,32 +3574,67 @@
 ository : null;%0A
+      %7D%0A      return null;%0A    %7D);%0A
   %7D%0A%0A  @Override

Check virtual file parent for validity before searching its child: EA-109104