public static void copyDir(
     @NotNull File fromDir, @NotNull File toDir, @Nullable final FileFilter filter)
     throws IOException {
   ensureExists(toDir);
   if (isAncestor(fromDir, toDir, true)) {
     LOG.error(fromDir.getAbsolutePath() + " is ancestor of " + toDir + ". Can't copy to itself.");
     return;
   }
   File[] files = fromDir.listFiles();
   if (files == null)
     throw new IOException(
         CommonBundle.message("exception.directory.is.invalid", fromDir.getPath()));
   if (!fromDir.canRead())
     throw new IOException(
         CommonBundle.message("exception.directory.is.not.readable", fromDir.getPath()));
   for (File file : files) {
     if (filter != null && !filter.accept(file)) {
       continue;
     }
     if (file.isDirectory()) {
       copyDir(file, new File(toDir, file.getName()), filter);
     } else {
       copy(file, new File(toDir, file.getName()));
     }
   }
 }
 public static boolean isFilePathAcceptable(@NotNull File root, @Nullable FileFilter fileFilter) {
   File file = root;
   do {
     if (fileFilter != null && !fileFilter.accept(file)) return false;
     file = file.getParentFile();
   } while (file != null);
   return true;
 }