docs: @NotNull
      public static File backup(@NotNull final Backupable source,
                                @NotNull final File target, final boolean zip) throws Exception {
          if (target.exists()) {
              throw new IOException("Backup file already exists:" + target.getAbsolutePath());
          }
          final BackupStrategy strategy = source.getBackupStrategy();
          strategy.beforeBackup();
          try (OutputStream output = new BufferedOutputStream(new FileOutputStream(target))) {
              final ArchiveOutputStream archive;
              if (zip) {
                  final ZipArchiveOutputStream zipArchive = new ZipArchiveOutputStream(output);
                  zipArchive.setLevel(Deflater.BEST_COMPRESSION);
                  archive = zipArchive;
              } else {
                  archive = new TarArchiveOutputStream(new GZIPOutputStream(output));
              }
              try (ArchiveOutputStream aos = archive) {
                  for (final VirtualFileDescriptor fd : strategy.getContents()) {
                      if (strategy.isInterrupted()) {
                          break;
                      }
                      if (fd.hasContent()) {
                          final long fileSize = Math.min(fd.getFileSize(), strategy.acceptFile(fd));
                          if (fileSize > 0L) {
                              archiveFile(aos, fd, fileSize);
                          }
                      }
                  }
              }
              if (strategy.isInterrupted()) {
                  logger.info("Backup interrupted, deleting \"" + target.getName() + "\"...");
                  IOUtil.deleteFile(target);
              } else {
                  logger.info("Backup file \"" + target.getName() + "\" created.");
              }
          } catch (Throwable t) {
              strategy.onError(t);
              throw ExodusException.toExodusException(t, "Backup failed");
          } finally {
              strategy.afterBackup();
          }
          return target;
      }