Added safe restore
This commit is contained in:
parent
b4597f6f1f
commit
3f1f1704b1
@ -85,12 +85,16 @@ public class TextileLogger {
|
||||
log(Level.ERROR, msg, data);
|
||||
}
|
||||
|
||||
void error(String message, Throwable throwable) {
|
||||
logger.error(prefix + message, throwable);
|
||||
}
|
||||
|
||||
public void fatal(String msg, Object... data) {
|
||||
log(Level.FATAL, msg, data);
|
||||
}
|
||||
|
||||
boolean sendFeedback(Level level, ServerCommandSource source, String msg, Object... args) {
|
||||
if(source != null && source.getEntity() instanceof PlayerEntity) {
|
||||
if(source != null && source.isExecutedByPlayer()) {
|
||||
MutableText text = Text.literal(messageFactory.newMessage(msg, args).getFormattedMessage());
|
||||
|
||||
if(level.intLevel() == Level.TRACE.intLevel()) text.formatted(Formatting.GREEN);
|
||||
|
@ -32,18 +32,20 @@ import net.szum123321.textile_backup.config.ConfigPOJO;
|
||||
import net.szum123321.textile_backup.Statics;
|
||||
import net.szum123321.textile_backup.mixin.MinecraftServerSessionAccessor;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.file.SimplePathVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileVisitResult;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Utilities {
|
||||
private final static ConfigHelper config = ConfigHelper.INSTANCE;
|
||||
@ -80,6 +82,22 @@ public class Utilities {
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void deleteDirectory(Path path) throws IOException {
|
||||
Files.walkFileTree(path, new SimplePathVisitor() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void updateTMPFSFlag(MinecraftServer server) {
|
||||
boolean flag = false;
|
||||
Path tmp_dir = Path.of(System.getProperty("java.io.tmpdir"));
|
||||
|
@ -31,7 +31,7 @@ import net.szum123321.textile_backup.core.create.BackupHelper;
|
||||
import net.szum123321.textile_backup.core.restore.decompressors.GenericTarDecompressor;
|
||||
import net.szum123321.textile_backup.core.restore.decompressors.ZipDecompressor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@ -51,54 +51,60 @@ public class RestoreBackupRunnable implements Runnable {
|
||||
|
||||
log.info("Shutting down server...");
|
||||
|
||||
ctx.getServer().stop(false);
|
||||
ctx.server().stop(false);
|
||||
awaitServerShutdown();
|
||||
|
||||
if(config.get().backupOldWorlds) {
|
||||
BackupHelper.create(
|
||||
BackupContext.Builder
|
||||
.newBackupContextBuilder()
|
||||
.setServer(ctx.getServer())
|
||||
.setServer(ctx.server())
|
||||
.setInitiator(ActionInitiator.Restore)
|
||||
.setComment("Old_World" + (ctx.getComment() != null ? "_" + ctx.getComment() : ""))
|
||||
.setComment("Old_World" + (ctx.comment() != null ? "_" + ctx.comment() : ""))
|
||||
.build()
|
||||
).run();
|
||||
}
|
||||
|
||||
Path worldFile = Utilities.getWorldFolder(ctx.getServer()).toPath();
|
||||
Path worldFile = Utilities.getWorldFolder(ctx.server());
|
||||
|
||||
log.info("Deleting old world...");
|
||||
try {
|
||||
Path tmp = Files.createTempDirectory (
|
||||
worldFile.getParent(),
|
||||
ctx.restoreableFile().getFile().getFileName().toString()
|
||||
);
|
||||
|
||||
if(!deleteDirectory(worldFile))
|
||||
log.error("Something went wrong while deleting old world!");
|
||||
tmp.toFile().deleteOnExit();
|
||||
|
||||
Files.createDirectories(worldFile);
|
||||
log.info("Starting decompression...");
|
||||
|
||||
log.info("Starting decompression...");
|
||||
if (ctx.restoreableFile().getArchiveFormat() == ConfigPOJO.ArchiveFormat.ZIP)
|
||||
ZipDecompressor.decompress(ctx.restoreableFile().getFile(), tmp);
|
||||
else
|
||||
GenericTarDecompressor.decompress(ctx.restoreableFile().getFile(), tmp);
|
||||
|
||||
if(ctx.getFile().getArchiveFormat() == ConfigPOJO.ArchiveFormat.ZIP)
|
||||
ZipDecompressor.decompress(ctx.getFile().getFile().toPath(), worldFile);
|
||||
else
|
||||
GenericTarDecompressor.decompress(ctx.getFile().getFile().toPath(), worldFile);
|
||||
log.info("Deleting old world...");
|
||||
|
||||
if(config.get().deleteOldBackupAfterRestore) {
|
||||
log.info("Deleting old backup");
|
||||
Utilities.deleteDirectory(worldFile);
|
||||
|
||||
if(!ctx.getFile().getFile().delete()) log.info("Something went wrong while deleting old backup");
|
||||
Files.move(tmp, worldFile);
|
||||
|
||||
if (config.get().deleteOldBackupAfterRestore) {
|
||||
log.info("Deleting old backup");
|
||||
|
||||
Files.delete(ctx.restoreableFile().getFile());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("An exception occurred while trying to restore a backup!", e);
|
||||
}
|
||||
|
||||
//in case we're playing on client
|
||||
Statics.globalShutdownBackupFlag.set(true);
|
||||
|
||||
log.info("Done!");
|
||||
|
||||
//Might solve #37
|
||||
//Idk if it's a good idea...
|
||||
//Runtime.getRuntime().exit(0);
|
||||
}
|
||||
|
||||
private void awaitServerShutdown() {
|
||||
while(((LivingServer)ctx.getServer()).isAlive()) {
|
||||
while(((LivingServer)ctx.server()).isAlive()) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
@ -106,15 +112,4 @@ public class RestoreBackupRunnable implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean deleteDirectory(File f) {
|
||||
boolean state = true;
|
||||
|
||||
if(f.isDirectory()) {
|
||||
for(File f2 : f.listFiles())
|
||||
state &= deleteDirectory(f2);
|
||||
}
|
||||
|
||||
return f.delete() && state;
|
||||
}
|
||||
}
|
@ -98,9 +98,9 @@ public class RestoreHelper {
|
||||
|
||||
private RestoreableFile(Path file) throws NoSuchElementException {
|
||||
this.file = file;
|
||||
archiveFormat = Utilities.getArchiveExtension(file).orElseThrow(() -> new NoSuchElementException("Couldn't get restoreableFile extension!"));
|
||||
archiveFormat = Utilities.getArchiveExtension(file).orElseThrow(() -> new NoSuchElementException("Couldn't get file extension!"));
|
||||
String extension = archiveFormat.getCompleteString();
|
||||
creationTime = Utilities.getFileCreationTime(file).orElseThrow(() -> new NoSuchElementException("Couldn't get restoreableFile creation time!"));
|
||||
creationTime = Utilities.getFileCreationTime(file).orElseThrow(() -> new NoSuchElementException("Couldn't get file creation time!"));
|
||||
|
||||
final String filename = file.getFileName().toString();
|
||||
|
||||
|
@ -36,7 +36,7 @@ import java.time.Instant;
|
||||
public class GenericTarDecompressor {
|
||||
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
|
||||
|
||||
public static void decompress(Path input, Path target) {
|
||||
public static void decompress(Path input, Path target) throws IOException {
|
||||
Instant start = Instant.now();
|
||||
|
||||
try (InputStream fileInputStream = Files.newInputStream(input);
|
||||
@ -60,13 +60,11 @@ public class GenericTarDecompressor {
|
||||
try (OutputStream outputStream = Files.newOutputStream(file);
|
||||
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
|
||||
IOUtils.copy(archiveInputStream, bufferedOutputStream);
|
||||
} catch (IOException e) {
|
||||
log.error("An exception occurred while trying to decompress file: {}", file.getFileName().toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException | CompressorException e) {
|
||||
log.error("An exception occurred! ", e);
|
||||
} catch (CompressorException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
log.info("Decompression took {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
|
||||
|
@ -35,7 +35,7 @@ import java.util.Iterator;
|
||||
public class ZipDecompressor {
|
||||
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
|
||||
|
||||
public static void decompress(Path inputFile, Path target) {
|
||||
public static void decompress(Path inputFile, Path target) throws IOException {
|
||||
Instant start = Instant.now();
|
||||
|
||||
try(ZipFile zipFile = new ZipFile(inputFile.toFile())) {
|
||||
@ -50,14 +50,9 @@ public class ZipDecompressor {
|
||||
try (OutputStream outputStream = Files.newOutputStream(file);
|
||||
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
|
||||
IOUtils.copy(zipFile.getInputStream(entry), bufferedOutputStream);
|
||||
} catch (IOException e) {
|
||||
log.error("An exception occurred while trying to decompress file: {}", entry.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("An exception occurred! ", e);
|
||||
}
|
||||
|
||||
log.info("Decompression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
|
||||
|
Loading…
Reference in New Issue
Block a user