private static boolean isUndo(SvnVcs vcs) {
   if (vcs == null || vcs.getProject() == null) {
     return false;
   }
   Project p = vcs.getProject();
   return UndoManager.getInstance(p).isUndoInProgress();
 }
  public boolean move(VirtualFile file, VirtualFile toDir) throws IOException {
    File srcFile = getIOFile(file);
    File dstFile = new File(getIOFile(toDir), file.getName());

    final SvnVcs vcs = getVCS(toDir);
    final SvnVcs sourceVcs = getVCS(file);
    if (vcs == null && sourceVcs == null) return false;

    if (vcs == null) {
      return false;
    }

    FileDocumentManager.getInstance().saveAllDocuments();
    if (sourceVcs == null) {
      return createItem(toDir, file.getName(), file.isDirectory(), true);
    }

    if (isPendingAdd(vcs.getProject(), toDir)) {

      myMovedFiles.add(new MovedFileInfo(sourceVcs.getProject(), srcFile, dstFile));
      return true;
    } else {
      final VirtualFile oldParent = file.getParent();
      myFilesToRefresh.add(oldParent);
      myFilesToRefresh.add(toDir);
      return doMove(sourceVcs, srcFile, dstFile);
    }
  }
 private boolean for17move(
     final SvnVcs vcs, final File src, final File dst, boolean undo, SVNStatus srcStatus)
     throws SVNException {
   if (srcStatus != null && srcStatus.getCopyFromURL() == null) {
     undo = false;
   }
   if (undo) {
     myUndoingMove = true;
     createRevertAction(vcs, dst, true).execute();
     copyUnversionedMembersOfDirectory(src, dst);
     if (srcStatus == null || SvnVcs.svnStatusIsUnversioned(srcStatus)) {
       FileUtil.delete(src);
     } else {
       createRevertAction(vcs, src, true).execute();
     }
     restoreFromUndoStorage(dst);
   } else {
     if (doUsualMove(vcs, src)) return true;
     // check destination directory
     final SVNStatus dstParentStatus = getFileStatus(vcs, dst.getParentFile());
     if (dstParentStatus == null || SvnVcs.svnStatusIsUnversioned(dstParentStatus)) {
       try {
         copyFileOrDir(src, dst);
       } catch (IOException e) {
         throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e);
       }
       createDeleteAction(vcs, src, true).execute();
       return false;
     }
     moveFileWithSvn(vcs, src, dst);
   }
   return false;
 }
  private void processDeletedFiles(Project project) {
    final List<Pair<FilePath, WorkingCopyFormat>> deletedFiles =
        new ArrayList<Pair<FilePath, WorkingCopyFormat>>();
    final Collection<FilePath> filesToProcess = new ArrayList<FilePath>();
    List<VcsException> exceptions = new ArrayList<VcsException>();
    final AbstractVcsHelper vcsHelper = AbstractVcsHelper.getInstance(project);

    try {
      fillDeletedFiles(project, deletedFiles, filesToProcess);
      if (deletedFiles.isEmpty() && filesToProcess.isEmpty() || myUndoingMove) return;
      SvnVcs vcs = SvnVcs.getInstance(project);
      final VcsShowConfirmationOption.Value value = vcs.getDeleteConfirmation().getValue();
      if (value != VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY) {
        if (!deletedFiles.isEmpty()) {
          final Collection<FilePath> confirmed =
              promptAboutDeletion(deletedFiles, vcs, value, vcsHelper);
          if (confirmed != null) {
            filesToProcess.addAll(confirmed);
          }
        }
        if (filesToProcess != null && !filesToProcess.isEmpty()) {
          runInBackground(
              project,
              "Deleting files from Subversion",
              createDeleteRunnable(project, vcs, filesToProcess, exceptions));
        }
        final List<FilePath> deletedFilesFiles =
            ObjectsConvertor.convert(
                deletedFiles,
                new Convertor<Pair<FilePath, WorkingCopyFormat>, FilePath>() {
                  @Override
                  public FilePath convert(Pair<FilePath, WorkingCopyFormat> o) {
                    return o.getFirst();
                  }
                });
        for (FilePath file : deletedFilesFiles) {
          final FilePath parent = file.getParentPath();
          if (parent != null) {
            myFilesToRefresh.add(parent.getVirtualFile());
          }
        }
        if (filesToProcess != null) {
          deletedFilesFiles.removeAll(filesToProcess);
        }
        for (FilePath file : deletedFilesFiles) {
          FileUtil.delete(file.getIOFile());
        }
      }
    } catch (SVNException e) {
      exceptions.add(new VcsException(e));
    }
    if (!exceptions.isEmpty()) {
      vcsHelper.showErrors(exceptions, SvnBundle.message("delete.files.errors.title"));
    }
  }
 private boolean doUsualMove(SvnVcs vcs, File src) {
   // if src is not under version control, do usual move.
   SVNStatus srcStatus = getFileStatus(vcs, src);
   if (srcStatus == null
       || SvnVcs.svnStatusIsUnversioned(srcStatus)
       || SvnVcs.svnStatusIs(srcStatus, SVNStatusType.STATUS_OBSTRUCTED)
       || SvnVcs.svnStatusIs(srcStatus, SVNStatusType.STATUS_MISSING)
       || SvnVcs.svnStatusIs(srcStatus, SVNStatusType.STATUS_EXTERNAL)) {
     return true;
   }
   return false;
 }
  private void fillAddedFiles(
      Project project,
      SvnVcs vcs,
      List<VirtualFile> addedVFiles,
      Map<VirtualFile, File> copyFromMap,
      Set<VirtualFile> recursiveItems) {
    final Collection<AddedFileInfo> addedFileInfos = myAddedFiles.remove(project);
    final ChangeListManager changeListManager = ChangeListManager.getInstance(project);

    for (AddedFileInfo addedFileInfo : addedFileInfos) {
      final File ioFile = new File(getIOFile(addedFileInfo.myDir), addedFileInfo.myName);
      VirtualFile addedFile = addedFileInfo.myDir.findChild(addedFileInfo.myName);
      if (addedFile == null) {
        addedFile = myLfs.refreshAndFindFileByIoFile(ioFile);
      }
      if (addedFile != null) {
        final SVNStatus fileStatus = getFileStatus(vcs, ioFile);
        if (fileStatus == null || !SvnVcs.svnStatusIs(fileStatus, SVNStatusType.STATUS_IGNORED)) {
          boolean isIgnored = changeListManager.isIgnoredFile(addedFile);
          if (!isIgnored) {
            addedVFiles.add(addedFile);
            copyFromMap.put(addedFile, addedFileInfo.myCopyFrom);
            if (addedFileInfo.myRecursive) {
              recursiveItems.add(addedFile);
            }
          }
        }
      }
    }
  }
  private boolean sameRoot(final SvnVcs vcs, final VirtualFile srcDir, final VirtualFile dstDir) {
    final UUIDHelper helper = new UUIDHelper(vcs);
    final String srcUUID = helper.getRepositoryUUID(vcs.getProject(), srcDir);
    final String dstUUID = helper.getRepositoryUUID(vcs.getProject(), dstDir);

    return srcUUID != null && dstUUID != null && srcUUID.equals(dstUUID);
  }
 private Collection<VirtualFile> promptAboutAddition(
     SvnVcs vcs,
     List<VirtualFile> addedVFiles,
     VcsShowConfirmationOption.Value value,
     AbstractVcsHelper vcsHelper) {
   Collection<VirtualFile> filesToProcess;
   if (value == VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY) {
     filesToProcess = addedVFiles;
   } else {
     final String singleFilePrompt;
     if (addedVFiles.size() == 1 && addedVFiles.get(0).isDirectory()) {
       singleFilePrompt = SvnBundle.getString("confirmation.text.add.dir");
     } else {
       singleFilePrompt = SvnBundle.getString("confirmation.text.add.file");
     }
     filesToProcess =
         vcsHelper.selectFilesToProcess(
             addedVFiles,
             SvnBundle.message("confirmation.title.add.multiple.files"),
             null,
             SvnBundle.message("confirmation.title.add.file"),
             singleFilePrompt,
             vcs.getAddConfirmation());
   }
   return filesToProcess;
 }
  private void fillMapping(final SvnMapping mapping, final List<SvnCopyRootSimple> list) {
    final LocalFileSystem lfs = LocalFileSystem.getInstance();

    for (SvnCopyRootSimple simple : list) {
      final VirtualFile copyRoot = lfs.findFileByIoFile(new File(simple.myCopyRoot));
      final VirtualFile vcsRoot = lfs.findFileByIoFile(new File(simple.myVcsRoot));

      if (copyRoot == null || vcsRoot == null) continue;

      final SvnVcs vcs = SvnVcs.getInstance(myProject);
      final SVNInfo svnInfo = vcs.getInfo(copyRoot);
      if ((svnInfo == null) || (svnInfo.getRepositoryRootURL() == null)) continue;

      final RootUrlInfo info =
          new RootUrlInfo(
              svnInfo.getRepositoryRootURL(),
              svnInfo.getURL(),
              SvnFormatSelector.getWorkingCopyFormat(svnInfo.getFile()),
              copyRoot,
              vcsRoot);
      mapping.add(info);
    }
  }
  /**
   * add file or directory:
   *
   * <p>parent directory is: unversioned: do nothing, return false versioned: entry is: null: create
   * entry, schedule for addition missing: do nothing, return false deleted, 'do' mode: try to
   * create entry and it schedule for addition if kind is the same, otherwise do nothing, return
   * false. deleted: 'undo' mode: try to revert non-recursively, if kind is the same, otherwise do
   * nothing, return false. anything else: return false.
   */
  private boolean createItem(
      VirtualFile dir, String name, boolean directory, final boolean recursive) {
    SvnVcs vcs = getVCS(dir);
    if (vcs == null) {
      return false;
    }
    final VcsShowConfirmationOption.Value value = vcs.getAddConfirmation().getValue();
    if (VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY.equals(value)) return false;

    if (isUndo(vcs) && SvnUtil.isAdminDirectory(dir, name)) {
      return false;
    }
    File ioDir = getIOFile(dir);
    boolean pendingAdd = isPendingAdd(vcs.getProject(), dir);
    if (!SvnUtil.isSvnVersioned(vcs.getProject(), ioDir) && !pendingAdd) {
      return false;
    }
    final File targetFile = new File(ioDir, name);
    SVNStatus status = getFileStatus(vcs, targetFile);

    if (status == null
        || status.getContentsStatus() == SVNStatusType.STATUS_NONE
        || status.getContentsStatus() == SVNStatusType.STATUS_UNVERSIONED) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(dir, name, null, recursive));
      return false;
    } else if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_MISSING)) {
      return false;
    } else if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_DELETED)) {
      SVNNodeKind kind = status.getKind();
      // kind differs.
      if (directory && kind != SVNNodeKind.DIR || !directory && kind != SVNNodeKind.FILE) {
        return false;
      }
      try {
        if (isUndo(vcs)) {
          createRevertAction(vcs, targetFile, false).execute();
          return true;
        }
        myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(dir, name, null, recursive));
        return false;
      } catch (SVNException e) {
        SVNFileUtil.deleteAll(targetFile, true);
        return false;
      }
    }
    return false;
  }
 private void processAddedFiles(Project project) {
   SvnVcs vcs = SvnVcs.getInstance(project);
   List<VirtualFile> addedVFiles = new ArrayList<VirtualFile>();
   Map<VirtualFile, File> copyFromMap = new HashMap<VirtualFile, File>();
   final Set<VirtualFile> recursiveItems = new HashSet<VirtualFile>();
   fillAddedFiles(project, vcs, addedVFiles, copyFromMap, recursiveItems);
   if (addedVFiles.isEmpty()) return;
   final VcsShowConfirmationOption.Value value = vcs.getAddConfirmation().getValue();
   if (value != VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY) {
     final AbstractVcsHelper vcsHelper = AbstractVcsHelper.getInstance(project);
     final Collection<VirtualFile> filesToProcess =
         promptAboutAddition(vcs, addedVFiles, value, vcsHelper);
     if (filesToProcess != null && !filesToProcess.isEmpty()) {
       final List<VcsException> exceptions = new ArrayList<VcsException>();
       runInBackground(
           project,
           "Adding files to Subversion",
           createAdditionRunnable(project, vcs, copyFromMap, filesToProcess, exceptions));
       if (!exceptions.isEmpty()) {
         vcsHelper.showErrors(exceptions, SvnBundle.message("add.files.errors.title"));
       }
     }
   }
 }
 private void fillDeletedFiles(
     Project project,
     List<Pair<FilePath, WorkingCopyFormat>> deletedFiles,
     Collection<FilePath> deleteAnyway)
     throws SVNException {
   final SvnVcs vcs = SvnVcs.getInstance(project);
   final Collection<File> files = myDeletedFiles.remove(project);
   for (final File file : files) {
     final SVNStatus status =
         new RepeatSvnActionThroughBusy() {
           @Override
           protected void executeImpl() throws SVNException {
             myT = vcs.getFactory(file).createStatusClient().doStatus(file, false);
           }
         }.compute();
     boolean isAdded = SVNStatusType.STATUS_ADDED.equals(status.getNodeStatus());
     final FilePath filePath = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file);
     if (isAdded) {
       deleteAnyway.add(filePath);
     } else {
       deletedFiles.add(Pair.create(filePath, vcs.getWorkingCopyFormat(file)));
     }
   }
 }
  public void realRefresh() {
    final SvnVcs vcs = SvnVcs.getInstance(myProject);
    final VirtualFile[] roots = myHelper.executeDefended(myProject);

    final CopiesApplier copiesApplier = new CopiesApplier();
    final CopiesDetector copiesDetector =
        new CopiesDetector(
            vcs,
            copiesApplier,
            new Getter<NestedCopiesData>() {
              public NestedCopiesData get() {
                return myTempSink.receive();
              }
            });
    // do not send additional request for nested copies when in init state
    copiesDetector.detectCopyRoots(roots, init());
  }
  @Nullable
  public File copy(final VirtualFile file, final VirtualFile toDir, final String copyName)
      throws IOException {
    SvnVcs vcs = getVCS(toDir);
    if (vcs == null) {
      vcs = getVCS(file);
    }
    if (vcs == null) {
      return null;
    }

    File srcFile = new File(file.getPath());
    File destFile = new File(new File(toDir.getPath()), copyName);
    final boolean dstDirUnderControl =
        SvnUtil.isSvnVersioned(vcs.getProject(), destFile.getParentFile());
    if (!dstDirUnderControl && !isPendingAdd(vcs.getProject(), toDir)) {
      return null;
    }

    if (!SvnUtil.isSvnVersioned(vcs.getProject(), srcFile.getParentFile())) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, null, false));
      return null;
    }

    final SVNStatus fileStatus = getFileStatus(vcs, srcFile);
    if (fileStatus != null && SvnVcs.svnStatusIs(fileStatus, SVNStatusType.STATUS_ADDED)) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, null, false));
      return null;
    }

    if (sameRoot(vcs, file.getParent(), toDir)) {
      myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, srcFile, false));
      return null;
    }

    myAddedFiles.putValue(vcs.getProject(), new AddedFileInfo(toDir, copyName, null, false));
    return null;
  }
  private boolean doMove(@NotNull SvnVcs vcs, final File src, final File dst) {
    long srcTime = src.lastModified();
    try {
      final boolean isUndo = isUndo(vcs);
      final String list = isUndo ? null : SvnChangelistListener.getCurrentMapping(vcs, src);

      WorkingCopyFormat format = vcs.getWorkingCopyFormat(src);
      final boolean is17OrLater =
          WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)
              || WorkingCopyFormat.ONE_DOT_SEVEN.equals(format);
      if (is17OrLater) {
        SVNStatus srcStatus = getFileStatus(vcs, src);
        final File toDir = dst.getParentFile();
        SVNStatus dstStatus = getFileStatus(vcs, toDir);
        final boolean srcUnversioned =
            srcStatus == null || SvnVcs.svnStatusIsUnversioned(srcStatus);
        if (srcUnversioned && (dstStatus == null || SvnVcs.svnStatusIsUnversioned(dstStatus))) {
          return false;
        }
        if (srcUnversioned) {
          SVNStatus dstWasStatus = getFileStatus(vcs, dst);
          if (dstWasStatus == null || SvnVcs.svnStatusIsUnversioned(dstWasStatus)) {
            return false;
          }
        }
        if (for17move(vcs, src, dst, isUndo, srcStatus)) return false;
      } else {
        if (for16move(vcs, src, dst, isUndo)) return false;
      }

      if (!isUndo && list != null) {
        SvnChangelistListener.putUnderList(vcs.getProject(), list, dst);
      }
      dst.setLastModified(srcTime);
    } catch (SVNException e) {
      addToMoveExceptions(vcs.getProject(), e);
      return false;
    } catch (VcsException e) {
      addToMoveExceptions(vcs.getProject(), e);
      return false;
    }
    return true;
  }
    public void detectCopyRoots(final VirtualFile[] roots, final boolean clearState) {
      final Getter<Boolean> cancelGetter =
          new Getter<Boolean>() {
            public Boolean get() {
              return myVcs.getProject().isDisposed();
            }
          };

      for (final VirtualFile vcsRoot : roots) {
        final List<Real> foundRoots =
            ForNestedRootChecker.getAllNestedWorkingCopies(vcsRoot, myVcs, false, cancelGetter);
        if (foundRoots.isEmpty()) {
          myLonelyRoots.add(vcsRoot);
        }
        // filter out bad(?) items
        for (Real foundRoot : foundRoots) {
          final SVNURL repoRoot = foundRoot.getInfo().getRepositoryRootURL();
          if (repoRoot == null) {
            LOG.info(
                "Error: cannot find repository URL for versioned folder: "
                    + foundRoot.getFile().getPath());
          } else {
            myRepositoryRoots.register(repoRoot);
            myTopRoots.add(
                new RootUrlInfo(
                    repoRoot,
                    foundRoot.getInfo().getURL(),
                    SvnFormatSelector.getWorkingCopyFormat(foundRoot.getInfo().getFile()),
                    foundRoot.getFile(),
                    vcsRoot));
          }
        }
      }

      if (!SvnConfiguration.getInstance(myVcs.getProject()).DETECT_NESTED_COPIES) {
        myApplier.apply(myVcs, myTopRoots, myLonelyRoots);
      } else {
        addNestedRoots(clearState);
      }
    }
 private static SVNStatus getExternalItemStatus(final SvnVcs vcs, final File file) {
   final SVNStatusClient statusClient = vcs.createStatusClient();
   try {
     if (file.isDirectory()) {
       return statusClient.doStatus(file, false);
     } else {
       final File parent = file.getParentFile();
       if (parent != null) {
         statusClient.setFilesProvider(
             new ISVNStatusFileProvider() {
               public Map getChildrenFiles(File parent) {
                 return Collections.singletonMap(file.getAbsolutePath(), file);
               }
             });
         final Ref<SVNStatus> refStatus = new Ref<SVNStatus>();
         statusClient.doStatus(
             parent,
             SVNRevision.WORKING,
             SVNDepth.FILES,
             false,
             true,
             false,
             false,
             new ISVNStatusHandler() {
               public void handleStatus(final SVNStatus status) throws SVNException {
                 if (file.equals(status.getFile())) {
                   refStatus.set(status);
                 }
               }
             },
             null);
         return refStatus.get();
       }
     }
   } catch (SVNException e) {
     //
   }
   return null;
 }
    public void handleStatus(final SVNStatus status) throws SVNException {
      myPartner.checkCanceled();
      final File ioFile = status.getFile();
      checkIfCopyRootWasReported();

      final LocalFileSystem lfs = LocalFileSystem.getInstance();
      VirtualFile vFile = lfs.findFileByIoFile(ioFile);
      if (vFile == null) {
        vFile = lfs.refreshAndFindFileByIoFile(ioFile);
      }
      if ((vFile != null) && myPartner.isExcluded(vFile)) return;

      if ((vFile != null) && (SvnVcs.svnStatusIsUnversioned(status))) {
        myReceiver.processUnversioned(vFile);
        if (vFile.isDirectory()) {
          processRecursively(vFile, myCurrentItem.getDepth());
        }
      } else {
        final FilePath path = VcsUtil.getFilePath(ioFile, status.getKind().equals(SVNNodeKind.DIR));
        myReceiver.process(path, status);
      }
    }
  private Collection<FilePath> promptAboutDeletion(
      List<Pair<FilePath, WorkingCopyFormat>> deletedFiles,
      SvnVcs vcs,
      VcsShowConfirmationOption.Value value,
      AbstractVcsHelper vcsHelper) {
    final Convertor<Pair<FilePath, WorkingCopyFormat>, FilePath> convertor =
        new Convertor<Pair<FilePath, WorkingCopyFormat>, FilePath>() {
          @Override
          public FilePath convert(Pair<FilePath, WorkingCopyFormat> o) {
            return o.getFirst();
          }
        };
    Collection<FilePath> filesToProcess;
    if (value == VcsShowConfirmationOption.Value.DO_ACTION_SILENTLY) {
      filesToProcess = ObjectsConvertor.convert(deletedFiles, convertor);
    } else {

      final String singleFilePrompt;
      if (deletedFiles.size() == 1 && deletedFiles.get(0).getFirst().isDirectory()) {
        singleFilePrompt =
            WorkingCopyFormat.ONE_DOT_SEVEN.equals(deletedFiles.get(0).getSecond())
                ? SvnBundle.getString("confirmation.text.delete.dir.17")
                : SvnBundle.getString("confirmation.text.delete.dir");
      } else {
        singleFilePrompt = SvnBundle.getString("confirmation.text.delete.file");
      }
      final Collection<FilePath> files =
          vcsHelper.selectFilePathsToProcess(
              ObjectsConvertor.convert(deletedFiles, convertor),
              SvnBundle.message("confirmation.title.delete.multiple.files"),
              null,
              SvnBundle.message("confirmation.title.delete.file"),
              singleFilePrompt,
              vcs.getDeleteConfirmation());
      filesToProcess = files == null ? null : new ArrayList<FilePath>(files);
    }
    return filesToProcess;
  }
    public void checkIfCopyRootWasReported() {
      if (!myMetCurrentItem && myCurrentItem.isIsInnerCopyRoot()) {
        myMetCurrentItem = true;
        final SVNStatus statusInner =
            SvnUtil.getStatus(SvnVcs.getInstance(myProject), myCurrentItem.getPath().getIOFile());
        if (statusInner == null) return;

        final SVNStatusType status = statusInner.getNodeStatus();
        if (SVNStatusType.OBSTRUCTED.equals(status)
            || SVNStatusType.STATUS_IGNORED.equals(status)
            || SVNStatusType.STATUS_NONE.equals(status)
            || SVNStatusType.STATUS_UNVERSIONED.equals(status)
            || SVNStatusType.UNKNOWN.equals(status)) {
          return;
        }
        if (myCurrentItem.getPath().getVirtualFile() != null) {
          myReceiver.processCopyRoot(
              myCurrentItem.getPath().getVirtualFile(),
              statusInner.getURL(),
              WorkingCopyFormat.getInstance(statusInner.getWorkingCopyFormat()));
        }
      }
    }
 private boolean for16move(SvnVcs vcs, final File src, final File dst, boolean undo)
     throws SVNException {
   final SVNMoveClient mover = vcs.createMoveClient();
   if (undo) {
     myUndoingMove = true;
     restoreFromUndoStorage(dst);
     new RepeatSvnActionThroughBusy() {
       @Override
       protected void executeImpl() throws SVNException {
         mover.undoMove(src, dst);
       }
     }.execute();
   } else {
     // if src is not under version control, do usual move.
     if (doUsualMove(vcs, src)) return true;
     new RepeatSvnActionThroughBusy() {
       @Override
       protected void executeImpl() throws SVNException {
         mover.doMove(src, dst);
       }
     }.execute();
   }
   return false;
 }
 protected VirtualFile[] execute(Project project) {
   return myPlVcsManager.getRootsUnderVcs(SvnVcs.getInstance(project));
 }
    private void addNestedRoots(final boolean clearState) {
      final List<VirtualFile> basicVfRoots =
          ObjectsConvertor.convert(
              myTopRoots,
              new Convertor<RootUrlInfo, VirtualFile>() {
                public VirtualFile convert(final RootUrlInfo real) {
                  return real.getVirtualFile();
                }
              });

      final ChangeListManager clManager = ChangeListManager.getInstance(myVcs.getProject());

      if (clearState) {
        // clear what was reported before (could be for currently-not-existing roots)
        myGate.get();
      }
      clManager.invokeAfterUpdate(
          new Runnable() {
            public void run() {
              final List<RootUrlInfo> nestedRoots = new ArrayList<RootUrlInfo>();

              final NestedCopiesData data = myGate.get();
              for (NestedCopiesBuilder.MyPointInfo info : data.getSet()) {
                if (NestedCopyType.external.equals(info.getType())
                    || NestedCopyType.switched.equals(info.getType())) {
                  final File infoFile = new File(info.getFile().getPath());
                  boolean copyFound = false;
                  for (RootUrlInfo topRoot : myTopRoots) {
                    if (topRoot.getIoFile().equals(infoFile)) {
                      topRoot.setType(info.getType());
                      copyFound = true;
                      break;
                    }
                  }
                  if (copyFound) {
                    continue;
                  }
                  try {
                    final SVNStatus svnStatus = SvnUtil.getStatus(myVcs, infoFile);
                    if (svnStatus.getURL() == null) continue;
                    info.setUrl(svnStatus.getURL());
                    info.setFormat(WorkingCopyFormat.getInstance(svnStatus.getWorkingCopyFormat()));
                  } catch (Exception e) {
                    continue;
                  }
                }
                for (RootUrlInfo topRoot : myTopRoots) {
                  if (VfsUtil.isAncestor(topRoot.getVirtualFile(), info.getFile(), true)) {
                    final SVNURL repoRoot = myRepositoryRoots.ask(info.getUrl());
                    if (repoRoot != null) {
                      final RootUrlInfo rootInfo =
                          new RootUrlInfo(
                              repoRoot,
                              info.getUrl(),
                              info.getFormat(),
                              info.getFile(),
                              topRoot.getRoot());
                      rootInfo.setType(info.getType());
                      nestedRoots.add(rootInfo);
                    }
                    break;
                  }
                }
              }
              // check those top roots which ARE externals, but that was not detected due to they
              // itself were the status request target
              // new SvnNestedTypeRechecker(myVcs.getProject(), myTopRoots).run();

              myTopRoots.addAll(nestedRoots);
              myApplier.apply(myVcs, myTopRoots, myLonelyRoots);
            }
          },
          InvokeAfterUpdateMode.SILENT_CALLBACK_POOLED,
          null,
          new Consumer<VcsDirtyScopeManager>() {
            public void consume(VcsDirtyScopeManager vcsDirtyScopeManager) {
              if (clearState) {
                vcsDirtyScopeManager.filesDirty(null, basicVfRoots);
              }
            }
          },
          null);
    }
  /**
   * delete file or directory (both 'undo' and 'do' modes) unversioned: do nothing, return false
   * obstructed: do nothing, return false external or wc root: do nothing, return false missing: do
   * nothing, return false
   *
   * <p>versioned: schedule for deletion, return true added: schedule for deletion (make
   * unversioned), return true copied, but not scheduled: schedule for deletion, return true
   * replaced: schedule for deletion, return true
   *
   * <p>deleted: do nothing, return true (strange)
   */
  public boolean delete(VirtualFile file) throws IOException {
    final SvnVcs vcs = getVCS(file);
    if (vcs != null && SvnUtil.isAdminDirectory(file)) {
      return true;
    }
    if (vcs == null) return false;
    final VcsShowConfirmationOption.Value value = vcs.getDeleteConfirmation().getValue();
    if (VcsShowConfirmationOption.Value.DO_NOTHING_SILENTLY.equals(value)) return false;

    final File ioFile = getIOFile(file);
    if (!SvnUtil.isSvnVersioned(vcs.getProject(), ioFile.getParentFile())) {
      return false;
    }
    if (SvnUtil.isWorkingCopyRoot(ioFile)) {
      return false;
    }

    SVNStatus status = getFileStatus(vcs, ioFile);

    if (status == null
        || SvnVcs.svnStatusIsUnversioned(status)
        || SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_OBSTRUCTED)
        || SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_MISSING)
        || SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_EXTERNAL)
        || SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_IGNORED)) {
      return false;
    } else if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_DELETED)) {
      if (isUndo(vcs)) {
        moveToUndoStorage(file);
      }
      return true;
    } else {
      if (vcs != null) {
        if (isAboveSourceOfCopyOrMove(vcs.getProject(), ioFile)) {
          myDeletedFiles.putValue(vcs.getProject(), ioFile);
          return true;
        }
        if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_ADDED)) {
          try {
            createRevertAction(vcs, ioFile, false).execute();
          } catch (SVNException e) {
            // ignore
          }
        } else {
          myDeletedFiles.putValue(vcs.getProject(), ioFile);
          // packages deleted from disk should not be deleted from svn (IDEADEV-16066)
          if (file.isDirectory() || isUndo(vcs)) return true;
        }
      }
      return false;
    }
  }