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; 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.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch; import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch;
import org.qortal.crypto.Crypto; import org.qortal.crypto.Crypto;
import org.qortal.settings.Settings; import org.qortal.settings.Settings;
import java.io.File; import java.io.*;
import java.io.IOException; import java.nio.charset.StandardCharsets;
import java.nio.file.*; import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
@ -133,9 +137,14 @@ public class ArbitraryDataDiff {
wasModified = true; wasModified = true;
} }
if (wasAdded | wasModified) { if (wasAdded) {
ArbitraryDataDiff.copyFilePathToBaseDir(after, diffPathAbsolute, filePathAfter); 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; return FileVisitResult.CONTINUE;
} }
@ -159,7 +168,7 @@ public class ArbitraryDataDiff {
} }
} }
private void findRemovedFiles() { private void findRemovedFiles() throws IOException {
try { try {
final Path pathBeforeAbsolute = this.pathBefore.toAbsolutePath(); final Path pathBeforeAbsolute = this.pathBefore.toAbsolutePath();
final Path pathAfterAbsolute = this.pathAfter.toAbsolutePath(); final Path pathAfterAbsolute = this.pathAfter.toAbsolutePath();
@ -219,7 +228,7 @@ public class ArbitraryDataDiff {
}); });
} catch (IOException e) { } 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 { private void writeMetadata() throws IOException {
ArbitraryDataMetadataPatch metadata = new ArbitraryDataMetadataPatch(this.diffPath); ArbitraryDataMetadataPatch metadata = new ArbitraryDataMetadataPatch(this.diffPath);
metadata.setPatchType("unified-diff");
metadata.setAddedPaths(this.addedPaths); metadata.setAddedPaths(this.addedPaths);
metadata.setModifiedPaths(this.modifiedPaths); metadata.setModifiedPaths(this.modifiedPaths);
metadata.setRemovedPaths(this.removedPaths); metadata.setRemovedPaths(this.removedPaths);
@ -264,6 +274,50 @@ public class ArbitraryDataDiff {
LOGGER.trace("Copying {} to {}", source, dest); LOGGER.trace("Copying {} to {}", source, dest);
Files.copy(source, dest, StandardCopyOption.REPLACE_EXISTING); 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() { public Path getDiffPath() {

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 static final Logger LOGGER = LogManager.getLogger(ArbitraryDataMetadataPatch.class);
private String patchType;
private List<Path> addedPaths; private List<Path> addedPaths;
private List<Path> modifiedPaths; private List<Path> modifiedPaths;
private List<Path> removedPaths; private List<Path> removedPaths;
@ -43,6 +44,12 @@ public class ArbitraryDataMetadataPatch extends ArbitraryDataMetadata {
} }
JSONObject patch = new JSONObject(this.jsonString); 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")) { if (patch.has("prevSig")) {
String prevSig = patch.getString("prevSig"); String prevSig = patch.getString("prevSig");
if (prevSig != null) { if (prevSig != null) {
@ -94,8 +101,9 @@ public class ArbitraryDataMetadataPatch extends ArbitraryDataMetadata {
changeMap.set(patch, new LinkedHashMap<>()); changeMap.set(patch, new LinkedHashMap<>());
changeMap.setAccessible(false); changeMap.setAccessible(false);
} catch (IllegalAccessException | NoSuchFieldException e) { } 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("prevSig", Base58.encode(this.previousSignature));
patch.put("prevHash", Base58.encode(this.previousHash)); patch.put("prevHash", Base58.encode(this.previousHash));
patch.put("added", new JSONArray(this.addedPaths)); 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) { public void setAddedPaths(List<Path> addedPaths) {
this.addedPaths = addedPaths; this.addedPaths = addedPaths;
} }

Loading…
Cancel
Save