-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add diff tool #89
Add diff tool #89
Changes from 6 commits
3d3e0d2
7d199a2
49e8f93
373c875
1d85bfe
759ac97
120679b
d75db08
354f201
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Diff-Tool | ||
|
||
This is a thin wrapper around `java-diff-utils` which provides the convenience of rendering diffs to a nice human | ||
readable String. | ||
|
||
## Usage | ||
|
||
```java | ||
final String expected = "..."; | ||
final String actual = "..."; | ||
|
||
// Create a diff using default configuration | ||
final StringDiff diff1 = StringDiff.simple(expected, actual); | ||
|
||
// Render as unified diff | ||
final String unifiedDiff = diff1.toString(); | ||
// Render as split diff | ||
final String splitDiff = diff1.toString(SplitDiffRenderer.INSTANCE); | ||
|
||
// Test whether compared Strings differed in line separators | ||
final boolean lineSeparatorDifference = diff1.hasLineSeparatorDifference() | ||
// Tests whether compared Strings differed in actual text | ||
final boolean textDifference = diff1.hasTextDifference() | ||
|
||
// Create a diff by configuring the java-diff-utils _DiffRowGenerator_ | ||
final DiffAlgorithm diffAlgorithm = DiffUtilsDiffAlgorithm.create(builder -> builder | ||
.showInlineDiffs(true) | ||
.inlineDiffByWord(true) | ||
.ignoreWhiteSpaces(true)); | ||
|
||
final StringDiff diff2 = StringDiff.using(diffAlgorithm, expected, actual); | ||
``` | ||
|
||
## Sample output | ||
|
||
Unified Diff: | ||
``` | ||
[...] | ||
6 6 Some unchanged lines6 | ||
7 7 Some unchanged lines7 | ||
8 8 Some unchanged lines8 | ||
9 - This is a test <<senctence>>. | ||
9 + This is a test <<for diffutils>>. | ||
10 10 This is the second line. | ||
11 11 Some unchanged lines9 | ||
12 12 Some unchanged lines10 | ||
13 13 Some unchanged lines11 | ||
14 14 Some unchanged lines12 | ||
15 - And here is the finish with way more than 80 characters and I'm very curious how this is going to be displayed in split view diff. | ||
16 15 This line is unchanged | ||
16 + This line has been added | ||
17 17 Some unchanged lines13 | ||
18 18 Some unchanged lines14 | ||
19 19 Some unchanged lines15 | ||
[...] | ||
[...] | ||
22 22 Some unchanged lines18 | ||
23 23 Some unchanged lines19 | ||
24 24 Some unchanged lines20 | ||
25 - <<Another>> <<difference>> | ||
25 + <<This>> <<has changed>> | ||
26 26 Some unchanged lines21 | ||
27 27 Some unchanged lines22 | ||
28 28 Some unchanged lines23 | ||
[...] | ||
``` | ||
|
||
Split Diff | ||
``` | ||
[...] | ||
6 Some unchanged lines6 | 6 Some unchanged lines6 | ||
7 Some unchanged lines7 | 7 Some unchanged lines7 | ||
8 Some unchanged lines8 | 8 Some unchanged lines8 | ||
9 ! This is a test <<senctence>>. | 9 ! This is a test <<for diffutils>>. | ||
10 This is the second line. | 10 This is the second line. | ||
11 Some unchanged lines9 | 11 Some unchanged lines9 | ||
12 Some unchanged lines10 | 12 Some unchanged lines10 | ||
13 Some unchanged lines11 | 13 Some unchanged lines11 | ||
14 Some unchanged lines12 | 14 Some unchanged lines12 | ||
15 - And here is the finish with way more than 80 characters and I'm very curious how this is going to be displayed in split view diff. | | ||
16 This line is unchanged | 15 This line is unchanged | ||
| 16 + This line has been added | ||
17 Some unchanged lines13 | 17 Some unchanged lines13 | ||
18 Some unchanged lines14 | 18 Some unchanged lines14 | ||
19 Some unchanged lines15 | 19 Some unchanged lines15 | ||
[...] | ||
[...] | ||
22 Some unchanged lines18 | 22 Some unchanged lines18 | ||
23 Some unchanged lines19 | 23 Some unchanged lines19 | ||
24 Some unchanged lines20 | 24 Some unchanged lines20 | ||
25 ! <<Another>> <<difference>> | 25 ! <<This>> <<has changed>> | ||
26 Some unchanged lines21 | 26 Some unchanged lines21 | ||
27 Some unchanged lines22 | 27 Some unchanged lines22 | ||
28 Some unchanged lines23 | 28 Some unchanged lines23 | ||
[...] | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
plugins { | ||
id("snapshot-tests.published-java-component") | ||
} | ||
description = "Diff Tool" | ||
ext.automaticModuleName = "de.skuzzle.test.snapshots.difftool" | ||
|
||
dependencies { | ||
api(libs.javadiffutils) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package de.skuzzle.difftool; | ||
|
||
import java.util.List; | ||
|
||
public interface DiffAlgorithm { | ||
|
||
List<DiffLine> diffOf(List<String> left, List<String> right); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package de.skuzzle.difftool; | ||
|
||
import java.util.Objects; | ||
|
||
public final class DiffLine { | ||
|
||
private final Type type; | ||
private final String oldLine; | ||
private final String newLine; | ||
|
||
public DiffLine(Type type, String oldLine, String newLine) { | ||
this.type = Objects.requireNonNull(type); | ||
this.oldLine = Objects.requireNonNull(oldLine); | ||
this.newLine = Objects.requireNonNull(newLine); | ||
} | ||
|
||
public enum Type { | ||
INSERT, | ||
DELETE, | ||
CHANGE, | ||
EQUAL | ||
} | ||
|
||
public Type type() { | ||
return type; | ||
} | ||
|
||
public String oldLine() { | ||
return oldLine; | ||
} | ||
|
||
public String newLine() { | ||
return newLine; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) | ||
return true; | ||
if (o == null || getClass() != o.getClass()) | ||
return false; | ||
final DiffLine diffLine = (DiffLine) o; | ||
return type == diffLine.type && oldLine.equals(diffLine.oldLine) && newLine.equals(diffLine.newLine); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(type, oldLine, newLine); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "[" + this.type + "," + this.oldLine + "," + this.newLine + "]"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package de.skuzzle.difftool; | ||
|
||
import java.util.List; | ||
|
||
/** | ||
* Defines how a diff is rendered as a String. | ||
*/ | ||
public interface DiffRenderer { | ||
|
||
/** | ||
* Creates a String representation of the provided diff. | ||
* | ||
* @param rows The diff. | ||
* @param diffSettings Additional parameters. | ||
* @return The String representation. | ||
*/ | ||
String renderDiff(List<DiffLine> rows, DiffSettings diffSettings); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package de.skuzzle.difftool; | ||
|
||
/** | ||
* Defines parameters that are used when rendering a diff to String using a | ||
* {@link DiffRenderer}. | ||
*/ | ||
public final class DiffSettings { | ||
|
||
public static final DiffSettings DEFAULT = new DiffSettings(5, 0, DiffSymbols.DEFAULT); | ||
|
||
private final int contextLines; | ||
private final int lineNumberOffset; | ||
private final DiffSymbols symbols; | ||
|
||
public DiffSettings(int contextLines, int lineNumberOffset, DiffSymbols symbols) { | ||
this.contextLines = contextLines; | ||
this.lineNumberOffset = lineNumberOffset; | ||
this.symbols = symbols; | ||
} | ||
|
||
public static DiffSettings withDefaultSymbols(int contextLines, int lineNumberOffset) { | ||
return new DiffSettings(contextLines, lineNumberOffset, DiffSymbols.DEFAULT); | ||
} | ||
|
||
public int contextLines() { | ||
return contextLines; | ||
} | ||
|
||
public int lineNumberOffset() { | ||
return lineNumberOffset; | ||
} | ||
|
||
public DiffSymbols symbols() { | ||
return symbols; | ||
} | ||
|
||
public static final class DiffSymbols { | ||
|
||
public static DiffSymbols DEFAULT = new DiffSymbols("!", "+", "-", " ", LineSeparator.SYSTEM, "[...]"); | ||
|
||
private final String changedLine; | ||
private final String addedLine; | ||
private final String deletedLine; | ||
private final String equalLine; | ||
private final LineSeparator newLineCharacter; | ||
private final String continuation; | ||
|
||
public DiffSymbols(String changedLine, String addedLine, String deletedLine, String equalLine, | ||
LineSeparator newLineCharacter, String continuation) { | ||
this.changedLine = changedLine; | ||
this.addedLine = addedLine; | ||
this.deletedLine = deletedLine; | ||
this.equalLine = equalLine; | ||
this.newLineCharacter = newLineCharacter; | ||
this.continuation = continuation; | ||
} | ||
|
||
public String changedLine() { | ||
return changedLine; | ||
} | ||
|
||
public String addedLine() { | ||
return addedLine; | ||
} | ||
|
||
public String deletedLine() { | ||
return deletedLine; | ||
} | ||
|
||
public String equalLine() { | ||
return equalLine; | ||
} | ||
|
||
public LineSeparator newLineCharacter() { | ||
return newLineCharacter; | ||
} | ||
|
||
public String continuation() { | ||
return continuation; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,67 @@ | ||||||||||||||
package de.skuzzle.difftool; | ||||||||||||||
|
||||||||||||||
import java.util.Locale; | ||||||||||||||
|
||||||||||||||
final class GitLineSeparator { | ||||||||||||||
|
||||||||||||||
static final LineSeparator GIT_LINE_SEPARATOR = determineGitLineSeparator(GitConfig.DEFAULT); | ||||||||||||||
|
||||||||||||||
static LineSeparator determineGitLineSeparator(GitConfig gitConfig) { | ||||||||||||||
final String autocrlf = gitConfig.autocrlf(); | ||||||||||||||
if (autocrlf == null) { | ||||||||||||||
return LineSeparator.SYSTEM; | ||||||||||||||
} | ||||||||||||||
switch (autocrlf.toLowerCase(Locale.ROOT)) { | ||||||||||||||
case "true": | ||||||||||||||
return LineSeparator.CRLF; | ||||||||||||||
case "input": | ||||||||||||||
return LineSeparator.LF; | ||||||||||||||
case "false": | ||||||||||||||
final String eol = gitConfig.eol(); | ||||||||||||||
if (eol == null) { | ||||||||||||||
return LineSeparator.SYSTEM; | ||||||||||||||
} | ||||||||||||||
switch (eol.toLowerCase(Locale.ROOT)) { | ||||||||||||||
case "crlf": | ||||||||||||||
return LineSeparator.CRLF; | ||||||||||||||
case "lf": | ||||||||||||||
return LineSeparator.LF; | ||||||||||||||
case "native": | ||||||||||||||
default: | ||||||||||||||
return LineSeparator.SYSTEM; | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
return LineSeparator.SYSTEM; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
static class GitConfig { | ||||||||||||||
|
||||||||||||||
static final GitConfig DEFAULT = new GitConfig(); | ||||||||||||||
|
||||||||||||||
String autocrlf() { | ||||||||||||||
return execute("git config core.autocrlf"); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
String eol() { | ||||||||||||||
return execute("git config core.eol"); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
static String execute(String command) { | ||||||||||||||
try { | ||||||||||||||
final Process exec = Runtime.getRuntime().exec(command); | ||||||||||||||
try (var err = exec.getErrorStream()) { | ||||||||||||||
err.readAllBytes(); | ||||||||||||||
} | ||||||||||||||
try (var in = exec.getInputStream()) { | ||||||||||||||
return new String(in.readAllBytes()); | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DefaultCharset: Implicit use of the platform default charset, which can result in differing behaviour between JVM executions or incorrect behavior if the encoding of the data source doesn't match expectations.
Suggested change
ℹ️ Expand to see all @sonatype-lift commandsYou can reply with the following commands. For example, reply with @sonatype-lift ignoreall to leave out all findings.
Note: When talking to LiftBot, you need to refresh the page to see its response. Help us improve LIFT! (Sonatype LiftBot external survey) Was this a good recommendation for you? Answering this survey will not impact your Lift settings. [ 🙁 Not relevant ] - [ 😕 Won't fix ] - [ 😑 Not critical, will fix ] - [ 🙂 Critical, will fix ] - [ 😊 Critical, fixing now ] |
||||||||||||||
} | ||||||||||||||
} catch (Exception e) { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. RESOURCE_LEAK: resource of type ℹ️ Expand to see all @sonatype-lift commandsYou can reply with the following commands. For example, reply with @sonatype-lift ignoreall to leave out all findings.
Note: When talking to LiftBot, you need to refresh the page to see its response. Help us improve LIFT! (Sonatype LiftBot external survey) Was this a good recommendation for you? Answering this survey will not impact your Lift settings. [ 🙁 Not relevant ] - [ 😕 Won't fix ] - [ 😑 Not critical, will fix ] - [ 🙂 Critical, will fix ] - [ 😊 Critical, fixing now ] |
||||||||||||||
return null; | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
private GitLineSeparator() { | ||||||||||||||
// hidden | ||||||||||||||
} | ||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RESOURCE_LEAK: resource of type
java.lang.Process
acquired by call toexec(...)
at line 51 is not released after line 55.ℹ️ Expand to see all @sonatype-lift commands
You can reply with the following commands. For example, reply with @sonatype-lift ignoreall to leave out all findings.
@sonatype-lift ignore
@sonatype-lift ignoreall
@sonatype-lift exclude <file|issue|path|tool>
file|issue|path|tool
from Lift findings by updating your config.toml fileNote: When talking to LiftBot, you need to refresh the page to see its response.
Click here to add LiftBot to another repo.
Help us improve LIFT! (Sonatype LiftBot external survey)
Was this a good recommendation for you? Answering this survey will not impact your Lift settings.
[ 🙁 Not relevant ] - [ 😕 Won't fix ] - [ 😑 Not critical, will fix ] - [ 🙂 Critical, will fix ] - [ 😊 Critical, fixing now ]