@Nullable
 private static VirtualFile findFileToPatchByComponents(
     ApplyPatchContext context, final String[] pathNameComponents, final int lastComponentToFind) {
   VirtualFile patchedDir = context.getBaseDir();
   for (int i = context.getSkipTopDirs(); i < lastComponentToFind; i++) {
     VirtualFile nextChild;
     if (pathNameComponents[i].equals("..")) {
       nextChild = patchedDir.getParent();
     } else {
       nextChild = patchedDir.findChild(pathNameComponents[i]);
     }
     if (nextChild == null) {
       if (context.isCreateDirectories()) {
         try {
           nextChild = patchedDir.createChildDirectory(null, pathNameComponents[i]);
         } catch (IOException e) {
           return null;
         }
       } else {
         context.registerMissingDirectory(patchedDir, pathNameComponents, i);
         return null;
       }
     }
     patchedDir = nextChild;
   }
   return patchedDir;
 }
 private static boolean checkPackageRename(
     final ApplyPatchContext context,
     final String[] beforeNameComponents,
     final String[] afterNameComponents) {
   int changedIndex = -1;
   for (int i = context.getSkipTopDirs(); i < afterNameComponents.length - 1; i++) {
     if (!beforeNameComponents[i].equals(afterNameComponents[i])) {
       if (changedIndex != -1) {
         return true;
       }
       changedIndex = i;
     }
   }
   if (changedIndex == -1) return false;
   VirtualFile oldDir =
       findFileToPatchByComponents(context, beforeNameComponents, changedIndex + 1);
   VirtualFile newDir =
       findFileToPatchByComponents(
           context.getPrepareContext(), afterNameComponents, changedIndex + 1);
   if (oldDir != null && newDir == null) {
     context.addPendingRename(oldDir, afterNameComponents[changedIndex]);
     return false;
   }
   return true;
 }
 @Nullable
 public static VirtualFile findPatchTarget(
     final ApplyPatchContext context,
     final String beforeName,
     final String afterName,
     final boolean isNewFile)
     throws IOException {
   VirtualFile file = null;
   if (beforeName != null) {
     file = findFileToPatchByName(context, beforeName, isNewFile);
   }
   if (file == null) {
     file = findFileToPatchByName(context, afterName, isNewFile);
   } else if (context.isAllowRename() && afterName != null && !beforeName.equals(afterName)) {
     String[] beforeNameComponents = beforeName.split("/");
     String[] afterNameComponents = afterName.split("/");
     if (!beforeNameComponents[beforeNameComponents.length - 1].equals(
         afterNameComponents[afterNameComponents.length - 1])) {
       context.registerBeforeRename(file);
       file.rename(FilePatch.class, afterNameComponents[afterNameComponents.length - 1]);
       context.addAffectedFile(file);
     }
     boolean needMove = (beforeNameComponents.length != afterNameComponents.length);
     if (!needMove) {
       needMove = checkPackageRename(context, beforeNameComponents, afterNameComponents);
     }
     if (needMove) {
       VirtualFile moveTarget =
           findFileToPatchByComponents(
               context, afterNameComponents, afterNameComponents.length - 1);
       if (moveTarget == null) {
         return null;
       }
       context.registerBeforeRename(file);
       file.move(FilePatch.class, moveTarget);
       context.addAffectedFile(file);
     }
   }
   return file;
 }
 public Result apply(
     final VirtualFile fileToPatch,
     final ApplyPatchContext context,
     final Project project,
     FilePath pathBeforeRename,
     Getter<CharSequence> baseContents,
     CommitContext commitContext)
     throws IOException {
   if (LOG.isDebugEnabled()) {
     LOG.debug("apply patch called for : " + fileToPatch.getPath());
   }
   context.addAffectedFile(getTarget(fileToPatch));
   if (myPatch.isNewFile()) {
     applyCreate(fileToPatch, commitContext);
   } else if (myPatch.isDeletedFile()) {
     FileEditorManagerImpl.getInstance(project).closeFile(fileToPatch);
     fileToPatch.delete(this);
   } else {
     return applyChange(project, fileToPatch, pathBeforeRename, baseContents);
   }
   return SUCCESS;
 }