Browse Source

Create a "unified-diff" patch using java-diff-utils instead of including the entire modified file. I still need to test how well this works with binary files.

qdn
CalDescent 3 years ago
parent
commit
cb6fc466d1
  1. 64
      src/main/java/org/qortal/arbitrary/ArbitraryDataDiff.java
  2. 18
      src/main/java/org/qortal/arbitrary/metadata/ArbitraryDataMetadataPatch.java

64
src/main/java/org/qortal/arbitrary/ArbitraryDataDiff.java

@ -1,13 +1,17 @@
package org.qortal.arbitrary;
import com.github.difflib.DiffUtils;
import com.github.difflib.UnifiedDiffUtils;
import com.github.difflib.patch.Patch;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch;
import org.qortal.crypto.Crypto;
import org.qortal.settings.Settings;
import java.io.File;
import java.io.IOException;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
@ -133,9 +137,14 @@ public class ArbitraryDataDiff {
wasModified = true;
}
if (wasAdded | wasModified) {
if (wasAdded) {
ArbitraryDataDiff.copyFilePathToBaseDir(after, diffPathAbsolute, filePathAfter);
}
if (wasModified) {
// Create patch using java-diff-utils
Path destination = Paths.get(diffPathAbsolute.toString(), filePathAfter.toString());
ArbitraryDataDiff.createAndCopyDiffUtilsPatch(filePathBefore, after, destination);
}
return FileVisitResult.CONTINUE;
}
@ -159,7 +168,7 @@ public class ArbitraryDataDiff {
}
}
private void findRemovedFiles() {
private void findRemovedFiles() throws IOException {
try {
final Path pathBeforeAbsolute = this.pathBefore.toAbsolutePath();
final Path pathAfterAbsolute = this.pathAfter.toAbsolutePath();
@ -219,7 +228,7 @@ public class ArbitraryDataDiff {
});
} catch (IOException e) {
LOGGER.info("IOException when walking through file tree: {}", e.getMessage());
throw new IOException(String.format("IOException when walking through file tree: %s", e.getMessage()));
}
}
@ -231,6 +240,7 @@ public class ArbitraryDataDiff {
private void writeMetadata() throws IOException {
ArbitraryDataMetadataPatch metadata = new ArbitraryDataMetadataPatch(this.diffPath);
metadata.setPatchType("unified-diff");
metadata.setAddedPaths(this.addedPaths);
metadata.setModifiedPaths(this.modifiedPaths);
metadata.setRemovedPaths(this.removedPaths);
@ -265,6 +275,50 @@ public class ArbitraryDataDiff {
Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING);
}
private static void createAndCopyDiffUtilsPatch(Path before, Path after, Path destination) throws IOException {
if (!Files.exists(before)) {
throw new IOException(String.format("File not found (before): %s", before.toString()));
}
if (!Files.exists(after)) {
throw new IOException(String.format("File not found (after): %s", after.toString()));
}
// Ensure parent folders exist in the destination
File file = new File(destination.toString());
File parent = file.getParentFile();
if (parent != null) {
parent.mkdirs();
}
// Delete an existing file if it exists
File destFile = destination.toFile();
if (destFile.exists() && destFile.isFile()) {
Files.delete(destination);
}
// Load the two files into memory
List<String> original = FileUtils.readLines(before.toFile(), StandardCharsets.UTF_8);
List<String> revised = FileUtils.readLines(after.toFile(), StandardCharsets.UTF_8);
// Generate diff information
Patch<String> diff = DiffUtils.diff(original, revised);
// Generate unified diff format
String originalFileName = before.getFileName().toString();
String revisedFileName = after.getFileName().toString();
List<String> unifiedDiff = UnifiedDiffUtils.generateUnifiedDiff(originalFileName, revisedFileName, original, diff, 0);
// Write the diff to the destination directory
FileWriter fileWriter = new FileWriter(destination.toString(), true);
BufferedWriter writer = new BufferedWriter(fileWriter);
for (String line : unifiedDiff) {
writer.append(line);
writer.newLine();
}
writer.flush();
writer.close();
}
public Path getDiffPath() {
return this.diffPath;

18
src/main/java/org/qortal/arbitrary/metadata/ArbitraryDataMetadataPatch.java

@ -17,6 +17,7 @@ public class ArbitraryDataMetadataPatch extends ArbitraryDataMetadata {
private static final Logger LOGGER = LogManager.getLogger(ArbitraryDataMetadataPatch.class);
private String patchType;
private List<Path> addedPaths;
private List<Path> modifiedPaths;
private List<Path> removedPaths;
@ -43,6 +44,12 @@ public class ArbitraryDataMetadataPatch extends ArbitraryDataMetadata {
}
JSONObject patch = new JSONObject(this.jsonString);
if (patch.has("patchType")) {
String patchType = patch.getString("patchType");
if (patchType != null) {
this.patchType = patchType;
}
}
if (patch.has("prevSig")) {
String prevSig = patch.getString("prevSig");
if (prevSig != null) {
@ -94,8 +101,9 @@ public class ArbitraryDataMetadataPatch extends ArbitraryDataMetadata {
changeMap.set(patch, new LinkedHashMap<>());
changeMap.setAccessible(false);
} catch (IllegalAccessException | NoSuchFieldException e) {
// Don't worry about failures as this is for ordering only
// Don't worry about failures as this is for optional ordering only
}
patch.put("patchType", this.patchType);
patch.put("prevSig", Base58.encode(this.previousSignature));
patch.put("prevHash", Base58.encode(this.previousHash));
patch.put("added", new JSONArray(this.addedPaths));
@ -107,6 +115,14 @@ public class ArbitraryDataMetadataPatch extends ArbitraryDataMetadata {
}
public void setPatchType(String patchType) {
this.patchType = patchType;
}
public String getPatchType() {
return this.patchType;
}
public void setAddedPaths(List<Path> addedPaths) {
this.addedPaths = addedPaths;
}

Loading…
Cancel
Save