Package one.tranic.t.utils.diff
Class SimplePatcher
java.lang.Object
one.tranic.t.utils.diff.SimplePatcher
SimplePatcher is just an accidental byproduct, and I don't recommend anyone to use it.
Example:
package one.tranic.goldpiglin.command;
import one.tranic.goldpiglin.GoldPiglin;
import one.tranic.goldpiglin.common.GoldPiglinLogger;
import one.tranic.t.utils.SimplePatcher;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class DiffCommand extends Command {
private final static List<String> INTERNAL_ERROR = List.of("Internal error");
private final static Path DIFF_DIR = GoldPiglin.getPlugin().getDataFolder().toPath().getParent().resolve("diff");
private final static Path Plugin_DIR = GoldPiglin.getPlugin().getDataFolder().toPath().getParent();
public DiffCommand(JavaPlugin plugin) {
super("diff");
this.setUsage("/diff <create> jar1 jar2 | /diff <merge> patch jar");
if (!DIFF_DIR.toFile().exists()) {
try {
Files.createDirectories(DIFF_DIR);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static List<String> getFiles(String prefix) {
try (final Stream<Path> files = Files.list(Plugin_DIR)) {
return files.filter(path ->
path.toString().endsWith("." + prefix) && path.toFile().isFile()
)
.map(Path::getFileName)
.map(Path::toString).toList();
} catch (IOException e) {
e.printStackTrace();
return INTERNAL_ERROR;
}
}
public static List<String> getJarFiles() {
return getFiles("jar");
}
public static List<String> getDiffFiles() {
return getFiles("diff");
}
@Override
public boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, String[] args) {
if (args.length == 0) {
return true;
}
if (args[0].equalsIgnoreCase("create")) {
if (args.length < 3) {
sender.sendMessage("Usage: /diff create <jar1> <jar2>");
return true;
}
return runCreateDiff(sender, commandLabel, args);
}
if (args[0].equalsIgnoreCase("merge")) {
if (args.length < 3) {
sender.sendMessage("Usage: /diff merge <patch> <jar>");
return true;
}
return runMergeDiff(sender, commandLabel, args);
}
return true;
}
private boolean runCreateDiff(@NotNull CommandSender sender, @NotNull String commandLabel, String[] args) {
GoldPiglinLogger.logger.info("Args: {}", String.join(" ", args));
var jar1 = args[1];
var jar2 = args[2];
var j1 = Plugin_DIR.resolve(jar1).toFile();
var j2 = Plugin_DIR.resolve(jar2).toFile();
if (!j1.exists() || !j2.exists()) {
sender.sendMessage("One of the jars does not exist");
return true;
}
try {
var diff = DIFF_DIR.resolve(jar1 + "-" + jar2 + ".diff");
var diffFile = diff.toFile();
if (!diffFile.exists()) {
diffFile.createNewFile();
} else {
diffFile.delete();
diffFile.createNewFile();
}
try (var fis1 = new FileInputStream(j1); var fis2 = new FileInputStream(j2)) {
try (ByteArrayOutputStream output = (ByteArrayOutputStream) SimplePatcher.createPatch(fis1, fis2); OutputStream fos = Files.newOutputStream(diff)) {
output.writeTo(fos);
fos.flush();
}
sender.sendMessage("Diff created at " + diff.toAbsolutePath());
}
} catch (IOException e) {
sender.sendMessage("Error: " + e.getMessage());
e.printStackTrace();
}
return true;
}
private boolean runMergeDiff(@NotNull CommandSender sender, @NotNull String commandLabel, String[] args) {
GoldPiglinLogger.logger.info("Args: {}", String.join(" ", args));
var patch = args[1];
var jar = args[2];
var p = DIFF_DIR.resolve(patch).toFile();
var j = Plugin_DIR.resolve(jar).toFile();
var j2 = Plugin_DIR.resolve(jar + ".new.jar");
try {
j2.toFile().createNewFile();
} catch (IOException e) {
e.printStackTrace();
sender.sendMessage("Error: " + e.getMessage());
return true;
}
try (var pS = new FileInputStream(p); var jS = new FileInputStream(j)) {
try (ByteArrayOutputStream fps = (ByteArrayOutputStream) SimplePatcher.applyPatch(pS, jS); var fos = Files.newOutputStream(j2)) {
fps.writeTo(fos);
fos.flush();
}
} catch (Exception exception) {
sender.sendMessage("Error: " + exception.getMessage());
exception.printStackTrace();
return true;
}
return false;
}
@Override
public @NotNull List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
List<String> list = new ArrayList<>();
if (args.length == 1) {
list.add("create");
list.add("merge");
}
if (args.length == 2) {
if (args[0].equalsIgnoreCase("create"))
list.addAll(getJarFiles());
if (args[0].equalsIgnoreCase("merge"))
list.addAll(getDiffFiles());
}
if (args.length == 3 && (args[0].equalsIgnoreCase("merge") || args[0].equalsIgnoreCase("create"))) {
list.addAll(getJarFiles());
}
return list;
}
}
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic void
applyPatch
(File patch, File dst, File outputFile) Applies a binary patch to a target file and writes the patched content to an output file.static void
applyPatch
(File patchFile, File targetFile, File outputFile, @Nullable ICompress compression) static OutputStream
applyPatch
(InputStream patch, InputStream dst) Applies a patch to a target file and returns the resulting file as an output stream.static File
Applies a binary patch file to a specified destination file and generates a new file with the patched content.static File
createPatch
(File newFile, File oldFile) Creates a temporary binary patch file that represents the differences between the specified new file and old file.static void
createPatch
(File newFile, File oldFile, File patchFile) Creates a binary patch file that defines the changes required to transform the contents of the old file into the new file.static void
createPatch
(File newFile, File oldFile, File patchFile, @Nullable ICompress compression) Creates a binary patch file that describes the changes required to transform the contents of the old file into the new file.static OutputStream
createPatch
(InputStream newFile, InputStream oldFile) Creates a binary patch that transforms the contents of the source file into the destination file.
-
Constructor Details
-
SimplePatcher
public SimplePatcher()
-
-
Method Details
-
createPatch
Creates a binary patch that transforms the contents of the source file into the destination file.- Parameters:
newFile
- the InputStream representing the source file's dataoldFile
- the InputStream representing the destination file's data- Returns:
- an OutputStream containing the binary patch data
- Throws:
IOException
- if an I/O error occurs while reading from the input streams or writing to the patch
-
createPatch
Creates a binary patch file that defines the changes required to transform the contents of the old file into the new file.The patch is stored in the specified patch file.
- Parameters:
newFile
- the file containing the target state after applying the patcholdFile
- the file containing the original state before applying the patchpatchFile
- the file where the generated patch will be saved; must not yet exist- Throws:
IOException
- if any of the input files do not exist, if the patch file already exists, or if an I/O error occurs while reading or writing
-
createPatch
public static void createPatch(File newFile, File oldFile, File patchFile, @Nullable @Nullable ICompress compression) throws IOException Creates a binary patch file that describes the changes required to transform the contents of the old file into the new file.The patch is written to the specified patch file, with optional compression applied.
- Parameters:
newFile
- the file containing the target state after applying the patcholdFile
- the file containing the original state before applying the patchpatchFile
- the file where the generated patch will be saved; must not yet existcompression
- the compression method to be applied to the patch output; may be null if no compression is desired- Throws:
IOException
- if any of the input files do not exist, if the patch file already exists, or if an I/O error occurs while reading or writing files
-
createPatch
Creates a temporary binary patch file that represents the differences between the specified new file and old file.The temporary patch file is deleted if an exception occurs during its creation.
- Parameters:
newFile
- the file representing the new version of the contentoldFile
- the file representing the old version of the content- Returns:
- a temporary file containing the binary patch data
- Throws:
IOException
- if an I/O error occurs, such as issues reading the input files, writing the patch file, or if any of the required files does not exist
-
applyPatch
Applies a patch to a target file and returns the resulting file as an output stream.- Parameters:
patch
- the input stream containing the patch data to be applieddst
- the input stream of the target file that will be patched- Returns:
- an output stream containing the patched file contents
- Throws:
IOException
- if an I/O error occurs while reading or writing streamsIllegalStateException
- if the patch does not match the target file, is corrupted, or contains invalid commands
-
applyPatch
Applies a binary patch to a target file and writes the patched content to an output file.- Parameters:
patch
- the patch file containing the binary data with instructions for applying the patchdst
- the target file to which the patch will be appliedoutputFile
- the file where the patched content will be written; must not yet exist- Throws:
IOException
- if the patch file does not exist, the target file does not exist, the output file already exists, or if an I/O error occurs during the process
-
applyPatch
public static void applyPatch(File patchFile, File targetFile, File outputFile, @Nullable @Nullable ICompress compression) throws IOException - Throws:
IOException
-
applyPath
Applies a binary patch file to a specified destination file and generates a new file with the patched content.- Parameters:
patch
- the file containing the patch data to be applieddst
- the file representing the target to which the patch will be applied- Returns:
- a temporary file containing the patched content after applying the patch
- Throws:
IOException
- if an I/O error occurs during patch application, such as issues reading or writing files, if the patch or destination file does not exist, or if the generated output file cannot be created
-