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