public static @NotNull ApplyPatchStatus applyContent(@NotNull Project project,
                                                       @NotNull ApplyFilePatchBase<?> patch,
                                                       @Nullable ApplyPatchContext context,
                                                       @NotNull VirtualFile file,
                                                       @Nullable CommitContext commitContext,
                                                       boolean reverse,
                                                       @Nullable String leftPanelTitle,
                                                       @Nullable String rightPanelTitle) {
    ApplyFilePatch.Result result = tryApplyPatch(project, patch, context, file, commitContext);

    ApplyPatchStatus status = result.getStatus();
    if (ApplyPatchStatus.ALREADY_APPLIED.equals(status) || ApplyPatchStatus.SUCCESS.equals(status)) {
      return status;
    }

    ApplyPatchForBaseRevisionTexts mergeData = result.getMergeData();
    if (mergeData == null) {
      return status;
    }

    Document document = FileDocumentManager.getInstance().getDocument(file);
    if (document == null) {
      return ApplyPatchStatus.FAILURE;
    }

    if (mergeData.getBase() == null && ApplyPatchStatus.PARTIAL.equals(status)) {
      WriteAction.run(() -> {
        VcsFacade.getInstance().runHeavyModificationTask(project, document, () -> document.setText(mergeData.getPatched()));
        FileDocumentManager.getInstance().saveDocument(document);
      });
      return status;
    }

    String baseContent = convertLineSeparators(mergeData.getBase());
    String localContent = convertLineSeparators(mergeData.getLocal());
    String patchedContent = mergeData.getPatched();

    if (localContent.equals(patchedContent)) {
      return ApplyPatchStatus.ALREADY_APPLIED;
    }

    Ref<ApplyPatchStatus> applyPatchStatusReference = new Ref<>();
    Consumer<MergeResult> callback = result13 -> {
      FileDocumentManager.getInstance().saveDocument(document);
      applyPatchStatusReference.setIfNull(result13 != MergeResult.CANCEL ? ApplyPatchStatus.SUCCESS : ApplyPatchStatus.FAILURE);
    };

    try {
      MergeRequest request;
      if (baseContent != null) {
        if (reverse) {
          if (leftPanelTitle == null) leftPanelTitle = VcsBundle.message("patch.apply.conflict.patched.version");
          if (rightPanelTitle == null) rightPanelTitle = VcsBundle.message("patch.apply.conflict.local.version");

          List<String> contents = Arrays.asList(patchedContent, baseContent, localContent);
          List<String> titles = Arrays.asList(leftPanelTitle, null, rightPanelTitle);

          request = PatchDiffRequestFactory
            .createMergeRequest(project, document, file, contents, null, titles, callback);
        }
        else {
          request = PatchDiffRequestFactory
            .createMergeRequest(project, document, file, baseContent, localContent, patchedContent, callback);
        }
      }
      else {
        TextFilePatch textPatch = (TextFilePatch)patch.getPatch();
        GenericPatchApplier applier = new GenericPatchApplier(localContent, textPatch.getHunks());
        applier.execute();

        final AppliedTextPatch appliedTextPatch = AppliedTextPatch.create(applier.getAppliedInfo());
        request = PatchDiffRequestFactory.createBadMergeRequest(project, document, file, localContent, appliedTextPatch, callback);
      }
      request.putUserData(DiffUserDataKeysEx.MERGE_ACTION_CAPTIONS, result12 -> result12.equals(MergeResult.CANCEL) ? VcsBundle
        .message("patch.apply.abort.action") : null);
      request.putUserData(DiffUserDataKeysEx.MERGE_CANCEL_HANDLER, viewer -> {
        String message = VcsBundle.message("patch.apply.abort.and.rollback.prompt");
        String title = VcsBundle.message("patch.apply.abort.title");
        String yesText = VcsBundle.message("patch.apply.abort.and.rollback.action");
        String noText = VcsBundle.message("patch.apply.skip.action");
        String cancelText = VcsBundle.message("patch.apply.continue.resolve.action");
        int result1 = Messages.showYesNoCancelDialog(viewer.getComponent().getRootPane(), message, title, yesText, noText, cancelText,
                                                     Messages.getQuestionIcon());
        if (result1 == Messages.YES) {
          applyPatchStatusReference.set(ApplyPatchStatus.ABORT);
        }
        else if (result1 == Messages.NO) {
          applyPatchStatusReference.set(ApplyPatchStatus.SKIP);
        }
        return result1 != Messages.CANCEL;
      });
      DiffManager.getInstance().showMerge(project, request);
      return applyPatchStatusReference.get();
    }
    catch (InvalidDiffRequestException e) {
      LOG.warn(e);
      return ApplyPatchStatus.FAILURE;
    }
  }
public static @NotNull ApplyPatchStatus applyContent(@NotNull Project project,
                                                       @NotNull ApplyFilePatchBase<?> patch,
                                                       @Nullable ApplyPatchContext context,
                                                       @NotNull VirtualFile file,
                                                       @Nullable CommitContext commitContext,
                                                       boolean reverse,
                                                       @Nullable String leftPanelTitle,
                                                       @Nullable String rightPanelTitle)