Skip to content

Commit 8c4728c

Browse files
committed
refactor: extract method for applying git diff to strings
1 parent a395347 commit 8c4728c

2 files changed

Lines changed: 103 additions & 63 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package org.variantsync.diffdetective.variation.diff.construction;
2+
3+
import org.eclipse.jgit.diff.*;
4+
import org.variantsync.diffdetective.diff.git.GitDiffer;
5+
import org.variantsync.diffdetective.diff.result.DiffParseException;
6+
import org.variantsync.diffdetective.variation.DiffLinesLabel;
7+
import org.variantsync.diffdetective.variation.diff.Time;
8+
import org.variantsync.diffdetective.variation.diff.VariationDiff;
9+
import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParseOptions;
10+
import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser;
11+
import org.variantsync.diffdetective.variation.diff.source.PatchString;
12+
13+
import java.io.BufferedReader;
14+
import java.io.ByteArrayOutputStream;
15+
import java.io.IOException;
16+
import java.io.StringReader;
17+
import java.nio.charset.StandardCharsets;
18+
19+
/**
20+
* Class which groups functions of parsing variation diffs with JGit.
21+
* @author Paul Bittner
22+
*/
23+
public final class JGitDiff {
24+
private JGitDiff() {}
25+
26+
/**
27+
* Creates a variation diff from to line-based text inputs.
28+
* Expects variability to be implemented via C preprocessor in those lines.
29+
* Uses JGit to diff the two files using the specified {@code options}, and afterwards, creates the variation diff.
30+
* @param linesBefore State of annotated lines before the change.
31+
* @param linesAfter State of annotated lines before the change.
32+
* @param algorithm Specification of which algorithm to use for diffing with JGit.
33+
* @param options various options for parsing
34+
* @return A variation diff comprising the changes.
35+
* @throws IOException when JGit fails in differencing
36+
* @throws DiffParseException when DiffDetective fails in parsing the JGit diff to a variation diff
37+
*/
38+
public static VariationDiff<DiffLinesLabel> diff(
39+
String linesBefore,
40+
String linesAfter,
41+
DiffAlgorithm.SupportedAlgorithm algorithm,
42+
VariationDiffParseOptions options
43+
) throws IOException, DiffParseException {
44+
final RawText[] text = new RawText[]{
45+
new RawText(linesBefore.getBytes()),
46+
new RawText(linesAfter.getBytes())
47+
};
48+
49+
// MYERS or HISTOGRAM
50+
final DiffAlgorithm diffAlgorithm = DiffAlgorithm.getAlgorithm(algorithm);
51+
final RawTextComparator comparator = RawTextComparator.DEFAULT;
52+
final EditList diff = diffAlgorithm.diff(
53+
comparator,
54+
text[Time.BEFORE.ordinal()],
55+
text[Time.AFTER.ordinal()]
56+
);
57+
58+
String textDiff;
59+
final ByteArrayOutputStream os = new ByteArrayOutputStream();
60+
61+
/*
62+
Using our own formatter without diff headers (paired with a maximum context (?))
63+
caused the formatter to crash due to index out of bounds exceptions.
64+
So I guess there is a hidden assumption in the DiffFormatter that expects the header
65+
to be there.
66+
67+
As a fix, we also use our own construction of embedding patches into the before file to obtain a full diff.
68+
*/
69+
// final DiffFormatter formatter = makeFormatterWithoutHeader(os);
70+
// formatter.setContext(Integer.MAX_VALUE); // FULL DIFF
71+
final DiffFormatter formatter = new DiffFormatter(os);
72+
73+
formatter.setDiffAlgorithm(diffAlgorithm);
74+
formatter.setDiffComparator(comparator);
75+
formatter.setOldPrefix("");
76+
formatter.setNewPrefix("");
77+
78+
formatter.format(
79+
diff,
80+
text[Time.BEFORE.ordinal()],
81+
text[Time.AFTER.ordinal()]);
82+
formatter.flush();
83+
textDiff = os.toString(StandardCharsets.UTF_8);
84+
formatter.close();
85+
os.close();
86+
87+
textDiff = GitDiffer.getFullDiff(
88+
new BufferedReader(new StringReader(linesBefore)),
89+
new BufferedReader(new StringReader(textDiff))
90+
);
91+
92+
//textDiff = textDiff.replace("\\ No newline at end of file\n", "");
93+
//textDiff = HUNK_HEADER_REGEX.matcher(textDiff).replaceAll("");
94+
95+
final VariationDiff<DiffLinesLabel> d = VariationDiffParser.createVariationDiff(textDiff, options);
96+
d.setSource(new PatchString(textDiff));
97+
return d;
98+
}
99+
}

src/main/java/org/variantsync/diffdetective/variation/diff/view/DiffView.java

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package org.variantsync.diffdetective.variation.diff.view;
22

