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