Do I really need hashes? idk.... Either way it has to get ugly before it gets beautiful ... I think
parent
85452efbca
commit
4007d8f86d
|
@ -123,6 +123,14 @@ public class ConfigPOJO implements ConfigData {
|
||||||
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
|
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
|
||||||
public ArchiveFormat format = ArchiveFormat.ZIP;
|
public ArchiveFormat format = ArchiveFormat.ZIP;
|
||||||
|
|
||||||
|
@Comment("""
|
||||||
|
The Strict mode (default) aborts backup creation in case of any problem and deletes the created files
|
||||||
|
Permissible mode keeps partial/damaged backup but won't allow to restore it
|
||||||
|
Very Permissible mode will skip the verification process. THIS MOST CERTAINLY WILL LEAD TO DATA LOSS OR CORRUPTION
|
||||||
|
""")
|
||||||
|
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
|
||||||
|
public ErrorHandlingMode errorErrorHandlingMode = ErrorHandlingMode.STRICT;
|
||||||
|
|
||||||
@Comment("\nMinimal permission level required to run commands\n")
|
@Comment("\nMinimal permission level required to run commands\n")
|
||||||
@ConfigEntry.Category("Manage")
|
@ConfigEntry.Category("Manage")
|
||||||
@ConfigEntry.Gui.NoTooltip()
|
@ConfigEntry.Gui.NoTooltip()
|
||||||
|
@ -177,6 +185,12 @@ public class ConfigPOJO implements ConfigData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum ErrorHandlingMode {
|
||||||
|
STRICT,
|
||||||
|
PERMISSIBLE,
|
||||||
|
VERY_PERMISSIBLE
|
||||||
|
}
|
||||||
|
|
||||||
public enum ArchiveFormat {
|
public enum ArchiveFormat {
|
||||||
ZIP("zip"),
|
ZIP("zip"),
|
||||||
GZIP("tar", "gz"),
|
GZIP("tar", "gz"),
|
||||||
|
|
|
@ -1,17 +1,30 @@
|
||||||
|
/*
|
||||||
|
* A simple backup mod for Fabric
|
||||||
|
* Copyright (C) 2022 Szum123321
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
package net.szum123321.textile_backup.core;
|
package net.szum123321.textile_backup.core;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public record CompressionStatus(long[] treeHash, LocalDateTime date, long startTimestamp, long finishTimestamp, boolean ok, Path[] brokenFiles) implements Serializable {
|
public record CompressionStatus(long treeHash, LocalDateTime date, long startTimestamp, long finishTimestamp, Map<Path, Exception> brokenFiles) implements Serializable {
|
||||||
public static final String DATA_FILENAME = "textile_status.data";
|
public static final String DATA_FILENAME = "textile_status.data";
|
||||||
public boolean isValid(long decompressedHash) { return true; }
|
public boolean isValid(long decompressedHash) { return true; }
|
||||||
public static class Builder {
|
|
||||||
public synchronized void update(Path path, long hash, Exception error) { throw new RuntimeException("UNIMPLEMENTED!"); }
|
|
||||||
public synchronized void update(Path path, Exception error) { throw new RuntimeException("UNIMPLEMENTED!"); }
|
|
||||||
public synchronized void update(Path path, long hash) { throw new RuntimeException("UNIMPLEMENTED!"); }
|
|
||||||
|
|
||||||
public CompressionStatus build() { throw new RuntimeException("UNIMPLEMENTED!"); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* A simple backup mod for Fabric
|
||||||
|
* Copyright (C) 2022 Szum123321
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.szum123321.textile_backup.core;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DataLeftException extends IOException {
|
||||||
|
public DataLeftException(long n) { super("Input stream closed with " + n + " bytes left!"); }
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* A simple backup mod for Fabric
|
||||||
|
* Copyright (C) 2022 Szum123321
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.szum123321.textile_backup.core.create;
|
||||||
|
|
||||||
|
import org.spongepowered.include.com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class BrokenFileHandler {
|
||||||
|
private final HashMap<Path, Exception> store = Maps.newHashMap();
|
||||||
|
public void handle(Path file, Exception e) { store.put(file, e); }
|
||||||
|
|
||||||
|
public boolean valid() { return store.isEmpty(); }
|
||||||
|
|
||||||
|
public Map<Path, Exception> get() {
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +1,26 @@
|
||||||
/*
|
/*
|
||||||
A simple backup mod for Fabric
|
* A simple backup mod for Fabric
|
||||||
Copyright (C) 2022 Szum123321
|
* Copyright (C) 2022 Szum123321
|
||||||
|
*
|
||||||
This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.szum123321.textile_backup.core.create;
|
package net.szum123321.textile_backup.core.create;
|
||||||
|
|
||||||
import net.szum123321.textile_backup.TextileBackup;
|
import net.szum123321.textile_backup.TextileBackup;
|
||||||
import net.szum123321.textile_backup.TextileLogger;
|
import net.szum123321.textile_backup.TextileLogger;
|
||||||
import net.szum123321.textile_backup.core.CompressionStatus;
|
import net.szum123321.textile_backup.core.FileTreeHashBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -28,15 +28,16 @@ import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
public record FileInputStreamSupplier(Path path, String name, CompressionStatus.Builder builder) implements InputSupplier {
|
public record FileInputStreamSupplier(Path path, String name, FileTreeHashBuilder hashTreeBuilder, BrokenFileHandler brokenFileHandler) implements InputSupplier {
|
||||||
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
|
private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InputStream getInputStream() throws IOException {
|
public InputStream getInputStream() throws IOException {
|
||||||
try {
|
try {
|
||||||
return new HashingInputStream(Files.newInputStream(path), path, null, builder);
|
//TODO: select hashing algorithm!
|
||||||
|
return new HashingInputStream(Files.newInputStream(path), path, null, hashTreeBuilder, brokenFileHandler);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
builder.update(path, e);
|
brokenFileHandler.handle(path, e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,41 +1,46 @@
|
||||||
/*
|
/*
|
||||||
A simple backup mod for Fabric
|
* A simple backup mod for Fabric
|
||||||
Copyright (C) 2022 Szum123321
|
* Copyright (C) 2022 Szum123321
|
||||||
|
*
|
||||||
This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.szum123321.textile_backup.core.create;
|
package net.szum123321.textile_backup.core.create;
|
||||||
|
|
||||||
import net.szum123321.textile_backup.core.CompressionStatus;
|
import net.szum123321.textile_backup.core.DataLeftException;
|
||||||
|
import net.szum123321.textile_backup.core.FileTreeHashBuilder;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.zip.Checksum;
|
import java.util.zip.Checksum;
|
||||||
|
|
||||||
|
//This class calculates a hash of the file on the input stream, submits it to FileTreeHashBuilder.
|
||||||
|
//In case the whole underlying stream hasn't been read, also puts it into BrokeFileHandler
|
||||||
public class HashingInputStream extends FilterInputStream {
|
public class HashingInputStream extends FilterInputStream {
|
||||||
|
|
||||||
private final Path path;
|
private final Path path;
|
||||||
private final Checksum hasher;
|
private final Checksum hasher;
|
||||||
private final CompressionStatus.Builder statusBuilder;
|
private final FileTreeHashBuilder hashBuilder;
|
||||||
|
private final BrokenFileHandler brokenFileHandler;
|
||||||
|
|
||||||
public HashingInputStream(InputStream in, Path path, Checksum hasher, CompressionStatus.Builder statusBuilder) {
|
public HashingInputStream(InputStream in, Path path, Checksum hasher, FileTreeHashBuilder hashBuilder, BrokenFileHandler brokenFileHandler) {
|
||||||
super(in);
|
super(in);
|
||||||
this.hasher = hasher;
|
|
||||||
this.statusBuilder = statusBuilder;
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
this.hasher = hasher;
|
||||||
|
this.hashBuilder = hashBuilder;
|
||||||
|
this.brokenFileHandler = brokenFileHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,8 +59,8 @@ public class HashingInputStream extends FilterInputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if(in.available() == 0) statusBuilder.update(path, hasher.getValue());
|
if(in.available() == 0) hashBuilder.update(path, hasher.getValue());
|
||||||
else statusBuilder.update(path, hasher.getValue(), new RuntimeException("AAAaa"));
|
else brokenFileHandler.handle(path, new DataLeftException(in.available()));
|
||||||
super.close();
|
super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
/*
|
/*
|
||||||
A simple backup mod for Fabric
|
* A simple backup mod for Fabric
|
||||||
Copyright (C) 2020 Szum123321
|
* Copyright (C) 2022 Szum123321
|
||||||
|
*
|
||||||
This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.szum123321.textile_backup.core.create;
|
package net.szum123321.textile_backup.core.create;
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ public class MakeBackupRunnable implements Runnable {
|
||||||
case TAR -> new AbstractTarArchiver().createArchive(world, outFile, context, coreCount);
|
case TAR -> new AbstractTarArchiver().createArchive(world, outFile, context, coreCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Cleanup(context.commandSource(), Utilities.getLevelName(context.server())).call();
|
Globals.INSTANCE.getQueueExecutor().submit(new Cleanup(context.commandSource(), Utilities.getLevelName(context.server())));
|
||||||
|
|
||||||
if(config.get().broadcastBackupDone) {
|
if(config.get().broadcastBackupDone) {
|
||||||
Utilities.notifyPlayers(
|
Utilities.notifyPlayers(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* A simple backup mod for Fabric
|
* A simple backup mod for Fabric
|
||||||
* Copyright (C) 2020 Szum123321
|
* Copyright (C) 2022 Szum123321
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,11 +20,11 @@ package net.szum123321.textile_backup.core.create.compressors;
|
||||||
|
|
||||||
import net.szum123321.textile_backup.TextileBackup;
|
import net.szum123321.textile_backup.TextileBackup;
|
||||||
import net.szum123321.textile_backup.TextileLogger;
|
import net.szum123321.textile_backup.TextileLogger;
|
||||||
import net.szum123321.textile_backup.core.ActionInitiator;
|
import net.szum123321.textile_backup.config.ConfigHelper;
|
||||||
import net.szum123321.textile_backup.core.CompressionStatus;
|
import net.szum123321.textile_backup.config.ConfigPOJO;
|
||||||
import net.szum123321.textile_backup.core.NoSpaceLeftOnDeviceException;
|
import net.szum123321.textile_backup.core.*;
|
||||||
import net.szum123321.textile_backup.core.Utilities;
|
|
||||||
import net.szum123321.textile_backup.core.create.BackupContext;
|
import net.szum123321.textile_backup.core.create.BackupContext;
|
||||||
|
import net.szum123321.textile_backup.core.create.BrokenFileHandler;
|
||||||
import net.szum123321.textile_backup.core.create.FileInputStreamSupplier;
|
import net.szum123321.textile_backup.core.create.FileInputStreamSupplier;
|
||||||
import net.szum123321.textile_backup.core.create.InputSupplier;
|
import net.szum123321.textile_backup.core.create.InputSupplier;
|
||||||
|
|
||||||
|
@ -45,32 +45,53 @@ public abstract class AbstractCompressor {
|
||||||
public void createArchive(Path inputFile, Path outputFile, BackupContext ctx, int coreLimit) {
|
public void createArchive(Path inputFile, Path outputFile, BackupContext ctx, int coreLimit) {
|
||||||
Instant start = Instant.now();
|
Instant start = Instant.now();
|
||||||
|
|
||||||
|
FileTreeHashBuilder fileHashBuilder = new FileTreeHashBuilder(() -> null); //TODO: select hashing algorithm
|
||||||
|
BrokenFileHandler brokenFileHandler = new BrokenFileHandler();
|
||||||
|
|
||||||
|
boolean keep = true;
|
||||||
|
|
||||||
try (OutputStream outStream = Files.newOutputStream(outputFile);
|
try (OutputStream outStream = Files.newOutputStream(outputFile);
|
||||||
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outStream);
|
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outStream);
|
||||||
OutputStream arc = createArchiveOutputStream(bufferedOutputStream, ctx, coreLimit);
|
OutputStream arc = createArchiveOutputStream(bufferedOutputStream, ctx, coreLimit);
|
||||||
Stream<Path> fileStream = Files.walk(inputFile)) {
|
Stream<Path> fileStream = Files.walk(inputFile)) {
|
||||||
|
var it = fileStream
|
||||||
CompressionStatus.Builder statusBuilder = new CompressionStatus.Builder();
|
|
||||||
|
|
||||||
fileStream
|
|
||||||
.filter(path -> !Utilities.isBlacklisted(inputFile.relativize(path)))
|
.filter(path -> !Utilities.isBlacklisted(inputFile.relativize(path)))
|
||||||
.filter(Files::isRegularFile).forEach(file -> {
|
.filter(Files::isRegularFile).iterator();
|
||||||
try {
|
|
||||||
addEntry(new FileInputStreamSupplier(file, inputFile.relativize(file).toString(), statusBuilder), arc);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("An exception occurred while trying to compress: {}", inputFile.relativize(file).toString(), e);
|
|
||||||
|
|
||||||
if (ctx.initiator() == ActionInitiator.Player)
|
while(it.hasNext()) {
|
||||||
log.sendError(ctx, "Something went wrong while compressing files!");
|
Path file = it.next();
|
||||||
|
|
||||||
|
try {
|
||||||
|
addEntry(new FileInputStreamSupplier(file, inputFile.relativize(file).toString(), fileHashBuilder, brokenFileHandler), arc);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode == ConfigPOJO.ErrorHandlingMode.STRICT) {
|
||||||
|
keep = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
brokenFileHandler.handle(file, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If there are still files left in the stream, we should handle them
|
||||||
|
while(it.hasNext()) {
|
||||||
|
Path file = it.next();
|
||||||
|
brokenFileHandler.handle(file, new DataLeftException(Files.size(file)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Instant now = Instant.now();
|
||||||
|
|
||||||
|
CompressionStatus status = new CompressionStatus (
|
||||||
|
fileHashBuilder.getValue(),
|
||||||
|
null, start.toEpochMilli(), now.toEpochMilli(),
|
||||||
|
brokenFileHandler.get()
|
||||||
|
);
|
||||||
|
|
||||||
//Serialize using gson?
|
//Serialize using gson?
|
||||||
ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
try (ByteArrayOutputStream bo = new ByteArrayOutputStream();
|
||||||
ObjectOutputStream o = new ObjectOutputStream(bo);
|
ObjectOutputStream o = new ObjectOutputStream(bo)) {
|
||||||
o.writeObject(statusBuilder.build());
|
o.writeObject(status);
|
||||||
|
addEntry(new StatusFileInputSupplier(bo.toByteArray()), arc);
|
||||||
addEntry(new StatusFileInputSupplier(bo.toByteArray(), bo.size()), arc);
|
}
|
||||||
|
|
||||||
finish(arc);
|
finish(arc);
|
||||||
} catch(NoSpaceLeftOnDeviceException e) {
|
} catch(NoSpaceLeftOnDeviceException e) {
|
||||||
|
@ -85,16 +106,17 @@ public abstract class AbstractCompressor {
|
||||||
log.sendError(ctx, "Backup failed. The file is corrupt.");
|
log.sendError(ctx, "Backup failed. The file is corrupt.");
|
||||||
log.error("For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems");
|
log.error("For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems");
|
||||||
}
|
}
|
||||||
|
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode == ConfigPOJO.ErrorHandlingMode.STRICT) keep = false;
|
||||||
} catch (IOException | InterruptedException | ExecutionException e) {
|
} catch (IOException | InterruptedException | ExecutionException e) {
|
||||||
log.error("An exception occurred!", e);
|
log.error("An exception occurred!", e);
|
||||||
if(ctx.initiator() == ActionInitiator.Player)
|
if(ctx.initiator() == ActionInitiator.Player)
|
||||||
log.sendError(ctx, "Something went wrong while compressing files!");
|
log.sendError(ctx, "Something went wrong while compressing files!");
|
||||||
|
if(ConfigHelper.INSTANCE.get().errorErrorHandlingMode == ConfigPOJO.ErrorHandlingMode.STRICT) keep = false;
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// close();
|
|
||||||
|
|
||||||
log.sendInfoAL(ctx, "Compression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
|
log.sendInfoAL(ctx, "Compression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,17 +131,13 @@ public abstract class AbstractCompressor {
|
||||||
//Same as above, just for ParallelGzipCompressor to shut down ExecutorService
|
//Same as above, just for ParallelGzipCompressor to shut down ExecutorService
|
||||||
}
|
}
|
||||||
|
|
||||||
private record StatusFileInputSupplier(byte[] data, int len) implements InputSupplier {
|
private record StatusFileInputSupplier(byte[] data) implements InputSupplier {
|
||||||
@Override
|
public InputStream getInputStream() { return new ByteArrayInputStream(data); }
|
||||||
public InputStream getInputStream() { return new ByteArrayInputStream(data, 0, len); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Path getPath() { return Path.of(CompressionStatus.DATA_FILENAME); }
|
public Path getPath() { return Path.of(CompressionStatus.DATA_FILENAME); }
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() { return CompressionStatus.DATA_FILENAME; }
|
public String getName() { return CompressionStatus.DATA_FILENAME; }
|
||||||
|
|
||||||
@Override
|
public InputStream get() { return getInputStream(); }
|
||||||
public InputStream get() { return new ByteArrayInputStream(data, 0, len); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* A simple backup mod for Fabric
|
* A simple backup mod for Fabric
|
||||||
* Copyright (C) 2020 Szum123321
|
* Copyright (C) 2022 Szum123321
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -99,7 +99,7 @@ public class ParallelZipCompressor extends ZipCompressor {
|
||||||
if(!STACKTRACE_NO_SPACE_ON_LEFT_ON_DEVICE[i].equals(cause.getStackTrace()[i])) match = false;
|
if(!STACKTRACE_NO_SPACE_ON_LEFT_ON_DEVICE[i].equals(cause.getStackTrace()[i])) match = false;
|
||||||
|
|
||||||
|
|
||||||
//For clarity' sake let's not throw the ExecutionException itself rather only the cause, as the EE is just the wrapper
|
//For clarity's sake let's not throw the ExecutionException itself rather only the cause, as the EE is just the wrapper
|
||||||
if(match) throw new NoSpaceLeftOnDeviceException(cause);
|
if(match) throw new NoSpaceLeftOnDeviceException(cause);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,9 @@
|
||||||
"text.autoconfig.textile_backup.option.format": "Archive and compression format",
|
"text.autoconfig.textile_backup.option.format": "Archive and compression format",
|
||||||
"text.autoconfig.textile_backup.option.format.@Tooltip": "See: https://github.com/Szum123321/textile_backup/wiki/Configuration#format",
|
"text.autoconfig.textile_backup.option.format.@Tooltip": "See: https://github.com/Szum123321/textile_backup/wiki/Configuration#format",
|
||||||
|
|
||||||
|
"text.autoconfig.textile_backup.option.errorErrorHandlingMode": "Compression error handling mode",
|
||||||
|
"text.autoconfig.textile_backup.option.errorErrorHandlingMode.@Tooltip": "DO NOT ALTER unless fully certain",
|
||||||
|
|
||||||
"text.autoconfig.textile_backup.option.permissionLevel": "Min permission level",
|
"text.autoconfig.textile_backup.option.permissionLevel": "Min permission level",
|
||||||
|
|
||||||
"text.autoconfig.textile_backup.option.alwaysSingleplayerAllowed": "Always allow on single-player",
|
"text.autoconfig.textile_backup.option.alwaysSingleplayerAllowed": "Always allow on single-player",
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
],
|
],
|
||||||
|
|
||||||
"depends": {
|
"depends": {
|
||||||
"fabricloader": ">=0.14.6",
|
"fabricloader": ">=0.14.0",
|
||||||
"fabric": "*",
|
"fabric": "*",
|
||||||
"minecraft": ">=1.19.1",
|
"minecraft": ">=1.19.1",
|
||||||
"cloth-config2": "*",
|
"cloth-config2": "*",
|
||||||
|
|
Loading…
Reference in New Issue