3-
import org.eclipse.jgit.diff.*;
3+
import org.eclipse.jgit.diff.DiffAlgorithm;
44
import org.tinylog.Logger;
5-
import org.variantsync.diffdetective.diff.git.GitDiffer;
65
import org.variantsync.diffdetective.diff.result.DiffParseException;
76
import org.variantsync.diffdetective.experiments.views.Main;
87
import org.variantsync.diffdetective.util.Assert;
@@ -11,16 +10,15 @@
1110
import org.variantsync.diffdetective.variation.Label;
1211
import org.variantsync.diffdetective.variation.diff.*;
1312
import org.variantsync.diffdetective.variation.diff.bad.BadVDiff;
14-
import org.variantsync.diffdetective.variation.diff.parse.VariationDiffParser;
13+
import org.variantsync.diffdetective.variation.diff.construction.JGitDiff;
1514
import org.variantsync.diffdetective.variation.tree.VariationTree;
1615
import org.variantsync.diffdetective.variation.tree.VariationTreeNode;
1716
import org.variantsync.diffdetective.variation.tree.view.TreeView;
1817
import org.variantsync.diffdetective.variation.tree.view.relevance.Relevance;
1918
import org.variantsync.functjonal.Cast;
2019

21-
import java.io.*;
20+
import java.io.IOException;
2221
import java.lang.reflect.Array;
23-
import java.nio.charset.StandardCharsets;
2422
import java.util.*;
2523
import java.util.function.BiPredicate;
2624

@@ -72,72 +70,15 @@ public static <L extends Label> BiPredicate<Time, Projection<L>> computeWhenNode
7270
* @throws DiffParseException When the text-based diff could not be parsed to a variation diff.
7371
*/
7472
private static <L extends Label> VariationDiff<DiffLinesLabel> naive(final VariationDiff<L> d, final Relevance rho, final String[] projectionViewText) throws IOException, DiffParseException {
75-
// Logger.info("q = " + q);
76-
final RawText[] text = new RawText[] {
77-
new RawText(projectionViewText[Time.BEFORE.ordinal()].getBytes()),
78-
new RawText(projectionViewText[Time.AFTER.ordinal()].getBytes())
79-
};
80-
81-
// MYERS or HISTOGRAM
82-
final DiffAlgorithm diffAlgorithm = DiffAlgorithm.getAlgorithm(DiffAlgorithm.SupportedAlgorithm.MYERS);
83-
final RawTextComparator comparator = RawTextComparator.DEFAULT;
84-
final EditList diff = diffAlgorithm.diff(
85-
comparator,
86-
text[Time.BEFORE.ordinal()],
87-
text[Time.AFTER.ordinal()]
88-
);
89-
90-
String textDiff;
91-
{
92-
final ByteArrayOutputStream os = new ByteArrayOutputStream();
93-
94-
/*
95-
Using our own formatter without diff headers (paired with a maximum context (?))
96-
caused the formatter to crash due to index out of bounds exceptions.
97-
So I guess there is a hidden assumption in the DiffFormatter that expects the header
98-
to be there.
99-
100-
As a fix, we also use our own construction of embedding patches into the before file to obtain a full diff.
101-
*/
102-
// final DiffFormatter formatter = makeFormatterWithoutHeader(os);
103-
// formatter.setContext(Integer.MAX_VALUE); // FULL DIFF
104-
final DiffFormatter formatter = new DiffFormatter(os);
105-
106-
formatter.setDiffAlgorithm(diffAlgorithm);
107-
formatter.setDiffComparator(comparator);
108-
formatter.setOldPrefix("");
109-
formatter.setNewPrefix("");
110-
111-
formatter.format(
112-
diff,
113-
text[Time.BEFORE.ordinal()],
114-
text[Time.AFTER.ordinal()]);
115-
formatter.flush();
116-
textDiff = os.toString(StandardCharsets.UTF_8);
117-
formatter.close();
118-
os.close();
119-
120-
// Logger.info("Initial Diff\n" + textDiff);
121-
122-
textDiff = GitDiffer.getFullDiff(
123-
new BufferedReader(new StringReader(projectionViewText[Time.BEFORE.ordinal()])),
124-
new BufferedReader(new StringReader(textDiff))
125-
);
126-
127-
//textDiff = textDiff.replace("\\ No newline at end of file\n", "");
128-
//textDiff = HUNK_HEADER_REGEX.matcher(textDiff).replaceAll("");
129-
}
130-
// Logger.info("Full Diff\n" + textDiff);
13173
final VariationDiff<DiffLinesLabel> view;
13274
try {
133-
view = VariationDiffParser.createVariationDiff(textDiff, Main.VARIATION_DIFF_PARSE_OPTIONS);
75+
view = JGitDiff.diff(projectionViewText[0], projectionViewText[1], DiffAlgorithm.SupportedAlgorithm.MYERS, Main.VARIATION_DIFF_PARSE_OPTIONS);
13476
} catch (DiffParseException e) {
13577
Logger.error("""
13678
Could not parse diff obtained with query {} at {}:
13779
Diff:
13880
""",
13981
d.getSource(), rho);
140-
System.out.println(textDiff);
14182
throw e;
14283
}
14384
view.setSource(new ViewSource<>(d, rho));

0 commit comments

Comments
 (0)