|
25 | 25 | import java.io.ByteArrayOutputStream; |
26 | 26 | import java.io.IOException; |
27 | 27 | import java.io.OutputStream; |
| 28 | +import java.util.Arrays; |
28 | 29 | import java.util.Collection; |
29 | 30 | import java.util.Collections; |
30 | 31 | import java.util.List; |
| 32 | +import java.util.zip.Deflater; |
| 33 | +import java.util.zip.DeflaterOutputStream; |
31 | 34 |
|
32 | 35 | import org.openrewrite.jgit.diff.DiffAlgorithm.SupportedAlgorithm; |
33 | 36 | import org.openrewrite.jgit.diff.DiffEntry.ChangeType; |
|
68 | 71 | import org.openrewrite.jgit.treewalk.filter.TreeFilter; |
69 | 72 | import org.openrewrite.jgit.util.LfsFactory; |
70 | 73 | import org.openrewrite.jgit.util.QuotedString; |
| 74 | +import org.openrewrite.jgit.util.io.BinaryHunkOutputStream; |
71 | 75 |
|
72 | 76 | /** |
73 | 77 | * Format a Git style patch script. |
@@ -96,6 +100,8 @@ public class DiffFormatter implements AutoCloseable { |
96 | 100 |
|
97 | 101 | private RawTextComparator comparator = RawTextComparator.DEFAULT; |
98 | 102 |
|
| 103 | + private boolean binaryPatch = false; |
| 104 | + |
99 | 105 | private int binaryFileThreshold = DEFAULT_BINARY_FILE_THRESHOLD; |
100 | 106 |
|
101 | 107 | private String oldPrefix = "a/"; //$NON-NLS-1$ |
@@ -259,6 +265,10 @@ public void setBinaryFileThreshold(int threshold) { |
259 | 265 | this.binaryFileThreshold = threshold; |
260 | 266 | } |
261 | 267 |
|
| 268 | + public void setBinary(boolean binaryPatch) { |
| 269 | + this.binaryPatch = binaryPatch; |
| 270 | + } |
| 271 | + |
262 | 272 | /** |
263 | 273 | * Set the prefix applied in front of old file paths. |
264 | 274 | * |
@@ -714,7 +724,7 @@ private static byte[] writeGitLinkText(AbbreviatedObjectId id) { |
714 | 724 | } |
715 | 725 |
|
716 | 726 | private String format(AbbreviatedObjectId id) { |
717 | | - if (id.isComplete() && reader != null) { |
| 727 | + if (id.isComplete() && reader != null && !binaryPatch) { |
718 | 728 | try { |
719 | 729 | id = reader.abbreviate(id.toObjectId(), abbreviationLength); |
720 | 730 | } catch (IOException cannotAbbreviate) { |
@@ -764,6 +774,8 @@ public void format(FileHeader head, RawText a, RawText b) |
764 | 774 | out.write(head.getBuffer(), start, end - start); |
765 | 775 | if (head.getPatchType() == PatchType.UNIFIED) |
766 | 776 | format(head.toEditList(), a, b); |
| 777 | + else if (head.getPatchType() == PatchType.GIT_BINARY && a != null && b != null) |
| 778 | + formatBinary(a, b); |
767 | 779 | } |
768 | 780 |
|
769 | 781 | /** |
@@ -816,6 +828,26 @@ public void format(EditList edits, RawText a, RawText b) |
816 | 828 | } |
817 | 829 | } |
818 | 830 |
|
| 831 | + private void formatBinary(RawText a, RawText b) throws IOException { |
| 832 | + byte[] oldImage = a.getRawContent(); |
| 833 | + byte[] newImage = b.getRawContent(); |
| 834 | + out.write(encodeASCII("literal " + newImage.length + "\n")); |
| 835 | + Deflater deflater = new Deflater(); |
| 836 | + deflater.setLevel(Deflater.BEST_SPEED); |
| 837 | + try (OutputStream os = new DeflaterOutputStream(new BinaryHunkOutputStream(out), deflater, 1024)) { |
| 838 | + os.write(newImage); |
| 839 | + } |
| 840 | + out.write('\n'); |
| 841 | + out.write(encodeASCII("literal " + oldImage.length + "\n")); |
| 842 | + deflater = new Deflater(); // deflater is stateful, reset it |
| 843 | + deflater.setLevel(Deflater.BEST_SPEED); |
| 844 | + try (OutputStream os = new DeflaterOutputStream(new BinaryHunkOutputStream(out), deflater, 1024)) { |
| 845 | + os.write(oldImage); |
| 846 | + } |
| 847 | + out.write('\n'); |
| 848 | + out.write('\n'); |
| 849 | + } |
| 850 | + |
819 | 851 | /** |
820 | 852 | * Output a line of context (unmodified line). |
821 | 853 | * |
@@ -997,17 +1029,45 @@ private FormatResult createFormatResult(DiffEntry ent) throws IOException, |
997 | 1029 | aRaw = new RawText(writeGitLinkText(ent.getOldId())); |
998 | 1030 | bRaw = new RawText(writeGitLinkText(ent.getNewId())); |
999 | 1031 | } else { |
1000 | | - try { |
1001 | | - aRaw = open(OLD, ent); |
1002 | | - bRaw = open(NEW, ent); |
1003 | | - } catch (BinaryBlobException e) { |
1004 | | - // Do nothing; we check for null below. |
1005 | | - formatOldNewPaths(buf, ent); |
1006 | | - buf.write(encodeASCII("Binary files differ\n")); //$NON-NLS-1$ |
1007 | | - editList = new EditList(); |
1008 | | - type = PatchType.BINARY; |
1009 | | - res.header = new FileHeader(buf.toByteArray(), editList, type); |
| 1032 | + if (binaryPatch) { |
| 1033 | + try { |
| 1034 | + aRaw = open(OLD, ent); |
| 1035 | + bRaw = open(NEW, ent); |
| 1036 | + } catch (BinaryBlobException e) { |
| 1037 | + // Do nothing; we check for null below. |
| 1038 | + formatOldNewPaths(buf, ent); |
| 1039 | + buf.write(encodeASCII("Binary files differ\n")); //$NON-NLS-1$ |
| 1040 | + editList = new EditList(); |
| 1041 | + type = PatchType.BINARY; |
| 1042 | + res.header = new FileHeader(buf.toByteArray(), editList, type); |
| 1043 | + return res; |
| 1044 | + } |
| 1045 | + |
| 1046 | + if (Arrays.equals(aRaw.getRawContent(), bRaw.getRawContent())) { |
| 1047 | + type = PatchType.GIT_BINARY; |
| 1048 | + res.header = new FileHeader(buf.toByteArray(), type); |
| 1049 | + return res; |
| 1050 | + } |
| 1051 | + |
| 1052 | + buf.write(encodeASCII("GIT binary patch\n")); |
| 1053 | + type = PatchType.GIT_BINARY; |
| 1054 | + res.header = new FileHeader(buf.toByteArray(), type); |
| 1055 | + res.a = aRaw; |
| 1056 | + res.b = bRaw; |
1010 | 1057 | return res; |
| 1058 | + } else { |
| 1059 | + try { |
| 1060 | + aRaw = open(OLD, ent); |
| 1061 | + bRaw = open(NEW, ent); |
| 1062 | + } catch (BinaryBlobException e) { |
| 1063 | + // Do nothing; we check for null below. |
| 1064 | + formatOldNewPaths(buf, ent); |
| 1065 | + buf.write(encodeASCII("Binary files differ\n")); //$NON-NLS-1$ |
| 1066 | + editList = new EditList(); |
| 1067 | + type = PatchType.BINARY; |
| 1068 | + res.header = new FileHeader(buf.toByteArray(), editList, type); |
| 1069 | + return res; |
| 1070 | + } |
1011 | 1071 | } |
1012 | 1072 | } |
1013 | 1073 |
|
@@ -1072,7 +1132,11 @@ private RawText open(DiffEntry.Side side, DiffEntry entry) |
1072 | 1132 |
|
1073 | 1133 | ObjectLoader ldr = LfsFactory.getInstance().applySmudgeFilter(repository, |
1074 | 1134 | source.open(side, entry), entry.getDiffAttribute()); |
1075 | | - return RawText.load(ldr, binaryFileThreshold); |
| 1135 | + if (binaryPatch) { |
| 1136 | + return RawText.loadBinary(ldr, binaryFileThreshold); |
| 1137 | + } else { |
| 1138 | + return RawText.load(ldr, binaryFileThreshold); |
| 1139 | + } |
1076 | 1140 | } |
1077 | 1141 |
|
1078 | 1142 | /** |
|
0 commit comments