void (@Nullable Project project, @NotNull Runnable onSuccess, @NotNull Runnable onFailure, boolean withReplace) { File directory = new File(DOWNLOAD_PATH); if (!directory.exists()) { //noinspection ResultOfMethodCallIgnored directory.mkdirs(); } File formatter = new File(DOWNLOAD_PATH + File.separator + SHFMT + (SystemInfo.isWindows ? WINDOWS_EXTENSION : "")); File oldFormatter = new File(DOWNLOAD_PATH + File.separator + OLD_SHFMT + (SystemInfo.isWindows ? WINDOWS_EXTENSION : "")); if (formatter.exists()) { if (withReplace) { boolean successful = renameOldFormatter(formatter, oldFormatter, onFailure); if (!successful) return; } else { setupFormatterPath(formatter, onSuccess, onFailure); return; } } String downloadName = SHFMT + (SystemInfo.isWindows ? WINDOWS_EXTENSION : ""); DownloadableFileService service = DownloadableFileService.getInstance(); DownloadableFileDescription description = service.createFileDescription(getShfmtDistributionLink(), downloadName); FileDownloader downloader = service.createDownloader(Collections.singletonList(description), downloadName); Task.Backgroundable task = new Task.Backgroundable(project, message("sh.label.download.shfmt.formatter")) { @Override public void run(@NotNull ProgressIndicator indicator) { try { List<Pair<File, DownloadableFileDescription>> pairs = downloader.download(new File(DOWNLOAD_PATH)); Pair<File, DownloadableFileDescription> first = ContainerUtil.getFirstItem(pairs); File file = first != null ? first.first : null; if (file != null) { FileUtil.setExecutable(file); ShSettings.setShfmtPath(file.getCanonicalPath()); if (withReplace) { LOG.info("Remove old formatter"); FileUtil.delete(oldFormatter); } ApplicationManager.getApplication().invokeLater(onSuccess); EXTERNAL_FORMATTER_DOWNLOADED_EVENT_ID.log(); } } catch (IOException e) { LOG.warn("Can't download shfmt formatter", e); if (withReplace) rollbackToOldFormatter(formatter, oldFormatter); ApplicationManager.getApplication().invokeLater(onFailure); } } }; BackgroundableProcessIndicator processIndicator = new BackgroundableProcessIndicator(task); processIndicator.setIndeterminate(false); ProgressManager.getInstance().runProcessWithProgressAsynchronously(task, processIndicator); }