Browse Source

Apply the unified-diff patch when combining layers.

qdn
CalDescent 3 years ago
parent
commit
9a88c0d579
  1. 20
      src/main/java/org/qortal/arbitrary/ArbitraryDataCombiner.java
  2. 70
      src/main/java/org/qortal/arbitrary/ArbitraryDataMerge.java

20
src/main/java/org/qortal/arbitrary/ArbitraryDataCombiner.java

@ -23,6 +23,7 @@ public class ArbitraryDataCombiner {
private Path pathAfter;
private byte[] signatureBefore;
private Path finalPath;
ArbitraryDataMetadataPatch metadata;
public ArbitraryDataCombiner(Path pathBefore, Path pathAfter, byte[] signatureBefore) {
this.pathBefore = pathBefore;
@ -33,6 +34,7 @@ public class ArbitraryDataCombiner {
public void combine() throws IOException {
try {
this.preExecute();
this.readMetadata();
this.validatePreviousSignature();
this.validatePreviousHash();
this.process();
@ -86,14 +88,17 @@ public class ArbitraryDataCombiner {
}
private void validatePreviousSignature() throws IOException {
private void readMetadata() throws IOException {
this.metadata = new ArbitraryDataMetadataPatch(this.pathAfter);
this.metadata.read();
}
private void validatePreviousSignature() {
if (this.signatureBefore == null) {
throw new IllegalStateException("No previous signature passed to the combiner");
}
ArbitraryDataMetadataPatch metadata = new ArbitraryDataMetadataPatch(this.pathAfter);
metadata.read();
byte[] previousSignature = metadata.getPreviousSignature();
byte[] previousSignature = this.metadata.getPreviousSignature();
if (previousSignature == null) {
throw new IllegalStateException("Unable to extract previous signature from patch metadata");
}
@ -105,9 +110,7 @@ public class ArbitraryDataCombiner {
}
private void validatePreviousHash() throws IOException {
ArbitraryDataMetadataPatch metadata = new ArbitraryDataMetadataPatch(this.pathAfter);
metadata.read();
byte[] previousHash = metadata.getPreviousHash();
byte[] previousHash = this.metadata.getPreviousHash();
if (previousHash == null) {
throw new IllegalStateException("Unable to extract previous hash from patch metadata");
}
@ -123,7 +126,8 @@ public class ArbitraryDataCombiner {
}
private void process() throws IOException {
ArbitraryDataMerge merge = new ArbitraryDataMerge(this.pathBefore, this.pathAfter);
String patchType = metadata.getPatchType();
ArbitraryDataMerge merge = new ArbitraryDataMerge(this.pathBefore, this.pathAfter, metadata.getPatchType());
merge.compute();
this.finalPath = merge.getMergePath();
}

70
src/main/java/org/qortal/arbitrary/ArbitraryDataMerge.java

@ -1,16 +1,25 @@
package org.qortal.arbitrary;
import com.github.difflib.DiffUtils;
import com.github.difflib.UnifiedDiffUtils;
import com.github.difflib.patch.Patch;
import com.github.difflib.patch.PatchFailedException;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jetty.util.IO;
import org.qortal.arbitrary.metadata.ArbitraryDataMetadataPatch;
import org.qortal.settings.Settings;
import org.qortal.utils.FilesystemUtils;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class ArbitraryDataMerge {
@ -19,13 +28,15 @@ public class ArbitraryDataMerge {
private Path pathBefore;
private Path pathAfter;
private String patchType;
private Path mergePath;
private String identifier;
private ArbitraryDataMetadataPatch metadata;
public ArbitraryDataMerge(Path pathBefore, Path pathAfter) {
public ArbitraryDataMerge(Path pathBefore, Path pathAfter, String patchType) {
this.pathBefore = pathBefore;
this.pathAfter = pathAfter;
this.patchType = patchType;
}
public void compute() throws IOException {
@ -87,8 +98,7 @@ public class ArbitraryDataMerge {
List<Path> modifiedPaths = this.metadata.getModifiedPaths();
for (Path path : modifiedPaths) {
LOGGER.info("File was modified: {}", path.toString());
Path filePath = Paths.get(this.pathAfter.toString(), path.toString());
ArbitraryDataMerge.copyPathToBaseDir(filePath, this.mergePath, path);
this.applyPatch(path);
}
List<Path> removedPaths = this.metadata.getRemovedPaths();
@ -98,6 +108,60 @@ public class ArbitraryDataMerge {
}
}
private void applyPatch(Path path) throws IOException {
if (Objects.equals(this.patchType, "unified-diff")) {
// Create destination file from patch
this.applyUnifiedDiffPatch(path);
}
else {
// Copy complete file
Path filePath = Paths.get(this.pathAfter.toString(), path.toString());
ArbitraryDataMerge.copyPathToBaseDir(filePath, this.mergePath, path);
}
}
private void applyUnifiedDiffPatch(Path path) throws IOException {
Path originalPath = Paths.get(this.pathBefore.toString(), path.toString());
Path patchPath = Paths.get(this.pathAfter.toString(), path.toString());
Path mergePath = Paths.get(this.mergePath.toString(), path.toString());
if (!patchPath.toFile().exists()) {
// Patch file doesn't exist, but its path was included in modifiedPaths
// TODO: We ought to throw an exception here, but skipping for now
return;
}
// Delete an existing file, as we are starting from a duplicate of pathBefore
File destFile = mergePath.toFile();
if (destFile.exists() && destFile.isFile()) {
Files.delete(mergePath);
}
List<String> originalContents = FileUtils.readLines(originalPath.toFile(), StandardCharsets.UTF_8);
List<String> patchContents = FileUtils.readLines(patchPath.toFile(), StandardCharsets.UTF_8);
// At first, parse the unified diff file and get the patch
Patch<String> patch = UnifiedDiffUtils.parseUnifiedDiff(patchContents);
// Then apply the computed patch to the given text
try {
List<String> patchedContents = DiffUtils.patch(originalContents, patch);
// Write the patched file to the merge directory
FileWriter fileWriter = new FileWriter(mergePath.toString(), true);
BufferedWriter writer = new BufferedWriter(fileWriter);
for (String line : patchedContents) {
writer.append(line);
writer.newLine();
}
writer.flush();
writer.close();
} catch (PatchFailedException e) {
throw new IllegalStateException(String.format("Failed to apply patch for path %s: %s", path, e.getMessage()));
}
}
private void copyMetadata() throws IOException {
Path filePath = Paths.get(this.pathAfter.toString(), ".qortal");
ArbitraryDataMerge.copyPathToBaseDir(filePath, this.mergePath, Paths.get(".qortal"));

Loading…
Cancel
Save