pt III, slowly moving to the new file handling api (File -> Path)
							parent
							
								
									a85db99d82
								
							
						
					
					
						commit
						b4597f6f1f
					
				| 
						 | 
				
			
			@ -20,7 +20,7 @@ package net.szum123321.textile_backup;
 | 
			
		|||
 | 
			
		||||
import net.szum123321.textile_backup.core.restore.AwaitThread;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.time.format.DateTimeFormatter;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.concurrent.ExecutorService;
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +35,6 @@ public class Statics {
 | 
			
		|||
    public static final AtomicBoolean globalShutdownBackupFlag = new AtomicBoolean(true);
 | 
			
		||||
    public static boolean disableWatchdog = false;
 | 
			
		||||
    public static AwaitThread restoreAwaitThread = null;
 | 
			
		||||
    public static Optional<File> untouchableFile = Optional.empty();
 | 
			
		||||
    public static Optional<Path> untouchableFile = Optional.empty();
 | 
			
		||||
    public static boolean disableTMPFiles = false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,6 @@ package net.szum123321.textile_backup.commands.manage;
 | 
			
		|||
import com.mojang.brigadier.arguments.StringArgumentType;
 | 
			
		||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
 | 
			
		||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.server.command.CommandManager;
 | 
			
		||||
import net.minecraft.server.command.ServerCommandSource;
 | 
			
		||||
import net.szum123321.textile_backup.TextileBackup;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,11 +30,13 @@ import net.szum123321.textile_backup.Statics;
 | 
			
		|||
import net.szum123321.textile_backup.commands.FileSuggestionProvider;
 | 
			
		||||
import net.szum123321.textile_backup.core.Utilities;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.time.format.DateTimeParseException;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
public class DeleteCommand {
 | 
			
		||||
    private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
 | 
			
		||||
| 
						 | 
				
			
			@ -57,28 +58,28 @@ public class DeleteCommand {
 | 
			
		|||
            throw CommandExceptions.DATE_TIME_PARSE_COMMAND_EXCEPTION_TYPE.create(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        File root = Utilities.getBackupRootPath(Utilities.getLevelName(source.getServer()));
 | 
			
		||||
        Path root = Utilities.getBackupRootPath(Utilities.getLevelName(source.getServer()));
 | 
			
		||||
 | 
			
		||||
        Optional<File> optionalFile =  Arrays.stream(root.listFiles())
 | 
			
		||||
                .filter(Utilities::isValidBackup)
 | 
			
		||||
        try (Stream<Path> stream = Files.list(root)) {
 | 
			
		||||
            stream.filter(Utilities::isValidBackup)
 | 
			
		||||
                    .filter(file -> Utilities.getFileCreationTime(file).orElse(LocalDateTime.MIN).equals(dateTime))
 | 
			
		||||
                .findFirst();
 | 
			
		||||
                    .findFirst().ifPresent(file -> {
 | 
			
		||||
                        if(Statics.untouchableFile.isEmpty() || !Statics.untouchableFile.get().equals(file)) {
 | 
			
		||||
                            try {
 | 
			
		||||
                                Files.delete(file);
 | 
			
		||||
                                log.sendInfo(source, "File {} successfully deleted!", file);
 | 
			
		||||
 | 
			
		||||
        if(optionalFile.isPresent()) {
 | 
			
		||||
            if(Statics.untouchableFile.isEmpty() || !Statics.untouchableFile.get().equals(optionalFile.get())) {
 | 
			
		||||
                if(optionalFile.get().delete()) {
 | 
			
		||||
                    log.sendInfo(source, "File {} successfully deleted!", optionalFile.get().getName());
 | 
			
		||||
 | 
			
		||||
                    if(source.getEntity() instanceof PlayerEntity)
 | 
			
		||||
                        log.info("Player {} deleted {}.", source.getPlayer().getName(), optionalFile.get().getName());
 | 
			
		||||
                } else {
 | 
			
		||||
                                if(source.isExecutedByPlayer())
 | 
			
		||||
                                    log.info("Player {} deleted {}.", source.getPlayer().getName(), file);
 | 
			
		||||
                            } catch (IOException e) {
 | 
			
		||||
                                log.sendError(source, "Something went wrong while deleting file!");
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            log.sendError(source, "Couldn't delete the file because it's being restored right now.");
 | 
			
		||||
                            log.sendHint(source, "If you want to abort restoration then use: /backup killR");
 | 
			
		||||
                        }
 | 
			
		||||
        } else {
 | 
			
		||||
                    });
 | 
			
		||||
        } catch (IOException ignored) {
 | 
			
		||||
            log.sendError(source, "Couldn't find file by this name.");
 | 
			
		||||
            log.sendHint(source, "Maybe try /backup list");
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ public class RestoreBackupCommand {
 | 
			
		|||
            Optional<RestoreHelper.RestoreableFile> backupFile = RestoreHelper.findFileAndLockIfPresent(dateTime, source.getServer());
 | 
			
		||||
 | 
			
		||||
            if(backupFile.isPresent()) {
 | 
			
		||||
                log.info("Found file to restore {}", backupFile.get().getFile().getName());
 | 
			
		||||
                log.info("Found file to restore {}", backupFile.get().getFile().getFileName().toString());
 | 
			
		||||
            } else {
 | 
			
		||||
                log.sendInfo(source, "No file created on {} was found!", dateTime.format(Statics.defaultDateTimeFormatter));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,19 +60,22 @@ public class Utilities {
 | 
			
		|||
		return 	((MinecraftServerSessionAccessor)server).getSession().getDirectoryName();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static File getWorldFolder(MinecraftServer server) {
 | 
			
		||||
	public static Path getWorldFolder(MinecraftServer server) {
 | 
			
		||||
		return ((MinecraftServerSessionAccessor)server)
 | 
			
		||||
				.getSession()
 | 
			
		||||
				.getWorldDirectory(World.OVERWORLD)
 | 
			
		||||
				.toFile();
 | 
			
		||||
				.getWorldDirectory(World.OVERWORLD);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static File getBackupRootPath(String worldName) {
 | 
			
		||||
		File path = new File(config.get().path).getAbsoluteFile();
 | 
			
		||||
	public static Path getBackupRootPath(String worldName) {
 | 
			
		||||
		Path path = Path.of(config.get().path).toAbsolutePath();
 | 
			
		||||
 | 
			
		||||
		if (config.get().perWorldBackup) path = path.toPath().resolve(worldName).toFile();
 | 
			
		||||
		if (config.get().perWorldBackup) path = path.resolve(worldName);
 | 
			
		||||
 | 
			
		||||
		if (!path.exists()) path.mkdirs();
 | 
			
		||||
		try {
 | 
			
		||||
			Files.createDirectories(path);
 | 
			
		||||
		} catch (IOException e) {
 | 
			
		||||
			//I REALLY shouldn't be handling this here
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return path;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +84,7 @@ public class Utilities {
 | 
			
		|||
		boolean flag = false;
 | 
			
		||||
		Path tmp_dir = Path.of(System.getProperty("java.io.tmpdir"));
 | 
			
		||||
		if(
 | 
			
		||||
				FileUtils.sizeOfDirectory(Utilities.getWorldFolder(server)) >=
 | 
			
		||||
				FileUtils.sizeOfDirectory(Utilities.getWorldFolder(server).toFile()) >=
 | 
			
		||||
				tmp_dir.toFile().getUsableSpace()
 | 
			
		||||
		) {
 | 
			
		||||
			log.error("Not enough space left in TMP directory! ({})", tmp_dir);
 | 
			
		||||
| 
						 | 
				
			
			@ -130,11 +133,11 @@ public class Utilities {
 | 
			
		|||
				.findAny();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static Optional<ConfigPOJO.ArchiveFormat> getArchiveExtension(File f) {
 | 
			
		||||
		return getArchiveExtension(f.getName());
 | 
			
		||||
	public static Optional<ConfigPOJO.ArchiveFormat> getArchiveExtension(Path f) {
 | 
			
		||||
		return getArchiveExtension(f.getFileName().toString());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static Optional<LocalDateTime> getFileCreationTime(File file) {
 | 
			
		||||
	public static Optional<LocalDateTime> getFileCreationTime(Path file) {
 | 
			
		||||
		LocalDateTime creationTime = null;
 | 
			
		||||
 | 
			
		||||
		if(getArchiveExtension(file).isPresent()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +146,7 @@ public class Utilities {
 | 
			
		|||
			try {
 | 
			
		||||
				creationTime = LocalDateTime.from(
 | 
			
		||||
						Utilities.getDateTimeFormatter().parse(
 | 
			
		||||
								file.getName().split(fileExtension)[0].split("#")[0]
 | 
			
		||||
								file.getFileName().toString().split(fileExtension)[0].split("#")[0]
 | 
			
		||||
						)
 | 
			
		||||
				);
 | 
			
		||||
			} catch (Exception ignored) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +155,7 @@ public class Utilities {
 | 
			
		|||
				try {
 | 
			
		||||
					creationTime = LocalDateTime.from(
 | 
			
		||||
							Utilities.getBackupDateTimeFormatter().parse(
 | 
			
		||||
									file.getName().split(fileExtension)[0].split("#")[0]
 | 
			
		||||
									file.getFileName().toString().split(fileExtension)[0].split("#")[0]
 | 
			
		||||
							)
 | 
			
		||||
					);
 | 
			
		||||
				} catch (Exception ignored2){}
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +163,7 @@ public class Utilities {
 | 
			
		|||
 | 
			
		||||
			if(creationTime == null) {
 | 
			
		||||
				try {
 | 
			
		||||
					FileTime fileTime = (FileTime) Files.getAttribute(file.toPath(), "creationTime");
 | 
			
		||||
					FileTime fileTime = (FileTime) Files.getAttribute(file, "creationTime");
 | 
			
		||||
					creationTime = LocalDateTime.ofInstant(fileTime.toInstant(), ZoneOffset.systemDefault());
 | 
			
		||||
				} catch (IOException ignored3) {}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -169,7 +172,7 @@ public class Utilities {
 | 
			
		|||
		return Optional.ofNullable(creationTime);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static boolean isValidBackup(File f) {
 | 
			
		||||
	public static boolean isValidBackup(Path f) {
 | 
			
		||||
		return getArchiveExtension(f).isPresent() && getFileCreationTime(f).isPresent() && isFileOk(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -177,6 +180,10 @@ public class Utilities {
 | 
			
		|||
		return f.exists() && f.isFile();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static boolean isFileOk(Path f) {
 | 
			
		||||
		return Files.exists(f) && Files.isRegularFile(f);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static DateTimeFormatter getDateTimeFormatter() {
 | 
			
		||||
		return DateTimeFormatter.ofPattern(config.get().dateTimeFormat);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,11 +26,13 @@ import net.szum123321.textile_backup.config.ConfigHelper;
 | 
			
		|||
import net.szum123321.textile_backup.core.Utilities;
 | 
			
		||||
import org.apache.commons.io.FileUtils;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.time.ZoneOffset;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Comparator;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
public class BackupHelper {
 | 
			
		||||
	private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
 | 
			
		||||
| 
						 | 
				
			
			@ -77,52 +79,76 @@ public class BackupHelper {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	public static int executeFileLimit(ServerCommandSource ctx, String worldName) {
 | 
			
		||||
		File root = Utilities.getBackupRootPath(worldName);
 | 
			
		||||
		Path root = Utilities.getBackupRootPath(worldName);
 | 
			
		||||
		int deletedFiles = 0;
 | 
			
		||||
 | 
			
		||||
		if (root.isDirectory() && root.exists() && root.listFiles() != null) {
 | 
			
		||||
 | 
			
		||||
		if (Files.isDirectory(root) && Files.exists(root) && !isEmpty(root)) {
 | 
			
		||||
			if (config.get().maxAge > 0) { // delete files older that configured
 | 
			
		||||
				final LocalDateTime now = LocalDateTime.now();
 | 
			
		||||
 | 
			
		||||
				deletedFiles += Arrays.stream(root.listFiles())
 | 
			
		||||
						.filter(Utilities::isValidBackup)// We check if we can get file's creation date so that the next line won't throw an exception
 | 
			
		||||
				try(Stream<Path> stream = Files.list(root)) {
 | 
			
		||||
					deletedFiles += stream
 | 
			
		||||
							.filter(Utilities::isValidBackup)// We check if we can get restoreableFile's creation date so that the next line won't throw an exception
 | 
			
		||||
							.filter(f -> now.toEpochSecond(ZoneOffset.UTC) - Utilities.getFileCreationTime(f).get().toEpochSecond(ZoneOffset.UTC) > config.get().maxAge)
 | 
			
		||||
							.map(f -> deleteFile(f, ctx))
 | 
			
		||||
							.filter(b -> b).count(); //a bit awkward
 | 
			
		||||
				} catch (IOException e) {
 | 
			
		||||
					throw new RuntimeException(e);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			if (config.get().backupsToKeep > 0 && root.listFiles().length > config.get().backupsToKeep) {
 | 
			
		||||
				deletedFiles += Arrays.stream(root.listFiles())
 | 
			
		||||
			}
 | 
			
		||||
			if (config.get().backupsToKeep > 0 /*&& root.listFiles().length > config.get().backupsToKeep*/) {
 | 
			
		||||
				try(Stream<Path> stream = Files.list(root)) {
 | 
			
		||||
					deletedFiles += stream
 | 
			
		||||
							.filter(Utilities::isValidBackup)
 | 
			
		||||
						.sorted(Comparator.comparing(f -> Utilities.getFileCreationTime((File) f).get()).reversed())
 | 
			
		||||
							.sorted(Comparator.comparing(f -> Utilities.getFileCreationTime((Path) f).get()).reversed())
 | 
			
		||||
							.skip(config.get().backupsToKeep)
 | 
			
		||||
							.map(f -> deleteFile(f, ctx))
 | 
			
		||||
							.filter(b -> b).count();
 | 
			
		||||
				} catch (IOException e) {
 | 
			
		||||
					throw new RuntimeException(e);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (config.get().maxSize > 0 && FileUtils.sizeOfDirectory(root) / 1024 > config.get().maxSize) {
 | 
			
		||||
			//It is fucking quadratic!
 | 
			
		||||
			/*if (config.get().maxSize > 0 && FileUtils.sizeOfDirectory(root) / 1024 > config.get().maxSize) {
 | 
			
		||||
				deletedFiles += Arrays.stream(root.listFiles())
 | 
			
		||||
						.filter(Utilities::isValidBackup)
 | 
			
		||||
						.sorted(Comparator.comparing(f -> Utilities.getFileCreationTime(f).get()))
 | 
			
		||||
						.takeWhile(f -> FileUtils.sizeOfDirectory(root) / 1024 > config.get().maxSize)
 | 
			
		||||
						.map(f -> deleteFile(f, ctx))
 | 
			
		||||
						.filter(b -> b).count();
 | 
			
		||||
			}
 | 
			
		||||
			}*/
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return deletedFiles;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static boolean deleteFile(File f, ServerCommandSource ctx) {
 | 
			
		||||
		if(Statics.untouchableFile.isEmpty()|| !Statics.untouchableFile.get().equals(f)) {
 | 
			
		||||
			if(f.delete()) {
 | 
			
		||||
				log.sendInfoAL(ctx, "Deleting: {}", f.getName());
 | 
			
		||||
				return true;
 | 
			
		||||
			} else {
 | 
			
		||||
				log.sendErrorAL(ctx, "Something went wrong while deleting: {}.", f.getName());
 | 
			
		||||
	private static boolean isEmpty(Path path) {
 | 
			
		||||
		if (Files.isDirectory(path)) {
 | 
			
		||||
			try (Stream<Path> entries = Files.list(path)) {
 | 
			
		||||
				return entries.findFirst().isEmpty();
 | 
			
		||||
			} catch (IOException e) {
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static boolean deleteFile(Path f, ServerCommandSource ctx) {
 | 
			
		||||
		if(Statics.untouchableFile.isEmpty()|| !Statics.untouchableFile.get().equals(f)) {
 | 
			
		||||
			try {
 | 
			
		||||
				Files.delete(f);
 | 
			
		||||
				log.sendInfoAL(ctx, "Deleting: {}", f);
 | 
			
		||||
			} catch (IOException e) {
 | 
			
		||||
				if(ctx.isExecutedByPlayer()) log.sendError(ctx, "Something went wrong while deleting: {}.", f);
 | 
			
		||||
				log.error("Something went wrong while deleting: {}.", f, e);
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -56,13 +56,12 @@ public class MakeBackupRunnable implements Runnable {
 | 
			
		|||
 | 
			
		||||
            log.sendInfoAL(context, "Starting backup");
 | 
			
		||||
 | 
			
		||||
            Path world = Utilities.getWorldFolder(context.getServer()).toPath();
 | 
			
		||||
            Path world = Utilities.getWorldFolder(context.getServer());
 | 
			
		||||
 | 
			
		||||
            log.trace("Minecraft world is: {}", world);
 | 
			
		||||
 | 
			
		||||
            Path outFile = Utilities
 | 
			
		||||
                    .getBackupRootPath(Utilities.getLevelName(context.getServer()))
 | 
			
		||||
                    .toPath()
 | 
			
		||||
                    .resolve(getFileName());
 | 
			
		||||
            log.trace("Outfile is: {}", outFile);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,43 +21,15 @@ package net.szum123321.textile_backup.core.restore;
 | 
			
		|||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.server.MinecraftServer;
 | 
			
		||||
import net.minecraft.server.command.ServerCommandSource;
 | 
			
		||||
import net.minecraft.util.Util;
 | 
			
		||||
import net.szum123321.textile_backup.core.ActionInitiator;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
public record RestoreContext(RestoreHelper.RestoreableFile file,
 | 
			
		||||
public record RestoreContext(RestoreHelper.RestoreableFile restoreableFile,
 | 
			
		||||
                             MinecraftServer server,
 | 
			
		||||
                             @Nullable String comment,
 | 
			
		||||
                             ActionInitiator initiator,
 | 
			
		||||
                             ServerCommandSource commandSource) {
 | 
			
		||||
 | 
			
		||||
    public RestoreHelper.RestoreableFile getFile() {
 | 
			
		||||
        return file;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public MinecraftServer getServer() {
 | 
			
		||||
        return server;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    public String getComment() {
 | 
			
		||||
        return comment;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ActionInitiator getInitiator() {
 | 
			
		||||
        return initiator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public UUID getInitiatorUUID() {
 | 
			
		||||
        return initiator.equals(ActionInitiator.Player) && commandSource.getEntity() != null ? commandSource.getEntity().getUuid(): Util.NIL_UUID;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ServerCommandSource getCommandSource() {
 | 
			
		||||
        return commandSource;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static final class Builder {
 | 
			
		||||
        private RestoreHelper.RestoreableFile file;
 | 
			
		||||
        private MinecraftServer server;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,23 +28,31 @@ import net.szum123321.textile_backup.core.ActionInitiator;
 | 
			
		|||
import net.szum123321.textile_backup.core.Utilities;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.file.Files;
 | 
			
		||||
import java.nio.file.Path;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
import java.util.stream.Stream;
 | 
			
		||||
 | 
			
		||||
public class RestoreHelper {
 | 
			
		||||
    private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
 | 
			
		||||
    private final static ConfigHelper config = ConfigHelper.INSTANCE;
 | 
			
		||||
 | 
			
		||||
    public static Optional<RestoreableFile> findFileAndLockIfPresent(LocalDateTime backupTime, MinecraftServer server) {
 | 
			
		||||
        File root = Utilities.getBackupRootPath(Utilities.getLevelName(server));
 | 
			
		||||
        Path root = Utilities.getBackupRootPath(Utilities.getLevelName(server));
 | 
			
		||||
 | 
			
		||||
        Optional<RestoreableFile> optionalFile =  Arrays.stream(root.listFiles())
 | 
			
		||||
        Optional<RestoreableFile> optionalFile;
 | 
			
		||||
        try (Stream<Path> stream = Files.list(root)) {
 | 
			
		||||
            optionalFile =  stream
 | 
			
		||||
                    .map(RestoreableFile::newInstance)
 | 
			
		||||
                    .flatMap(Optional::stream)
 | 
			
		||||
                    .filter(rf -> rf.getCreationTime().equals(backupTime))
 | 
			
		||||
                    .findFirst();
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            throw new RuntimeException(e);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Statics.untouchableFile = optionalFile.map(RestoreableFile::getFile);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +60,8 @@ public class RestoreHelper {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public static AwaitThread create(RestoreContext ctx) {
 | 
			
		||||
        if(ctx.getInitiator() == ActionInitiator.Player)
 | 
			
		||||
            log.info("Backup restoration was initiated by: {}", ctx.getCommandSource().getName());
 | 
			
		||||
        if(ctx.initiator() == ActionInitiator.Player)
 | 
			
		||||
            log.info("Backup restoration was initiated by: {}", ctx.commandSource().getName());
 | 
			
		||||
        else
 | 
			
		||||
            log.info("Backup restoration was initiated form Server Console");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,28 +77,32 @@ public class RestoreHelper {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<RestoreableFile> getAvailableBackups(MinecraftServer server) {
 | 
			
		||||
        File root = Utilities.getBackupRootPath(Utilities.getLevelName(server));
 | 
			
		||||
        Path root = Utilities.getBackupRootPath(Utilities.getLevelName(server));
 | 
			
		||||
 | 
			
		||||
        return Arrays.stream(root.listFiles())
 | 
			
		||||
                .filter(Utilities::isValidBackup)
 | 
			
		||||
        try (Stream<Path> stream = Files.list(root)) {
 | 
			
		||||
            return stream.filter(Utilities::isValidBackup)
 | 
			
		||||
                    .map(RestoreableFile::newInstance)
 | 
			
		||||
                    .flatMap(Optional::stream)
 | 
			
		||||
                    .collect(Collectors.toList());
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            log.error("Error while listing available backups", e);
 | 
			
		||||
            return new LinkedList<>();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class RestoreableFile implements Comparable<RestoreableFile> {
 | 
			
		||||
        private final File file;
 | 
			
		||||
        private final Path file;
 | 
			
		||||
        private final ConfigPOJO.ArchiveFormat archiveFormat;
 | 
			
		||||
        private final LocalDateTime creationTime;
 | 
			
		||||
        private final String comment;
 | 
			
		||||
 | 
			
		||||
        private RestoreableFile(File file) throws NoSuchElementException {
 | 
			
		||||
        private RestoreableFile(Path file) throws NoSuchElementException {
 | 
			
		||||
            this.file = file;
 | 
			
		||||
            archiveFormat = Utilities.getArchiveExtension(file).orElseThrow(() -> new NoSuchElementException("Couldn't get file extension!"));
 | 
			
		||||
            archiveFormat = Utilities.getArchiveExtension(file).orElseThrow(() -> new NoSuchElementException("Couldn't get restoreableFile extension!"));
 | 
			
		||||
            String extension = archiveFormat.getCompleteString();
 | 
			
		||||
            creationTime = Utilities.getFileCreationTime(file).orElseThrow(() -> new NoSuchElementException("Couldn't get file creation time!"));
 | 
			
		||||
            creationTime = Utilities.getFileCreationTime(file).orElseThrow(() -> new NoSuchElementException("Couldn't get restoreableFile creation time!"));
 | 
			
		||||
 | 
			
		||||
            final String filename = file.getName();
 | 
			
		||||
            final String filename = file.getFileName().toString();
 | 
			
		||||
 | 
			
		||||
            if(filename.split("#").length > 1) {
 | 
			
		||||
                this.comment = filename.split("#")[1].split(extension)[0];
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +111,7 @@ public class RestoreHelper {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Optional<RestoreableFile> newInstance(File file) {
 | 
			
		||||
        public static Optional<RestoreableFile> newInstance(Path file) {
 | 
			
		||||
            try {
 | 
			
		||||
                return Optional.of(new RestoreableFile(file));
 | 
			
		||||
            } catch (NoSuchElementException ignored) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -107,7 +119,7 @@ public class RestoreHelper {
 | 
			
		|||
            return Optional.empty();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public File getFile() {
 | 
			
		||||
        public Path getFile() {
 | 
			
		||||
            return file;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue