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 static boolean isUndo(SvnVcs vcs) {
   if (vcs == null || vcs.getProject() == null) {
     return false;
   }
   Project p = vcs.getProject();
   return UndoManager.getInstance(p).isUndoInProgress();
 }
  /**
   * 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;
    }
  }
  public byte[] loadContent() throws IOException, VcsException {
    ContentLoader loader = new ContentLoader(myURL, myRevision, myPegRevision);
    if (ApplicationManager.getApplication().isDispatchThread() && !myRevision.isLocal()) {
      ProgressManager.getInstance()
          .runProcessWithProgressSynchronously(
              loader,
              SvnBundle.message("progress.title.loading.file.content"),
              false,
              myVCS.getProject());
    } else {
      loader.run();
    }

    VcsException exception = loader.getException();
    if (exception == null) {
      final byte[] contents = loader.getContents();
      ContentRevisionCache.checkContentsSize(myURL, contents.length);
      return contents;
    } else {
      LOG.info(
          "Failed to load file '"
              + myURL
              + "' content at revision: "
              + myRevision
              + "\n"
              + exception.getMessage(),
          exception);
      throw exception;
    }
  }
    @Override
    public void apply(
        @NotNull MultiMap<VirtualFile, TextFilePatchInProgress> patchGroups,
        @Nullable LocalChangeList localList,
        @Nullable String fileName,
        @Nullable
            TransparentlyFailedValueI<Map<String, Map<String, CharSequence>>, PatchSyntaxException>
                additionalInfo) {
      final List<FilePatch> patches;
      try {
        patches = ApplyPatchSaveToFileExecutor.patchGroupsToOneGroup(patchGroups, myBaseDir);
      } catch (IOException e) {
        myInner.handleException(e, true);
        return;
      }

      final PatchApplier<BinaryFilePatch> patchApplier =
          new PatchApplier<BinaryFilePatch>(
              myVcs.getProject(), myBaseDir, patches, localList, null, null);
      patchApplier.execute(false, true); // 3
      boolean thereAreCreations = false;
      for (FilePatch patch : patches) {
        if (patch.isNewFile() || !Comparing.equal(patch.getAfterName(), patch.getBeforeName())) {
          thereAreCreations = true;
          break;
        }
      }
      if (thereAreCreations) {
        // restore deletion of old directory:
        myInner.next(new DirectoryAddition()); // 2
      }
      appendResolveConflictToContext(myInner); // 1
      appendTailToContextLast(myInner); // 4
      myInner.ping();
    }
  public SvnKitManager(@NotNull SvnVcs vcs) {
    myVcs = vcs;
    myProject = myVcs.getProject();
    myConfiguration = myVcs.getSvnConfiguration();

    refreshSSLProperty();
  }
  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);
  }
  public void execute() {
    int ok =
        Messages.showOkCancelDialog(
            myVcs.getProject(),
            (myChange.isMoved()
                ? SvnBundle.message(
                    "confirmation.resolve.tree.conflict.merge.moved",
                    myOldPresentation,
                    myNewPresentation)
                : SvnBundle.message(
                    "confirmation.resolve.tree.conflict.merge.renamed",
                    myOldPresentation,
                    myNewPresentation)),
            TreeConflictRefreshablePanel.TITLE,
            Messages.getQuestionIcon());
    if (Messages.OK != ok) return;

    FileDocumentManager.getInstance().saveAllDocuments();
    // final String name = "Merge changes from theirs for: " + myOldPresentation;

    final Continuation fragmented = Continuation.createFragmented(myVcs.getProject(), false);
    fragmented.addExceptionHandler(
        VcsException.class,
        new Consumer<VcsException>() {
          @Override
          public void consume(VcsException e) {
            myWarnings.add(e);
            if (e.isWarning()) {
              return;
            }
            AbstractVcsHelper.getInstance(myVcs.getProject())
                .showErrors(myWarnings, TreeConflictRefreshablePanel.TITLE);
          }
        });

    final List<TaskDescriptor> tasks = new SmartList<TaskDescriptor>();
    tasks.add(
        myDescription.isDirectory()
            ? new PreloadChangesContentsForDir()
            : new PreloadChangesContentsForFile());
    tasks.add(new ConvertTextPaths());
    tasks.add(new PatchCreator());
    tasks.add(new SelectPatchesInApplyPatchDialog());
    tasks.add(new SelectBinaryFiles());

    fragmented.run(tasks);
  }
  /**
   * 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 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 SvnAuthenticationManager getManager(final AuthManagerType type, final SvnVcs vcs) {
   if (AuthManagerType.active.equals(type)) {
     return getInteractiveManager(vcs);
   } else if (AuthManagerType.passive.equals(type)) {
     return getPassiveAuthenticationManager(vcs.getProject());
   } else if (AuthManagerType.usual.equals(type)) {
     return getAuthenticationManager(vcs);
   }
   throw new IllegalArgumentException();
 }
 public SvnAuthenticationManager getInteractiveManager(final SvnVcs svnVcs) {
   if (myInteractiveManager == null) {
     myInteractiveManager =
         new SvnAuthenticationManager(svnVcs.getProject(), new File(getConfigurationDirectory()));
     myInteractiveManager.setRuntimeStorage(RUNTIME_AUTH_CACHE);
     myInteractiveProvider =
         new SvnInteractiveAuthenticationProvider(svnVcs, myInteractiveManager);
     myInteractiveManager.setAuthenticationProvider(myInteractiveProvider);
   }
   return myInteractiveManager;
 }
 public SvnAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) {
   if (myAuthManager == null) {
     // reloaded when configuration directory changes
     myAuthManager =
         new SvnAuthenticationManager(svnVcs.getProject(), new File(getConfigurationDirectory()));
     Disposer.register(
         svnVcs.getProject(),
         new Disposable() {
           @Override
           public void dispose() {
             myAuthManager = null;
           }
         });
     getInteractiveManager(svnVcs);
     // to init
     myAuthManager.setAuthenticationProvider(
         new SvnAuthenticationProvider(svnVcs, myInteractiveProvider, RUNTIME_AUTH_CACHE));
     myAuthManager.setRuntimeStorage(RUNTIME_AUTH_CACHE);
   }
   return myAuthManager;
 }
  private boolean getAddedFilesPlaceOption() {
    final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject());
    boolean add = Boolean.TRUE.equals(configuration.isKeepNewFilesAsIsForTreeConflictMerge());
    if (configuration.isKeepNewFilesAsIsForTreeConflictMerge() != null) {
      return add;
    }
    if (!containAdditions(myTheirsChanges) && !containAdditions(myTheirsBinaryChanges)) {
      return false;
    }
    return Messages.YES
        == MessageDialogBuilder.yesNo(
                TreeConflictRefreshablePanel.TITLE,
                "Keep newly created file(s) in their original place?")
            .yesText("Keep")
            .noText("Move")
            .doNotAsk(
                new DialogWrapper.DoNotAskOption() {
                  @Override
                  public boolean isToBeShown() {
                    return true;
                  }

                  @Override
                  public void setToBeShown(boolean value, int exitCode) {
                    if (!value) {
                      if (exitCode == 0) {
                        // yes
                        configuration.setKeepNewFilesAsIsForTreeConflictMerge(true);
                      } else {
                        configuration.setKeepNewFilesAsIsForTreeConflictMerge(false);
                      }
                    }
                  }

                  @Override
                  public boolean canBeHidden() {
                    return true;
                  }

                  @Override
                  public boolean shouldSaveOptionsOnCancel() {
                    return true;
                  }

                  @NotNull
                  @Override
                  public String getDoNotShowMessage() {
                    return CommonBundle.message("dialog.options.do.not.ask");
                  }
                })
            .show();
  }
Пример #15
0
 @Override
 public void reportAppendableHistory(
     FilePath path, final VcsAppendableHistorySessionPartner partner) throws VcsException {
   // we need + 1 rows to be reported to further detect that number of rows exceeded the limit
   reportAppendableHistory(
       path,
       partner,
       null,
       null,
       VcsConfiguration.getInstance(myVcs.getProject()).MAXIMUM_HISTORY_ROWS + 1,
       null,
       false);
 }
  @Nullable
  public String getContent() throws VcsException {
    try {
      if (myUseBaseRevision) {
        return ContentRevisionCache.getOrLoadCurrentAsString(
                myVcs.getProject(),
                myFile,
                myVcs.getKeyInstanceMethod(),
                new CurrentRevisionProvider() {
                  @Override
                  public VcsRevisionNumber getCurrentRevision() throws VcsException {
                    return getRevisionNumber();
                  }

                  @Override
                  public Pair<VcsRevisionNumber, byte[]> get() throws VcsException, IOException {
                    return Pair.create(getRevisionNumber(), getUpToDateBinaryContent());
                  }
                })
            .getSecond();
      } else {
        return ContentRevisionCache.getOrLoadAsString(
            myVcs.getProject(),
            myFile,
            getRevisionNumber(),
            myVcs.getKeyInstanceMethod(),
            ContentRevisionCache.UniqueType.REPOSITORY_CONTENT,
            new Throwable2Computable<byte[], VcsException, IOException>() {
              @Override
              public byte[] compute() throws VcsException, IOException {
                return getUpToDateBinaryContent();
              }
            });
      }
    } catch (IOException e) {
      throw new VcsException(e);
    }
  }
  public void reportAppendableHistory(
      FilePath path, final VcsAppendableHistorySessionPartner partner) throws VcsException {
    final FilePath committedPath = ChangesUtil.getCommittedPath(myVcs.getProject(), path);

    final LogLoader logLoader;
    if (path.isNonLocal()) {
      logLoader = new RepositoryLoader(myVcs, path);
    } else {
      logLoader = new LocalLoader(myVcs, path);
    }

    try {
      logLoader.preliminary();
    } catch (SVNCancelException e) {
      return;
    } catch (SVNException e) {
      throw new VcsException(e);
    }
    logLoader.initSupports15();

    final MyHistorySession historySession =
        new MyHistorySession(
            Collections.<VcsFileRevision>emptyList(),
            committedPath,
            Boolean.TRUE.equals(logLoader.mySupport15),
            null);

    final Ref<Boolean> sessionReported = new Ref<Boolean>();
    final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
    if (indicator != null) {
      indicator.setText(SvnBundle.message("progress.text2.collecting.history", path.getName()));
    }
    final Consumer<VcsFileRevision> consumer =
        new Consumer<VcsFileRevision>() {
          public void consume(VcsFileRevision vcsFileRevision) {
            if (!Boolean.TRUE.equals(sessionReported.get())) {
              partner.reportCreatedEmptySession(historySession);
              sessionReported.set(true);
            }
            partner.acceptRevision(vcsFileRevision);
          }
        };

    logLoader.setConsumer(consumer);
    logLoader.load();
    logLoader.check();
  }
    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 Collection<FilePath> chooseBinaryFiles(List<Change> converted, Set<FilePath> paths) {
    String singleMessage = "";
    if (paths.size() == 1) {
      final Change change = converted.get(0);
      final FileStatus status = change.getFileStatus();
      final FilePath path = ChangesUtil.getFilePath(change);
      final String stringPath = TreeConflictRefreshablePanel.filePath(path);
      if (FileStatus.DELETED.equals(status)) {
        singleMessage = "Delete binary file " + stringPath + " (according to theirs changes)?";
      } else if (FileStatus.ADDED.equals(status)) {
        singleMessage = "Create binary file " + stringPath + " (according to theirs changes)?";
      } else {
        singleMessage =
            "Apply changes to binary file " + stringPath + " (according to theirs changes)?";
      }
    }
    return AbstractVcsHelper.getInstance(myVcs.getProject())
        .selectFilePathsToProcess(
            new ArrayList<FilePath>(paths),
            TreeConflictRefreshablePanel.TITLE,
            "Select binary files to patch",
            TreeConflictRefreshablePanel.TITLE,
            singleMessage,
            new VcsShowConfirmationOption() {

              @Override
              public Value getValue() {
                return null;
              }

              @Override
              public void setValue(Value value) {}

              @Override
              public boolean isPersistent() {
                return false;
              }
            });
  }
  public byte[] getContent() throws IOException, VcsException {
    byte[] result;

    if (SVNRevision.HEAD.equals(myRevision)) {
      result = loadContent();
    } else {
      result =
          ContentRevisionCache.getOrLoadAsBytes(
              myVCS.getProject(),
              VcsUtil.getFilePathOnNonLocal(myURL, false),
              getRevisionNumber(),
              myVCS.getKeyInstanceMethod(),
              ContentRevisionCache.UniqueType.REMOTE_CONTENT,
              new Throwable2Computable<byte[], VcsException, IOException>() {
                @Override
                public byte[] compute() throws VcsException, IOException {
                  return loadContent();
                }
              });
    }

    return result;
  }
  private static void addRecursively(final SvnVcs activeVcs, final VirtualFile file)
      throws SVNException {
    final SVNWCClient wcClient = activeVcs.createWCClient();
    final SvnExcludingIgnoredOperation operation =
        new SvnExcludingIgnoredOperation(
            activeVcs.getProject(),
            new SvnExcludingIgnoredOperation.Operation() {
              public void doOperation(final VirtualFile virtualFile) throws SVNException {
                final File ioFile = new File(virtualFile.getPath());
                final ProgressIndicator indicator =
                    ProgressManager.getInstance().getProgressIndicator();
                if (indicator != null) {
                  indicator.checkCanceled();
                  indicator.setText(
                      SvnBundle.message(
                          "share.or.import.add.progress.text", virtualFile.getPath()));
                }
                wcClient.doAdd(ioFile, true, false, false, SVNDepth.EMPTY, false, false);
              }
            },
            SVNDepth.INFINITY);

    operation.execute(file);
  }
  @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;
  }
Пример #23
0
  public void reportAppendableHistory(
      FilePath path,
      final VcsAppendableHistorySessionPartner partner,
      @Nullable final SVNRevision from,
      @Nullable final SVNRevision to,
      final int limit,
      SVNRevision peg,
      final boolean forceBackwards)
      throws VcsException {
    FilePath committedPath = path;
    Change change = ChangeListManager.getInstance(myVcs.getProject()).getChange(path);
    if (change != null) {
      final ContentRevision beforeRevision = change.getBeforeRevision();
      final ContentRevision afterRevision = change.getAfterRevision();
      if (beforeRevision != null
          && afterRevision != null
          && !beforeRevision.getFile().equals(afterRevision.getFile())
          && afterRevision.getFile().equals(path)) {
        committedPath = beforeRevision.getFile();
      }
      // revision can be VcsRevisionNumber.NULL
      if (peg == null
          && change.getBeforeRevision() != null
          && change.getBeforeRevision().getRevisionNumber() instanceof SvnRevisionNumber) {
        peg = ((SvnRevisionNumber) change.getBeforeRevision().getRevisionNumber()).getRevision();
      }
    }

    final boolean showMergeSources =
        SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate();
    final LogLoader logLoader;
    if (path.isNonLocal()) {
      logLoader =
          new RepositoryLoader(
              myVcs, committedPath, from, to, limit, peg, forceBackwards, showMergeSources);
    } else {
      logLoader = new LocalLoader(myVcs, committedPath, from, to, limit, peg, showMergeSources);
    }

    try {
      logLoader.preliminary();
    } catch (SVNCancelException e) {
      throw new VcsException(e);
    } catch (SVNException e) {
      throw new VcsException(e);
    }
    logLoader.check();
    if (showMergeSources) {
      logLoader.initSupports15();
    }

    final SvnHistorySession historySession =
        new SvnHistorySession(
            myVcs,
            Collections.<VcsFileRevision>emptyList(),
            committedPath,
            showMergeSources && Boolean.TRUE.equals(logLoader.mySupport15),
            null,
            false,
            !path.isNonLocal());

    final Ref<Boolean> sessionReported = new Ref<Boolean>();
    final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
    if (indicator != null) {
      indicator.setText(SvnBundle.message("progress.text2.collecting.history", path.getName()));
    }
    final Consumer<VcsFileRevision> consumer =
        new Consumer<VcsFileRevision>() {
          @Override
          public void consume(VcsFileRevision vcsFileRevision) {
            if (!Boolean.TRUE.equals(sessionReported.get())) {
              partner.reportCreatedEmptySession(historySession);
              sessionReported.set(true);
            }
            partner.acceptRevision(vcsFileRevision);
          }
        };

    logLoader.setConsumer(consumer);
    logLoader.load();
    logLoader.check();
  }
    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);
    }